Nginx实现udp负载均衡(部署+测试)

  1. 下载:wget http://nginx.org/download/nginx-1.16.1.tar.gz
    本地下载(内含部署文档): 点击下载 nginx-1.16.1
  2. 安装依赖
    apt-get install gcc gcc-c++ autoconf automake
    apt-get install zlib1g-dev openssl libssl-dev libpcre3 libpcre3-dev
    
  3. 安装
    tar xvf nginx-1.16.1.tar.gz
    cd nginx-1.16.1
    ./configure --with-stream
    make
    make install
    ldconfig
    
  4. nginx配置udp转发
    vi /usr/local/nginx/conf/nginx.conf 修改如下:
    	#user  nobody;
    	worker_processes  1;
    
    	#error_log  logs/error.log;
    	#error_log  logs/error.log  notice;
    	#error_log  logs/error.log  info;
    
    	#pid        logs/nginx.pid;
    
    	events {
    	    worker_connections  1024;
    	}
    	stream {
    		upstream dns_servers{
    			least_conn;
    			server 192.168.2.125:20001 ;
    			server 192.168.2.125:20002 ;
    		}
    		server {
    			listen 20000 udp;
    			proxy_pass dns_servers;
    			proxy_buffer_size 16k;
    			proxy_timeout 10s;
    		}
    	}
    	```
    
  5. 启动
    vi /usr/lib/systemd/system/nginx.service
    	[Unit]
    	Description=nginx - high performance web server
    	After=network.target remote-fs.target nss-lookup.target
    
    	[Service]
    	Type=forking
    	ExecStart=/usr/local/nginx/sbin/nginx
    	ExecReload=/usr/local/nginx/sbin/nginx -s reload
    	ExecStop=/usr/local/nginx/sbin/nginx -s stop
    
    	[Install]
    	WantedBy=multi-user.target
    systemctl daemon-reload //重新加载服务
    
    systemctl start nginx  //启动
    systemctl stop nginx  //停止
    systemctl reload nginx  //重启 可以不用停止nginx服务,使修改的配置生效
    systemctl restart nginx  //重启
    systemctl enable nginx  //设置开机启动
    systemctl disable nginx  //禁用开机启动
    systemctl status nginx  //查看服务状态
    
  6. 测试代码
  • server.py 启动两台服务端
# coding=utf-8
import time, threading
import random
import gevent
import signal
from gevent import socket
import sys, os

remote = (("192.168.2.125", 20001), ("192.168.2.125", 20002))
ncli = range(0, len(remote))
threads = []
def serverThread(arg, val):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(remote[arg])
    print "[%d]Thread: Bind %s" % (arg, remote[arg])
    while True:
        try:
            recv_data, addr = sock.recvfrom(1024)
            print '[%d]Thread: Recv from %s:%s' % (arg, addr, recv_data)
            send_data = '[%s]Hello, %s!' % (remote[arg], recv_data)
            sock.sendto(send_data, addr)
        except Exception as e:
            print e
    sock.close()

def Process():
    try:
        for i in ncli:
            t = threading.Thread(target=serverThread, args=(i,0))
            t.setDaemon(True)
            threads.append(t)
        for i in ncli:
            threads[i].start()
    except KeyboardInterrupt:
        print 'end'

def signal_handler(signum, frame):
    print 'PID:[%d] exit!' % os.getpid()
    os.kill(os.getpid(),signal.SIGKILL)	

def CtrlSignalExit():
    signal.signal(signal.SIGINT, signal_handler)

if __name__ == '__main__':
    CtrlSignalExit()
    Process()
    while True:
        alive = False
        for i in ncli:
            alive = alive or threads[i].isAlive()
            time.sleep(0.01)
        if not alive:
            break
  • client.py 启动多台客户端
# coding=utf-8

import time, threading
import random
import gevent
import signal
from gevent import socket
import sys, os

thread_num = 5  #open thread num
is_exit = True
time_out_count = 0
start_time = 0
thread_count = range(0,thread_num)

def clientThread(arg,val):
    sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    socket.setdefaulttimeout(3)
    remote = ("192.168.2.125", 20000)

    count = 0
    while is_exit:
        try:
            count += 1
            
            global thread_count
            thread_count[arg] = count
            send_data = '[%d]Client: Test:%d' % (arg, count)
            sock.sendto(send_data,remote)
            recv_data,address = sock.recvfrom(1024)
            print recv_data
        except socket.timeout as e:
            global time_out_count
            time_out_count += 1
            print 'time out'
            if is_exit == False:
                break
        time.sleep(1)
    sock.close()

ncli = range(0,thread_num)
threads = []
def press_test():
    try:
        for i in ncli:
            t = threading.Thread(target=clientThread, args=(i,0))
            t.setDaemon(True)
            threads.append(t)
        for i in ncli:
            threads[i].start()
    except KeyboardInterrupt:
        print 'end'

def signal_handler(signum, frame):
    tatol_count = 0
    time_count = int(time.time() - start_time)
    global is_exit
    is_exit = False
    time.sleep(1)
    print '\n**********Press Result*********'
    for i,val in enumerate(thread_count):
        tatol_count += val
        print 'index:%d count:%d' % (i,val)
    print 'Press test end time out:%d' % (time_out_count)
    print 'Press test time:%ds' % (time_count)
    print 'Press test tatol count:%d' % (tatol_count)
    if time_count > 0:
        print 'Press test average second num:%d' % (tatol_count/time_count)

def CtrlSignalExit():
    signal.signal(signal.SIGINT, signal_handler)

if __name__ == '__main__':
    global start_time
    start_time = time.time()
    CtrlSignalExit()
    press_test()
    while True:
        alive = False
        for i in ncli:
            alive = alive or threads[i].isAlive()
            time.sleep(0.01)
        if not alive:
            break
  1. 测试结果
  • 服务端
[0]Thread: Bind ('192.168.2.125', 20001)
[1]Thread: Bind ('192.168.2.125', 20002)

[0]Thread: Recv from ('192.168.2.125', 38190):[0]Client: Test:1
[1]Thread: Recv from ('192.168.2.125', 59498):[1]Client: Test:1
[1]Thread: Recv from ('192.168.2.125', 60757):[2]Client: Test:1
[0]Thread: Recv from ('192.168.2.125', 50820):[3]Client: Test:1
[0]Thread: Recv from ('192.168.2.125', 56942):[4]Client: Test:1
[1]Thread: Recv from ('192.168.2.125', 60757):[2]Client: Test:2
[0]Thread: Recv from ('192.168.2.125', 38190):[0]Client: Test:2
[1]Thread: Recv from ('192.168.2.125', 59498):[1]Client: Test:2
[0]Thread: Recv from ('192.168.2.125', 56942):[4]Client: Test:2
[0]Thread: Recv from ('192.168.2.125', 50820):[3]Client: Test:2
[1]Thread: Recv from ('192.168.2.125', 60757):[2]Client: Test:3
[0]Thread: Recv from ('192.168.2.125', 38190):[0]Client: Test:3
[0]Thread: Recv from ('192.168.2.125', 50820):[3]Client: Test:3
[1]Thread: Recv from ('192.168.2.125', 59498):[1]Client: Test:3
[0]Thread: Recv from ('192.168.2.125', 56942):[4]Client: Test:3
  • 客户端
[('192.168.2.125', 20002)]Hello, [2]Client: Test:1!
[('192.168.2.125', 20001)]Hello, [0]Client: Test:1!
[('192.168.2.125', 20002)]Hello, [1]Client: Test:1!
[('192.168.2.125', 20001)]Hello, [3]Client: Test:1!
[('192.168.2.125', 20001)]Hello, [4]Client: Test:1!
[('192.168.2.125', 20002)]Hello, [2]Client: Test:2!
[('192.168.2.125', 20002)]Hello, [1]Client: Test:2!
[('192.168.2.125', 20001)]Hello, [4]Client: Test:2!
[('192.168.2.125', 20001)]Hello, [0]Client: Test:2!
[('192.168.2.125', 20001)]Hello, [3]Client: Test:2!
[('192.168.2.125', 20001)]Hello, [3]Client: Test:3!
[('192.168.2.125', 20001)]Hello, [0]Client: Test:3!
[('192.168.2.125', 20002)]Hello, [2]Client: Test:3!
[('192.168.2.125', 20002)]Hello, [1]Client: Test:3!
[('192.168.2.125', 20001)]Hello, [4]Client: Test:3!
对于Nginx负载均衡部署,有几种常见的方式可以实现。 1. 基于代理模块的负载均衡: 使用Nginx的`proxy_pass`指令来代理后端服务器,通过配置多个代理服务器,实现请求的负载均衡。可以配置不同的负载均衡算法,如轮询、IP哈希、权重等。 示例配置: ```nginx http { upstream backend { server backend1.example.com; server backend2.example.com; server backend3.example.com; } server { listen 80; location / { proxy_pass http://backend; } } } ``` 2. 基于HTTP模块的负载均衡: 使用Nginx的`ngx_http_upstream_module`模块提供的负载均衡功能。通过配置`upstream`块来定义后端服务器组,并在`location`中指定负载均衡方式。 示例配置: ```nginx http { upstream backend { least_conn; server backend1.example.com; server backend2.example.com; server backend3.example.com; } server { listen 80; location / { proxy_pass http://backend; } } } ``` 3. 基于TCP/UDP模块的负载均衡: 对于非HTTP协议的负载均衡,可以使用Nginx的`stream`模块。通过配置`stream`块来定义后端服务器组,并指定负载均衡方式。 示例配置: ```nginx stream { upstream backend { least_conn; server backend1.example.com:8080; server backend2.example.com:8080; server backend3.example.com:8080; } server { listen 80; proxy_pass backend; } } ``` 以上是几种常见的Nginx负载均衡部署方式,可以根据实际需求选择适合的方式。请注意在实际应用中根据情况进行调优和安全配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值