1
defunct9 2017-12-13 22:04:36 +08:00 via iPhone 1
开 ssh,我上去看看
|
3
likuku 2017-12-13 22:24:54 +08:00 1
网卡 /交换机转发率 /CPU 到顶了?
|
4
defunct9 2017-12-13 22:27:50 +08:00 via iPhone
程序扔出来看看
|
5
hugee 2017-12-13 22:34:21 +08:00 1
要看具体程序
|
6
changnet 2017-12-13 22:35:49 +08:00 1
一般来说,内网服务器不太可能是因为网络问题,硬件也没变。基本上是你的程序写得有问题,比如你两个线程是不是存在竞争,或者你这个服务器是跑在虚拟机下的,就会这样。
|
7
qk3z OP |
8
blahgeek 2017-12-13 23:00:51 +08:00 1
之前在 Cloudflare 的 blog 里看到过,个人觉得写的很清晰
https://blog.cloudflare.com/how-to-receive-a-million-packets/ https://blog.cloudflare.com/kernel-bypass/ |
9
blahgeek 2017-12-13 23:02:28 +08:00
其中提到了你遇到的问题:
The receiving performance is down compared to a single threaded program. That's caused by a lock contention on the UDP receive buffer side. ... Fortunately, there is a workaround recently added to Linux: the SO_REUSEPORT flag |
10
Michaelssss 2017-12-13 23:02:53 +08:00 1
我小小算了下。。。208MB/S,大概比千兆网络强
|
11
changnet 2017-12-13 23:12:45 +08:00 1
@qk3z 虚拟机开多线程、多进程都是会降性能的。双线程大概只有 1/2,三线程 1/3。这个你 google 一下就知道,无论是 virtualbox 还是 vm 都有这个问题。我之前测自己程序性能时也踩这个坑了。
|
12
changnet 2017-12-13 23:54:24 +08:00
|
13
wsy2220 2017-12-13 23:57:44 +08:00 1
测性能别用虚拟机
|
14
tempdban 2017-12-14 08:37:05 +08:00 via Android 1
mtcp+dpdk
|
15
Panic 2017-12-14 08:50:13 +08:00 1
绑定进程到特定核试试,cpu 亲和性
|
16
watzds 2017-12-14 09:27:58 +08:00 via Android 1
@blahgeek 你说的是开一个端口,两个线程收,需要加锁。这种情况可以加 SO_REUSEPORT。
楼主直接开了两个端口吧 |
17
afeicool 2017-12-14 09:37:21 +08:00 1
好奇实际业务上下文:)
|
18
realpg 2017-12-14 09:38:43 +08:00 1
一般普通服务器 udp 纯发包的服务器 万兆网卡只要程序写的不弱智 不任何优化 最次也能跑大约 2.2Gbps
|
19
qk3z OP |
20
qk3z OP |
21
nullen 2017-12-14 09:51:02 +08:00 1
|
22
airqj 2017-12-14 10:02:09 +08:00 1
先不要业务逻辑 收到包后就丢掉 看看最大能接收多少
尽量减少内核态与用户态的数据拷贝 |
24
catror 2017-12-14 10:09:58 +08:00 1
你这内核协议栈瓶颈都没达到,不需要上 DPDK 之类的技术。在物理机上测试时,可以考虑两个线程分辨绑定不同的核来测。性能上不去主要原因应该还是 CPU 或者锁竞争。
|
25
defunct9 2017-12-14 14:07:45 +08:00 1
#include <unistd.h>
#include <stdlib.h> #include <string.h> #include <stdio.h> #include <stdbool.h> #include <arpa/inet.h> #include <pthread.h> void* do_work(void *arg) { int *port = (int *) arg; int listen_socket = socket(AF_INET, SOCK_STREAM, 0); int one = 1; setsockopt(listen_socket, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(*port); int ret = bind(listen_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); listen(listen_socket, 5); struct sockaddr_in cli_addr; memset(&cli_addr, 0, sizeof(cli_addr)); int addr_length = sizeof(cli_addr); do { int cli_sock = accept(listen_socket, (struct sockaddr *) &cli_addr, (socklen_t *) &addr_length); close(cli_sock); } while (true); close(listen_socket); return 0; } int main(int ac, const char *av[]) { int port = atoi(av[1]); const int MAX_THREADS = 10; pthread_t tid[MAX_THREADS]; for (int i = 0; i < MAX_THREADS; i++) { pthread_create(&tid[i], NULL, do_work, &port); } for (int i = 0; i < MAX_THREADS; i++) { pthread_join(tid[i], NULL); } return 0; } |
27
janxin 2017-12-14 14:19:43 +08:00 1
先看问题在哪个层面再说吧,从现在的描述细节反正是可以排除硬件层面。
那么优先考虑代码层面。因为没有就不好猜了。 其次考虑系统优化层面。如果都调整过了,那回过头去看代码层面。或者写个能处理的 C 程序,证明是代码层面问题(如果时间够,没办法了 |