Open16

Laravelで行ってるキューコンテナの代替探し

takotakotakotako

学習動機:

主にLaravelサーバをECS上に建てている受託会社に勤務しているが、現状時間がかかる処理はWebAPIサーバーとは別に立てられているLaravelのキューコンテナを使っている。

しかしキューコンテナには下記のような理由があるので、Laravelからリプレイスしたいという要望をもらった。

  1. わざわざwebapiサーバとは別にキューコンテナ用のサーバを立ち上げる必要がある。
    a. 特にクライアントが技術感度が高く非同期処理をサポートしている言語について知識があったり、既にそのような処理ができるサーバーが立っている場合、Laravel都合でキュー用のサーバーを立てる必要がある旨を伝えると失注につながりやすい。
    2.キューコンテナを使う都合上、AWS上でSQLやElastiCache(主にRedisのようなKVS)などのサービスや、ECSのサービスのマシンパワーを上げる必要が出てくるのでインフラコストが上がる。

このスクラップでは、Laravelからgoにリプレイスするにあたって必要なデータをまとめたい。

takotakotakotako

前提として、

  1. 重い処理を扱うような非機能要件を実装したことがない。
  2. Laravelの経験がない。
  3. キューコンテナについての知識がない。
  4. awsのコストまでの概算ができるわけではない。
takotakotakotako

公式にはRedisやAmazonSQS以外にデータベースにテーブルを作ってそこでキューを管理する方法も書いてあるが、これは一般的なのだろうか??

  1. キュー管理もRDBMSの責務にすると、ディスクIOが多くなってレイテンシーが上がる可能性が高い。
    現状は受託として基幹系システムを作ることが多く、大量データを裁くことも多いのでRDBMSとキュー管理の責務は分けたい
  2. 別言語でマイクロサービス化を検討する場合、DBのポータビリティが低くなりアプリケーションがインフラに強く依存してしまう可能性が高い。
    (マイクロサービスに対してDBを分ける場合は問題ない。)

https://readouble.com/laravel/9.x/ja/queues.html

takotakotakotako

Goの場合

Goの場合、goroutineで軽量スレッドを立てることで非同期処理できる。

  1. goはプロセスのランタイム上にスレッドプールを持っている。
  2. システムコールをしなくてもランタイム上のメモリを使うので、スレッド処理のオーバーヘッドが小さい。

ことなどはわかっていたが、いざ非同期処理が標準でサポートされていない言語の挙動を知ると改めてgoroutineがもてはやされている意味がわかった気がする。

takotakotakotako

Goの場合、goroutineで軽量スレッドを立てることで非同期処理できる。

否、非同期処理ではなく並行処理
非同期処理はnodeのようなシングルスレッドのランタイムでも使われる。
なので、マルチスレッドのランタイムでスレッドを非同期処理というのは間違っている(気がする

takotakotakotako

非同期処理はノンブロッキングで関数呼び出しを受けるが、その実行順序(呼び出された順番)はqueueで管理しているので、マルチスレッドで対応しているという言い方は間違っている。

takotakotakotako

並行処理と並列処理

おそらく、コア数の話だった気がする。
並列処理がシングルコアでCPUがスケジューリングをして処理を進める。
並行処理はマルチコアでそれぞれのスレッドがCPUを占領できる(”CPUを占領できる”という言い回しはあっているのだろうか??

takotakotakotako

逆だ。

並列処理がマルチコアで、並行処理がシングルコアでスケジューリングか

takotakotakotako

スレッドに対してコアが割り当てられるんだな。
てっきりプロセスにコアが割り当てられるんだと思ってた。

実行中のプログラムは『プロセス』と呼ばれ、プロセスは 1 つ以上の『スレッド』を持ちます。

とあるので、あくまでプロセスは仮想メモリの割り当てくらいしかされないのかな・

takotakotakotako

ecsにGoのwebapiサーバがlistenしていると仮定すると、initのプロセスはコンテナが削除されるまで残り続けるから、goroutineが途中で強制シグナルを受けつけることもないからDBの整合性が取れなくなる心配もない。

アプリケーションのPreserntation層などに書くのもありだけど、関数をcli化しちゃってLambda経由で叩くのも良さそうかな??

takotakotakotako

今回はサーバーの処理が常駐するので必要ないが、仮に単発のプロセスを起動する場合はsync.WaitGroupの処理が必要になる

takotakotakotako

そもそもPHPはGoと同じように軽量なスレッドを立てることができないのだろうか??
そもそもスレッド立てができるのであればGoにリプレイスする必要ないな。。。。

わからないことは下記。

  • PHPはシングルスレッド?マルチスレッド?
    *PHPで並列処理をする方法は?