🦷

ちょっとした検索サービスを作っていました

2022/12/30に公開

いくつかの Web サイトから情報をリアルタイムに受け取ってきて Elasticsearch にため込んで、ユーザーからのリクエストに応じて検索した結果を返す簡単なサイトを何年か動かしていました。

構成イメージ図

構成のポイント

Prober

Websocket でメッセージを受け取って SQS に受け渡すプログラムです。ここだけは Python で作っていて 1 サイトあたり 30MB ぐらいのメモリ消費量で動くようなプロセスを Docker Compose 環境 → 最後は Kubernetes 環境上で動作させていました。
なお、最初の数年間ぐらいは Prober が直接 Elasticsearch の REST API を直叩きしてメッセージを格納していましたが、さすがにメンテナンスや OS 再起動のときに削除メッセージを取りこぼすと無いものを検索結果として返す動きになってしまっていました。そのため、直近では SQS を挟んで取りこぼしがなくなるように、複数の Prober がメッセージを受け取るような構成にしてました。

ref.
Websocket を受信し続けるプログラムを書いていた
Python プログラムを常駐させて動かし続けるための Dockerfile を書いていた
環境変数を渡して Docker コンテナを実行する
認証付き Websocket にアクセスする node.js コードのサンプル

Eator

SQS に集められたメッセージを解析して更新や削除と幾ばくかのフィルタリングをした上で Elasticsearch に格納し直すためのプログラムでした。これも Prober と同様に node.js で作っていて Docker Compose 環境の中で動かしてました。
SQS のメッセージ数に応じて Scaling するところは、Cloudwatch Metrics を使うとカッコいいのでしょうが、定期的に Systemd でサービスとしてプロセスを多めに立ち上げてやり SQS から 0 個ないし 1 個ぐらいしかメッセージを取得できないことが続くと自滅するような感じのロジックでそれなりに動いていたので最後までそのままでした。

ref.
node.js から Elasticsearch を触る
node.js で Amazon SQS のメッセージキューを受信する

Express (Web)

検索サイトでユーザーが入れてきた検索ワードを Elasticsearch に投げる前に一度クエリをパースして綺麗にしてから投げ込む node.js を Express で組んでいました。
地味に Web ページ自体は jQuery で組んでて SPA みたいな動きにさせてました。Angular で作り直そうかしらと思ってたけども終了したのでおしまいに。

ref.
Elasticsearch をバックエンドにしてラップした検索 API を Express で簡単に作った

ALB

最初に作ったときには ALB の IP アドレスがたまたま某隣国の国際的な電機メーカーが使っていたものを再利用されていたみたいで、大量に端末の操作ログのようなものをボンボンと投げつけられていたりしました。始めはやたらと Web に 404 エラーが出てくるな……ぐらいの気持ちだったのですが、アクセスログや実際の POST データを試しに取得したら青ざめるレベルの情報が来てました。(もう時効だと思うので書きますが、さすが怖いですね。そのメーカーのスマホは一生買わないと思います) さすがにそういうのは見たくなったので AWS サポートに連絡したあとに ALB を再作成しています。

また、過去には大量のクエリを連続で機械的に投げ込む輩が出たりしてたので、ALB の Security Group で IP アドレス制限を入れたりしてました。

Discussion