Upgrade to Pro — share decks privately, control downloads, hide ads and more …

多様なプロトコルと 駆動モデルをサポートするIoTゲートウェイの開発と運用の知見

多様なプロトコルと 駆動モデルをサポートするIoTゲートウェイの開発と運用の知見

Go Conference 2023, "Go"ld Sponsor Session
https://gocon.jp/2023/sessions/A5-SP/

Takeshi Shinoda

June 02, 2023
Tweet

More Decks by Takeshi Shinoda

Other Decks in Programming

Transcript

  1. ©2023 MODE, Inc.
 • MODE, Inc.に勤務
 • テックリード・エンジニア
 • 2018年9月よりMODE社


    • Go歴はMODE歴と同じ約4年と10ヶ月
 • 組み込み関数では len() が好き
 • https://twitter.com/takeshinoda
 篠田 健 (しのだ たけし)

  2. ©2023 MODE, Inc.
 会社概要
 社名
 MODE, Inc.
 設立
 2014年創業
 (2017年日本オフィス開設)


    事業内容
 統合 IoT ソリューションの企画・ 
 開発・運営
 創立者
 Gaku Ueda / Ethan Kan
 所在地
 サンフランシスコ / 東京

  3. ©2023 MODE, Inc.
 現場ではたらくコンピュータ
 • 過酷な環境で動くこともある。
 ◦ トンネルの中。
 ◦ エンジンを切ると電源が落ちる自動車。


    ◦ 工事現場の重機の中。
 ◦ 電波の悪い工場の中。
 • H/Wは現場の物理環境に合わせて異なる。
 ◦ ユーザーが稼働させているロボットの中。
 ◦ IntelもあればArmもある。
 • 遠くにあるので基本的にネットの切れ目が縁の切れ目。
 ◦ LTEとかの接続で何かの不都合で復旧しない場合手動で直す。
 ◦ 最悪山奥のトンネルにある。

  4. ©2023 MODE, Inc.
 IoTゲートウェイは現場で何をしているの
 BLE
 EnOcean
 Twilite
 Serial
 TCP/UDP
 OBD-II


    BACNet
 NMEA Sentence
 CSV/JSON
 etc…
 各種センサー
 工場・生産設備
 建設現場
 重機
 輸送車両
 倉庫
 ロボット
 エンタメ演出
 etc…
 MQTT
 Gateway! MODE Cloud

  5. ©2023 MODE, Inc.
 ソフトウェアとしての動作環境の特徴
 • 動的なスケールアウト・アップはできない。
 • インターネットへの接続が必ずしも安定しない。
 ◦ 太い回線であることも期待できない。


    • IoTゲートウェイと接続する機器のプロトコルと動作モデルは機器による。
 ◦ 単純なセンサーは一方的にデータを送信してくる。
 ◦ データを要求してデータを非同期に返すプロトコル。
 ◦ ペアリングが必要なパターンもある。
 ◦ データを要求してその後消すオペレーションなど。
 ◦ CIFSなどを通じた単なるファイル連携もある。
 • エラーがあっても止めず、常に最後の遠隔操作手段は残したい。
 • Go製アプリケーションをLinuxの上で動かせるくらいはリッチ。

  6. ©2023 MODE, Inc.
 機器との通信
 ←データ送信
 機器設定→
 各機器のハンドリング 
 色んな働きをする Goroutine

    いっぱい! 不定期にデータは 来るしクラウドから 指示が来る💦 go func() { for { read() write() } }() go func() { for { read() write() } }()
  7. ©2023 MODE, Inc.
 各制御機器のモジュール内のデータ保護
 go func() { for { read()

    write() } }() • 不定期にデータは機器からゲートウェイに上がる。 
 • 不定期にクラウドから設定変更などの割込み処理がゲートウェイでは発生する。 
 • 各対応機器のモジュール内のデータ保護の為の Mutexロックなどが煩雑になりがち。 
 main(){} モジュール
  8. ©2023 MODE, Inc.
 各種機器を制御するモジュールのGoroutine
 func (d *Device) Start() { go

    func() { for { select { case fn := <-d.message: fn() case data := <- d.inputCh: d.upstream <- data case <- d.doneCh: return } } }() } 各機器は常にひとつ以上の専用Goroutineで制御
 1. コードがどのGoroutineで動くかがモジュールの開発 者が把握しやすい
 2. 機器の駆動モデルに合わせた開発がしやすい
 3. ハンドリングの為の割り込みを制御しやすい
 func (d *Device) ChangeInterval()) { d.message <- func() { /* Do something */ } }
  9. ©2023 MODE, Inc.
 初期の頃のIoTゲートウェイ内のGoroutineヒエラルキー
 go func() { for { ...

    } }() go func() { for { ... } }() go func() { for { ... } }() go func() { for { ... } }() go func() { for { ... } }() MQTT
 MQTT
 通信制御
 • センサーGoroutineハンド リング
 • データ収集・変換
 • 制御指示
 Channel
 Channel
 Channel
 • 各Goroutine間はChannelを通じてデータと指示を伝搬。 
 • それぞれのモジュールはひとつ以上の Goroutineが独自に動いており、 制御対象の機器実行モデルは Goroutine内で閉じていたため、上流のハ ンドリングモジュールは起動と停止とクラウドからの指示を伝搬することだ けを気にすることができた。 
 Channel
 ホントはも 少し多段
  10. ©2023 MODE, Inc.
 一度Channelが詰まると全部詰まる
 go func() { for { ...

    } }() go func() { for { ... } }() go func() { for { ... } }() go func() { for { ... } }() go func() { for { ... } }() Channel
 Channel
 • 多様な現場で多様な用途に使われるので、様々な要因でラ ンダムに詰まりがち
 ◦ データのアップロードが単に追いつかない 
 ◦ センサーをぶら下げすぎる 
 ◦ 不定期なクラウドからの指示が何故か秘孔を突く 
 ◦ どこかの考慮不足のコード 
 upstreamCh <- data
 みんなここで止まる

  11. ©2023 MODE, Inc.
 これを全モジュールのデータ伝搬に入れてしのぐのも限界がある
 select { case upstreamCh <- data:

    default: // error logging, buffering }
 • そもそも大事なデータが抜け落ちる。 
 • defaultに入るような状態になって自動的に回復することもあまり期待できない。 
 • あちこちにこれがあるのは何かがおかしい。 
 • コードには upstream 方向と downstream 方向のデータの流れも、それらを考慮すると詰ま り要因を全部洗い出したり考慮をしていると開発が立ちゆかない懸念。 
 ×

  12. ©2023 MODE, Inc.
 問題の整理と設計の方針の整理
 問題の整理
 IoTゲートウェイの動作環境はユーザーにより多様なため様々なデータの流通パターンがあり、ランダ ムにChannel詰まりの不具合を掴みやすい。 
 方針の整理
 Option1:

    Channelによるデータ伝搬をやめる
 対応機器の駆動モデルを事前に予測できないので Goroutine単位のモジュール開発パターンを取れない のはつらい
 Option2: チャンネルによる連結はやめずにモジュールの独立性を高める ← 方針はこちらで
 モジュール外の出来事に気を配るような開発は様々な現場と機器に対応するため無理がある 

  13. ©2023 MODE, Inc.
 イベント受信に基づいたモジュール設計
 1. イベントの送受信だけを結節点にするモジュール設計。 
 2. Goroutine の良いところは軽量にしかもChannelにより簡単に動作を制御できるところにあ

    る。
 3. 各モジュールの独立性を高める Scratchの設計は、GoroutineとChannelの特性とかなりマッ チして参考にできる。
 a. 独立性を高める:
 i. 他のモジュールの動作次第で全部詰まることを考えない 
 ii. 別のモジュールの設計に依存しない (気にせず開発できる )
 iii. 処理対象機器の動作モデルに全体設計が引きずられない 
 4. 最初の実装は実行そのものを関数として Goroutineに渡していたがやりすぎだった
 a. テストがやりにくい
 b. 引数に柔軟性がない (ぜんぶクロージャとして渡す )
 c. ふつうの開発モデルから逸脱している 

  14. ©2023 MODE, Inc.
 イベントを受け取りイベントを送出するのがモジュール
 Channel Filter Module Channel • モジュールはイベントを受け取り、イベントの内容に基づき独自に処理をする。

    
 機器から受信したデータや 
 自分の状態を知らせるイベントの発行 
 受信データの加工
 特定条件データのドロップ 
 などの前処理

  15. ©2023 MODE, Inc.
 イベントの種類は基本的に固定
 • IoTゲートウェイという用途限定のユースケースと割切り、自由なイベントは作れない。
 • 自由にすると関数を実行させる最初のモデルに近くなるし、他のモジュールの仕様を知る必要が 出てくる。
 const

    ( DiscoveredModuleType EventType = "discoveredModule" UnregisterKernelModuleType EventType = "unregisterKernelModule" KernelType EventType = "kernel" MeasuredType EventType = "measured" LargeDataType EventType = "largeData" ModeEventType EventType = "modeEvent" ModeCommandType EventType = "modeCommand" ModeKVNotifyType EventType = "modeKVNotify" < ...省略... > NotificationType EventType = "notification" BroadcastNotificationType EventType = "broadcastNotification" )
  16. ©2023 MODE, Inc.
 基本的にはEventはブロードキャストされる
 Core Module MQTT Module CO2 Sensor

    Module Thermometer Module Event Router Channel Channel • すべてのイベントはEvent Routerに投げられる。
 • MeasuredEvent が欲しいとインターフェース定義を満たせばそのす べてのモジュールに伝搬される。 
 type MeasuredEventReceivable interface { MeasuredEventCh() chan<- MeasuredEvent } 温度測ったから MeasuredEvent送った よ!あとは知らないよ! 測定値が欲しいよ!必要 だったらこっちで判断して クラウドに送るね!
  17. ©2023 MODE, Inc.
 基本的にはEventはブロードキャストされる
 Core Module MQTT Module CO2 Sensor

    Module UdevEvent Module Event Router Channel Channel 新しいデバイスが見つかっ たよ! もしかして自分のかもしれ ないからデバイス系のイベ ント全部拾うよ!
  18. ©2023 MODE, Inc.
 新しい設計でのモジュールのGoroutineの雰囲気
 func (m *DriverModule) Start() error {

    if err := m.initializeDevice(); err != nil {...} go func() { select { case event := <- m.eventReceiverCh: m.doSomethingBy(event) case data := <- m.deviceMeasuredCh: m.sendCh <- parseData(data) case <- m.doneCh: // Do something to stop the process gracefully return } }() }
  19. ©2023 MODE, Inc.
 結局 EventRouter で詰まるのでは?
 Core Module MQTT Module

    CO2 Sensor Module TooBusySensor Module Event Router Channel Channel • 少なくとも詰まりポイントは EventRouterだけ見ればいいのでランダム に詰まられるよりはよい。
 • バッファリングでできるだけ突発的・各現場での様々なデータ流量に対 応できるようにはしている。
 • 転送先がBusyの時は捨てる。
 ◦ 各モジュールは用途的にたくさんデータが来ると予想されるならそれなり の実装にするという期待を前提とする。 

  20. ©2023 MODE, Inc.
 We are hiring!
 MODE社ではエンジニアを広く募集しております!! 
 • IoTエッジサイドのシステムプログラミングを楽しみたい。

    
 • IoTプラットフォームのクラウドシステムをビシバシ作りたい方。 
 • サンフランシスコと東京オフィスの 2拠点でグローバルな開発を体験できます。 
 • 基本的にはリモートワークです。 IoTなので現場に出ることはあります。 
 このあと13:30-14:00まで、ベイエリア在住のCEO (日本語でも英語でも可) が企業ブースでお待 ちしておりますのでお話ししてみてください! 
 上記以外の時間帯にも弊社エンジニアと HR担当がお待ちいたしております!