7 ポイント 投稿者 GN⁺ 2023-07-29 | 3件のコメント | WhatsAppで共有
  • RPC cancellation のオプトイン方式が context.allowCancellation() 呼び出しから、スキーマの allowCancellation アノテーションへ変更
  • context.allowCancellation() を使っていないユーザーは、1.0 へのアップグレード時に変更不要で、cancellation はデフォルトで引き続き無効
  • 1.0 は 長期サポート (LTS) 性格のリリースで、1.0 branch に bugfix を長期的に backport する計画
  • Cap’n Proto RPC の性能改善として、RPC 実装と KJ I/O framework のメモリ割り当て削減、一部 RPC protocol message の省略、小さな message の buffering 改善による syscall 削減を適用
  • KJ は MacOS と BSD 系で非同期 I/O 処理に kqueue() を使用し、従来のより低速な poll() ベース方式から変更
  • KJ HTTP client と server 実装が CONNECT method をサポート
  • capnp::RevocableServer が追加され、wrapper が lifetime を制御しないオブジェクトを RPC wrapper として export する際、use-after-free bug の回避を助ける構造を提供
  • 2.0 開発は新しい v2 branch で進め、master branch は既存プロジェクトが変更で中断しないよう 1.0 LTS branch にする計画
  • 2.0 の計画は serialization format や RPC protocol の後方互換性を壊す変更ではなく、C++ API と KJ 中心の変更であり、他言語で書かれたアプリケーションには影響しない
  • 2.0 の計画には、C++20 または C++23 compiler の要求、C++20 coroutine の使用、exception disabled と no-RTTI mode のサポート終了、kj::Maybekj::AsyncOutputStream API の変更などが含まれる

3件のコメント

 
alstjr7375 2023-07-29

おお..ついにこれが

 
GN⁺ 2023-07-29
Hacker News の意見
  • Cap'n Proto と Sandstorm コミュニティに、とても悲しい知らせを伝えます。Go 実装の中心的な貢献者だった Ian Denhardt(HN の zenhack)が数週間前に急逝しました。この3年間、彼とは多くの共同作業を重ね、友人にもなっていたため、大きな喪失感を覚えています
    事実上プロジェクトリードとして、これから Ian の大きな穴を埋めなければならないので、プロジェクトに貢献できる方がいれば切実に助けが必要です。C++、Rust など他の実装の貢献者やメンテナーであれば、ぜひ連絡を取りたいです。Ian の仕事を引き継ぐには、非常に優秀な人たちと一緒に取り組む必要があります
    RIP Ian、一緒に働きながら本当に多くを学びました。連絡先: https://github.com/lthibaulthttps://matrix.to/#/#go-capnp:matrix.org、Telegram @lthibault、gmail louist87

    • 突然亡くなった人たちを何度か見てきましたが、本当に魂が打ち砕かれるような出来事です。そうしたことが起きるたびに、人生がどれほど脆いものか、すべてがどれほど一瞬で変わり得るかを思い知らされます
      将来から目をそらしているわけではありませんが、人生の小さなことをもっと楽しもうと思うようになりました。Ian は多くの人に届く素晴らしい遺産を残しました。RIP Ian
    • 知らなかったので衝撃を受けています。Ian の ブログ が本当に好きだったので、とても残念です
    • @zenhack は Haskell バインディング も管理していたようです
    • 直接は知りませんでしたが、Sandstorm を復活させようとしていた最近のフォークである Tempest の取り組みを大いに尊敬していました。この知らせを共有してくれてありがとうございます
    • 本当に悲しい知らせです。Ian は多くの人にインスピレーションを与え、コミュニティ全体にとって大きな喪失となるでしょう
  • Cap'n Proto 以外にプロミス・パイプライニングを備えたプロトコルがこれほど少ないことに驚きます。思い浮かぶ別の例は 9p だけですが、9p は汎用プロトコルではありません
    https://capnproto.org/news/2013-12-13-promise-pipelining-cap...

    • 素晴らしい機能ではありますが、クエリを明示的にまとめる方式に比べると、バックエンドを最適化しにくそうです。たとえば、パイプライン化された複数の個別 RPC 呼び出しよりも、単一の SQL クエリで完結するカスタム RPC 呼び出しのほうがよい場合があります
      それでも、もっと広く使われてもよさそうな機能です
    • パイプライニングはよくないアイデアです。オブジェクトインスタンスを実体化するため、堅牢な実装がはるかに難しくなります。もはやステートレスな呼び出しではなく、特定のオブジェクトインスタンスに対して関数を実行する構造になります
      たとえばクライアント Joe が Service A を呼び出し、その約束された結果を Service B に渡すと、Service B はそのプロミス結果を得るために Service A へリモート呼び出しを行う必要があります
      この時点でセキュリティ境界は一気に複雑になります。委譲モデルをどうするかも問題ですが、より深刻なのはバックプレッシャーが失われる点です。クライアント Joe が Service A に何千もの呼び出しを作り、まだ実体化されていない結果を Service B に渡すと、Service A が DDoS のように殺到し、Service B がタイムアウトする可能性があります
    • 9p にプロミス・パイプライニングがあるとは知りませんでした。より正確には、クライアントがファイルディスクリプタを選べるので、ファイルを開いた直後にそのファイルを読むリクエストを送ることができ、open が失敗すると read も EBADF で失敗する仕組みで、これは見事です
      ただしプロミス・パイプライニングにはクライアント側の対応も必要です。ユーザーが複数の walk を発行したとき、最初の walk 応答を待たずにすべて送る 9p クライアントがあるのか気になります
      また 9p は、ファイルディスクリプタに対してのみプロミス・パイプライニングを提供します。これだけでも多くのことができますが、ディレクトリ内のすべてのファイルを読みたいなら、read を発行したあと、その read の結果に対して walk できる必要がありますが、9p はこれをサポートしていないようです。私のリモートシステムコールプロトコルライブラリである rsyscall では、実際にこれをサポートしています
    • Cap'n Proto の精神的な祖先としては、Mark Miller の E 言語とともに開発された CapTP/VatTP、別名 Pluribus があります。言葉遊びとして “unum” という仕掛けもあります。より深い系譜は彼の論文を見ればよく、そこには Barbara Liskov のプロミス・パイプライニングや、CLU の拡張である Argus の関連アイデアも出てきます
      Mark Miller は後に JavaScript のプロミス提案も書いたと記憶しています。ただし RPC 拡張は実現せず、代わりにパイプライニングとはあまり相性がよくなさそうな async/await を手にすることになりました
      E の方式で分散権限システムを作ろうとする、より最近の試みである Spritely Goblins と OCapN もパイプライニングを志向しているため、cap-talk にいれば、実際のユースケースは少なくても、似たようなプロトコルをいくつかさらに聞けるはずです
      ただし素晴らしい機能ではあっても、プロミス・パイプライニングでは実際に明示的なプロミスでプログラミングする必要があるようで、それがどれほど扱いにくくなり得るかはすでによく知られています
      反対側、つまりイベントループと協調的並行実行の「アクティブオブジェクト」側で、興味深いがあまり知られていないアイデアとしては、DCOM/COM+ の causality IDs があります。再入性を制御する手段であり、Microsoft ドキュメントの CoGetCurrentLogicalThreadId と Effective COM の CALLTYPE_TOPLEVEL_CALLPENDING に関する議論を見るとよいです。後には Win8/UWP の ASTA で新機能のように売り込もうとしていたようです
      [1] http://erights.org/elib/distrib/captp/index.html
      [2] http://erights.org/talks/thesis/index.html
      [3] https://spritely.institute/goblins/
      [4] https://github.com/ocapn/ocapn
      [5] https://groups.google.com/g/captalk/
      [6] https://learn.microsoft.com/openspecs/windows_protocols/ms-d...
      [7] https://learn.microsoft.com/windows/win32/api/combaseapi/nf-...
      [8] https://archive.org/details/effectivecom50wa00boxd/page/150
      [9] https://devblogs.microsoft.com/oldnewthing/20210224-00/?p=10...
    • Cap'n Proto のプロミス・パイプライニングが正確にどう動作するのかは分かりませんが、ディレクトリを読んでその中の全項目に stat をかけたい場合や、2 つの応答値のうち片方だけを次の呼び出しに渡したい場合が気になります
      後者は何とか可能そうですが、前者は結果リストの値の個数などに依存します
  • リリースおめでとうございます。10年越しなので本当にうれしいでしょうね。今後、ほかの言語実装にもさらに作業が入るのか気になります
    フォーマットのアイデアはとても気に入っていますが、私たちのスタックで主に使っている言語は、製品で使いたいと思えるほどサポートされていません

    • これは実際、Cap'n Proto の最大の弱点です。私がきちんと管理しているのは C++ 実装だけで、ほかの実装はさまざまなコントリビューターによるものなので、完成度や品質の水準にばらつきがあります
      残念ながら、ここで新しいことを約束するのは難しいです。Cap'n Proto の作業は、私の主プロジェクトである Cloudflare Workers ランタイムの必要性に左右されており、そこでは主に C++ を使っています。Go や Rust のサービスともやり取りしていて、それらの実装はその場では役割を果たしているようです
      つまり Cap'n Proto はオープンソースプロジェクトであり、人々の役に立ってほしいとは思っていますが、私が売ろうとしている製品ではないので、誰もが採用するようにすることへ特に注力しているわけではありません。いつもどおり、コントリビューションは歓迎します
      大きな変化があり得る一つのケースは、Cloudflare が Cap'n Proto を Workers プラットフォームの公開機能にすると決めた場合です。そうなれば、複数の言語で本当に磨き込む直接的な必要性が生まれます。時々議論はしていますが、現時点で計画はありません
    • C++ 実装を包むラッパーではなく、RPC レイヤーを直接書こうとしていた人たちはいましたが、直接得られるメリットに比べて、書き直さなければならないコードが本当に多いです
      試してみたいならやってみても構いません。人々はかなり協力的である可能性が高いです。ただ、単純に作業量が非常に多いことは知っておくべきです
  • 背景を付け加えると、Kenton は Google の社内 proto システムを何年も運用した後に退社し、自分のオープンソース版を作りました

    • おそらく彼が protobuf をオープンソースとして公開した人物でしょう
  • Cloudflare の社員で、Cap'n Proto を protobuf などの別のものではなく選ぶ判断に関わった人がいれば、どのような考慮があったのか気になります。その理由が私にとっても重要なのか、それとも巨大な規模を扱わない限り気にしなくてよいものなのかを知りたいです

    • Cloudflare が 2014年に Cap'n Proto を使った内容を扱ったブログ記事があります。私が入社する3年前です: https://blog.cloudflare.com/introducing-lua-capnproto-better...
      今でも Cloudflare のデータパイプライン、つまりエッジでログと分析を生成するシステムは、おおむね Cap'n Proto シリアライゼーションに基づいています。私はそのプロジェクトには個人的にあまり関わっていませんでした
      Cloudflare Workers の場合は、私がプロジェクトを始めたので自分のものを使った、ということです。おそらく期待している説明ではないでしょう
      それでも Cap'n Proto の RPC プロトコルは代替案よりはるかに表現力が高く、Workers Runtime のサンドボックス実装や Durable Objects のような分散システム機能の実装に大いに役立ったと思います。 https://blog.cloudflare.com/introducing-workers-durable-obje...
    • Cloudflare で働いているわけではありませんが、彼らの仕事を追っていて、ときどき性能に敏感なプロジェクトを扱っています。推測ですが、Cap'n Proto、flatbuffers、SBE などは、Avro や protobuf のようなほかのデータフォーマットとは別のカテゴリとして見ていたのだと思います
      Parquet のような列指向ではなく、レコードに近い形のデータを選び、事前のパース時間が実質 0 の形式を求めるなら、選択肢はかなり限られます。読み取り時にフィールド値を変えるならマーシャリングは発生し得ます
      https://capnproto.org/news/2014-06-17-capnproto-flatbuffers-...でこのトレードオフを扱っています
      Cap'n Proto はもともと https://sandstorm.io/ のために作られ、Kenton が Cloudflare に雇われた後に行ったその仕事は、最終的に Cloudflare Workers へつながったのでしょう
      もう一つの考慮事項: https://github.com/google/flatbuffers/issues/2#issuecomment-...
    • 私が入社して1年少し経った頃の状況をまとめると、Cloudflare はエッジから中央の地点へログを送り、顧客向け分析とエンタープライズ顧客向けのログ提供を行う仕組みを作っていました
      その全体を構築した中心的エンジニアである Albert Strasheim が有力なシリアライゼーションの選択肢をベンチマークし、Cap'n Proto が protobuf よりかなり速いという結果を得たのだと理解しています
      優れた C++ 実装があり、nginx で使えました。記憶では、少し Lua も関わっていました。利用側で使っていた Go 実装には荒い部分がありましたが、必要な中核部分は人々が直せました
      Cloudflare は常にマシンコスト効率を重視していたため、当時の性能要件を考えると自然な選択でした。データチームにいた間、Cap'n Proto はかなり扱いやすく、中央スキーマリポジトリで proto 定義を共有するやり方もうまく機能していました
    • Cloudflare Workers のリード開発者が Cap'n Proto の作者なので、選択は容易だった可能性が高いです
  • Cap'n Proto が OCapN 標準化作業に参加している点に期待しています。これが Cap'n Proto 2.0 の作業の一部になるのか気になります
    https://github.com/ocapn/ocapn

    • 残念ながら、その参加を主導していた Ian “zenhack” Denhardt が最近突然亡くなりました
      私は OCapN が好きですが、今抱えている仕事が多く、個人的にどれだけ時間を投入できるか分かりません。もっと良い知らせを伝えられればよかったのですが、私たち皆にとって悲劇的な喪失です
  • Cap'n Protoを使ったことはありませんが、プロトコルにおいて必須フィールドがなぜ問題になるのかを説明したkentonvの非常に有益なFAQ回答 [1] には感謝しています。
    protobuf 3にrequiredフィールドがなぜないのかと聞かれるたびに、よくリンクしています。
    [1] https://capnproto.org/faq.html#how-do-i-make-a-field-require...

    • 本当に価値のある視点です。私も以前は、なぜそうなのか理解しづらかったです。要点は、protobufとCap'n Protoを、単一バージョンの単一プロセスが見る世界を表すメモリ内データ構造ではなく、API境界を越えて異なるスキーマバージョンと下位・上位互換で動作しなければならないシリアライズ形式として理解することでした。
      したがって、「不正な状態を表現不可能にせよ」という広く繰り返されるマントラは、ここには当てはまりません。
    • Typicalは型の進化を助けるために非対称フィールドを提供しています。
      https://github.com/stepchowfun/typical#asymmetric-fields-can...
      必須フィールドを安全に追加・削除できるように、Typicalは任意フィールドと必須フィールドの中間状態であるasymmetricを提供します。構造体のasymmetricフィールドは、書き込み側には必須、読み取り側には任意と見なされます。任意フィールドと異なり、asymmetricフィールドは必須へ安全に昇格したり、その逆に戻したりできます。
    • この論理を拡張すると、事実上すべての静的型をなくそうという結論にもなり得るのではないかと思います。正直、完全に間違っているとも言えませんし、Alan Kayがオブジェクト指向を動的型付けとレイトバインディングで定義した理由でもあります。ところが私たちはその逆へ進みながら、同じ教訓を何度も学び直しています。
    • FAQ [1] には「正しい答えは、アプリケーションが必要に応じてアプリケーションレベルのコードで検証すること」とあります。
      アプリケーションコードに依存する代わりに、必須メッセージ検証をオン・オフできるパラメータがあればよかったと思います。アプリケーション内部やメッセージバスではオフにできますが、一般的にはオンになっていれば開発者にとって大きな助けになります。
      [1] https://capnproto.org/faq.html#how-do-i-make-a-field-require...
    • 同じ文脈の落とし穴がもう一つあります。生成されたクライアントで受け取る場合のように、不要なものまでデシリアライズされる問題です。
      Goのインターフェースで本当に気に入っている点は、自分が使うものだけをリモートで型付けし、残りはスキップできることです。サービスが使ってもいない契約変更のせいで障害が起きるのは楽しくありませんし、見つけるのも困難です。
  • 素晴らしい成果です。正直に言うと、Cap'n Protoはおすすめしません。C++ APIが非常にぎこちないです。
    ゼロコピー解析の利点も期待より小さいです。使い勝手がぎこちないため、データをCap'n Protoのデータ構造のまま持ち続けたいと思う可能性は低く、99%は結局自分のデータ構造へコピーすることになります。
    世の中はこの種のバイナリ実装についてはおおむねProtobufに落ち着いているので、他のシステムとの摩擦も大きくなります。
    私はシリアライズ用途でしか使ったことがありません。RPCのほうはもっと魅力的かもしれません。
    Protobuf/gRPCの代わりにThriftが成功していれば本当によかったのにと思います。以前にも以後にも見たどのものより設計がはるかに良く、柔軟でした。主にひどいドキュメントのせいで消えていったように見えますし、背後に大きな名前がなかったことも理由だったのでしょう。

    • ゼロコピーに必要なAPIが、特に書き込み側でややぎこちなくなる点には同意します。読み取り側は大きくは違いません。一方で、ゼロコピーはmmap()と併用する場合のような特定のシナリオでのみパラダイムシフトに近く、ネットワーク通信ではRDMAのような強力な手法を使わない限り、大きくは変わりません。
      ゼロコピーがあまり重要でないユースケース向けに、Cap'n Protoに「普通のC構造体」またはそれに近い形を使い、protobufのように一度コピーするシリアライズを提供する任意の代替APIをずっと追加したいと思っていましたが、まだできていません。
      ただ個人的には、シリアライズよりもRPCプロトコルのほうにずっと強い関心を持ってきました。RPCプロトコルは、些細でないほぼすべてのユースケースで実際のパラダイムシフトだと思います。
    • protobufではなくflatbuffersのことを言っているように思います。事実上の標準として定着しており、いくつか別の場所ではSBEが使われています。
      いずれにせよ、バイナリシリアライズの主な問題はスキーマとメッセージのバージョン管理、そしてデルタエンコーディングです。この2つを無視すれば、フラットなバイナリシリアライズは些細なものです。
      上の2つをどちらもうまく扱う解法を提供するライブラリはありません。
    • スキーマが不要なら、MessagePackはかなり優れていると思います。ただしV8のJSONシリアライズが異常に速いので、MessagePackでも勝つのは難しく、他の言語ではJSONのほうが速い場合も多いです。一方でバイト数は減らせます。
    • fbthriftは今でも元気に生きています。
  • capnp のアイデアはいつも気に入っていたが、結局はメッセージエンコーディングプロトコルであるにもかかわらず、私のサーバーアーキテクチャをどう組むべきかにまで意見を持っている点が気に障る。
    gRPC にも確かにこうした問題はあるが、protobuf とは非常に明確に分離されており、protobuf には gRPC 関連機能があるにはある。
    こうした絡み合いのせいで、capnp と比較するたびに flatbuffers や protobuf のほうに傾いてしまう。特に fb と pb の実装のほうがはるかに単純で、セキュリティとメンテナンスの観点では単純さを非常に高く評価しているためだ。
    優れたサードパーティ製の言語実装が不足していることも、この判断が妥当だという直接的なシグナルだと思う。バス係数と長期的な生存性も非常に悪い。単純さが支配する。

    • cap'n'proto に触れるたびに感じた問題は、サーバーアーキテクチャに意見を持っていることだけでなく、C++ では STL に対する非常に主張の強い代替である KJ まで一緒に持ち込む点だ。数年前に触ったとき、既存のコードベースのあちこちに入り込んでいて作業しづらかった。
      Rust 版も独自の規範的な生活様式を要求する。その多くはゼロコピーの世界観では筋が通っているが、それでもいろいろな表現を難しくし、ドキュメントも読みにくかった。
      だからこの理由だけでも、たいてい flatbuffers を選ぶことになる。
      それでも、いつか cap'n'proto が必要で有用な状況が来ることを願っているし、何年も試そうとしてフォークしてある複数の趣味プロジェクトのうち、どれか一つでも終わらせたい。高品質なエンジニアリングが入っているのは確かだ。
    • シリアライゼーション層がRPC の選択にどう影響するのか気になる。
  • 新しくはないが、この名前が Star Trek Voyager への意図的なオマージュなのか、それとも私の知らない別の参照があるのか気になる。
    https://memory-alpha.fandom.com/wiki/Captain_Proton

    • その参照は実際には考えたことがない。
      Cap'n Proto という名前は、もともと Capabilities and Protobufs を意味していた。Protocol Buffers ベースのケイパビリティベース RPC プロトコルだった。しかし初期に、まったく別のシリアライゼーション形式を試してみたくなった。それでも「Proto」はプロトコルという意味で依然として合っていたので、名前を維持した。
      “cerealization protocol” という言葉遊びは実は別の人が教えてくれたものだが、すぐにロゴに追加した。
    • “cerealization protocol” と宣伝していたので、いつも Cap'n Crunch シリアルへの参照だと思っていた。
 
bbulbum 2023-07-30

Serialization/RPC のことだと思いますが、誤字のようです