メモリーセーフなプログラミング言語Rustに特化したカンファレンスRustNL 2024から、IoTデバイスなどとの通信を可能にするRustライブラリー、postcardとそれを応用したプロトコルスタック、postcard-rpcの解説セッションを紹介する。動画は以下から参照して欲しい。
●動画:Postcard: An Unreasonably Effective Tool for Machine to Machine Communication
セッションを担当したのはOne VariableというRustに特化したベルリンのコンサルティング会社のエンジニア、James Munns氏だ。One VariableはRustを開発言語として使うことを特徴としており、Munns氏はその中でもエンベデッドシステムの構築を担当しているという。
●参考:Munns氏の所属するOne Variableの公式ページ:https://onevariable.com/
マシンとマシンを接続して通信を行うpostcardに関するセッション
ここでは「マシンとマシンの接続」と説明しているが、「ここにいる皆さんが使っているようなマシンではなくこういう機械を繋いでデータをやり取りすることが必要なケースを想定しています」として参加者にノートPCやスマートフォンなどではないマシンの例を見せてこれから説明するpostcardの前提となる「ここで想定しているマシンとは何か?」を簡単に説明した。
ガスクロマトグラフィーの分析機器をサンプルとして紹介
ここではガスクロマトグラフィーの分析機器を見せて、この機器からデータを処理するためには何が必要かを説明。
PCにUSBで接続されたMCUからデータを取り出すアプリケーションを想定
PCと接続されるMCU(Micro Controller Unit)にはいわゆるコンピュータとして稼働するOSがないかもしれず、処理のためのデータバッファーやプログラムをロードするためのメモリー領域も限定されるかもしれないという状況において、即座にアプリケーションを開発することを求められたら何が必要か? という問いを参加者に提示した。
その中でOne VariableはRustを使っているユーザーが多く、Rustで実装することを許してくれるというのが利点のひとつだと説明。そしてRustのシリアライズ、デシリアライズのライブラリーserdeがあることで、データ通信の基本機能の実装は「すでに終わっている」と説明した。
Rustには通信のためのシリアライズ、デシリアライズ機能が存在しているのが利点
そしてRustのカンファレンスらしくソースコードを使って説明。
Rustのソースコードを使って説明
エンベデッドシステムには、通常のコンピュータが備えているOSやライブラリーなどが欠けている場合が多いことを紹介。
エンベデッドシステムには通常のコンピュータに付属している機能が欠けている場合が多い
Rustの「#![no_std]」というアトリビュートを設定することで、Rustの標準ライブラリーを使用せずにプログラミングを行う設定が可能であることを説明。no_stdは標準のライブラリーを使わないことで機種に依存しないプログラムを書くことが可能になる。ここからはpostcardについての特徴を紹介する内容となった。
#![no_std]を設定する理由は最小規模のチップセットでも実行可能にすること
そしてpostcardについてはserdeのデータフォーマットと同様な使い方を可能にすることがデザインの主眼であることを紹介。
serdeのデータフォーマットと同じ使い勝手を提供する
またプロセッサの種類や規模などに制約されないように「どのコンピュータやMCUでも動くことがポイント」と語る。
そして「メモリー使用量を抑えること」「コード自体のサイズを抑えること」「、開発のための時間を少なくすること」「CPUの処理時間も抑制すること」を優先順位として挙げた。
postcard実装における優先順位。メモリー使用量を抑えることが最重要
プログラムの中では「Iterator(反復子)と同じように使えることが理想である」と説明し、実際にMunns氏は多くのプロジェクトでpostcardを使ったと説明した。
多くのプロジェクトでpostcardを利用したと説明
postcardはオープンソースプロジェクトとしてMunns氏のプライベートなリポジトリーで公開されていることからも、自身が開発して現場で使いこんでいるソフトウェアであることは自明だろう。
そこからネットワークのスタックを使ってよりハードウェアに近い層からアプリケーション層までの段階で、データ送受信のアプリケーション層が最も難しく、下位の層は比較的簡単であることを解説。
ネットワークをレイヤーに分けて説明。下位層は簡単だがアプリケーション層は難しい
そしてこれまでの開発経験から「『プロトコル』に相当する層が抜けていることに気付いた」と語った。ここではアプリケーションの中でどのように通信を行うかまでを実装しており、ビジネスロジックと混在していたことを紹介。ただしそのプロトコルに値するコードはそれほど難しいわけではなく、毎回プロジェクトごとにコピー&ペーストをしていたと説明した。
プロトコルレイヤーが抜けていたと説明
postcardというソフトウェアにシリアライズ、デシリアライズ機能を担当させ、個別にカスムメイドされたプロトコルを開発することは簡単であったと説明。
postcardで個別の仕様を満足するプロトコルを毎回作っていた
プロトコルの層を追加することで、アプリケーション層はプロジェクトごと、ビジネスロジックごとに書き起こす必要があるが、以前よりは簡単になったと語った。
アプリケーション層の下にプロトコル層を追加
そのプロトコル層に相当するのがpostcard-rpcで、これはpostcardの上に実装されたソフトウェアである。
postcardの上に実装されたpostcard-rpc
メッセージの交換についてはリクエストとレスポンスを返すという非常に基本的な内容で、トピックやストリーミング、ノーティフィケーションなどの要素で構成されている。Kafkaのような重厚なメッセージングソフトウェアとは異なり、シンプルさが特徴であり、エラー処理などもシステム側で責任を持つのではなくアプリケーション層でデベロッパーが責任を持つという発想だろう。
リクエストとレスポンスが基本動作
リクエストはクライアント、サーバーのどちらでも起点となり得ること、レスポンスがないこともあり得ることなどを説明した。
PC(クライアント)からMCU(サーバー)への通信の例
ここではPCがクライアント、MCUがサーバーと位置付けられているが、システムの大きさではなくメッセージの起点がどちら側にあるか? によって決定されていることに注意したい。
より詳細なソフトウェアのスタックを紹介するスライドでは、NUSB crate、embassy-usb crateなどが紹介された。
クライアントとサーバーのソフトウェアスタックを紹介
そしてここでもRustのソースコードを使って送受信の例を紹介。Rustに特化したカンファレンスだけあって、この手のコードを見せることは必須なのかもしれない。
Rustのソースコードでデータ送受信の例を紹介
実際にデータ送受信を行う際のヘッダーとして、ユニークなキーとシーケンス番号が追加されると説明。可能な限りデータ量、使用するメモリー量を減らすというデザインテーマに沿った実装であることを解説した。
最後にpostcard-rpcがマシン同士の通信を可能な限り簡単にするという目的に沿っていることをもう一度確認して、質疑応答に移った。
マシン同士のコミュニケーションを簡単にするpostcard-rpc
分散処理ではなくモノリシックなアプリケーションにおいても処理を待たせないということが重要であることは、Robiusでも強く意識されていた考え方だが、マシン間の通信スタックであるpostcard-rpcでも非同期で処理を止めないことが重要であると訴求されていた。
なおRustのシリアライゼーション処理のライブラリーであるserdeやpostcardについては以下を参照されたい。
●参考:
serde:https://serde.rs/
postcard:https://github.com/jamesmunns/postcard
postcard-rpcについてはMunns氏によるドキュメントが解説資料としては最適だろう。
●Munns氏のpostcard-rpc解説:https://github.com/jamesmunns/postcard-rpc/blob/main/docs/overview.md
やや駆け足ながらエネルギッシュに語るJames Munns氏は、エンベデッド系システムにおけるRustの優位性を今後も訴えていくだろう。これからも新たなユースケースが期待される。
Enjoyed this article? Sign up for our newsletter to receive regular insights and stay connected.

