Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[レビュー] Serverの責務分割 #1

Open
atty303 opened this issue Feb 8, 2024 · 2 comments · May be fixed by #3
Open

[レビュー] Serverの責務分割 #1

atty303 opened this issue Feb 8, 2024 · 2 comments · May be fixed by #3

Comments

@atty303
Copy link

atty303 commented Feb 8, 2024

Server が select するのは責務にあってそうです。
ただacceptした後のsend/recvやHTTPメッセージのハンドリングまでやっているのは責務過剰です。
例えば Connection クラスを作って、これがHTTP接続の1つの recv/send を担うようにすれば、かなり見通しが良くなると思います。

@kotto5
Copy link
Owner

kotto5 commented Feb 8, 2024

おっしゃる通りですね。ありがとうございます!

socket 状態の監視を server 側で一括 (select() )で行なっている ( io多重化 )
この実装を保ちながら取り入れる方法を考えてみます.

Connection クラスと Server クラスは 以下の情報を交換し合う

  • Connection -> Server : 監視して欲しいfd と状態 ( recv or send )
  • Server -> Connection : 監視したfd の状態 ( ready or error )

@kotto5
Copy link
Owner

kotto5 commented Feb 8, 2024

review 内容 メモ

Serverクラスが肥大化している. connection を作成するServer クラスと、client との通信を担当するConnectionクラスに分割しましょう

A: 僕 R: reviewer

A: まず制約があります.

  1. 監視するsocket 全てを一度のselect で監視する (42 の課題要件)
    案としては開発時にありましたが、クライアントの通信の中で監視するfd が増えることがあります (cgi, file 読み取り). この場合に、Connectionクラス内部でServerクラスにアクセスせずに実装する方法が思いつかずやめました。
    ですが、Connectionクラスの返り値として、監視したいfd と監視したい状態を返すようにすれば、実現が可能な気がします.

R: 1 の制約には何の意味があるのでしょうか? Server に受け渡さなくても、Connectionクラスが自分の担当するfd を監視するのはどうでしょうか.

(マルチプロセス?)
A: 1の制約にはCPU使用率を下げる意味があると思います。これからの説明は「CPU 使用率が100%に(高く)なることには問題がある」という前提に基づいています。(後ほど指摘される)
これは一度でselect することで達成されることであり、その他に比べて全く意味の違うことだと考えています。
Connectionクラスにselect させるとしましょう。現状では、select() 関数はブロッキングモードで実行されています。このままの実装では、server クラスの select() がブロック解除されるまで各connection はチェックされないので、新規の接続が発生しない限りconnection クラスは実行されません。
また、connection クラスもブロッキングモードでselect するならば、Server クラスをブロッキングすることになります。

では、Server クラスのselect() をノンブロッキングモードで実行するとします。この場合、server クラスが他のconnection をブロッキングすることはなくなりましたが、以前としてconnection クラスが server クラスをブロッキングします。

では、Connection クラスもノンブロッキングモードで実行するとします。この場合、Connection クラスの実行を含めたメインループ内でブロッキング処理が存在しないため、CPU 使用率は100% になります。

R: CPU使用率が高いとなぜ問題なのですか?

A: サーバーのコストが高くなるからです( 自分の勘違い )

R: それは間違っています。サーバーのコストは割り当てているCPU の数とその占有時間に依存します。
また、CPU使用率を下げるために sleep 0 を使うのが有効かと思いましたが、適切でないかもしれません。sleep 0 を用いると、CPU使用率を下げio wait の割合を高める作用があります。しかしこれは、ユーザーランドのCPU使用からカーネルランドのCPU使用に変わっただけなので、意味がないかもしれません ( idle 状態にはならないということ? )
寧ろ、運用を考えた場合、CPU使用率が低い方が問題があります。利用できるリソースを持て余していると言うことです。無駄な処理にCPU使用率がとられるのが悪いことです。

A: なるほど (最後は少し疑問。自
分の実装なら、trafic に比例してCPU使用率が上がる。対して全てをノンブロッキングモードにすると、CPU使用率は一定。この状態だと、CPUの割り当てを増やすかどうかの判断がしずらいのでは?
自分の実装では、CPU使用率が100%の状態で、インスタンスを増やせばcpu loadが減り、待たれるタスクが減少することが確定している。
ノンブロッキングな実装では、インスタンスを増やしてパフォーマンスが改善するかどうか確認する方法が無いように感じる。)

R: とはいえ、node js 等、シングルプロセスでio多重化しているプログラムがどのようにそれを管理しているのかは気になりますね.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants