<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Chalkboard</title><description>コードと人生、両方をデバッグする技術者の日々</description><link>https://www.chalkboard.me/</link><language>ja</language><item><title>v2.Kafka/Pulsarの選択ガイドラインを作りたい(1-2章)</title><link>https://www.chalkboard.me/posts/kafka-pulsar-guideline2/</link><guid isPermaLink="true">https://www.chalkboard.me/posts/kafka-pulsar-guideline2/</guid><description>前回の記事では、Kafka と Pulsar の選択ガイドラインを作るにあたっての 目次 の骨子と、ガイドラインに盛り込むべき項目を洗い出しました。今回は、その目次のうち 1章（ガイドラインの目的） および 2章（基本的なアーキテクチャの違い）について、どのように内容をまとめるかを検討していきます。  </description><pubDate>Thu, 23 Jan 2025 03:38:13 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;p&amp;gt;&amp;lt;a href=&quot;https://www.chalkboard.me/posts/kafka-pulsar-guideline/&quot;&amp;gt;前回の記事&amp;lt;/a&amp;gt;では、Kafka と Pulsar の選択ガイドラインを作るにあたっての &amp;lt;strong&amp;gt;目次&amp;lt;/strong&amp;gt; の骨子と、ガイドラインに盛り込むべき項目を洗い出しました。今回は、その目次のうち &amp;lt;strong&amp;gt;1章（ガイドラインの目的）&amp;lt;/strong&amp;gt; および &amp;lt;strong&amp;gt;2章（基本的なアーキテクチャの違い）&amp;lt;/strong&amp;gt; について、どのように内容をまとめるかを検討していきます。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;1章：ガイドラインの目的&amp;lt;/h2&amp;gt;
&amp;lt;h3&amp;gt;1. 背景と目的の明示&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;なぜガイドラインが必要なのか？&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
Kafka チームと Pulsar チームがそれぞれ存在するため、利用者からの「どちらを使えばいいの？」という疑問に対して一貫した選定基準を示す必要がある。合併後の新体制下で混乱が生じないよう、標準となる方針を定義したい。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;このガイドラインで扱う範囲&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
前回の記事で示した &amp;lt;strong&amp;gt;目次&amp;lt;/strong&amp;gt; にある通り、基本的なアーキテクチャ比較や運用・管理面、セキュリティ、コスト試算などを網羅して解説する。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;2. 想定読者と想定シナリオ&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;主な対象&amp;lt;/strong&amp;gt;: 新規にメッセージング基盤を導入したい社内ユーザ（開発チーム）。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;規模感&amp;lt;/strong&amp;gt;: 小規模から大規模まで特に限定しない。社内システムであれば、必要な規模に応じてチームと相談しながら対応可能。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;SLA / SLO&amp;lt;/strong&amp;gt;: Kafka / Pulsar ともに公式ドキュメントで提示されている基準があり、それらへのリンクを参照する形で対応。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;3. ガイドラインの適用範囲（スコープ）&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;取り上げるトピック&amp;lt;/strong&amp;gt;: 前回の記事の目次に挙げた
&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;基本アーキテクチャの違い&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;選定判断のポイント（ユースケース別）&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;運用・管理面&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;セキュリティ / マルチテナント&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;パフォーマンステスト&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;コスト試算&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;運用体制・権限分掌&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;事例紹介・参考リンク&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;あえて取り上げない（詳細に踏み込まない）トピック&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;アプリケーション開発者向けのコードレベルの詳細実装&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Producer/Consumerの実装サンプルやSDK設定などは、利用者向けの個別ドキュメントに委ねる。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;他のフレームワークやOSSとの高度な連携&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Kafka StreamsやFlinkなどのストリーミング処理基盤、分析ツールとの連携、あるいは他PFとの連携はスコープ外。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;4. このガイドラインを参照することで得られる価値&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;導入判断をスムーズに進められる&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
Kafka と Pulsar の違いや運用面の注意事項が整理されたガイドラインを参照することで、短時間で適切な判断が下せる。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;運用フローのベースラインを確立できる&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
障害対応フロー、バージョンアップ方針などが概念的に分かるので、導入後のトラブル対応のイメージができる。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;h2&amp;gt;2章：基本的なアーキテクチャの違い&amp;lt;/h2&amp;gt;
&amp;lt;h3&amp;gt;1. どの程度の深さまで解説するか&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;ガイドラインとしては、&amp;lt;strong&amp;gt;「利用・運用する際に必要なポイント」&amp;lt;/strong&amp;gt; を中心に説明し、コードレベルや内部実装の詳細な仕組みには踏み込まない。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;各製品の公式ドキュメントや、インストールガイド・設定ガイドへのリンクを提示して、さらなる詳細を知りたい場合の参考情報を提供する。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;2. Kafka の概要&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;ログ構造&amp;lt;/strong&amp;gt;: Broker 内のパーティション単位でメッセージを保持し、必要に応じてレプリケーションを行う。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;ZooKeeper / KIP-500&amp;lt;/strong&amp;gt;: これまでは ZooKeeper が必須だったが、KIP-500 により ZooKeeper を排除したアーキテクチャも利用可能になる。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;スケール方法&amp;lt;/strong&amp;gt;: Broker 台数、パーティション数を増やすことで負荷分散。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;用途の特徴&amp;lt;/strong&amp;gt;: 主に &amp;lt;strong&amp;gt;イベントストリーミング&amp;lt;/strong&amp;gt; としての大規模ログ処理が得意。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;3. Pulsar の概要&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Broker と BookKeeper の分離&amp;lt;/strong&amp;gt;: Pulsar Broker はメッセージを一時的に中継し、データの永続化は BookKeeper クラスタが担当する。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;マルチテナント設計&amp;lt;/strong&amp;gt;: テナントや Namespace を使って分離管理する仕組みが標準で備わっている。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;スケールアウト&amp;lt;/strong&amp;gt;: Broker 層、BookKeeper 層をそれぞれ独立して増減可能。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;用途の特徴&amp;lt;/strong&amp;gt;: &amp;lt;strong&amp;gt;Pub/Sub, キューイング&amp;lt;/strong&amp;gt; 用途としての柔軟性が高く、大量トピックを同時に扱うケースでも適している。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;4. 比較の観点（例）&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;データの書き込み・読み取りフロー&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Kafka: Broker のパーティションに書き込み → コンシューマがログを順次読み取り&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Pulsar: Broker が BookKeeper に書き込み → Broker がクライアントにメッセージを配信&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;スケーラビリティと障害対応&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Kafka: パーティション数が多いほど設計・管理が複雑になる可能性がある&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Pulsar: BookKeeper 層のレプリカ構成で耐障害性を高める一方、ネットワーク帯域にも配慮が必要&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;マルチテナントとアクセス制御&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Kafka: ACL や RBAC (SASL/SSL) で制御。大規模になるとクラスター分割なども検討&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Pulsar: テナント / Namespace を切り分けることで、論理的にプロジェクトごとに独立性を保つ&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;p&amp;gt;ここではあくまで高レベルの比較とポイントに留め、詳細は各運用チームや公式ドキュメントのリファレンスを参照できるようにする。&amp;lt;/p&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;h2&amp;gt;まとめ&amp;lt;/h2&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;1章（ガイドラインの目的）&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;社内で Kafka / Pulsar を導入する際の指針をまとめることが目的。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;想定読者は新規導入を検討する社内ユーザ。規模は限定せず、SLA/SLO は各プロダクト公式の基準を参照。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;コードレベルのサンプルや他のフレームワーク連携等は詳細に扱わない。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;2章（基本的なアーキテクチャの違い）&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;運用や導入を検討する上で重要になるポイントを抽出し、高レベルにまとめる。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Kafka は Broker 内パーティション構造 + ZooKeeper (KIP-500) という構成が特徴。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Pulsar は Broker と BookKeeper を分離し、マルチテナントを標準でサポート。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;スケール方法や障害時の挙動など、運用・管理の観点で比較する。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;p&amp;gt;次回は &amp;lt;strong&amp;gt;3章以降&amp;lt;/strong&amp;gt;、具体的な「ユースケース別の選定基準」や「運用・管理面の考慮事項」などをもう少し掘り下げていきたいと思います。&amp;lt;/p&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>【調査ログ】Apache Pulsar と Kafka の比較 ～サブスクリプション、ルーティング、順序制御編～</title><link>https://www.chalkboard.me/posts/report-pulsar-kafka-1/</link><guid isPermaLink="true">https://www.chalkboard.me/posts/report-pulsar-kafka-1/</guid><description>Pulsar は「サブスクリプションタイプ」を複数用意しており、1つのトピックに対して異なるタイプのコンシューマを同時に動かすことが可能です。一方 Kafka では、1つの「Consumer Group」で「パーティション割り当て」中心のモデルが確立されており、並列度の確保と順序保証はパーティション単位で管理するのが基本となります。</description><pubDate>Tue, 21 Jan 2025 22:59:52 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;h2&amp;gt;はじめに&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;本記事では、メッセージングシステムとして代表的な &amp;lt;strong&amp;gt;Apache Pulsar&amp;lt;/strong&amp;gt; と &amp;lt;strong&amp;gt;Apache Kafka&amp;lt;/strong&amp;gt; を比較しながら、以下の点に着目して解説します。&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;両者における &amp;lt;strong&amp;gt;サブスクリプションモデルの違い&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Producer 側の &amp;lt;strong&amp;gt;ルーティング方式&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;順序保証(Ordering)の考え方&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Pulsar のサブスクリプションタイプを使った &amp;lt;strong&amp;gt;具体的なユースケース例&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;p&amp;gt;Pulsar は「サブスクリプションタイプ」を複数用意しており、1つのトピックに対して異なるタイプのコンシューマを同時に動かすことが可能です。一方 Kafka では、1つの「Consumer Group」で「パーティション割り当て」中心のモデルが確立されており、並列度の確保と順序保証はパーティション単位で管理するのが基本となります。&amp;lt;/p&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;h2&amp;gt;1. サブスクリプションモデルの違い&amp;lt;/h2&amp;gt;
&amp;lt;h3&amp;gt;1-1. Kafka の場合&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Consumer Group&amp;lt;/strong&amp;gt; に属する複数の Consumer は、Kafka ブローカーから &amp;lt;strong&amp;gt;パーティションごと&amp;lt;/strong&amp;gt; に割り当てを受けます。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;1パーティション = 1Consumer&amp;lt;/strong&amp;gt; の関係が基本で、パーティション内のメッセージは常に同じ Consumer が読むことになります。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;並列度を上げたい場合は、パーティション数を増やし、Consumer をスケールアウトさせる設計が必要です。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;パーティション内部でさらに並列化&amp;lt;/strong&amp;gt;したい場合は、アプリケーション側で工夫（スレッドプールなど）して順序を崩さないよう制御する必要があります。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;1-2. Pulsar の場合&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;Pulsar には &amp;lt;strong&amp;gt;4種類のサブスクリプションタイプ&amp;lt;/strong&amp;gt; が存在し、Consumer がトピックを購読するときに指定できます。1つのトピックに対して複数のサブスクリプションを張ることも可能で、それぞれ異なるタイプを選べます。&amp;lt;/p&amp;gt;
&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Exclusive&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;1つのサブスクリプションに対し &amp;lt;strong&amp;gt;1つの Consumer&amp;lt;/strong&amp;gt; だけがアクティブにメッセージを受け取る。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;完全にシリアルな読み出しが可能。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Failover&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;複数の Consumer が同じサブスクリプションを購読できるが、同時にアクティブなのは &amp;lt;strong&amp;gt;1つだけ&amp;lt;/strong&amp;gt;。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;アクティブな Consumer が落ちたときに &amp;lt;strong&amp;gt;フェイルオーバー&amp;lt;/strong&amp;gt; で別の Consumer が引き継ぐ。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Exclusive と同様にシリアルな読み出しを行いつつ、高可用性を確保できる。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Shared&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;1つのサブスクリプションに &amp;lt;strong&amp;gt;複数の Consumer&amp;lt;/strong&amp;gt; が同時に参加し、メッセージを &amp;lt;strong&amp;gt;ラウンドロビン&amp;lt;/strong&amp;gt; などで振り分ける。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;パーティション内の順序保証は崩れる&amp;lt;/strong&amp;gt; 代わりに、高いスループットを得られる。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Key_Shared&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Shared と似ているが、&amp;lt;strong&amp;gt;Message Key&amp;lt;/strong&amp;gt; (Producer 側で設定) ごとに &amp;lt;strong&amp;gt;同じ Consumer&amp;lt;/strong&amp;gt; に割り当てる。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;同じ Key のメッセージ&amp;lt;/strong&amp;gt; は必ず同じ Consumer が受け取り、パーティション内でキー単位の順序が保たれる。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;異なる Key は別の Consumer が同時に処理するため、キーごとのシリアル処理を維持しつつ並列化が可能。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;h2&amp;gt;2. ルーティング方式の違い (Producer 側)&amp;lt;/h2&amp;gt;
&amp;lt;h3&amp;gt;2-1. Kafka&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Producer でメッセージを送る際、&amp;lt;strong&amp;gt;Key&amp;lt;/strong&amp;gt; を指定すると、その Key のハッシュ値をもとに &amp;lt;strong&amp;gt;特定パーティション&amp;lt;/strong&amp;gt; へ常にルーティングされます。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Key を指定しない場合はラウンドロビンなどでパーティションが割り当てられることが多いです。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;同じ Key のメッセージを同じパーティションに集約&amp;lt;/strong&amp;gt; できるのが特徴。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;2-2. Pulsar&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Pulsar の Producer も似たように、メッセージごとに &amp;lt;code&amp;gt;messageKey&amp;lt;/code&amp;gt; をセットし、&amp;lt;strong&amp;gt;パーティションルーティングを KeyHash に切り替える&amp;lt;/strong&amp;gt; ことで、同じ Key が同じパーティションへ送られます。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;何も指定しなければデフォルトはラウンドロビンなど、設定次第で柔軟に振り分けることができます。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Key_Shared サブスクリプションと組み合わせると、&amp;lt;strong&amp;gt;「同じ Key → 同じパーティション → 同じ Consumer」&amp;lt;/strong&amp;gt; のフローを構築可能です。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;h2&amp;gt;3. 順序保証の考え方&amp;lt;/h2&amp;gt;
&amp;lt;h3&amp;gt;3-1. パーティション内の順序&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Kafka&amp;lt;/strong&amp;gt; / &amp;lt;strong&amp;gt;Pulsar&amp;lt;/strong&amp;gt; ともに、&amp;lt;strong&amp;gt;単一パーティション&amp;lt;/strong&amp;gt; ではメッセージが受信された順に &amp;lt;strong&amp;gt;append-only&amp;lt;/strong&amp;gt; なログとしてブローカーに保存されます。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Consumer はそのログをオフセット順に読み出すため、&amp;lt;strong&amp;gt;パーティション内のメッセージ順序は保証&amp;lt;/strong&amp;gt; されます。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;複数 Producer が同じパーティションに書き込む場合、&amp;lt;strong&amp;gt;ブローカーが受信した順序&amp;lt;/strong&amp;gt; で確定し、Producer の送信時刻順とは必ずしも一致しない点は共通です。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;3-2. パーティションをまたぐグローバル順序&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;いずれのシステムも、&amp;lt;strong&amp;gt;パーティションをまたぐグローバルな順序保証は行いません&amp;lt;/strong&amp;gt;。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;パーティション間で到着時刻が前後するのは一般的で、完全な時系列を保つにはアプリケーション側の追加ロジックが必要です。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;「すべてのメッセージで厳密な順序が必要」な場合は &amp;lt;strong&amp;gt;パーティション数を1つ&amp;lt;/strong&amp;gt; にするか、キーを工夫して常に同じパーティションへルーティングする必要があります。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;3-3. Pulsar におけるサブスクリプションタイプと順序の関係&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Exclusive / Failover&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;1つの Consumer (またはアクティブ1台) がすべてのメッセージを読み取るため、&amp;lt;strong&amp;gt;パーティション内の完全な順序が保たれる&amp;lt;/strong&amp;gt;。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Shared&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;パーティション内のメッセージが複数 Consumer に分散するため、&amp;lt;strong&amp;gt;グローバルな順序は崩れる&amp;lt;/strong&amp;gt;。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Key_Shared&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;同じ Key のメッセージ&amp;lt;/strong&amp;gt; は順序が保証される一方、&amp;lt;strong&amp;gt;Key が異なるもの同士&amp;lt;/strong&amp;gt; では順序は保証されない。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;これは Kafka でも同じパーティションにキーを集めれば保持できる考え方と同様だが、Pulsar はキー単位で Consumer を自動振り分けする仕組みが標準機能として提供されている点が特徴的。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;h2&amp;gt;4. サブスクリプションタイプを活かしたユースケース実例&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Pulsar では、&amp;lt;strong&amp;gt;1つのトピック&amp;lt;/strong&amp;gt; に複数のサブスクリプションを張り、それぞれ &amp;lt;strong&amp;gt;異なるサブスクリプションタイプ&amp;lt;/strong&amp;gt; を同時に利用できます。&amp;lt;br&amp;gt;
ここでは具体例を 3つ示します。&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;4-1. 監査ログ + リアルタイム分析&amp;lt;/h3&amp;gt;
&amp;lt;h4&amp;gt;シナリオ&amp;lt;/h4&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;トピック &amp;lt;code&amp;gt;audit-logs&amp;lt;/code&amp;gt; にユーザ操作ログなどを集積している。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;監査&amp;lt;/strong&amp;gt; 向けには「時系列どおり全メッセージを1台で処理」したい (順序重視)。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;リアルタイム分析&amp;lt;/strong&amp;gt; 向けには「並列分散」して高スループットで処理したい (スピード重視)。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h4&amp;gt;実装イメージ&amp;lt;/h4&amp;gt;
&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;監査向けサブスクリプション&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;サブスクリプション名: &amp;lt;code&amp;gt;audit-subscription&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;タイプ: &amp;lt;strong&amp;gt;Exclusive&amp;lt;/strong&amp;gt; (もしくは Failover)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;1台(またはフェイルオーバー構成)でログをすべて取得し、厳密な時系列で保存・検証する。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;分析向けサブスクリプション&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;サブスクリプション名: &amp;lt;code&amp;gt;analysis-subscription&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;タイプ: &amp;lt;strong&amp;gt;Shared&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;複数インスタンスで並列に取り込み、リアルタイム集計・ダッシュボード更新などを行う。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;h3&amp;gt;4-2. ユーザIDごとのワークフロー制御 + バッチ処理&amp;lt;/h3&amp;gt;
&amp;lt;h4&amp;gt;シナリオ&amp;lt;/h4&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;ECサイトのイベント &amp;lt;code&amp;gt;user-events&amp;lt;/code&amp;gt;。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;リアルタイムには &amp;lt;strong&amp;gt;「ユーザID単位の順序」を守りたい&amp;lt;/strong&amp;gt; (注文→決済→配送リクエスト などのステートマシン処理)。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;別途 &amp;lt;strong&amp;gt;バッチ処理&amp;lt;/strong&amp;gt; で全メッセージを定期的に取得し、大規模分析したい。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h4&amp;gt;実装イメージ&amp;lt;/h4&amp;gt;
&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ワークフロー制御用サブスクリプション&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;サブスクリプション名: &amp;lt;code&amp;gt;workflow-subscription&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;タイプ: &amp;lt;strong&amp;gt;Key_Shared&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;userId&amp;lt;/code&amp;gt; をキーとして、同じユーザIDのイベントは必ず同じ Consumer が順序通りに処理する。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;バッチ用サブスクリプション&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;サブスクリプション名: &amp;lt;code&amp;gt;batch-subscription&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;タイプ: &amp;lt;strong&amp;gt;Exclusive / Failover / Shared&amp;lt;/strong&amp;gt; のいずれか&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;定期的に全メッセージを取得し、Hadoop/Spark などでまとめて分析。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;h3&amp;gt;4-3. 高信頼レプリケーション + 即時アラート&amp;lt;/h3&amp;gt;
&amp;lt;h4&amp;gt;シナリオ&amp;lt;/h4&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;IoT センサーからのデータ &amp;lt;code&amp;gt;sensor-data&amp;lt;/code&amp;gt; が大量に流れてくる。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;すべてのデータを &amp;lt;strong&amp;gt;バックアップ&amp;lt;/strong&amp;gt; (外部ストレージなど) し、高い耐久性を確保したい。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;一方で &amp;lt;strong&amp;gt;リアルタイムアラート&amp;lt;/strong&amp;gt; (閾値超過検知など) にも活用したい。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h4&amp;gt;実装イメージ&amp;lt;/h4&amp;gt;
&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;レプリケーション/バックアップ用サブスクリプション&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;サブスクリプション名: &amp;lt;code&amp;gt;backup-subscription&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;タイプ: &amp;lt;strong&amp;gt;Exclusive&amp;lt;/strong&amp;gt; (または Failover)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;1台がすべてのメッセージを漏れなく取り込み、外部に連携する。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;障害時は Failover で別 Consumer がすぐに引き継ぐ。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;リアルタイムアラート用サブスクリプション&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;サブスクリプション名: &amp;lt;code&amp;gt;alert-subscription&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;タイプ: &amp;lt;strong&amp;gt;Shared&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;センサーイベントを並列に処理し、閾値超過時に即アラートを発行。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;スケールアウトしやすく、高速応答が期待できる。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;h2&amp;gt;5. まとめ&amp;lt;/h2&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;順序保証(Ordering)&amp;lt;/strong&amp;gt; の観点では、&amp;lt;strong&amp;gt;Kafka&amp;lt;/strong&amp;gt; も &amp;lt;strong&amp;gt;Pulsar&amp;lt;/strong&amp;gt; も &amp;lt;strong&amp;gt;「パーティション単位で到着順を保証し、パーティション間のグローバル順序は保証しない」&amp;lt;/strong&amp;gt; という点では共通しています。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;違い&amp;lt;/strong&amp;gt; は、&amp;lt;strong&amp;gt;Pulsar&amp;lt;/strong&amp;gt; が標準で持つ &amp;lt;strong&amp;gt;多様なサブスクリプションタイプ&amp;lt;/strong&amp;gt; による &amp;lt;strong&amp;gt;Consumer モデルの柔軟性&amp;lt;/strong&amp;gt; にあります。
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Kafka では「Consumer Group → パーティション割り当て」で順序制御するのが主流。1パーティションを複数 Consumer で並行処理したい場合はアプリケーション側の管理が必要。&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Pulsar では &amp;lt;strong&amp;gt;Shared / Key_Shared&amp;lt;/strong&amp;gt; が用意されており、&amp;lt;strong&amp;gt;パーティション内でも並列かつ Key 単位で順序を維持&amp;lt;/strong&amp;gt; するような運用が容易です。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;同じトピックを複数の目的で読みたい場合、Kafka では通常トピックを複製するか Consumer Group を別々に作成しますが、&amp;lt;strong&amp;gt;Pulsar では「サブスクリプションごとに異なるタイプ」を併用&amp;lt;/strong&amp;gt; できるため、1つのデータストリームをより多角的に活用できるのが特徴です。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;p&amp;gt;以上のように、&amp;lt;strong&amp;gt;Pulsar vs Kafka&amp;lt;/strong&amp;gt; の比較ポイントとして、&amp;lt;/p&amp;gt;
&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;サブスクリプション(コンシューマモデル)&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Producer からのルーティング&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;順序保証の範囲(パーティション内 vs グローバル)&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;ユースケース別の活用方法&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;p&amp;gt;を理解しておくと、要件に合ったメッセージング設計を行いやすくなります。&amp;lt;/p&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>v1.Kafka/Pulsarの選択ガイドラインを作りたい</title><link>https://www.chalkboard.me/posts/kafka-pulsar-guideline/</link><guid isPermaLink="true">https://www.chalkboard.me/posts/kafka-pulsar-guideline/</guid><description>さて、問題は、利用者から見てどっちのプロダクトを使えばいいのだろうか？ということが分かりづらいことです。 もちろん目に見えた機能差異はありますので、それらを必要としている人にとってはあまり困らないかもしれませんが、そういったものがない利用者にとっての最適解をガイドするのが運用側の役割でもあります。  今回はもしガイドを作成するとしたらどんな内容にしていくのがいいのだろうか？ というのを考えながらそれをメモして、複数記事にわたって掘り下げたいと思います。</description><pubDate>Tue, 21 Jan 2025 22:56:41 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;h2&amp;gt;Kafka と Pulsar のガイドライン作成に向けた調査メモ&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;私は今、OSSのApachePulsarを扱うチームに所属しています。&amp;lt;br&amp;gt;
最近、会社と会社がフィージョンした結果、社内に我々Pulsarチームと、新しい仲間のKafkaチームが出来上がりました。&amp;lt;br&amp;gt;
PulsarとKafkaはともにApache Software Foundationに寄贈されているOSSであり、どちらも分散メッセージング基盤の代表格です。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;さて、問題は、利用者から見てどっちのプロダクトを使えばいいのだろうか？ということが分かりづらいことです。&amp;lt;br&amp;gt;
もちろん目に見えた機能差異はありますので、それらを必要としている人にとってはあまり困らないかもしれませんが、そういったものがない利用者にとっての最適解をガイドするのが運用側の役割でもあります。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;今回はもしガイドを作成するとしたらどんな内容にしていくのがいいのだろうか？&amp;lt;br&amp;gt;
というのを考えながらそれをメモして、複数記事にわたって掘り下げたいと思います。&amp;lt;/p&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;h2&amp;gt;ガイドラインに盛り込むべき主な項目&amp;lt;/h2&amp;gt;
&amp;lt;h3&amp;gt;1. ガイドラインの目的と前提&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;目的&amp;lt;/strong&amp;gt;: なぜガイドラインが必要なのか、どんなシーンで参照されるのかを明確化する
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;例: 「新規システムでメッセージング基盤を使いたい」「既存システムのリプレースを検討している」「開発チームが検証したい」など&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;前提&amp;lt;/strong&amp;gt;: どの程度の規模（メッセージ量、利用ユーザー数）、どんな SLA/SLO を想定しているか
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;「スモールスタート向け」「エンタープライズ全体の大規模ユースケース」など&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;2. 基本的なアーキテクチャの違い&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Kafka の全体像&amp;lt;/strong&amp;gt;: Broker 内のログ構造、パーティション管理、Zookeeper もしくは KIP-500 (ZooKeeperless) の話など&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Pulsar の全体像&amp;lt;/strong&amp;gt;: Broker と BookKeeper の分離構成、journal &amp;amp; ledger、マルチテナント設計など&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;比較ポイント&amp;lt;/strong&amp;gt;: どこにデータが書き込まれ、どこで読み出されるのか。どのようにスケールするのか。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;3. 選定判断のポイント（ユースケース・要件別）&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;スループット要件 / レイテンシ要件&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;どれくらいのメッセージ量を捌きたいか、それに応じた Kafka/Pulsar の性能事例&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;トピック数 / サブスクリプション数 / テナント数&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;マルチテナントや大量トピックが想定される場合は Pulsar が便利、など&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Geo-Replication / 複数データセンター運用&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;リージョンをまたいだ運用が必要なら Pulsar のジオレプリケーション機能が活きる&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;キューイング用途 or イベントストリーミング用途&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Kafka ではイベントストリーミング、Pulsar はキューイングと Pub/Sub を混在させられる etc.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;4. 運用・管理面の考慮事項&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;インフラ構成&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;オンプレかクラウドか、Kubernetes での運用か、マネージドサービス（Confluent Cloud, StreamNative etc.）を利用するか&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;スケーラビリティ&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;どのようにノードを増減して負荷に対応するか&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Kafka は Broker 台数増減、Pulsar は Broker 層と BookKeeper 層を分離して増やす構成&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;可観測性（モニタリング / ログ / トレース）&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Prometheus, Grafana などの統合監視のやり方&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;死活監視・リソース監視・トピックのレイテンシ監視 etc.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;障害対応・リカバリー&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Broker/Bookie の故障に対する自動復旧や、データ再配置までの手順&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;メンテナンスやバージョンアップの手順・注意点&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;5. セキュリティ / 認証・認可 / マルチテナント&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;認証方式の違い&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Kafka: SASL/SSL、RBAC、ACL&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Pulsar: TLS、Token 認証、Namespace レベルのアクセス制御&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;マルチテナント管理&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Kafka で複数部門やプロジェクトを分割管理するにはどうするか&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Pulsar のテナント/Namespace を使った場合の運用フロー&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;監査ログやコンプライアンス要件&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;金融や医療などの高いセキュリティ要件への対応&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;6. パフォーマンステスト項目&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;テストシナリオ定義&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;「一定のメッセージサイズ・一定のメッセージレートで書き込み＋読み取り」&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;「多くのトピックを同時に扱う」など現場想定シナリオ&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;測定環境・条件&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;同一ハードウェアでの比較を行うか、クラウドのどのインスタンスタイプを使うか&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;どんなネットワーク条件下で測定するか&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;測定するメトリクス&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;スループット (MB/s, msg/sec)、平均レイテンシ、p99 レイテンシ&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;CPU / メモリ / ディスク IO / ネットワーク帯域使用量&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Broker/BookKeeper のリソース使用率など&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;7. コスト試算&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;インフラコスト&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Kafka: Broker 台数とストレージ容量、レプリケーション係数&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Pulsar: Broker 層 + BookKeeper 層（journal / ledger のストレージ構成）、必要な高速ディスク数&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;クラウド上での料金計算例&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;EC2 インスタンスタイプ、EBS の種類や IOPS、ネットワーク転送料 etc.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;オンプレの場合&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;物理サーバー・ディスク構成、保守運用コスト&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;8. ガイドライン策定後の運用体制 / 権限分掌&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;チーム連携&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Pulsar チーム / Kafka チーム / インフラチーム / セキュリティチーム それぞれの役割&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;サポート体制・問い合わせフロー&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;社内サービスデスクの窓口や、マネージドベンダーとの連携&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;バージョンアップ方針&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;どのように長期サポートバージョンを選定するか、メジャーバージョンアップをいつ行うか&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h3&amp;gt;9. 事例紹介・参考リンク&amp;lt;/h3&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;社内事例&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;具体的にどのプロジェクトがどのように Kafka/Pulsar を使っているか&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;運用実績（メッセージ量、成功例・失敗例）&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;一般的なユースケース例&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;ログ収集・IoT・金融・SaaS 通知など&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;関連ドキュメント・OSS ツールのリンク&amp;lt;/strong&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;オフィシャルドキュメント、運用ガイドライン、Metrics ツール等&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;h2&amp;gt;ガイドライン執筆のための調査 &amp;amp; 測定項目&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;ガイドラインを作成するにあたって、上記の各項目を裏付ける &amp;lt;strong&amp;gt;客観的なデータやエビデンス&amp;lt;/strong&amp;gt; が必要になります。そこで、特に重視したい調査・測定項目を整理しました。&amp;lt;/p&amp;gt;
&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;性能比較テスト&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;同じ条件で Kafka / Pulsar に対して書き込み・読み出しを行い、スループットやレイテンシを比較&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;1 トピックあたりの負荷試験だけでなく、「大量トピック同時利用」や「マルチテナント運用」を想定したテスト&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;p99 レイテンシ、レプリカ数を変えた場合の耐障害性と性能差&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;運用負荷や障害時の復旧テスト&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Pulsar で BookKeeper ノードが 1 台故障したときの自動リカバリ挙動&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Kafka で Broker がダウンしたときのリーダーエレクションの時間&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;マルチクラスターレプリケーション（あるいは Geo-Replication）が有効な状態での障害テスト&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;セキュリティ・認可設定の検証&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Kafka の ACL をどの程度細かく設定できるか&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Pulsar のテナント/Namespace ポリシーでどんな要件に対応できるか&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;実際に認証がうまくいかないケースや権限設定ミスがあった場合、どのような影響が出るか&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;コストの試算&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;クラウド環境で、想定メッセージ量を捌くために必要なインスタンス数・スペックはどのくらいか&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;長期保存をしたい場合、ストレージにかかるコスト差（オンプレディスクの買い増し vs. クラウドストレージ）&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;マネージドサービスを利用する場合のライセンスやサブスクリプション費用&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;実運用事例のヒアリング&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;社内の既存ユーザーに対して、「導入してよかった点」「苦労した点」「改善要望」などをインタビュー&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;チーム間の連携や運用フローの課題も洗い出しておく&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;p&amp;gt;ひとまずこれをバージョン1の骨子として、よくわからんなーってところを詰めていこうと思います。&amp;lt;br&amp;gt;
わたしkafkaのことは本当によくわかりませんし・・・。&amp;lt;/p&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>JavaのOSSによくみられる「shading」ってなんだ</title><link>https://www.chalkboard.me/posts/java-oss-shading/</link><guid isPermaLink="true">https://www.chalkboard.me/posts/java-oss-shading/</guid><description>javaのOSSでは「shading」と呼ばれる方法を用いて、shaded-jarを作成し、ライブラリの機能が外側から破壊されないように工夫されているんだなというはなし</description><pubDate>Mon, 14 Oct 2024 14:09:58 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;h1&amp;gt;Shadingって何&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;最近、本業の業務がOSSの運用・保守を中心に行う部署になったこともあって、「アプリケーション」開発とは異なる概念に行き合うことが増えてきた。&amp;lt;br&amp;gt;
アプリケーションを開発していたときは、ベースはOSSの組み合わせで実現され、ロジックやデータフローを表現していけばそれで良かった。&amp;lt;br&amp;gt;
しかし、OSSの保守運用（コミッター活動を含む）となると話は別で、ネイティブな言語仕様やOSSが隠してくれていた泥臭い部分の解決について理解することが重要になる。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;PR&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;例えば下記のPR。&amp;lt;br&amp;gt;
&amp;lt;a href=&quot;https://github.com/apache/pulsar/pull/19458&quot;&amp;gt;https://github.com/apache/pulsar/pull/19458&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
これは見ての通り、Apache Pulsarで使用されるClient側コードの修正になっている。&amp;lt;br&amp;gt;
修正対象の事象はClassのロードエラーで、アプリケーション開発だとまずお目にかからないエラーだ。なぜならそんなコードはコンパイルできないからである。&amp;lt;br&amp;gt;
しかしOSSでは発生しうる。&amp;lt;br&amp;gt;
この原因になったのがOSS側で行っているshadingである。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;クラスパスの解決&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;shadingの説明に入る前に、Javaにおけるクラスパスの解決についておさらい。&amp;lt;br&amp;gt;
maven, gradleを使用している際に、同名のクラスパスに複数のバージョンが重なっている場合どのように解決されるか？&amp;lt;br&amp;gt;
通常は一番新しいバージョンによって上書きされる。&amp;lt;br&amp;gt;
この上書きは、jarにまとめられる単位で行われるので、自作のコードだけでなく、dependencyすべてが影響を受けるということだ。&amp;lt;br&amp;gt;
これを利用して、脆弱性対応がされていない外部ライブラリの依存を無理やり新しいバージョンに差し替えることも可能である。（正しく動くかは別の話）&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;OSSにおけるクラスパスの解決&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Apache Pulsarなど、独立性が強いOSSにおいては、外部依存のライブラリによって自らのクライアントが使用しているバージョンが変更されることは望ましい挙動ではない。&amp;lt;br&amp;gt;
特に、ClientはSpringFrameworkなどに組み込まれて使われることも一般的であるため、内部で使用している有名どころのOSSなんかはすぐに衝突してしまう。&amp;lt;br&amp;gt;
こうなると、正しい挙動をするかどうかが保証されなくなってしまうし、いちいち正しいバージョンになるように解決することは人手でも自動でも不可能に近い。&amp;lt;br&amp;gt;
(&amp;lt;code&amp;gt;dependency-hell&amp;lt;/code&amp;gt; と呼ばれる)&amp;lt;br&amp;gt;
これを解決する方法の一つがshadingである&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;shading&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;shadingは「あるクラスパスを別のクラスパスで表現し直す」機能である。&amp;lt;br&amp;gt;
実際にコードを見てみる。&amp;lt;br&amp;gt;
&amp;lt;a href=&quot;https://github.com/massakam/pulsar/blob/42c72d1177f2be6ade02f84d5eedb910d51cd891/pulsar-client-shaded/pom.xml&quot;&amp;gt;https://github.com/massakam/pulsar/blob/42c72d1177f2be6ade02f84d5eedb910d51cd891/pulsar-client-shaded/pom.xml&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;maven-shade-plugin によってshadingを行っているタスクである。&amp;lt;/p&amp;gt;
&amp;lt;pre&amp;gt;&amp;lt;code class=&quot;language-xml&quot;&amp;gt;      &amp;lt;plugin&amp;gt;
&amp;lt;!-- Shade all the dependencies to avoid conflicts --&amp;gt;
&amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
&amp;lt;artifactId&amp;gt;maven-shade-plugin&amp;lt;/artifactId&amp;gt;
&amp;lt;executions&amp;gt;
&amp;lt;execution&amp;gt;
&amp;lt;phase&amp;gt;${shadePluginPhase}&amp;lt;/phase&amp;gt;
&amp;lt;goals&amp;gt;
&amp;lt;goal&amp;gt;shade&amp;lt;/goal&amp;gt;
&amp;lt;/goals&amp;gt;
&amp;lt;configuration&amp;gt;
&amp;lt;createDependencyReducedPom&amp;gt;true&amp;lt;/createDependencyReducedPom&amp;gt;
&amp;lt;promoteTransitiveDependencies&amp;gt;true&amp;lt;/promoteTransitiveDependencies&amp;gt;
&amp;lt;minimizeJar&amp;gt;false&amp;lt;/minimizeJar&amp;gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          &amp;amp;lt;artifactSet&amp;amp;gt;
            &amp;amp;lt;includes&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.apache.pulsar:pulsar-client-original&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.apache.bookkeeper:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.apache.commons:commons-lang3&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;commons-codec:commons-codec&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;commons-collections:commons-collections&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.asynchttpclient:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;io.netty:netty-codec-http&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;io.netty:netty-transport-native-epoll&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.reactivestreams:reactive-streams&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;com.typesafe.netty:netty-reactive-streams&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.javassist:javassist&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;com.google.guava:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.checkerframework:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;com.google.code.findbugs:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;com.google.errorprone:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;com.google.j2objc:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;com.google.code.gson:gson&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;com.fasterxml.jackson.*:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;io.netty:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;io.netty.incubator:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;io.perfmark:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.eclipse.jetty:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;com.yahoo.datasketches:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;commons-*:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;io.swagger:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;io.airlift:*&amp;amp;lt;/include&amp;amp;gt;

              &amp;amp;lt;include&amp;amp;gt;org.apache.pulsar:pulsar-common&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;com.yahoo.datasketches:sketches-core&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.objenesis:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.yaml:snakeyaml&amp;amp;lt;/include&amp;amp;gt;

              &amp;amp;lt;include&amp;amp;gt;org.apache.avro:*&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;!-- Avro transitive dependencies--&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;com.thoughtworks.paranamer:paranamer&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.apache.commons:commons-compress&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.tukaani:xz&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;!-- Issue #6834, Since Netty ByteBuf shaded, we need also shade this module --&amp;amp;gt;
              &amp;amp;lt;include&amp;amp;gt;org.apache.pulsar:pulsar-client-messagecrypto-bc&amp;amp;lt;/include&amp;amp;gt;
            &amp;amp;lt;/includes&amp;amp;gt;
            &amp;amp;lt;excludes&amp;amp;gt;
              &amp;amp;lt;exclude&amp;amp;gt;com.fasterxml.jackson.core:jackson-annotations&amp;amp;lt;/exclude&amp;amp;gt;
            &amp;amp;lt;/excludes&amp;amp;gt;
          &amp;amp;lt;/artifactSet&amp;amp;gt;
          &amp;amp;lt;filters&amp;amp;gt;
            &amp;amp;lt;filter&amp;amp;gt;
              &amp;amp;lt;artifact&amp;amp;gt;org.apache.pulsar:pulsar-client-original&amp;amp;lt;/artifact&amp;amp;gt;
              &amp;amp;lt;includes&amp;amp;gt;
                &amp;amp;lt;include&amp;amp;gt;**&amp;amp;lt;/include&amp;amp;gt;
              &amp;amp;lt;/includes&amp;amp;gt;
              &amp;amp;lt;excludes&amp;amp;gt;
                &amp;amp;lt;!-- bouncycastle jars could not be shaded, or the signatures will be wrong--&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;org/bouncycastle/**&amp;amp;lt;/exclude&amp;amp;gt;
              &amp;amp;lt;/excludes&amp;amp;gt;
            &amp;amp;lt;/filter&amp;amp;gt;
          &amp;amp;lt;/filters&amp;amp;gt;
          &amp;amp;lt;relocations&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.asynchttpclient&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.asynchttpclient&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.apache.commons&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.apache.commons&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;io.airlift&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.io.airlift&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;com.google&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.com.google&amp;amp;lt;/shadedPattern&amp;amp;gt;
              &amp;amp;lt;excludes&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;com.google.protobuf.*&amp;amp;lt;/exclude&amp;amp;gt;
              &amp;amp;lt;/excludes&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;com.fasterxml.jackson&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.com.fasterxml.jackson&amp;amp;lt;/shadedPattern&amp;amp;gt;
              &amp;amp;lt;excludes&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;com.fasterxml.jackson.annotation.*&amp;amp;lt;/exclude&amp;amp;gt;
              &amp;amp;lt;/excludes&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;io.netty&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.io.netty&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.checkerframework&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.checkerframework&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;javax.annotation&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.javax.annotation&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;io.swagger&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.io.swagger&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.apache.pulsar.policies&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.apache.pulsar.policies&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;com.yahoo.datasketches&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.com.yahoo.datasketches&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;com.yahoo.sketches&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.com.yahoo.sketches&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.eclipse.jetty&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.eclipse&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.reactivestreams&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.reactivestreams&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;com.typesafe&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.com.typesafe&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;com.yahoo.memory&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.com.yahoo.memory&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.objenesis&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.objenesis&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.yaml&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.yaml&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.apache.avro&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.apache.avro&amp;amp;lt;/shadedPattern&amp;amp;gt;
              &amp;amp;lt;excludes&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;org.apache.avro.reflect.AvroAlias&amp;amp;lt;/exclude&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;org.apache.avro.reflect.AvroDefault&amp;amp;lt;/exclude&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;org.apache.avro.reflect.AvroEncode&amp;amp;lt;/exclude&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;org.apache.avro.reflect.AvroIgnore&amp;amp;lt;/exclude&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;org.apache.avro.reflect.AvroMeta&amp;amp;lt;/exclude&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;org.apache.avro.reflect.AvroName&amp;amp;lt;/exclude&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;org.apache.avro.reflect.AvroSchema&amp;amp;lt;/exclude&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;org.apache.avro.reflect.Nullable&amp;amp;lt;/exclude&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;org.apache.avro.reflect.Stringable&amp;amp;lt;/exclude&amp;amp;gt;
                &amp;amp;lt;exclude&amp;amp;gt;org.apache.avro.reflect.Union&amp;amp;lt;/exclude&amp;amp;gt;
              &amp;amp;lt;/excludes&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;!--Avro transitive dependencies--&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.codehaus.jackson&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.codehaus.jackson&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;com.thoughtworks.paranamer&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.com.thoughtworks.paranamer&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.apache.commons&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.apache.commons&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.tukaani&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.tukaani&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
            &amp;amp;lt;relocation&amp;amp;gt;
              &amp;amp;lt;pattern&amp;amp;gt;org.apache.bookkeeper&amp;amp;lt;/pattern&amp;amp;gt;
              &amp;amp;lt;shadedPattern&amp;amp;gt;org.apache.pulsar.shade.org.apache.bookkeeper&amp;amp;lt;/shadedPattern&amp;amp;gt;
            &amp;amp;lt;/relocation&amp;amp;gt;
          &amp;amp;lt;/relocations&amp;amp;gt;
          &amp;amp;lt;transformers&amp;amp;gt;
            &amp;amp;lt;transformer implementation=&amp;amp;quot;org.apache.maven.plugins.shade.resource.ServicesResourceTransformer&amp;amp;quot; /&amp;amp;gt;
            &amp;amp;lt;transformer implementation=&amp;amp;quot;org.apache.maven.plugins.shade.resource.PluginXmlResourceTransformer&amp;amp;quot; /&amp;amp;gt;
          &amp;amp;lt;/transformers&amp;amp;gt;
        &amp;amp;lt;/configuration&amp;amp;gt;
      &amp;amp;lt;/execution&amp;amp;gt;
    &amp;amp;lt;/executions&amp;amp;gt;
  &amp;amp;lt;/plugin&amp;amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;artifactSet.includeはshading対象のクラスパスを示し、relocations.relocationはどのクラスパスをどんなクラスパスに変更するかが記載されている。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;ここで重要なのは、shadingの対象にするにはincludeにそのパスを記載する必要があるということと、&amp;lt;br&amp;gt;
relocationは実際にそのクラスファイルが存在するかは気にしていないとうことである。&amp;lt;br&amp;gt;
PRの編集内容がまさにそれを修正している。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;PRの修正内容&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;PRでは、主に &amp;lt;code&amp;gt;&amp;lt; include &amp;gt;com.fasterxml.jackson.&lt;em&gt;:&lt;/em&gt;&amp;lt;/ include &amp;gt;&amp;lt;/code&amp;gt; の追加と、それによって不要になるincludeの削除を行っている。&amp;lt;br&amp;gt;
また、ユーザがアノテーションを使用する都合でjacksonのanotationクラスはexcludeされている。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;実際に問題を発生させていたのは、&amp;lt;code&amp;gt;pulsar-client-shaded&amp;lt;/code&amp;gt; で jacksonのdatatypeをinclude指定内にも関わらず、com.fasterxml.jacksonをリロケーションしていることにある。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;これによって、リロケーションされたdatatypeは解決できるクラスがなくなってしまったため、例外になっている。&amp;lt;/p&amp;gt;
&amp;lt;h1&amp;gt;まとめ&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;shadingは適切に利用すると依存関係の変更からライブラリを守ることができる。&amp;lt;br&amp;gt;
しかし、新しいライブラリを追加したときや、ワイルドカードを使用できないときなどはinclude/excludeとrelocationの設定を正しく行わなければ実行時エラーを招く原因になる。&amp;lt;br&amp;gt;
あまり業務アプリケーションで使用したい機能ではないね。そんなシチュエーションは限られていると思うけど。&amp;lt;/p&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>AIでふっるいCVEの調査にあたりをつけてみる</title><link>https://www.chalkboard.me/posts/ai-cve-challenge/</link><guid isPermaLink="true">https://www.chalkboard.me/posts/ai-cve-challenge/</guid><description>生成AIを使用して、AIが学んでいそうにないふるいCVE(脆弱性)の調査をやってみました。</description><pubDate>Wed, 18 Sep 2024 12:21:18 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;h1&amp;gt;今回の試み&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;最近よくLLM周りのツールを色々触っているのですが、新規開発ばかりに利用して、既存改修などではあまり活用できていません。(Cursorの力は借りていますが)&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;そこで、今回はOSS絡みで調査が必要になっている古い脆弱性「CVE-2015-5237」について、生成AIを使用しながら調査してみたいと思います。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;事前情報&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;CVE-2015-5237は &amp;lt;a href=&quot;https://github.com/protocolbuffers/protobuf/issues/760&quot;&amp;gt;https://github.com/protocolbuffers/protobuf/issues/760&amp;lt;/a&amp;gt;で2015年に報告されたバッファオーバーフローに関する古い脆弱性です。&amp;lt;br&amp;gt;
大元のgoogle/protobufは当時様々なOSSが採用していたこともあり、影響としては大きなものであったようです。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;ただ、2015年当時の脆弱性ということもあって、あまり詳しい情報はやり取りがありません。google/protobufの実装は色々あるのですが、C++の話はしていますが他のクライアントでどうなのか不明です。&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;脆弱性検知ツールでの扱い&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&quot;https://security.snyk.io/vuln/?search=CVE-2015-5237&quot;&amp;gt;snyk&amp;lt;/a&amp;gt;において、C++とPHPに脆弱性を認めていますが、Javaの脆弱性はかなり低い評価になっています。(Redhatのスコアが低いためと見られる)&amp;lt;br&amp;gt;
この点についてなぜそうなのか記録が残っていません。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;つまり、Web上にはたいした情報が転がっていないという状況です。&amp;lt;/p&amp;gt;
&amp;lt;h1&amp;gt;調査の試み&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;まず、検索AI Perplexityを試してみましたが、これは惨敗か、、と思いきや下記を見つけてくれました。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&quot;https://security.snyk.io/vuln/SNYK-JAVA-COMGOOGLEPROTOBUF-173761&quot;&amp;gt;https://security.snyk.io/vuln/SNYK-JAVA-COMGOOGLEPROTOBUF-173761&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;最初、SnykのDBを見たときは前述の通り、javaには低いスコアしかないなあ、と思ったのですが、どうやらUIが悪く、全部表示されていない上にページングもできないようです。&amp;lt;br&amp;gt;
Mavenで絞った場合に限り上記を確認できました。Javaでもハイスコアとなっています。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;コードベースの調査&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;次に、v2.4.1のprotobufをダウンロードして、Cursorで質問しました。この際に使用したLLM modelはclaude3.5 sonnetと割と強めのAIを選定しています。&amp;lt;br&amp;gt;
質問の際には &amp;lt;code&amp;gt;Codebase Answers&amp;lt;/code&amp;gt; を使用しています。  この機能では、開いているファイルだけでなく、質問内容から内蔵のベクトルDBにベクトル化されているソースコードを検索し、必要そうなファイルをLLMに渡してくれます。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;以下、全文を掲載します。&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;Q. 初期情報を与えて質問する&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;このプロジェクトはCVE-2015-5237: Integer overflow in serialization が報告されたprotobufです。&amp;lt;br&amp;gt;
下記のIssueに書かれている脆弱性が埋め込まれているコードを特定してください&amp;lt;/p&amp;gt;
&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;int is used to express the size of serialized messages. If the size exceeds 4 GiB, the application may allocate a buffer which is too small, or protobuf itself does this, in google::protobuf::MessageLite::SerializeToString. This lead to a heap buffer overflow, which may be exploitable for code execution in some cases.
It has been suggested that serialization of messages larger than 2 GiB is unsupported. But there is no good way for an application to ensure that the limit is not exceeded accidentally, without imposing rather draconian limits. To some degree, this is an gets-style interface.
Right now, this is more or less harmless because the message sizes involved are substantial. But this will change over time. My worry is that it will be difficult to fix this because some of the overflowing computations end up in generated *.pb.cc files, so the eventual fix will not be a simple library update.
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;h3&amp;gt;A. 回答&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;この脆弱性は主にメッセージのシリアライズ処理に関連しています。特に重要な部分は以下のコードブロックにあります:&amp;lt;/p&amp;gt;
&amp;lt;pre&amp;gt;&amp;lt;code class=&quot;language-229:258:src/google/protobuf/message_lite.cc&quot;&amp;gt;  GOOGLE_DCHECK(IsInitialized()) &amp;lt;&amp;lt; InitializationErrorMessage(&quot;serialize&quot;, *this);
return SerializePartialToCodedStream(output);
}&lt;/p&gt;
&lt;p&gt;bool MessageLite::SerializePartialToCodedStream(
io::CodedOutputStream* output) const {
const int size = ByteSize();  // Force size to be cached.
uint8* buffer = output-&amp;gt;GetDirectBufferForNBytesAndAdvance(size);
if (buffer != NULL) {
uint8* end = SerializeWithCachedSizesToArray(buffer);
if (end - buffer != size) {
ByteSizeConsistencyError(size, ByteSize(), end - buffer);
}
return true;
} else {
int original_byte_count = output-&amp;gt;ByteCount();
SerializeWithCachedSizes(output);
if (output-&amp;gt;HadError()) {
return false;
}
int final_byte_count = output-&amp;gt;ByteCount();&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (final_byte_count - original_byte_count != size) {
  ByteSizeConsistencyError(size, ByteSize(),
                           final_byte_count - original_byte_count);
}

return true;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}
}
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;このコードブロックでは、&amp;lt;code&amp;gt;SerializeToString&amp;lt;/code&amp;gt;メソッドが実装されています。ここで、メッセージのサイズを&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;型で扱っているため、4GiBを超えるサイズのメッセージをシリアライズしようとすると整数オーバーフローが発生する可能性があります。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;また、以下のコードブロックも関連しています:&amp;lt;/p&amp;gt;
&amp;lt;pre&amp;gt;&amp;lt;code class=&quot;language-499:522:src/google/protobuf/io/coded_stream.cc&quot;&amp;gt;  const void* void_buffer;
int buffer_size;
if (NextNonEmpty(input_, &amp;amp;void_buffer, &amp;amp;buffer_size)) {
buffer_ = reinterpret_cast&amp;lt;const uint8*&amp;gt;(void_buffer);
buffer_end_ = buffer_ + buffer_size;
GOOGLE_CHECK_GE(buffer_size, 0);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (total_bytes_read_ &amp;amp;lt;= INT_MAX - buffer_size) {
  total_bytes_read_ += buffer_size;
} else {
  // Overflow.  Reset buffer_end_ to not include the bytes beyond INT_MAX.
  // We can&apos;t get that far anyway, because total_bytes_limit_ is guaranteed
  // to be less than it.  We need to keep track of the number of bytes
  // we discarded, though, so that we can call input_-&amp;amp;gt;BackUp() to back
  // up over them on destruction.

  // The following line is equivalent to:
  //   overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX;
  // except that it avoids overflows.  Signed integer overflow has
  // undefined results according to the C standard.
  overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size);
  buffer_end_ -= overflow_bytes_;
  total_bytes_read_ = INT_MAX;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;このコードでは、バッファサイズの計算が行われていますが、&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;型を使用しているため、同様に整数オーバーフローの問題が発生する可能性があります。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;これらのコードブロックは、大きなメッセージをシリアライズする際に整数オーバーフローを引き起こし、結果としてバッファオーバーフローを引き起こす可能性があります。これは、メモリ破壊や潜在的なコード実行の脆弱性につながる可能性があります。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;修正するには、これらの部分で64ビット整数型を使用するか、メッセージサイズに上限を設けるなどの対策が必要です。また、生成された*.pb.ccファイルにも影響を与える可能性があるため、単純なライブラリの更新だけでは解決できない可能性があります。&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;Q. 他のパッケージへの影響を聞く&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;javaディレクトリ以下にあるprotobuf-javaにこの影響がどう関わるか調べてください&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;A. 追加の回答&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;protobuf-javaにおけるCVE-2015-5237の影響を調査しました。この脆弱性は主にメッセージのシリアライズ処理に関連しています。javaディレクトリ以下の関連するコードを確認したところ、以下の点が重要です：&amp;lt;/p&amp;gt;
&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;MessageLite.javaファイル:&amp;lt;br&amp;gt;
このインターフェースはシリアライズメソッドを定義しています。特に &amp;lt;code&amp;gt;toByteString()&amp;lt;/code&amp;gt; メソッドが関連しています。&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;pre&amp;gt;&amp;lt;code class=&quot;language-90:97:java/src/main/java/com/google/protobuf/MessageLite.java&quot;&amp;gt;  ByteString toByteString();&lt;/p&gt;
&lt;p&gt;/**&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Serializes the message to a {@code byte} array and returns it.  This is&lt;/li&gt;
&lt;li&gt;just a trivial wrapper around&lt;/li&gt;
&lt;li&gt;{@link #writeTo(CodedOutputStream)}.
*/
byte[] toByteArray();
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;ol start=&quot;2&quot;&amp;gt;
&amp;lt;li&amp;gt;AbstractMessageLite.java:&amp;lt;br&amp;gt;
このクラスは &amp;lt;code&amp;gt;toByteString()&amp;lt;/code&amp;gt; メソッドを実装しています。ここでメッセージサイズの計算と実際のシリアライズが行われます。&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;pre&amp;gt;&amp;lt;code class=&quot;language-47:58:java/src/main/java/com/google/protobuf/AbstractMessageLite.java&quot;&amp;gt;  public ByteString toByteString() {
try {
final ByteString.CodedBuilder out =
ByteString.newCodedBuilder(getSerializedSize());
writeTo(out.getCodedOutput());
return out.build();
} catch (IOException e) {
throw new RuntimeException(
&quot;Serializing to a ByteString threw an IOException (should &quot; +
&quot;never happen).&quot;, e);
}
}
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;ol start=&quot;3&quot;&amp;gt;
&amp;lt;li&amp;gt;CodedOutputStream.java:&amp;lt;br&amp;gt;
このクラスはバイトストリームへの書き込みを担当します。特に &amp;lt;code&amp;gt;computeMessageSizeNoTag()&amp;lt;/code&amp;gt; メソッドがメッセージサイズの計算に関与しています。&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;pre&amp;gt;&amp;lt;code class=&quot;language-727:730:java/src/main/java/com/google/protobuf/CodedOutputStream.java&quot;&amp;gt;  public static int computeMessageSizeNoTag(final MessageLite value) {
final int size = value.getSerializedSize();
return computeRawVarint32Size(size) + size;
}
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;ol start=&quot;4&quot;&amp;gt;
&amp;lt;li&amp;gt;CodedInputStream.java:&amp;lt;br&amp;gt;
このクラスはサイズ制限を設定するメソッドを持っています。これは大きすぎるメッセージの処理を防ぐために使用されます。&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;pre&amp;gt;&amp;lt;code class=&quot;language-578:586:java/src/main/java/com/google/protobuf/CodedInputStream.java&quot;&amp;gt;  public int setSizeLimit(final int limit) {
if (limit &amp;lt; 0) {
throw new IllegalArgumentException(
&quot;Size limit cannot be negative: &quot; + limit);
}
final int oldLimit = sizeLimit;
sizeLimit = limit;
return oldLimit;
}
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;これらのコードは、メッセージのシリアライズとデシリアライズ、およびサイズの計算と制限に関連しています。CVE-2015-5237の脆弱性は、4GiBを超えるサイズのメッセージを処理する際に整数オーバーフローが発生する可能性があるというものです。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Java実装では、int型（32ビット）を使用してメッセージサイズを扱っているため、この問題が発生する可能性があります。特に、&amp;lt;code&amp;gt;CodedOutputStream.computeMessageSizeNoTag()&amp;lt;/code&amp;gt;メソッドや&amp;lt;code&amp;gt;AbstractMessageLite.toByteString()&amp;lt;/code&amp;gt;メソッドでのサイズ計算において、大きなメッセージを扱う際にオーバーフローが起こる可能性があります。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;この脆弱性を修正するためには、メッセージサイズの計算と制限において64ビット整数を使用するか、明示的にサイズチェックを行うなどの対策が必要です。また、&amp;lt;code&amp;gt;CodedInputStream.setSizeLimit()&amp;lt;/code&amp;gt;メソッドを適切に使用して、処理するメッセージサイズに上限を設けることも重要です。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;評価&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;まず、最初の質問で返されたC++のコードはまさしく対象のコードでした。これはまだ、Issueの中に示唆があるので見つけられるのもわかりますが、解説付きで探してくれるのは大変ありがたいです。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;次の質問は、javaパッケージに与える影響を水平に質問しただけですが、こちらも的確にシリアライズを行っている関数と、int型で定義された計算フローを見つけてくれました。&amp;lt;br&amp;gt;
この実装からして、C++だけでなくjavaでも間違いなく4GBを超えるメッセージを取り扱うとバッファオーバーフローを引き起こせることがわかります。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;なぜJVMで発生するバッファオーバーフローがハイスコアに評価されているのか疑問は残りますが、下記2点がわかるまで30分たらずでした。ニンゲンの手だけではこうは行かないでしょう。&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;セキュリティベンダーでC++もjavaもハイリスクに分類されている&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;コードベースでみて、C++、Javaどちらでも発生しうる&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>2024-08-30</title><link>https://www.chalkboard.me/posts/diary-2024-08-30/</link><guid isPermaLink="true">https://www.chalkboard.me/posts/diary-2024-08-30/</guid><description>2024-08-30 日記</description><pubDate>Fri, 30 Aug 2024 02:01:21 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;h1&amp;gt;Topics&amp;lt;/h1&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;台風が来ているけど帰省する話&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;AIの利活用の話&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;h1&amp;gt;台風が来ているけど帰省する話&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;1ヶ月前から、8/29-9/1にお盆に代わって帰省することを考えていた。&amp;lt;br&amp;gt;
妻もそのつもりでスケジュールを組んでいたので、今さら帰らないという選択肢も取りづらい。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;しかし、8/28日段階で想定できる台風の強さと経路はなかなかのもので、大阪から松山への移動はともかく、9/1段階で伊丹空港への影響が強く懸念される状況にあった。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&quot;https://ik.imagekit.io/0vbjzxbih/7163c510-3f58-41a8-b7c3-4bad9b094588/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%882024-08-309.52.53.png&quot; alt=&quot;スクリーンショット2024-08-309.52.53.png&quot;&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;a href=&quot;https://weathernews.jp/s/topics/202408/290275/&quot;&amp;gt;引用&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;この台風10号はうまく偏西風に乗れておらず、東西を高気圧に挟まれて進路に影響を受ける状態であり、時間単位で気象予報に変化が見られるような状況だったので、3,4日先の天気の見通しが全く立たない。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;移動手段&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;大阪と愛媛の間を移動する手段はいくつかある。&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;飛行機
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;ANA、JAL共にあるがANAがメインで伊丹空港を使用する。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;新幹線・電車
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;広島あたりまで新幹線で行ってから、電車で四国に乗り入れるルート。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;陸路
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;自家用車 or 高速バス&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;船
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;オレンジフェリーが東予港と大阪港を結んでいる。夜に出て朝着く感じ。&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;p&amp;gt;しかし、空路と海路は台風にすこぶる弱いのである。&amp;lt;br&amp;gt;
新幹線と電車の併用と陸路は大して所要時間に差はない。&amp;lt;br&amp;gt;
まして、自分は自家用車を持っているので陸路以外の選択肢はなかった。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;陸路の場合、瀬戸大橋や明石大橋が台風の影響を受けるが、滅多なことで通行止めには至らない。それよりも、問題になるのは1歳になったばかりの子供の存在だった。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;空路は飛行時間1時間未満、海路は一泊なのでそこまでストレスもないが、陸路で帰る場合の拘束時間はトータル6時間を超える。&amp;lt;br&amp;gt;
その間チャイルドシートに縛っておくのはまあ不可能なので、必然的に一泊しながらの移動となる。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;乳児連れでの陸路長距離移動&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;一泊することを前提にすると、泊まれる宿は限られてくる。行けるところまで行って、そのへんで泊まろう、というムーブを夜にやる場合、普通のビジネスホテルなどに泊まることはできない。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;なので必然的に宿泊先はレジャーホテルになる。注意点としては、半数以上のレジャーホテルは18歳未満の立入禁止であり、子供を入れるわけにはいかないということだ。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;こういうときにはファインガーデンが有望だが、個人的に最近のファインガーデンはやたらとたばこ臭い部屋が多くて辟易しているので、何か別の選択肢を見つけたい。&amp;lt;br&amp;gt;
（実際、今回泊まったファインガーデン岡山もかなりタバコ臭かった。つらみ）&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;到着しました&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;3h/3hに移動が分割されるのでそういう意味でも楽な経路だった。日を選べば宿泊費も1万円以下に収まるので飛行機と駐車場を併用するよりは経済的。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;9/1の台風の影響がどうなるかわからないが、影響が少なければ海路が使えるはず。&amp;lt;br&amp;gt;
陸路でもいいが、その場合はまた宿泊先を探さないといけない…。&amp;lt;/p&amp;gt;
&amp;lt;h1&amp;gt;AIの利活用の話&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;OpenAIやClaudeのAPIを中心としていた開発周りのAI利活用も、Vercelのv0、Cursorエディタ、Create.xyz、有名どころのツールに付随するようになったAIアシスタントなど広がりを見せている。&amp;lt;br&amp;gt;
完全に群雄割拠の状態にあるので、これが定まってくるにはもう暫く掛かると思うが、莫大なお金を背景に安定したリリースを続けるOpenAIに一日の長があるようには見えている。&amp;lt;br&amp;gt;
(画像生成まわりの話とかはよくわからないが…)&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;AIを活用するエンジニアが増えるのは間違いないので、そこと関わる側の立場としては、作成されたコードに責任を持っているエンジニアであり続けることが重要だろうと思う。&amp;lt;br&amp;gt;
AIで作って、問題があったらAIに直してもらって、というトライアンドエラーは残念ながら本番環境には通用しない。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;何かしら問題があったならそれはもうビジネスに影響が出ているわけだが、その開発を続ける限り再発防止策のとりようがない。&amp;lt;br&amp;gt;
AIは責任を持ってくれないので使う側が責任を持ち続けるしかない。要は、すべてのAIが作成したコードは、作成した当事者が完全に説明可能である必要がある。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;AIに使われるエンジニアは使い捨てのなにかしか作れずあまり価値がない。うまく付き合うのが大事になるだろう。&amp;lt;/p&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>ブログのシステムを刷新しました</title><link>https://www.chalkboard.me/posts/blog-renewal/</link><guid isPermaLink="true">https://www.chalkboard.me/posts/blog-renewal/</guid><description>wordpressのブログから、HeadlessCMSとAstroを使用したブログにシステムを刷新しました</description><pubDate>Sat, 17 Aug 2024 13:10:28 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;h1&amp;gt;前書き&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;AWSでWordpress + GraphQL + Next.jsによるSSGを行っていたのですが、どうやっても微妙にコストが出続けるため、思い切って構成を大幅に変更し、SaaSを多用するようにしました。&amp;lt;br&amp;gt;
今回の変更により、ほぼ0円でブログシステムの運用が可能になったはずです。&amp;lt;/p&amp;gt;
&amp;lt;h1&amp;gt;システム構成&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;img src=&quot;https://ik.imagekit.io/0vbjzxbih/3fc59470-cb17-4faa-bffb-ab1a90d15198/system.png&quot; alt=&quot;system.png&quot;&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;SaaS&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Headless CMSにはNewtを採用しています。これは、公式が多数のチュートリアルで他のシステムやフレームワークとの連携を公開しているから採用しやすいのが理由でした。&amp;lt;br&amp;gt;
また、AWS S3やCDNとの連携も簡単であり、通信量の大部分を占めるはずの画像をCDN経由にすることで、よりお得にNewtが使えるようになるのは本当に親切だと思います。&amp;lt;br&amp;gt;
Newtは画像配布のSaaSとしてImgixとImageKitの2社をサポートしています。画像の配布だけならどちらを選んでもまず無料枠に収まるのではないでしょうか。&amp;lt;br&amp;gt;
アプリケーションの公開にはVercelを使用しています。NewtのWebhookとの相性、Astroとの相性などが理由です。Newtに記事を公開してから数分でデプロイが完了するのでSSGをしている感覚があまりありません。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;Framework&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Astroを採用しました。Next.jsやNuxt.jsもSSGは可能ですが機能的に重たすぎ、GoogleAnalyticsなどとの外部スクリプトの統合がビミョーに特別対応が必要だったりして取り回しが悪いところを全て解決できる点が魅力です。SSG中心に考えるならAstroでいいじゃんというのが今回やってみての感想でした。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;また、Astroはデザインテンプレートが充実しています。私のようにデザインの能力が皆無な人間でも、デザインテンプレートを拝借し、データの導線だけ自分で実装してしまえば良いデザインに相乗りできてしまうのは本当に良い体験でした&amp;lt;/p&amp;gt;
&amp;lt;h1&amp;gt;Newtの話&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;他のHeadless CMSを触ったわけではないので比較はできないのですが、少なくともWordpressをAPI経由で使うよりはずっと建設的な開発が可能です。&amp;lt;br&amp;gt;
Newtはデータモデルを自分で定義、リレーションさせることができます。記事というデータモデル、タグというデータモデル、カテゴリというデータモデル、のように。&amp;lt;br&amp;gt;
それぞれのモデルにはどんなデータが紐づくかを定義し、モデルとモデルの間のリレーションも定義していきます。&amp;lt;br&amp;gt;
投稿フェーズではそれに沿って入力フォームを埋めたらよいだけなので、GUIは難しくありません。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;クライアントの話&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Newtが提供するNode.js向けのクライアントはいくつかのAPIを提供してくれますが、その構造はいたってシンプルになっています。&amp;lt;br&amp;gt;
おそらく内部的にはGraphQLが採用されているのかな、と思いますが、APIの本数でどうこうするよりは与えるパラメータによって柔軟にフィールドの取得ができます。&amp;lt;br&amp;gt;
開発のおすすめとしては、適当にAPIを叩いてJSONを取得し、そのJSONをOpenAIなどに貼り付けてTypescript用の型を生成してもらってマッピングするとあとが楽です。&amp;lt;/p&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>任天堂の中途採用面接に挑んで負けた話</title><link>https://www.chalkboard.me/posts/%E4%BB%BB%E5%A4%A9%E5%A0%82%E3%81%AE%E4%B8%AD%E9%80%94%E9%9D%A2%E6%8E%A5%E3%81%AB%E6%8C%91%E3%82%93%E3%81%A7%E8%B2%A0%E3%81%91%E3%81%9F%E8%A9%B1/</link><guid isPermaLink="true">https://www.chalkboard.me/posts/%E4%BB%BB%E5%A4%A9%E5%A0%82%E3%81%AE%E4%B8%AD%E9%80%94%E9%9D%A2%E6%8E%A5%E3%81%AB%E6%8C%91%E3%82%93%E3%81%A7%E8%B2%A0%E3%81%91%E3%81%9F%E8%A9%B1/</guid><description>2020-08-21に任天堂さんのエンジニア向け中途採用面接に応募した記録です</description><pubDate>Sat, 17 Aug 2024 06:14:21 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;2020-08-21 の再掲です。
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;なかなか楽しかったので、経緯をまとめつつ、どんなことをしたのか受験者のマナーの範囲で書き記したいと思います。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;きっかけ&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;自分のキャリアプランに悩みがあったので、履歴書を登録してどんなところから声をかけてもらえるだろうか、今の自分にどれだけの可能性があるだろうか、と思ってビズリーチに登録しました。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;そこで、たくさんの企業から面接どうですか、という声をいただき、関西で就業可能で興味があるものを実際に受けさせていただいていました。&amp;lt;br&amp;gt;
(結局、条件や面接過程で辞退したり、落ちたりして現職のままですが)&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;ある時、唐突に任天堂からオファーが届きました。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;オファーの内容&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;そこには、ある種ユニークな誘い文句(僕のキャリアに関するコメント)と、ゲームエンジニアだけを任天堂が求めているわけではないのだ、という旨が書かれていました。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;言われてみれば当然なのですが、ぼんやり任天堂といえばゲームだし、それ関連の知識を持ってない自分には全く関係ない企業だと言う先入観があったので、とても驚いたのを覚えています。&amp;lt;br&amp;gt;
自分がオファーを受けたのは、ネットワーク、またはツール開発を担当する領域の部門であり、ゲームの裏側や、開発そのものを支えるような部門でした。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;(ちなみに年収は応相談となっていました)&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;1回目の面談&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;とはいえ、自分が任天堂に入社したとして活躍できる、役に立つイメージが湧くわけではなかったので、面談という形でお時間を頂戴しました。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;後になって知ることですが、僕の面談を担当いただいた方はゲームキューブや、ゲームキューブの初期のゲームソフト開発に関わった方であったようで、検索するといくつかの記事が出てきました。&amp;lt;br&amp;gt;
子供の頃遊んでいたアレらを作った人なのか、と思うと尊敬の念を禁じえません。とても良い経験になりました。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;面談では、具体的な業務内容や、知っておけば良い知識などに関してお話を聞きました。曰く、オンラインゲームを支える技術、という本の冒頭を理解しておけば良い、というお言葉を頂戴しましたので自分はそれに従いました。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;気づき&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;ここでわかったことは、Webのネットワークとゲームのネットワークの知識は根底を同じくする、ということです。&amp;lt;br&amp;gt;
なので、たくさん新たに勉強しなければなりませんが、既に戦える道具もまた多く持っているのです。&amp;lt;br&amp;gt;
(具体的には任天堂がAWSのイベントなどで発表したネットワークがらみのお話などを拝見すると良いです。Webをかじっている人間でもちゃんと読めるはず)&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;それ当然じゃん、と思うところなのですが、あまりにもゲーム界隈のネットワークのイメージがつかなすぎて、全然同じという感覚が持てていませんでした。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;違いは、ゲームが関わる世界で必要とされるネットワーク接続は、その多くがステートフルなものである、というところです。我々Webに携わる人間はステートレスな世界に生きていますが、それとは真反対です。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;面白そうだな、という理由だけで&amp;lt;br&amp;gt;
ここまでで、大体意思は固まっていました。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;企業にも仕事にも興味あるし、面接内容にも興味あるぞ、と。&amp;lt;br&amp;gt;
実際転職するかどうかなんてのは、受かってから考えればいいか、という形でした。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;後に、志望理由を問われて自分は無邪気に下記のように答えています。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;一番の理由は面白い仕事ができそうだからです。&amp;lt;br&amp;gt;
ユーザの心を直接動かすようなものを作っていくという仕事はそうあるものではないし、ネットワークを通じて新しいコミュニケーションの形を作っていける機会があるというのは本当に面白そうです。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;第一関門 ポートフォリオ評価&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;おそらく合否にそこまで関わっていない気がしますが、プログラミングクイズと、今までに作ったサンプルアプリケーションの提出を依頼されます。&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;サンプルアプリケーション&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;自分は2,3個提出しました。本当はもうちょいまともなシステムが1個合ったのですがアングラだったので出せませんでした…。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Sinatraで構築されたTwitterAPIを利用するシステム。&amp;lt;br&amp;gt;
フォローしているニュースアカウントの投稿の、評判がいいIT関連ニュースだけをSlackに通知するもの&amp;lt;br&amp;gt;
FrontからAPIコールするAPIのサンプルアプリケーション。docker-composeのサンプルでつくっており、nginxのプロキシを使ってCORSを避けつつ複数のアプリケーションを呼んでる感じ&amp;lt;br&amp;gt;
プログラミングクイズ&amp;lt;br&amp;gt;
ちょっと歴のあるプログラマなら下記のサイトを知っているでしょう。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&quot;http://cp1.nintendo.co.jp/&quot;&amp;gt;http://cp1.nintendo.co.jp/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;任天堂が昔、採用に使ったCodePuzzleです。&amp;lt;br&amp;gt;
これに関してある条件の元、Puzzleを解いた成果物を提出する必要があります。&amp;lt;br&amp;gt;
競技プログラミングなどと比べてもまさにPuzzleという難しさがあります。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;なお、面接でこれらに触れられることはありませんでした!&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;第二関門 一次面接(技術面接)&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;任天堂の面接官の特徴かもしれませんが、とても良く履歴書や職務経歴書を読み込んでくれているように感じます。&amp;lt;br&amp;gt;
自分は結構な企業のいろんな段階の面接を経験しましたが、その中でもトップクラスに丁寧な面接をしてくれます。(悪い記憶が本当にない)&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;1次面接のメインは技術に関する知識とコーディング能力です。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;口頭試問では、知っている言語の特性、フレームワークの特性、ネットワーク、データベース、セキュリティ(暗号、Web)などに関して幅広く質問されます。&amp;lt;br&amp;gt;
ど忘れしていると、ヒントを出してくれるので、なんとか細かい点も思い出せました。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;コーディングテストは、そこまで難しいものではありません。競技プログラミングの初級ランクを広く抑えておけば大丈夫と思います。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;ただ、コーディングしている様子を見られながらなので妙な焦りから問題文の意図をよく読み違えました。落ち着いて読みましょう…。&amp;lt;br&amp;gt;
コロナ下でしたので、自分はリモートで画面共有でしたが、普段は会議室で行われるそうです。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;(再帰処理、嫌いなんだよな…。)&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;第三関門 二次面接(技術/人事面接)&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;自分の場合ちょっとイレギュラーなのかもしれませんが、前半技術面接、後半人事面接という形で進行しました。&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;技術面接&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;ここでは、システム構成に関する例題とその解決のシミュレーションをしていきます。AWSの面接に似ています。&amp;lt;br&amp;gt;
1対2の面接になります。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;雰囲気はそのへんのWeb系企業と同様で、特有なラフな雰囲気でした。僕は任天堂に保守的なイメージを持っていたので(面接はスーツだろうな、と思う程度には)これは意外でした。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;小さなシステムから要件を叶えていき、面接官が新たな要件や障害を加え、それの対応を見ていく形です。&amp;lt;br&amp;gt;
30分超行いました。正直、反省点が多かったです…。ぱっといい解決策出ないですね。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;少なくともリードレプリカなDBを置く構成や、レプリケーションにつよいNoSQLなDBを使う構成、日本だけでなく、色んな国の間で使われる前提のシステム構成などを知っておかないとクリアできない例が出てきます。&amp;lt;br&amp;gt;
ネットワークがブツブツ途切れるような環境にデータを送るには、という前提には本当に困りました…。P2Pネットワーク的な発想がぱっと出る人どれくらいいるでしょうね。&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;人事面接&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;技術の方が退出、人事の方が入出され、ここから1対4になります。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;技術の方々がある程度ラフな雰囲気だったのに対し、人事の方はThe任天堂という感じで、まさしく自分のイメージしていた保守的な任天堂の姿でした。&amp;lt;br&amp;gt;
今までのキャリアに関して担当の方が一通り紹介してくれます(このシステム、他で見たことがない)&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;その後、志望理由を始め、色々根掘り葉掘りされます。&amp;lt;br&amp;gt;
自分は転職が複数あったのでその理由の深堀りもかなりありました。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;全体として、一般的な人事面接ですが、質問一つ一つが鋭いので、生半可に答えを用意していると死ぬでしょう。&amp;lt;br&amp;gt;
本心で答えられるとベストです。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;あ、ちなみに好きなゲームは？のようなゲームに関する設問は一切でてきませんでした。&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;第四関門 最終面接&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;2次面接から1ヶ月以上経ってます。なるほど、これが任天堂のやり方か…。（担当者の方も合否決まるまでめっちゃ長いとはいってました）&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;おそらく、この3次面接が決まった段階では、スケジュール調整されて見えないライバルが複数横に並んでいます。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;コロナ下でしたが、最終面接は京都本社で行われました。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;面接前にアンケートを記入するのですが、Paizaのスコア記入欄がありました。&amp;lt;br&amp;gt;
ちょっと意外です。AtCoderやLeetCodeじゃないんだ、となりました。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;最終面接は、1対7です。歴戦のツワモノと思われる方々と進行の方がお一人います。&amp;lt;br&amp;gt;
質問のベースは2次面接の人事面接と同じですが、ツワモノがそれだけ揃っているので、疑問点とかあればガンガン質問が来ます。&amp;lt;br&amp;gt;
比較的現職におけるポジション、仕事(役割)、リスクアセスメント、ストレス対処、失敗経験の深堀り、性格の傾向に絡む質問が多かったように思います。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;印象的だったのは、自分が仕事で大事にしているものなどを話すと、それに対して「たしかにそれは大事だね」等感想を述べてくれたりするところです。&amp;lt;br&amp;gt;
他社では顔色を変えない面接官を多く見ました。それに比べ、これだけ多人数な面接をされても全く圧迫感がありませんでしたし、何なら少し楽しい気持ちで去れたのは初めてでした。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;この一連の面接を通して、自分のキャリアを見直せたところもあり、良い経験になりました&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;合否報告&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;10日後にメールできました。&amp;lt;br&amp;gt;
要約すると「採用人数少ないんだ、今回はごめんね」的なことが書かれてました。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;なるほど、誰か僕より強いやつがいたんだろうな、と思えるので、特にフィードバックがなくても納得の行く良い文面でした。お祈りよりずっといい。(事実はどうあれ)&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;まとめ&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;選考期間はおよそ3ヶ月強&amp;lt;br&amp;gt;
任天堂はゲームに詳しくなくてもオファーをくれる&amp;lt;br&amp;gt;
任天堂の面接はめっちゃ好印象&amp;lt;br&amp;gt;
思ったよりコーディングテストはイージーだが、口頭試問の難易度は高め&amp;lt;br&amp;gt;
自分はとても印象が良かったので、ぜひ機会があれば挑んでいただきたいなーと思います。&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;なお交通費は少しだけ黒字で出してくれました。&amp;lt;/p&amp;gt;&lt;/p&gt;
</content:encoded></item></channel></rss>