V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
qk3z
V2EX  ›  Java

有没有大大搞过高性能的 udp 服务器的,遇到个问题,想请教下。 已经调了两天了,方法基本上都已经试过了。本人小弱鸡,谢谢啦~

  •  
  •   qk3z · 2017-12-13 21:39:45 +08:00 · 5371 次点击
    这是一个创建于 2562 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在不考虑丢包率的状态下,开一个端口服务器最高每秒收包 16w 左右。这个还能有什么方法再提升么?
    我开两个线程两个端口收包,就变成一个端口收 10 多万每秒,一个端口收 4、5 万每秒,感觉不对劲额,是不是有什么问题?先谢谢大家指点了。。。

    忘了说一点,一个数据包 1.3k 左右,大小固定死了。
    第 1 条附言  ·  2017-12-14 09:53:03 +08:00
    我看网卡上每秒是能接收到二三十万包的,但是 java 服务端这边开一个端口最多每秒就十六七万了..。
    把系统内核的 socket 缓存调大,能高个几万,但是和实际网卡接包数还是有差距。
    谢谢大家留言,我先放物理机上再测测,实在不行就放代码了...
    第 2 条附言  ·  2017-12-14 14:06:22 +08:00
    物理机上跑性能果然上升了一倍多,但是多端口多线程还是没什么提升。
    目前存在的问题就是网卡收包速还是略大于程序接收的包数,丢失的数据过多。
    程序就不贴了,就是简单的 udp socket 套接字接收数据,再一次谢谢各位大佬的意见。
    27 条回复    2017-12-14 14:19:43 +08:00
    defunct9
        1
    defunct9  
       2017-12-13 22:04:36 +08:00 via iPhone   ❤️ 1
    开 ssh,我上去看看
    qk3z
        2
    qk3z  
    OP
       2017-12-13 22:10:28 +08:00
    @defunct9 #1 公司内网服务器...
    likuku
        3
    likuku  
       2017-12-13 22:24:54 +08:00   ❤️ 1
    网卡 /交换机转发率 /CPU 到顶了?
    defunct9
        4
    defunct9  
       2017-12-13 22:27:50 +08:00 via iPhone
    程序扔出来看看
    hugee
        5
    hugee  
       2017-12-13 22:34:21 +08:00   ❤️ 1
    要看具体程序
    changnet
        6
    changnet  
       2017-12-13 22:35:49 +08:00   ❤️ 1
    一般来说,内网服务器不太可能是因为网络问题,硬件也没变。基本上是你的程序写得有问题,比如你两个线程是不是存在竞争,或者你这个服务器是跑在虚拟机下的,就会这样。
    qk3z
        7
    qk3z  
    OP
       2017-12-13 22:51:10 +08:00
    @defunct9 #4
    @hugee #5 明天放代码给给位看看,谢谢指点


    @likuku #3 这个是虚拟机,CPU,网卡应该没到顶...
    @changnet #6 是在虚拟机下跑的,准备明天放到物理机上看看有没有提升。要不就是程序写得有问题...
    blahgeek
        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/
    blahgeek
        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
    Michaelssss
        10
    Michaelssss  
       2017-12-13 23:02:53 +08:00   ❤️ 1
    我小小算了下。。。208MB/S,大概比千兆网络强
    changnet
        11
    changnet  
       2017-12-13 23:12:45 +08:00   ❤️ 1
    @qk3z 虚拟机开多线程、多进程都是会降性能的。双线程大概只有 1/2,三线程 1/3。这个你 google 一下就知道,无论是 virtualbox 还是 vm 都有这个问题。我之前测自己程序性能时也踩这个坑了。
    changnet
        12
    changnet  
       2017-12-13 23:54:24 +08:00
    @changnet
    @qk3z
    一激动,貌似搞错了。是给虚拟机加 cpu 核心数量性能才会降得这么厉害,就是设置虚拟的 cpu 数量。多线程貌似没这个问题,不过虚拟机是工作在单线程。多线程反而会降一些性能,但是不会降这么厉害。
    wsy2220
        13
    wsy2220  
       2017-12-13 23:57:44 +08:00   ❤️ 1
    测性能别用虚拟机
    tempdban
        14
    tempdban  
       2017-12-14 08:37:05 +08:00 via Android   ❤️ 1
    mtcp+dpdk
    Panic
        15
    Panic  
       2017-12-14 08:50:13 +08:00   ❤️ 1
    绑定进程到特定核试试,cpu 亲和性
    watzds
        16
    watzds  
       2017-12-14 09:27:58 +08:00 via Android   ❤️ 1
    @blahgeek 你说的是开一个端口,两个线程收,需要加锁。这种情况可以加 SO_REUSEPORT。
    楼主直接开了两个端口吧
    afeicool
        17
    afeicool  
       2017-12-14 09:37:21 +08:00   ❤️ 1
    好奇实际业务上下文:)
    realpg
        18
    realpg  
       2017-12-14 09:38:43 +08:00   ❤️ 1
    一般普通服务器 udp 纯发包的服务器 万兆网卡只要程序写的不弱智 不任何优化 最次也能跑大约 2.2Gbps
    qk3z
        19
    qk3z  
    OP
       2017-12-14 09:39:06 +08:00
    @tempdban #14 使用 java 写的...
    @Michaelssss #10 万兆网卡...
    qk3z
        20
    qk3z  
    OP
       2017-12-14 09:44:37 +08:00
    @afeicool #17 C 那边给发数据包,java 这边接收并统计计算啥的,但是现在这边接收达不到性能要求。
    @realpg #18 是 Java 服务器么... 可能我程序也有问题吧 0.0
    nullen
        21
    nullen  
       2017-12-14 09:51:02 +08:00   ❤️ 1
    airqj
        22
    airqj  
       2017-12-14 10:02:09 +08:00   ❤️ 1
    先不要业务逻辑 收到包后就丢掉 看看最大能接收多少
    尽量减少内核态与用户态的数据拷贝
    realpg
        23
    realpg  
       2017-12-14 10:09:45 +08:00 via Android
    @qk3z
    C 和 PYTHON 都能
    JAVA 没研究过
    写高性能服务器很少用
    catror
        24
    catror  
       2017-12-14 10:09:58 +08:00   ❤️ 1
    你这内核协议栈瓶颈都没达到,不需要上 DPDK 之类的技术。在物理机上测试时,可以考虑两个线程分辨绑定不同的核来测。性能上不去主要原因应该还是 CPU 或者锁竞争。
    defunct9
        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;
    }
    qk3z
        26
    qk3z  
    OP
       2017-12-14 14:10:11 +08:00
    @defunct9 #25 我知道 C 达到这个性能是可以的,但我这个需要用 java 搞定,还是谢谢大佬了。
    janxin
        27
    janxin  
       2017-12-14 14:19:43 +08:00   ❤️ 1
    先看问题在哪个层面再说吧,从现在的描述细节反正是可以排除硬件层面。
    那么优先考虑代码层面。因为没有就不好猜了。
    其次考虑系统优化层面。如果都调整过了,那回过头去看代码层面。或者写个能处理的 C 程序,证明是代码层面问题(如果时间够,没办法了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2945 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 14:39 · PVG 22:39 · LAX 06:39 · JFK 09:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.