zoukankan      html  css  js  c++  java
  • Linux下基于Erlang的高并发TCP连接压力实验

    1、实验环境:

    联想小型机:

    操作系统:RedHat Enterprise LinuxServer release6.4Santiago

                内核版本号:Linux server1 2.6.32-358.el6.x86_64#1 SMP

                CPU型号:IntelRXeonRCPU E7-4820 @2.00Ghz

                          4cpu,每颗cpu物理核数为8,总物理核数为32,逻辑核数为64

               内存:132G

    磁盘:289G

    2、基于erlang开发设计了TCPserver,

    ErlangTCP通信机制,首先在指定的端口创建socket,通过侦听会在指定的端口返回一个侦听的#Port<0.501>,然后server生成一个进程在accept等待client连接到来,client通过connect与server进行连接,一旦连接成功client在本地会返回一个#Port<0.502>,以后client通过该项端口进行数据的发送和接收;server端一旦accept到连接了,便将在server端返回一个#Port<0.503>,这样一个tcp连接便有server的#Port<0.503>和client的#Port<0.502>进行标识,由此得出:(1tcp连接过程序的建立,server端的port=clientport+1;(2)port的打开的数量上限决定着tcp连接的个数。

    erlangportIO句柄,因而终于决定tcp连接数的是server可以同一时候打开文件的个数。在该系统下默认打开是1024,通过ulimit –n 1000000能够改动上限值为1000000。该值不能超过硬限制的个数。

    假设要进一步提高。须要从软限制和硬限制双方面考虑,详细可參考:还有一方面/proc/sys/net/ipv4/ip_local_port_range的值决定了一个侦听端口所能接收的最大tcp连接数,改动该值能够通过vi /etc/sysctl.conf,改动后运行sysctcl -p使其生效。提高连接数的一个方法是通过开多个侦听端口来接收client的连接。怎样改动操作系统所能打开的最大文件数和ip_local_port_range成为影响tcp连接总数的两个关键点。

                    Erlang虚拟机默认的port上限为65536, erlang17通过erl +Q 1000000能够改动端口上限为1000000,利用erlang:system_info(port_limit)进行查询,系统能够打开的最大文件描写叙述符能够通过erlang:system_info(check_io)中的max_fds进行查看,查看系统当前port数量能够用erlang:length(erlang:ports())得到

    3、代码:

    tcp_client

    -module(tcp_client).

    -export([start/1,send_data/2,close/1,loop_start/2]).

    loop_start(Port,Num)->

        case start(Port)of

            system_limit -> io:format("");

            _-> loop_start(Port,Num+1)

        end.

    start(Port)->

        try

            case gen_tcp:connect("127.0.0.1",Port, [binary,{packet,raw},{active,true},{reuseaddr,true}])of

                {ok,Socket}->Socket;

                {error,Reason}-> {error,Reason}

            end

        catch

            throw:T->T;

            exit:R->R;

            error:E->E

        end.

    send_data(Socket,Data)when is_list(Data)orelse is_binary(Data)->

        gen_tcp:send(Socket,Data),

        receive

            {tcp,Socket,Bin}->

                io:format("recv~p~n",[Bin]);

            {tcp_closed,Socket}->

                io:format("receive server don't accept connection!~n")

        end.

    close(Socket)when is_port(Socket)->

        gen_tcp:close(Socket).

     

    generic_server

    -module(generic_server).

    -behaviour(gen_server).

    -define(TCP_OPTIONS,[binary,{packet,raw},{reuseaddr,true},{active,false}]).

    -export([start/4,init/1, handle_cast/2,accept/1,accept_loop/5]).

    -export([]).

    -record(server_state, {port,loop,ip=any,lsocket=null,conn=0,maxconn}).

    start(ServerName,Port,Max,{M,F})->

        gen_server:start_link({local,ServerName},?MODULE,[#server_state{port=Port,maxconn=Max,loop={M,F}}],[]).

    init([State=#server_state{port=Port}])->

        case gen_tcp:listen(Port,?

    TCP_OPTIONS)of

            {ok,LSocket}->

                {ok,accept(State#server_state{lsocket=LSocket})};

            {error,Reason}->

                {stop,{create_listen_socket,Reason}}

        end.

    accept(State=#server_state{lsocket=LSocket,loop=Loop,conn=Conn,maxconn=Max})->

        Pid = spawn(generic_server,accept_loop,[self(),LSocket,Loop,Conn,Max]),

        State.

    accept_loop(Server,LSocket,{M,F},Conn,Max)->

        erlang:group_leader(erlang:whereis(user),self()),

        {ok,Sock} = gen_tcp:accept(LSocket),

        if

           true ->

                gen_server:cast(Server,{accept_new,self()}),

                M:F(Sock)

        end.

    handle_cast({accept_new,FromPid},State)->

        Conn =State#server_state.conn,

        io:format("current connect is~p~n",[Conn+1]),

        LSocket =State#server_state.lsocket,

        Loop=State#server_state.loop,

        Max=State#server_state.maxconn,

        Pid=spawn(generic_server,accept_loop,[self(),LSocket,Loop,Conn+1,Max]),

        {noreply, State#server_state{conn=Conn+1}};

    handle_cast({connect_close,FromPid},State)->

        Conn=State#server_state.conn,

        io:format("current connect is~p~n",[Conn-1]),

    {noreply, State#server_state{conn=Conn-1}}.

     

    echo_server:

    -module(echo_server).

    -export([start/1,loop/1]).

    start(Port)->

        Max =4,

        generic_server:start(echo_server, Port, Max, {?

    MODULE,loop}).

    loop(Sock)->

        case gen_tcp:recv(Sock,0)of

           {ok,Data}->

               gen_tcp:send(Sock,Data),

               loop(Sock);

            {error,closed} ->

                io:format("client sock close~n"),

                gen_server:cast(echo_server,{connect_close,self()})

        end.

    4、通信流程

     

     

    5、结论

           设定ulimit  –n 100000。假定ip_local_port_range   1   65535,侦听一个port的连接数为65534,再打开一个侦听port为100000-65534=34466,   单端口受制于ip_local_port_range的范围。总共的连接数为打开的文件描写叙述符个数。

  • 相关阅读:
    2016 大连网赛
    LightOJ 1012 简单bfs,水
    Pyhton学习——Day30
    Client初见——python
    Server初见——python
    Pyhton学习——Day29
    Pyhton学习——Day28
    Pyhton学习——Day27
    Pyhton学习——Day26
    函数基础作业
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5100152.html
Copyright © 2011-2022 走看看