Golang TcpProxy和Nodejs TcpProxy

本身平時的工做基本都在php和nodejs之間徘徊,可是目前面對python和java的猛烈攻擊呢,其實心裏有一種隱隱的痛「PHP是世界上最好的語言「,」nodejs在cpu密集時服務完全癱瘓"。。。php

看了半個月python真實發現,其實它太像php語言了,因此基本不用怎麼理解就會了。golang看了1個多月了真的得多寫多看源代碼才能收穫,別看才30幾個關鍵字可是內容真的不少,golang的性能是真的高能夠大大縮減服務器開銷,舉個例子web服務中php須要100臺機器,那麼golang可能只須要10臺甚至更少!java

最近在研究mysql proxy,其實mysql自己是支持代理的,可是想本身嘗試下這樣就會很靈活:node

  • 靈活slb mysql負載均衡
  • 讀寫直接經過proxy直接進行判斷
  • 提早預警或拒絕危險性sql
  • ...太多太多太多好處

如下是golang mysql proxy的代碼python

package main
 
import (
       "net"
       "fmt"
       "time"
)
 
const (
       MYSQL_ADDRESS = "mysq-host"
       MYSQL_PORT = "3306"
)
 
func main() {
       listener, err := net.Listen("tcp", ":1234")
       if err != nil {
              fmt.Println("tcp", err.Error())
              return
       } else {
              fmt.Println("tcp", listener.Addr(), "success")
       }
 
       for {
              user, err := listener.Accept()
              if err != nil {
                     fmt.Println("accept error: ", err.Error())
                     continue
              }
              go proxyRequest(user)
       }
}
 
 
//打理用戶請求
func proxyRequest(user net.Conn) {
 
       fmt.Println(user.LocalAddr())
       bytes := make([]byte, 10240)
 
       conn, err := net.Dial("tcp", MYSQL_ADDRESS + ":" + MYSQL_PORT)
 
       if err != nil {
              fmt.Println(conn.RemoteAddr(), "error:", err.Error())
              conn.Close()
              return
       }
 
       ch := make(chan bool, 1)
       go proxyResponse(user, conn, ch)
 
       for {
              n, err := user.Read(bytes)
              if err != nil {
                     break
              }
              fmt.Println(string(bytes[:n]))
              conn.Write(bytes[:n])
       }
 
       defer close(ch)
 
       select {
       case <-ch:
              conn.Close()
              user.Close()
              fmt.Println("proxy over")
       case <-time.After(time.Second * 60):
              fmt.Println("proxy timeout")
       }
 
}
 
//代理服務的返回給用戶
func proxyResponse(user net.Conn, service net.Conn, ch chan bool) {
       bytes := make([]byte, 10240)
 
       for {
              n, err := service.Read(bytes)
              if err != nil {
                     break
              }
              user.Write(bytes[:n])
       }
 
       ch <- true
}

如下是nodejs簡單的proxymysql

var net = require('net');
var model = require('../../models/proxy');
var trace = require('../../libs/trace');

//代理表
var proxys = [];
//tcp server
var server = null;
//proxy information
var information = {count: 0, success: 0, error: 0};

/**
 * 啓動服務
 * @param info array
 * @param callback function
 */
exports.start = (info, callback) => {
    model.getProxyListFromServer(info.id, (err, result)=> {
        if (err) {
            callback(err, err);
        } else {
            proxys = result;
            initServer(info.port, info.to_host, info.to_port);

            callback(null);
        }
    });
};


/**
 * 中止服務.
 * @return bool
 */
exports.stop = function () {
    if (server && server.listening) {
        server.close();
        server = null;
        return true;
    }
    return false;
};


/**
 * 獲取信息
 * @return object
 */
exports.getInfo = () => {
    return information;
};


/**
 * 初始化tcp proxy server.
 * @param port
 * @param toHost
 * @param toPort
 */
function initServer(port, toHost, toPort) {
    server = net.createServer((client)=> {
        information.count++;

        client.on('end', () => {
            connect.end();
        });

        var connect = net.createConnection({host: toHost, port: toPort}, (err)=> {
        });
        connect.on('error', (err)=> {
            information.error++;
        });
        connect.on('end', ()=> {
            information.success++;
        });

        client.pipe(connect);
        connect.pipe(client);

        // client.on('data', function (data) {
        //     var buf = Buffer.from(data);
        //     console.log('data: ' + buf.toString());
        // });
    });

    server.listen(port, (err) => {
        if (err) {
            trace.log('proxy server error', err);
            process.exit();
        }
        trace.log('proxy server started', port);
    });
}
相關文章
相關標籤/搜索