Slide 1

Slide 1 text

©2023 MODE, Inc.
 多様なプロトコルと
 駆動モデルをサポートする
 IoTゲートウェイの開発と運用の知見
 Takeshi Shinoda 2023-06-02


Slide 2

Slide 2 text

©2023 MODE, Inc.
 ● MODE, Inc.に勤務
 ● テックリード・エンジニア
 ● 2018年9月よりMODE社
 ● Go歴はMODE歴と同じ約4年と10ヶ月
 ● 組み込み関数では len() が好き
 ● https://twitter.com/takeshinoda
 篠田 健 (しのだ たけし)


Slide 3

Slide 3 text

©2023 MODE, Inc.
 会社概要
 社名
 MODE, Inc.
 設立
 2014年創業
 (2017年日本オフィス開設)
 事業内容
 統合 IoT ソリューションの企画・ 
 開発・運営
 創立者
 Gaku Ueda / Ethan Kan
 所在地
 サンフランシスコ / 東京


Slide 4

Slide 4 text

©2023 MODE, Inc.
 AGENDA
 1. MODE社における汎用IoTゲートウェイの働く現場
 2. 当初のIoTゲートウェイの実装パターンと問題
 3. Goroutine を中心としたモジュールの設計
 4. まとめ


Slide 5

Slide 5 text

©2023 MODE, Inc.
 01
 MODE社における汎用IoTゲートウェイの働く現場


Slide 6

Slide 6 text

©2023 MODE, Inc.
 IoTゲートウェイのはたらく場所
 現場 クラウド


Slide 7

Slide 7 text

©2023 MODE, Inc.
 IoTゲートウェイのはたらく場所
 現場 クラウド
 こっち

Slide 8

Slide 8 text

©2023 MODE, Inc.
 現場ではたらくコンピュータ
 ● 過酷な環境で動くこともある。
 ○ トンネルの中。
 ○ エンジンを切ると電源が落ちる自動車。
 ○ 工事現場の重機の中。
 ○ 電波の悪い工場の中。
 ● H/Wは現場の物理環境に合わせて異なる。
 ○ ユーザーが稼働させているロボットの中。
 ○ IntelもあればArmもある。
 ● 遠くにあるので基本的にネットの切れ目が縁の切れ目。
 ○ LTEとかの接続で何かの不都合で復旧しない場合手動で直す。
 ○ 最悪山奥のトンネルにある。


Slide 9

Slide 9 text

©2023 MODE, Inc.
 IoTゲートウェイは現場で何をしているの
 BLE
 EnOcean
 Twilite
 Serial
 TCP/UDP
 OBD-II
 BACNet
 NMEA Sentence
 CSV/JSON
 etc…
 各種センサー
 工場・生産設備
 建設現場
 重機
 輸送車両
 倉庫
 ロボット
 エンタメ演出
 etc…
 MQTT
 Gateway! MODE Cloud


Slide 10

Slide 10 text

©2023 MODE, Inc.
 ソフトウェアとしての動作環境の特徴
 ● 動的なスケールアウト・アップはできない。
 ● インターネットへの接続が必ずしも安定しない。
 ○ 太い回線であることも期待できない。
 ● IoTゲートウェイと接続する機器のプロトコルと動作モデルは機器による。
 ○ 単純なセンサーは一方的にデータを送信してくる。
 ○ データを要求してデータを非同期に返すプロトコル。
 ○ ペアリングが必要なパターンもある。
 ○ データを要求してその後消すオペレーションなど。
 ○ CIFSなどを通じた単なるファイル連携もある。
 ● エラーがあっても止めず、常に最後の遠隔操作手段は残したい。
 ● Go製アプリケーションをLinuxの上で動かせるくらいはリッチ。


Slide 11

Slide 11 text

©2023 MODE, Inc.
 02
 当初のIoTゲートウェイの実装パターンと問題


Slide 12

Slide 12 text

©2023 MODE, Inc.
 機器との通信
 ←データ送信
 機器設定→
 各機器のハンドリング 
 色んな働きをする Goroutine いっぱい! 不定期にデータは 来るしクラウドから 指示が来る💦 go func() { for { read() write() } }() go func() { for { read() write() } }()

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

©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 */ } }

Slide 15

Slide 15 text

©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
 ホントはも 少し多段

Slide 16

Slide 16 text

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


Slide 17

Slide 17 text

©2023 MODE, Inc.
 これを全モジュールのデータ伝搬に入れてしのぐのも限界がある
 select { case upstreamCh <- data: default: // error logging, buffering }
 ● そもそも大事なデータが抜け落ちる。 
 ● defaultに入るような状態になって自動的に回復することもあまり期待できない。 
 ● あちこちにこれがあるのは何かがおかしい。 
 ● コードには upstream 方向と downstream 方向のデータの流れも、それらを考慮すると詰ま り要因を全部洗い出したり考慮をしていると開発が立ちゆかない懸念。 
 ×


Slide 18

Slide 18 text

©2023 MODE, Inc.
 03
 Goroutine を中心としたモジュールの設計


Slide 19

Slide 19 text

©2023 MODE, Inc.
 問題の整理と設計の方針の整理
 問題の整理
 IoTゲートウェイの動作環境はユーザーにより多様なため様々なデータの流通パターンがあり、ランダ ムにChannel詰まりの不具合を掴みやすい。 
 方針の整理
 Option1: Channelによるデータ伝搬をやめる
 対応機器の駆動モデルを事前に予測できないので Goroutine単位のモジュール開発パターンを取れない のはつらい
 Option2: チャンネルによる連結はやめずにモジュールの独立性を高める ← 方針はこちらで
 モジュール外の出来事に気を配るような開発は様々な現場と機器に対応するため無理がある 


Slide 20

Slide 20 text

©2023 MODE, Inc.
 channel
 goroutine
 構造を次のように変える
 前
 後


Slide 21

Slide 21 text

©2023 MODE, Inc.
 突然ですが Scratch を参考にしてみる
 Mouse Click!!

Slide 22

Slide 22 text

©2023 MODE, Inc.
 各スプライトは他スプライトのことをしらない
 - 各スプライトはそれぞれスレッドを持ち、自分へのイベント (この場合メッセージの受信 )に基づいて各 自独自に振る舞う。
 - これでもかなり複雑なゲームを作れる。 


Slide 23

Slide 23 text

©2023 MODE, Inc.
 イベント受信に基づいたモジュール設計
 1. イベントの送受信だけを結節点にするモジュール設計。 
 2. Goroutine の良いところは軽量にしかもChannelにより簡単に動作を制御できるところにあ る。
 3. 各モジュールの独立性を高める Scratchの設計は、GoroutineとChannelの特性とかなりマッ チして参考にできる。
 a. 独立性を高める:
 i. 他のモジュールの動作次第で全部詰まることを考えない 
 ii. 別のモジュールの設計に依存しない (気にせず開発できる )
 iii. 処理対象機器の動作モデルに全体設計が引きずられない 
 4. 最初の実装は実行そのものを関数として Goroutineに渡していたがやりすぎだった
 a. テストがやりにくい
 b. 引数に柔軟性がない (ぜんぶクロージャとして渡す )
 c. ふつうの開発モデルから逸脱している 


Slide 24

Slide 24 text

©2023 MODE, Inc.
 イベントを受け取りイベントを送出するのがモジュール
 Channel Filter Module Channel ● モジュールはイベントを受け取り、イベントの内容に基づき独自に処理をする。 
 機器から受信したデータや 
 自分の状態を知らせるイベントの発行 
 受信データの加工
 特定条件データのドロップ 
 などの前処理


Slide 25

Slide 25 text

©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" )

Slide 26

Slide 26 text

©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送った よ!あとは知らないよ! 測定値が欲しいよ!必要 だったらこっちで判断して クラウドに送るね!

Slide 27

Slide 27 text

©2023 MODE, Inc.
 基本的にはEventはブロードキャストされる
 Core Module MQTT Module CO2 Sensor Module UdevEvent Module Event Router Channel Channel 新しいデバイスが見つかっ たよ! もしかして自分のかもしれ ないからデバイス系のイベ ント全部拾うよ!

Slide 28

Slide 28 text

©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 } }() }

Slide 29

Slide 29 text

©2023 MODE, Inc.
 別Goroutineから呼び出されうるポイントを限定
 ● これを満たすとモジュールとして動作できる。 
 ● この関数以外から知らないGoroutineの呼び出しはない。
 type Module interface { Start(Configs) error Stop(context.Context) error Status() ModuleStatus }

Slide 30

Slide 30 text

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


Slide 31

Slide 31 text

©2023 MODE, Inc.
 04
 まとめ


Slide 32

Slide 32 text

©2023 MODE, Inc.
 まとめ
 ● GoroutineとChannelの良いところを組み合わせれば、独立性の高いモジュール機 構を採用しても難しくなく実装できる。
 ● 分散システムとかでは無く、単体プロセスで頑張るソフトウェアの場合、Channelのパ イプラインは考えがちだが詰まりポイントを見つけにくいので要注意。


Slide 33

Slide 33 text

©2023 MODE, Inc.
 05
 さいごに…


Slide 34

Slide 34 text

©2023 MODE, Inc.
 We are hiring!


Slide 35

Slide 35 text

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


Slide 36

Slide 36 text

©2023 MODE, Inc.
 ありがとうございました!!