DIYインスタントメッセージングサービス

私たちは皆ICQの使用に慣れており、多くの人がプロジェクトでこの機能を実装しています。 eJabberなどの既製のソリューションがあります。



自分でこれを行う方法に興味がある場合は、インスタントメッセージングサービスのサーバー部分が考慮されるカースト向けのウェルカムです。 クライアントでは、あなたが自分でそれを理解できることを願っています...



「Short Message Service-これは基本的にHTTP上で実行されるキューサーバーであり、JSフレームワークと簡単に統合できるはずです。 すべての結果はJSONで返されます。 サーバーとの交換は、AJAXを介してブラウザーから実行されます。



POSTメソッドを使用して、キー(URL(またはその一部))によってデータを書き込みます。 GETメソッドを使用して、書き込まれた内容をキューから(URLであるキーによって)抽出します。 したがって、次のようになります。uriがキーで、queueがデータである1つのハッシュテーブル。 キューはメッセージ文字列を表します。 必要に応じて、時間を追加できます。 開発のための多くのアイデアがありますが。



トピックにとても近い:

  1. #include <sys / types.h>
  2. #include <sys / time.h>
  3. #include <sys / queue.h>
  4. #include <stdlib.h>
  5. #include <err.h>
  6. #include <event.h>
  7. #include <evhttp.h>
  8. #include <map>
  9. #include <string>
  10. #include <queue>
  11. 名前空間 std を使用し ます
  12. std :: map < string、queue < string >> ht ;
  13. void generic_handler struct evhttp_request * req、 void * arg
  14. {
  15. struct evbuffer * buf ;
  16. buf = evbuffer_new ;
  17. if buf == NULL
  18. err 1"応答バッファの作成に失敗しました" ;
  19. string key = evhttp_request_uri req ;
  20. ストリングアウト;
  21. if req- > type == EVHTTP_REQ_POST {
  22. const char * str_len = evhttp_find_header req- > input_headers、 "Content-Length" ;
  23. int len = atoi str_len ;
  24. アウト。 assign const char * EVBUFFER_DATA req- > input_buffer 、len ;
  25. if ht。find key == ht。end {
  26. キュー<文字列> q ;
  27. q。 プッシュ アウト ;
  28. ht。 insert pair < string、queue < string >> key、q ;
  29. } その他
  30. ht [キー]プッシュ アウト ;
  31. evbuffer_add_printf buf、 "{ \" result \ "\" Ok \ " } \ r \ n " ;
  32. } else {
  33. if ht。find key == ht。end {
  34. evbuffer_add_printf buf、 "{ \" result \ " :null} \ r \ n " ;
  35. } else {
  36. queue <文字列> q = ht [キー] ;
  37. if q。 サイズ {
  38. out = q。 フロント ;
  39. q。 ポップ ;
  40. ht [キー] = q ;
  41. evbuffer_add_printf buf、 "{ \" result \ "\" %s \ " }"out。c_str ;
  42. } else {
  43. evbuffer_add_printf buf、 "{ \" result \ " :null}"
  44. }
  45. }
  46. }
  47. evhttp_send_reply req、HTTP_OK、 "OK" 、buf ;
  48. }
  49. int main int argc、 char ** argv
  50. {
  51. struct evhttp * httpd ;
  52. event_init ;
  53. httpd = evhttp_start "0.0.0.0"8080 ;
  54. evhttp_set_gencb httpd、generic_handler、 NULL ;
  55. event_dispatch ;
  56. evhttp_free httpd ;
  57. 0を 返し ます
  58. }


コードに関する説明:

行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万人のクライアントが落ち着いてプルします。



All Articles