Golang TcpProxy和Nodejs TcpProxy

gofounder · · 861 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

自己平时的工作基本都在php和nodejs之间徘徊,但是目前面对python和java的猛烈攻击呢,其实内心有一种隐隐的痛“PHP是世界上最好的语言“,”nodejs在cpu密集时服务彻底瘫痪"。。。

看了半个月python真实发现,其实它太像php语言了,所以基本不用怎么理解就会了。golang看了1个多月了真的得多写多看源代码才能收获,别看才30几个关键字但是内容真的很多,golang的性能是真的高可以大大缩减服务器开销,举个例子web服务中php需要100台机器,那么golang可能只需要10台甚至更少!

最近在研究mysql proxy,其实mysql本身是支持代理的,但是想自己尝试下这样就会很灵活:

  • 灵活slb mysql负载均衡
  • 读写直接通过proxy直接进行判断
  • 提前预警或拒绝危险性sql
  • ...太多太多太多好处

以下是golang mysql proxy的代码

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简单的proxy

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);
    });
}

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:gofounder

查看原文:Golang TcpProxy和Nodejs TcpProxy

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

861 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传