利用libevent验证SO_REUSEPORT内核态的负载均衡

1,768 阅读1分钟

复用端口(SO_REUSEPORT)基本介绍

Linux kernel 3.9版本引入SO_REUSEPORT的新特性:

  • 允许多个套接字 bind()/listen() 同一个TCP/UDP端口
  • 内核层面实现负载均衡

解决了网络编程著名的惊群问题

代码

https://github.com/feelc/blogs-share/tree/main/0_multithread_server

为了多个线程可以绑定同一个IP和端口,则需要对socket进行如下的设置:

int32_t enable = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));

启动后用netstat查看网络状态可以看到
5个线程同时监听了同一个TCP协议的IP和PORT,
5个线程同时监听了同一个UDP协议的IP和PORT。

# netstat -annp |egrep main |egrep 55555
tcp        0      0 127.0.0.1:55555         0.0.0.0:*               LISTEN      3035124/./main      
tcp        0      0 127.0.0.1:55555         0.0.0.0:*               LISTEN      3035124/./main      
tcp        0      0 127.0.0.1:55555         0.0.0.0:*               LISTEN      3035124/./main      
tcp        0      0 127.0.0.1:55555         0.0.0.0:*               LISTEN      3035124/./main      
tcp        0      0 127.0.0.1:55555         0.0.0.0:*               LISTEN      3035124/./main      
udp        0      0 127.0.0.1:55555         0.0.0.0:*                           3035055/./main      
udp        0      0 127.0.0.1:55555         0.0.0.0:*                           3035055/./main      
udp        0      0 127.0.0.1:55555         0.0.0.0:*                           3035055/./main      
udp        0      0 127.0.0.1:55555         0.0.0.0:*                           3035055/./main      
udp        0      0 127.0.0.1:55555         0.0.0.0:*                           3035055/./main

测试

测试程序分10组请求,每组启动1000个客户端

#!/bin/bash

for (( i = 0; i < 10; i++ )); do
    echo $i
    for (( j = 0; j < 1000; j++ )); do
        ./client &
    done
    sleep 0.1
done

执行完毕后,观看服务端的输出:

tid: 0, cnt: 2058
tid: 1, cnt: 1996
tid: 2, cnt: 1917
tid: 3, cnt: 2008
tid: 4, cnt: 2021

服务端共有5个线程,可以看到每个线程处理的请求数相差不大,这就是内核负载均衡的效果。

内核负载均衡的实现原理请看连接