サーバー[投稿]建設C1000K(1) - 基本

(1)のサーバ・ビルドC1000K - 基本

http:// www.ideawu.net/blog/archives/740.html

 

再生回数:107007 |  32件のコメント

有名な  C10K問題提起、それは2013年から2001年で、現在は12年後、C10K問題、任意の普通のプログラマ、C10Kを書きやすく、手の言語とライブラリを使用することができませんサーバー。それはソフトウェアの進歩の恩恵を受けたが、また、ハードウェアのパフォーマンスを向上させることの恩恵を受けました。

さて、考慮すべき時である  C1000Kこれは、同様のTwitterは、weibo、Facebookのこれらのサイトは、それらが同時ユーザーの数千万人を持っている。ある、すべての百万接続の問題を、だけでなく、メッセージがほぼリアルタイムのユーザーにプッシュすることにしたいですあなたは非常に多くのユーザーをサポートするために何百台ものサーバを使用することができますが、TCPネットワーク接続上のユーザのサーバと何百万人を維持する必要がありますが、各サーバは百万接続(C1000K)をサポートすることができれば、あなただけの10必要サーバー。

多くの技術は、請求が解決することがあります  C1000Kの  ようにErlangの、JavaのNIO、などなどの問題を、私たちは最初に見つける必要があり、C1000Kは問題は主にこれらの点で解決を制限するものな要因:

  1. オペレーティングシステムは、百万接続をサポートすることができますか?
  2. どのくらいのメモリオペレーティングシステム百万接続の必要性を維持するには?
  3. アプリケーションは、接続されているどのくらいのメモリ百万を維持する必要がありますか?
  4. 一万の接続されたネットワークのスループットが制限を超えて?

これらの下には、分析すべきいくつかの質問です。

1.オペレーティング・システムは、百万接続をサポートすることができますか?

ほとんど  のLinux  オペレーティングシステムは、グローバルシステム、およびプロセスレベルの制限に、開いているファイル(最大オープンファイル)制限の最大数が含まれているため、オペレーティングシステム、デフォルトでは、それは!C1000Kをサポートしていません。

グローバル制限

Linuxで実行:

猫を/ proc / sys / fs /ファイル-NR

次の出力のようなプリントライン:

5100 0 101747

3番目の数字が  101747 オープン(最大オープンファイル)ファイルのグローバル最大数の現在のシステムであり、我々は唯一の10万なので、このサーバーでこの値C1000Kをサポートできないことがわかります。多くの小規模なシステムでは、この値を変更するために、 、rootとして/etc/sysctl.confファイルを変更します。

fs.file-MAX = 1020000 
net.ipv4.ip_conntrack_max = 1020000 
net.ipv4.netfilter.ip_conntrack_max = 1020000

サービスを有効にするには、システムを再起動する必要があります。

#Linuxの
$ sudoをのsysctl -p /etc/sysctl.confを
#BSD 
$ sudoを/etc/rc.d/sysctlリロード

プロセス制限

実行:

ulimitの-n

出力:

1024

各プロセスの説明は、1024個のファイルまで、現在唯一のオープンLinuxシステムである。C1000Kをサポートするために、あなたはまた、制限値を変更する必要があります。

一時的な修正

ulimitの-n 1020000

root以外で操作している場合は、あなたがエラーを取得します、1024年に修正されないことがあります。

-bash:ulimitの:開いているファイルは:制限を変更することはできません:操作は許可されていません

恒久的な変更

/etc/security/limits.confを編集ファイル、次の行を追加します。

#/etc/security/limits.confをする
102万NOFILEハードワーク
作業102万ソフトNOFILE

最初の列は、  work あなたが埋めることができ、作業のユーザーを表し  *、または  root[保存して終了し、再ログインサーバー。

注:定数(知るには、/usr/include/linux/fs.hでNR_OPEN)があるLinuxカーネルのソースは、RHEL 5は1048576(2 ^ 20)であるとして、開いているファイルの最大数を制限し、そう、支援するために  C1000Kを、あなたまた、カーネルを再コンパイルする必要があるかもしれません。

2.どのくらいのメモリオペレーティングシステムは百万の接続を維持する必要がありますか?

オペレーティングシステムのパラメータの限界を解決するため、我々はメモリの占有を見なければならない。まず、オペレーティングシステム自体は、Linuxオペレーティングシステム用のこれらの接続のメモリフットプリントを維持するために、ソケット(FD)は整数であるので、私は、オペレーティングシステムを推測このような理由から。しかし、そこにメモリソケットの送信があると、バッファを解析しない占有受ける。百万の接続がメモリ4M / 8Mによって占められ、その後、いくつかの管理情報が含まれるべきで、それは100Mであるべきである管理、I書き込みネットワークを確認するために最も独創Cプログラム:

サーバー

書式#include <stdio.hに> 
する#include <stdlib.h>に含ま
書式#include <string.hの> 
書式#include <unistd.h> 
の#include <ERRNO.H> 
書式#include <ARPA / inet.h> 
の#include <netinetのTCP / .H> 
の#include <SYS / select.h> 

の#define MAX_PORTS 10 

INTメイン(INTのargc、char型** ARGV){ 
    構造体のsockaddr_in ADDR。
    * IP = "0.0.0.0"のconst char型。
    int型OPT = 1; 
    int型BUFSIZE; 
    socklen_t optlen; 
    int型の接続= 0; 
    int型base_port = 7000; 
    IF(ARGC> 2){ 
        base_port = ATOI(ARGV [1])。
    } 

    int型server_socks [MAX_PORTS]。

    I <MAX_PORTS;(int型のために、私は= 0;
        addr.sin_family = AF_INET; 
        addr.sin_port = htons((短い)ポート)。
        inet_pton(AF_INET、IP、およびaddr.sin_addr)。

        int型serv_sock; 
        (==)(serv_sock =ソケット(AF_INET、SOCK_STREAM、0)-1)であれば{ 
            後藤sock_err。
        } 
        (のsetsockopt(serv_sock、SOL_SOCKET、SO_REUSEADDR、&OPT、はsizeof(OPT))== -1){もし
            後藤sock_err。
        } 
        (バインド(serv_sock、(いるsockaddr *)&ADDR、はsizeof(ADDR))== -1){もし
            後藤sock_err。
        } 
        (リッスン(serv_sock、1024)== -1)の場合{ 
            後藤sock_err。
        } 

        server_socks [I] = serv_sock。
        printf( "サーバーがポートをリッスンた:%d \ n"は、ポート)。
    } 

    // optlen =はsizeof(BUFSIZE)。
    //のgetsockopt(serv_sock、SOL_SOCKET、SO_RCVBUF、&bufsizeは、&​​optlen); 
    // printfの( "サイズBUFデフォルトセンド/ RECVた:%d \ n"は、bufsizeは); 

    一方、(1){ 
        FD_SET readset。
        FD_ZERO(&readset)。
        int型maxfd = 0; 
        以下のために(INT iが= 0; I <MAX_PORTS; I ++){ 
            FD_SET(server_socks [I]、&readset)。
            IF(server_socks [I]> maxfd){ 
                maxfd = server_socks [I]。
            } 
        } 
        int型RET =選択(maxfd + 1、&readset、NULL、NULL、NULL); 
            }他{ 
                のprintf( "!選択エラー%sの\ n"は、はstrerror(errnoに)); 
                出口(0); 
            } 
        } 

        (RET> 0){場合
            (INT iが0 = I ++; I <MAX_PORTS)のための{ 
                {(FD_ISSET(server_socks [I]、&readset)!)もし
                    続けます。
                } 
                のsocklen_t addrlenは=はsizeof(ADDR)。
                ; INT靴下=(server_socks [i]は、(いるsockaddr *)&ADDR、&addrlenは)を受け入れます 
                IF(靴下== -1){ 
                    後藤sock_err。
                } 
                接続++。 
                のprintf( "接続:%dはやFD:%D \ n"は、接続、靴下)
    } 

    0を返します。
sock_err:
    のprintf( "エラー:%S \ n"は、はstrerror(errnoに))。
    0を返します。
}

サーバは、テストを容易にすることであるポート10、リッスンしていることに注意してください。サーバーは、10個のポートをリッスンように、1つのクライアントのみ試験機なので、テストして、30,000人以上を作成するために、同じIPポートにより接続しないでくださいサーバマシン間接続300,000作成することができます。

クライアント

書式#include <stdio.hに> 
する#include <stdlib.h>に含ま
書式#include <string.hの> 
書式#include <unistd.h> 
の#include <ERRNO.H> 
書式#include <ARPA / inet.h> 
の#include <netinetのTCP / .H> 

int型のmain(int型ARGC、チャー** ARGV){ 
    IF(ARGC <= 2){ 
        のprintf( "使用法:%sのIPポート\ n"は、ARGV [0])。
        出口(0); 
    } 

    ADDRのsockaddr_in構造体。
    CONSTのchar * IP = ARGV [1]。
    INT base_port = ATOI(ARGV [2])。
    int型OPT = 1; 
    int型BUFSIZE; 
    socklen_t optlen; 
    int型の接続= 0; 

    BZERO(&ADDR、はsizeof(ADDR))。
    addr.sin_family = AF_INET; 
    inet_pton(AF_INET、IP、およびADDR。

    チャーtmp_data [10]。
    int型のインデックス= 0; 
    一方、(1){ 
        IF(++インデックス> = 10){ 
            インデックス= 0。
        } 
        INTポート= base_port +指数; 
        printf( "%sの接続:%dの\ n"は、IP、ポート)。

        addr.sin_port = htons((短い)ポート)。

        int型の靴下。
        (==)(靴下=ソケット(AF_INET、SOCK_STREAM、0)-1)であれば{ 
            後藤sock_err。
        } 
        (CONNECT(靴下、(いるsockaddr *)&ADDR、はsizeof(ADDR))== -1){もし
            後藤sock_err。
        } 

        接続++。
        printf( "接続:%dはやFD:%D \ n"は、接続、靴下)

        IF(接続%10000 == 9999){
            printf( "Enterキーを押して続行します。");
            getchar(); 
        } 
        はusleep(×1000 1)。
        / * 
           BUFSIZE = 5000; 
           setsockopt(serv_sock、SOL_SOCKET、SO_SNDBUF、&bufsizeは、はsizeof(BUFSIZE))。
           setsockopt(serv_sock、SOL_SOCKET、SO_RCVBUF、&bufsizeは、はsizeof(BUFSIZE))。
         * / 
    } 

    戻り0。
sock_err:
    のprintf( "エラー:%S \ n"は、はstrerror(errnoに))。
    0を返します。
}

私はアイドル状態になっている10万の接続をテストし、データが送信されず、何も受信されない。このとき、プロセスは専用メモリの1MB未満占める。しかし、プログラムが終了する前と後にfreeコマンドを比較することで、使用するオペレーティングシステムを見つけます万語の接続は、オペレーティングシステム自体がメモリの2ギガバイト!接続ごとにその2キロバイトまでにかかります!千万の接続を維持するために200M(約)メモリ。

あなたは変更することができます

/ proc / sys / net / IPv4の/ tcp_wmem 
は、/ proc / sys / net / IPv4の/ tcp_rmem

TCPコネクションの送信および受信バッファサイズ(おかげ@制御するegmkangを)。

何百万人もどのくらいのメモリへの接続を維持するために3.アプリケーション?

上記のテストコードを見つけることができますを通じて、アプリケーションは、オペレーティングシステムが専用メモリを占有します、百万無料接続を維持するために、psコマンドで見た図、アプリケーション自体が少ないメモリを占めます。

4.百万接続されたネットワークのスループットが制限を超えて?

アクティブ百万接続20%、1キロバイトあたりのデータ伝送に接続されたそれぞれの仮定、必要なネットワーク帯域幅が0.2M X 1キロバイト/ SX 8 = 1.6Gbpsであり、サーバは、少なくとも10ギガビットNIC(10Gbpsの)を必要とします。

概要

Linuxシステムがサポートするカーネルパラメータとシステム構成を変更する必要がありC1000K。C1000Kアプリケーションでは、この要件は、少なくとも10ギガバイトのメモリである必要があり、アプリケーション自体がメモリを必要とする場合、サーバは、少なくとも2ギガバイトのメモリを必要とする必要があると同時に、カードは少なくともギガビットNICでなければなりません。

もちろん、これは理論だけで、実用的なアプリケーションは、ハンドルのビジネスデータへのより多くのメモリとCPUリソースを必要とします。

テストツール

接続テストオペレーティングシステムツールの最大数:  https://github.com/ideawu/c1000k

---------------------------

参考:

http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/
http://www.lognormal.com/blog/2012/09/27/linux- TCPIP-チューニング/

次へ:  ビルドC1000Kサーバ(2) -を達成します

関連記事:

    1. sockaddr_in構造体を削除することを忘れないでください
    2. (2)のサーバ・ビルドC1000K - 百万彗星サーバー接続を達成するために
    3. データ伝送を実現するための機構を待って停止します
    4. Libevent 2 HTTPクライアントの例
    5. 興味深いことに、メイン関数のパラメータ

おすすめ

転載: www.cnblogs.com/jinanxiaolaohu/p/12169697.html