2015-09-22 4 views
7

मुझे कोई समस्या है: मैं एक एरलांग सर्वर बनाना चाहता हूं जो 1 एम एक साथ खुले टीसीपी कनेक्शन को पकड़ सके। मैंने फाइल डिस्क्रिप्टर को बढ़ाने के लिए अपने ओएस (ओरेकल लिनक्स 7) को ट्यून किया। सर्वर पर मैं gen_tcp कार्य करें: सुननेएरलांग एक साथ 1 एम क्लाइंट कनेक्ट करें

// point_1
सॉकेट = gen_tcp: स्वीकार
अंडे (हैंडल (सॉकेट)) // एक और धागा
वापस point_1

तो मैं कनेक्ट करने के लिए अनुक्रमिक रूप से इसकी कोई समस्या नहीं, 100 सेकंड में मैंने 100K क्लाइंट जुड़े; लेकिन मेरे पास और अधिक गठबंधन नहीं था।

यदि मैं उन्हें conncurent तरीके से कनेक्ट करना चाहता हूं, तो केवल 80 कनेक्शन 100 से बने होते हैं, उदाहरण के लिए।

यह कैसे मैं सब कुछ चलाने है:

erlc *.erl 
erl +Q 134217727 +P 1000000 -env ERL_MAX_PORTS 40960000 -env ERTS_MAX_PORTS 40960000 

// एक सर्वर है कि बंदरगाह 9999

ex:start(1, 9999) 

// 100 ग्राहकों पोर्ट पर कनेक्ट करने का प्रयास पर सुनने होगा शुरू 9999

ex:connect_clients(100, 9999) 

मुझे आपको कुछ कोड दिखाएं:

यहाँ
start(Num,LPort) -> 
    case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of 
    {ok, ListenSock} -> 
     start_servers(Num,ListenSock), 
     {ok, Port} = inet:port(ListenSock), 
     Port; 
    {error,Reason} -> 
     {error,Reason} 
    end. 

start_servers(0,_) -> 
    ok; 
start_servers(Num,LS) -> 
    spawn(?MODULE,server,[LS,0]), 
    start_servers(Num-1,LS). 

server(LS, Nr) -> 
    io:format("before accept ~w~n",[Nr]), 
    case gen_tcp:accept(LS) of 
    {ok,S} -> 
     io:format("after accept ~w~n",[Nr]), 
     spawn(ex,loop,[S]), 
     server(LS, Nr+1); 
    Other -> 
     io:format("accept returned ~w - goodbye!~n",[Other]), 
     ok 
    end. 

loop(S) -> 
    inet:setopts(S,[{active,once}]), 
    receive 
    {tcp,S, _Data} -> 
     Answer = 1, 
     gen_tcp:send(S,Answer), 
     loop(S); 
    {tcp_closed,S} -> 
     io:format("Socket ~w closed [~w]~n",[S,self()]), 
     ok 
    end. 

client(PortNo) -> 
    {ok,Sock} = gen_tcp:connect("localhost", PortNo, 
    []). 

connect_clients(Number, Port) -> 
    spawn(ex, client, [Port]), 
    case Number of 
    0 -> ok; 
    _ -> connect_clients(Number-1, Port) 
    end. 

उत्तर

8

मैं देख रहा हूँ कम से कम दो मुद्दों:

  • आप अपने बैकलॉग सुनने को बढ़ाने के लिए की जरूरत है; यह 5 तक डिफ़ॉल्ट है। आप अपने श्रवण विकल्पों में {backlog, N} सेट करके इसे बढ़ा सकते हैं, उदाहरण के लिए, {backlog, 1024}

  • आपका server/2 समारोह दोषपूर्ण है क्योंकि यह एक कनेक्शन को स्वीकार करता है, तो loop/1 को चलाने के लिए एक नई प्रक्रिया spawns लेकिन यह है कि नई प्रक्रिया को स्वीकार कर लिया सॉकेट के लिए controlling process नहीं है। loop/1 फ़ंक्शन इनकमिंग संदेशों को प्राप्त करने के प्रयास में सॉकेट पर {active,once} मोड सेट करने का प्रयास करता है, लेकिन चूंकि यह नियंत्रण प्रक्रिया में नहीं चल रहा है, यह काम नहीं करेगा। इस दृष्टिकोण के साथ

    server(LS, Nr) -> 
        io:format("before accept ~w~n",[Nr]), 
        case gen_tcp:accept(LS) of 
        {ok,S} -> 
         io:format("after accept ~w~n",[Nr]), 
         spawn(ex,server,[LS,Nr+1]), 
         loop(S); 
        Other -> 
         io:format("accept returned ~w - goodbye!~n",[Other]), 
         ok 
        end. 
    

    :

इसके बजाय पाश उत्पन्न करने वाले (आप ok = inet:setopts(S,[{active,once}]), वहाँ के बजाय कह कर inet_setopts/2 के रिटर्न मान सत्यापित करना चाहिए।), आप के बजाय एक नई स्वीकर्ता अंडे चाहिए, इस तरह , सॉकेट को स्वीकार करने वाली प्रक्रिया loop/1 चलाती है और इसलिए सॉकेट की नियंत्रण प्रक्रिया को बदलने की कोई आवश्यकता नहीं है।

+0

दरअसल, आप उन दो मुद्दों के बारे में सही थे। मैंने उनको तय किया। अब जब मैं connect_clients (1000, 99 99) कहता हूं तो यह लगभग 100 प्रति सेकेंड जोड़ता है और यह 800 तक जाता है; तो यह बंद हो जाता है। सर्वर क्रैश नहीं होता है इसलिए मैं इसे फिर से कॉल कर सकता हूं, एक क्लाइंट को जोड़ सकता हूं या मैं कितना नंबर चाहता हूं। लेकिन मैं लगभग 800 प्रति कॉल से अधिक कनेक्ट नहीं कर सकता। काश मैं connect_clients (1000000, 99 99) को कॉल कर सकता हूं, लेकिन फिर मेरा वीएम फ्रीज हो जाता है। कोई विचार? धन्यवाद जिसके लिए आपने पहले ही मेरी मदद की है। –

+1

साथ ही, याद रखें, स्वीकार करते समय बेहतर थ्रुपुट के लिए आपको एक ही सुनो सॉकेट पर 'gen_tcp: स्वीकार/1'' कॉल करने वाली कई स्वीकार्य प्रक्रियाएं हो सकती हैं। –

+0

@ ŞtefanStan कहना मुश्किल है कि आप क्या नई समस्याएं मार रहे हैं। क्या आप 'sasl' सक्षम के साथ चल रहे हैं? आप यह सुनिश्चित करने के लिए इसे शुरू कर सकते हैं कि आप किसी भी समस्या का सामना नहीं कर रहे हैं जो अनजान हो सकता है। क्या आप सुनिश्चित हैं कि आपके ओएस को आपको आवश्यक कनेक्शन की संख्या की अनुमति देने के लिए ठीक से स्थापित किया गया है? आपके खोल में 'ulimit -n' क्या इंगित करता है? इसके अलावा, आप Erlang/OTP का किस संस्करण का उपयोग कर रहे हैं? –

संबंधित मुद्दे