今更感あるけど、LINE Trial Bot、Facebook Messager Platform、Microsoft Bot Frameworkと色々ある。 個人で勝手に自分用のBotを動かしていて、現状の記録。
構成
今はこうなってる、シンプル*1
+------------+ +--------------+ | Bot Server | ==> | http gateway | +------------+ +--------------+ ==> +-----------+ | rabbit mq | +---------+ +-------------+ <== +-----------+ | Bot API | <== | bot workers | +---------+ +-------------+
Bot ServerとBot APIってのは、メッセージをwebhookで投げてくれるやつと、メッセージを送信出来るAPIであればなんでもいい。
http gateway
nginxをreverse proxyに、akka-httpでリクエストを待ち受けるアプリケーションを立ててる。こいつの責務はリクエストを受けて、そもそものメッセージかどうかのvalidationなどして、message queueに投げるとこまで。mqに投げる以外のIOは無いし、そもそもmqに投げる処理もactorに渡してるから一瞬でレスポンス返してる。200でも202でもそのへん返したらいい。
もしBot Serverがwebhookじゃなくてstreamingでメッセージをくれるなら、適当にstreaming取ってくるprocessをこいつの代わりにおいたらいい。
rabbit mq
ただのmessage queue。shardっぽくユーザidやroom idに応じてqueueを適当に分けるなどしてる*2。
http gatewayとrabbitmqさえ生きていたら、データは落ちない
bot workers
ここは、大きく分けて以下の3種類のworkerがいる
- message consumer actor
- worker supervisor actor
- worker actor (⇔ user actor)
message consumer actor
message queueの数に合わせて横に増やせる、便利。特定ユーザのメッセージは同じqueueに連なってるわけだし、対応するactorを用意するだけ。処理が遅くなってもそもそものqueueの分け方を増やしたら良いだけ*3。基本的に処理が正常に済んでからackするようにして、messageをちゃんと処理するようにする。
worker supervisor actor
次に、messageはこいつに投げられる。何をするかってこいつは特定のユーザ(user/worker actor)にメッセージを投げることが出来るやつ。誰宛のメッセージかを確認して、そいつにroutingする。
worker actor (⇔ user actor)
残りのこいつは、worker actorと言いつつ実際はuser actorで、ユーザが今どういう状態なのかってのを表すFSMとして機能してる。対話式のbotとか出来て面白い。後はこういうメッセージ飛ばしといてって投げるだけ。
状態持ってるやつのdeployってのがよく分からなくて、適当に死ぬ前に必要なのだけ保存して起動時に復旧してるけど、akka-persistenceのsnapshotだけとか使えたりもするのかな、まだやってない。journal取る程じゃない。
他
- server provisioning全部ansibleに変えた
- server process、全部systemdの管理下にした
- mqのmessage数とかmackerelで見れて楽しい
〆
- 初akka
- 無駄機能
- この記事自体ネタです