米国株式市場には、プレマーケット、マーケットオープン後、マーケットクローズの3つの取引時間があります。データ配信は、プッシュ通知を使用するか、数値増分のロジック(可能な限り帯域幅を節約)を採用します。初回送信では全量データを送りますが、2回目以降はすべてのフィールドを増分で推送します。
なぜ最適解を用いないのか?複数のプロジェクトグループに分散しており、一部はすでに数年ローンチされています。弊社は新規の連携のため、できる限り互換性を保つようにしています。
いくつかの問題点
概要だけでは、特に問題がないように見えるかもしれないが、社内システムアーキテクチャに組み込まれた問題や、それらを引き起こす一連の問題が発生する。直前に問題を解決したにもかかわらず、新たな問題が発生し、その問題は以前の問題によって引き起こされたものである。
取引時間帯の認識エラー
盤中ステージを protobuf
で定義されている 0 と認識していますが、増分配信のため、業務側ではこの 0 がデフォルト値なのか、それとも実際の取引値なのかを明確に判断できません。
分かりやすく言うと、0 を受信した際に、それが新しい行情設定の値なのか、protobuf のデフォルト値なのかを判断できないということです。
オプショナルについて
protobuf 3.15 以降、proto3 では (proto2 と同様に) オプショナルキーワードを使用してスカラーフィールドの存在情報を指定できるようになりました。
チーム内の通信プロトコルは protobuf
をベースにしていますが、歴史的な理由により選択されたバージョンが古く、optional
キーワードをサポートしていません。理解している方はご存知でしょう。底层から protobuf
を導入したため、プロジェクトの底层は静的ライブラリとして protobuf
を公開しており、その結果、全体のコンパイルチェーン全体をアップグレードする必要があり、このコストは非常に高くなっています。
GCC のバージョン問題
ようやく解決策を思いついたのだが、底层で異なるバージョンのリリースをするという方法を試みた。可能な限り protobuf
の新しいバージョンのコンパイル依存関係の伝播を制御しようとした。しかし、コンパイル時に gcc
のバージョンが低すぎて、protobuf
の新機能に対応していないことが判明した。
グループ内でよく使われるサーバーの種類:CentOS7、CentOS8。CentOS7 のデフォルトの gcc
バージョンは 4.8 であり、CentOS8 のデフォルトの gcc
バージョンは 8.3 である。protobuf
の新機能は gcc
のバージョンが 7.4 以上であることを必要とするため、CentOS7 はサポートできない。
Bug 82461 - [7 Regression] Temporary required for brace-initializing (non-literal-type) member variable。
結局、関連サービスのデプロイやコンパイルサーバーを CentOS8 に移動することで問題を解決した。
理論的な列挙
問題を全体的に見直すと、よりシンプルで効率的な解決策があります。それは、列挙の定義を調整し、1から番号付けするようにすることです。これにより、デフォルト値とビジネス値を明確に区別でき、上記のような問題を防ぐことができます。
なぜ 1 から始める方が合理的なのか?
protobuf
において、enum 型のデフォルト値は固定で 0 に設定されています。もし、有意義なビジネス値を 0 (例えば「市場中」) に定義した場合、増量プッシュ時にビジネス側では受信した 0 がビジネス値なのか、未設定のデフォルト値なのか判断できません。一方、enum を 1 から定義すれば、0 は無意味なデフォルト値または「未知」の状態として保持でき、問題が解決されます。
推奨される実践:
- protobuf の enum を設計する際には、常に 0 を無意味なデフォルト値 (例:
UNKNOWN
またはRESERVED
) として定義すること。 - 実際のビジネス値を 1 から割り当て、デフォルト値 0 と区別できるようにすること。
この小さな調整により、取引時間帯の識別の問題を解決するだけでなく、将来のプロトコル設計にも貴重な教訓を提供しました。