私たちは皆ICQの使用に慣れており、多くの人がプロジェクトでこの機能を実装しています。 eJabberなどの既製のソリューションがあります。
自分でこれを行う方法に興味がある場合は、インスタントメッセージングサービスのサーバー部分が考慮されるカースト向けのウェルカムです。 クライアントでは、あなたが自分でそれを理解できることを願っています...
「Short Message Service-これは基本的にHTTP上で実行されるキューサーバーであり、JSフレームワークと簡単に統合できるはずです。 すべての結果はJSONで返されます。 サーバーとの交換は、AJAXを介してブラウザーから実行されます。
POSTメソッドを使用して、キー(URL(またはその一部))によってデータを書き込みます。 GETメソッドを使用して、書き込まれた内容をキューから(URLであるキーによって)抽出します。 したがって、次のようになります。uriがキーで、queueがデータである1つのハッシュテーブル。 キューはメッセージ文字列を表します。 必要に応じて、時間を追加できます。 開発のための多くのアイデアがありますが。
トピックにとても近い:
- #include <sys / types.h>
- #include <sys / time.h>
- #include <sys / queue.h>
- #include <stdlib.h>
- #include <err.h>
- #include <event.h>
- #include <evhttp.h>
- #include <map>
- #include <string>
- #include <queue>
- 名前空間 std を使用し ます 。
- std :: map < string、queue < string >> ht ;
- void generic_handler ( struct evhttp_request * req、 void * arg )
- {
- struct evbuffer * buf ;
- buf = evbuffer_new ( ) ;
- if ( buf == NULL )
- err ( 1 、 "応答バッファの作成に失敗しました" ) ;
- string key = evhttp_request_uri ( req ) ;
- ストリングアウト;
- if ( req- > type == EVHTTP_REQ_POST ) {
- const char * str_len = evhttp_find_header ( req- > input_headers、 "Content-Length" ) ;
- int len = atoi ( str_len ) ;
- アウト。 assign ( ( const char * ) EVBUFFER_DATA ( req- > input_buffer ) 、len ) ;
- if ( ht。find ( key ) == ht。end ( ) ) {
- キュー<文字列> q ;
- q。 プッシュ (アウト) ;
- ht。 insert ( pair < string、queue < string >> ( key、q ) ) ;
- } その他
- ht [キー] 。 プッシュ (アウト) ;
- evbuffer_add_printf ( buf、 "{ \" result \ " : \" Ok \ " } \ r \ n " ) ;
- } else {
- if ( ht。find ( key ) == ht。end ( ) ) {
- evbuffer_add_printf ( buf、 "{ \" result \ " :null} \ r \ n " ) ;
- } else {
- queue <文字列> q = ht [キー] ;
- if ( q。 サイズ ( ) ) {
- out = q。 フロント ( ) ;
- q。 ポップ ( ) ;
- ht [キー] = q ;
- evbuffer_add_printf ( buf、 "{ \" result \ " : \" %s \ " }" 、 out。c_str ( ) ) ;
- } else {
- evbuffer_add_printf ( buf、 "{ \" result \ " :null}" )
- }
- }
- }
- evhttp_send_reply ( req、HTTP_OK、 "OK" 、buf ) ;
- }
- int main ( int argc、 char ** argv )
- {
- struct evhttp * httpd ;
- event_init ( ) ;
- httpd = evhttp_start ( "0.0.0.0" 、 8080 ) ;
- evhttp_set_gencb ( httpd、generic_handler、 NULL ) ;
- event_dispatch ( ) ;
- evhttp_free ( httpd ) ;
- 0を 返し ます 。
- }
コードに関する説明:
行58〜63は、WEBサーバーを初期化します。 基礎として、libeventに基づくWEBサーバーを使用します。 それは素晴らしい性能を持っています。 2.3GHzラップトップでは、2k qpsのパフォーマンスが得られます。 すべてのURLが処理されます。
pg。20-22-バッファの初期化
23ページでは、REQUEST_IRIを取得してキーに使用しています。 最適化のための多くの提案があります。
26ページでPOSTを確認します。 間違いなく、HEADを確認できます(evhttpがサポートしていない他のメソッド)。 人生が複雑になるまで。
p。28-30は、データが保存される変数を形成します。 ガベージはバッファに蓄積されるため、Content-Lengthヘッダーに示されているバイト数を書き込みます
30-35ページそのようなキーが存在しない場合、新しいキューを開始し、データ要素をキューに挿入します
それ以外の場合は、データ項目をキューに挿入するだけです
ページ38-GETメソッドを満たす
39ページでキーが存在するかどうかを確認します
40ページ-いいえ-空の結果に関するメッセージを表示する
42ページ-キーに関するデータを取得
43ページ-キューが空かどうかを確認
p。44-47-いいえ、キューからメッセージを選択して表示します。キューは1つのメッセージで削減されます
逃げる必要性に少し火をつけることができます。 はい、間違いなく追加します。
49ページ、はい、キューは空です。これについてお知らせします。
53ページでリクエストを確定し、レスポンスコード200 OKを送信します
モデルはシングルスレッドであるため、レコードをロックする必要はありません。 この問題はまだ解決されますが。
Ab結果
Concurrency Level: 3
Time taken for tests: 0.415 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 83000 bytes
HTML transferred: 19000 bytes
Requests per second: 2409.31 [#/sec] (mean)
Time per request: 1.245 [ms] (mean)
Time per request: 0.415 [ms] (mean, across all concurrent requests)
Transfer rate: 195.29 [Kbytes/sec] received
10,000メッセージで消費されるメモリ量は600K強
実際、nginxをインストールし、セキュリティを担当する予定です(ngx_http_accesskey_module)
設定の一部:
location /test {
proxy_pass 127.0.0.1:8080;
## ngx_http_accesskey_module
}
しかし、nginxを使用すると、パフォーマンスは800 rpsに達します。
多くのアイデアがあります-どのように、どこに進むべきか。 たとえば、アクティビティステータスの表示、スパム対策。
他のアイデアは大歓迎です。 私は仕事をせずに座っていますが、それを試すことができるプロジェクトはありません。 私の推定によると、同時に、1〜1.5分(130〜200 rps)の頻度でリクエストを行うと、約1万人のクライアントが落ち着いてプルします。