某种情况下造成服务器发送消息无比延迟的原因

大家好!小弟最近在学习erlang,熟悉代码做了一个消息转发的server,但是在测试性能的时候遇到一个问题,请教各位,是哪里的问题,谢谢! 

我开发的消息转发server的功能: 
Aclient Bclient都连入Server,都并加入一个组C,Aclient向C组发一条消息,Server负责将消息发给C组内除了A外的其他Client,也就是B。开发没用OTP这些高级东西。SOCKET使用二进制,{active true},{packet 2}. 

消息Server的设计: 
有一个独立的进程负责监听client连入,当有新的client连入会为client申请独立的进程(client_recv process)负责接受这个client发来的消息,有一个独立的进程(group_manager process)维护分组和组的client成员列表,每个组(group process)有一个独立进程负责向组内的client转发消息。 

当Aclient连入server,就会为A启动(client_recv process)负责接受A发来的消息并通过进程通信告诉给group_manager来建立一个组group。Bclient连入操作和A一样,都会加入同一个组。 
当A发消息给SERVER要求把消息给组的其他成员时,client_recv通过进程通讯将消息给group进程,group进程便利组的成员列表将消息转发。 

在测试性能时遇到的问题: 
测试的时候A向SERVER发送100W的消息,用了8秒就发完了,并自动退出了,消息内容都一样,在内网做的测试。 
而SERVER通过tcpdump监听,确实也是在8秒把所有消息都收完了,不在有来自A的消息进入,但是SERVER向B转发消息用了很长时间,超过10分钟,最后我结束进程了。 

在程序内做了打印来判断程序的运行流程,发现SERVER一直执行从client_recv接受A的消息并给group来转发。 

请问是我设计的有问题造成消息转发很慢吗?还是由于进程间通讯造成的?有什么办法可以调优? 

(以下只节选该作者出问题的代码,注意循环后面的那个ok原子)

72.group(Client)->%%负责组的消息群发的进程   
73.    ?DEBUG("group \r\n",[]),   
74.    receive   
75.        {join,Socket,ClientName,CPid} ->   
76.            ?DEBUG("group ClientName ~s\r\n",[ClientName]),   
77.            ?DEBUG("group Client set ~w\r\n",[Client]),   
78.            case lists:keysearch(ClientName,#client.name,Client) of   
79.                false->   
80.                    ?DEBUG("group new client\r\n",[]),   
81.                    ClientNew = #client{name=ClientName,pid=CPid,socket=Socket},   
82.                    ClientTmp = [ClientNew|Client],   
83.                    group(ClientTmp);   
84.                {value,SingleClient}->   
85.                    ?DEBUG("group client is set ~s\r\n",[SingleClient#client.name]),   
86.                    group(Client)   
87.            end;   
88.        {send,ClientName,Msg}->   
89.            ?DEBUG("group recv client send ~s\r\n",[Msg]),   
90.            lists:foreach(fun(T)->send(ClientName,T,Msg) end,Client),   
91.            group(Client)   
92.    end,   
93.    ok.   


 

以下是高手的招数

1.你的send不是很高效,gen_tcp:send是会阻塞的,如果客户很慢,缓冲区已满就会阻塞,把TCP_OPTIONS加上{delay_send, true}测试一下有没有提高。

 

2.既然瓶颈在CPU上,还是使用fprof分析一下吧,测试可以减少到100-1000次

最容易出现的问题是receive匹配顺序,或者是没有匹配到,建议加一个任意匹配检查一下是否有没有匹配的消息

 

3.建议把receive里面加上_Any匹配一下,打印输出或者是exit都可以,没有匹配的消息对性能影响特别大,特别是你这里大量消息的情况。

 

4.感谢qiezi的帮忙!
代码的group下去掉一个无用ok,在server和client增加了tcp属性的设置{nodelay, false}, {delay_send, true},100W的数据在本地单机跑大概用40秒,迅驰1.7 1.5G内存的笔记本上。比以前快多了,谢谢qiezi一直在帮助,学到以前没了解的东西。

在我测试用的服务器上依然出现SERVER端CPU占用99%导致发消息慢的情况。感觉可能是服务器设置或erlang安装造成的问题,因为即使把代码放到同一机器走127.0.0.1的时候一样会出现cpu占满的情况的。

我在安装erlang的时候记得提示 没有java odbc libgd好像没别的库少了,各位还有别的办法吗?谢谢!

 

5.1. 你最初的代码没有设置client socket的options,不知后来有没有改过。
2. 安装erlang时有没有enable-kernel-poll? 运行server时有没有加 +K true选项? kernel poll对提高性能作用很大。

 

6.使用+K true了
我发现是我安装的时候没有disable smp,我的服务器是单核的。
执行shell的时候 -smp disable后 cpu运转还是99%但是运行速度已经升上来了,100w的数据 A服务器发SERVER SERVER转发B服务器 A服务器发送完用5秒,B服务器收完用11秒,消息内容长度1bytes,78bytes发8秒,收21秒。

可是CPU占用依然高,总是瞬间99%,这个问题各位有办法解决吗?
cpu占用到99%这应该算不正常吧?

7.CPU占用率高是肯定的。楼主能否说下目前的tcp选项?erlang邮件列表中建议你使用{active,once} 代替{active,true},您有试过吗?


你可能感兴趣的:(某种情况下造成服务器发送消息无比延迟的原因)