使用Nginx转发TCP/UDP

环境

  • OS: Centos6-x86_64
  • Nginx: 1.12.1

编译安装Nginx

从1.9.0开始,nginx就支持对TCP的转发,而到了1.9.13时,UDP转发也支持了。提供此功能的模块为ngx_stream_core。不过Nginx默认没有开启此模块,所以需要手动安装。

cd /usr/local/src
wget http://nginx.org/download/nginx-1.12.1.tar.gz
tar zxf nginx-1.12.1.tar.gz
cd nginx-1.12.1
./configure --prefix=/usr/local/nginx --with-stream --without-http
make && make install

Note:由于是传输层转发,本着最小化原则,就关闭了http功能。


配置Nginx

TCP转发

目标:通过3000端口访问本机Mysql(其中mysql使用yum安装,默认配置文件)

/usr/local/nginx/conf/nginx.conf配置如下:

user  nobody;
worker_processes  auto;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    use epoll;
    worker_connections  1024;
}


stream {
    server {
        listen 3000;
        proxy_pass 127.0.0.1:3306;

    # 也支持socket
    # proxy_pass unix:/var/lib/mysql/mysql.socket;
    }
}

首先,先通过3306端口访问mysql:

image.png

然后,启动Nginx:

image.png

最后使用3000端口访问mysql:

image.png

UDP转发

目标: 发送UDP数据到3000端口,3001端口可以接收

/usr/local/nginx/conf/nginx.conf配置如下:

user  nobody;
worker_processes  auto;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    use epoll;
    worker_connections  1024;
}


stream {
    server {
        listen 3000 udp;
        proxy_pass 127.0.0.1:3001;

    }
}

这里写一个my_socket_server.py侦听在3001端口,用于接收UDP数据:

# coding=utf-8

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sock.bind(('127.0.0.1', 3001))

print ('start server on [%s]:%s' % ('127.0.0.1', 3001))

while True:
    data, addr = sock.recvfrom(1024)
    print ('Received from %s:%s' % (addr,data))
    sock.sendto(b'Hello, %s!' % data, addr)

再写一个my_socket_client.py用于向Nginx侦听的3000端口发送数据:

# coding=utf-8

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

while True:
    data = raw_input('Input msg: ')
    if len(data) == 0:
        continue
    s.sendto(data.encode(), ('127.0.0.1', 3000))
    print (s.recv(1024).decode('utf-8'))

同时运行两个脚本,在client端发送数据:

4.gif

UDP转发遇到的一个坑

修改下client脚本,改为连续发送2000个数据包:

# coding=utf-8

import socket


s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

for data in range(2000):
    s.sendto(str(data).encode(), ('127.0.0.1', 3000))
    print (s.recv(1024).decode('utf-8'))

然后运行client脚本,发现经常会遇到如下情况:

image.png

由图可知只成功了511个。

查看文档得知listen指令有个backlog参数,此参数在Linux系统中默认为511:

image.png

悲剧的是backlog参数和udp参数不能同时使用。如果哪位朋友有好的解决办法,请赐教!!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,952评论 19 139
  • 更改ip和dnsVi /etc/sysconfig/network-scripts/ifcfg-eth0vi /...
    Xwei_阅读 1,854评论 0 3
  • 1.简介:  Nginx:engine X ,2002年,开源,商业版 http协议:web服务器(类似于ht...
    尛尛大尹阅读 1,895评论 0 3
  • 今天分享的书是心理学大师埃利斯的代表作《我的情绪为何总被他人左右》。 个人感悟: 1.遇事先冷静,解决情绪问题,然...
    欢喜园阅读 168评论 1 2
  • 什么是线程 线程是程序执行的一条路径,一个进程中可以包含多条线程 多线程并发执行可以提高程序的效率,可以同时完成多...
    WXFA阅读 176评论 0 0