最高の暗号取引プラットフォーム

ブローカーの定義

ブローカーの定義
ブローカーモデル
接続組み合わせの複雑度はブローカーが引き受ける

Perforceブローカ

Perforceブローカとエンドユーザとの間の接続を暗号化するには、ブローカに有効なプライベートキーと証明書のペアが P4SSLDIR 環境変数で指定されたディレクトリに登録されている必要があります。ブローカに対する証明書とキーの生成および管理は、Perforceサーバで行う場合と同様に行われます。詳細については、SSLのサポートを有効にするを参照してください。ユーザのPerforceアプリケーションは、ブローカのフィンガープリントを信頼するように設定されていなければなりません。

PerforceブローカとPerforceサーバとの間の接続を暗号化するには、ブローカがPerforceサーバのフィンガープリントを信頼するように設定されていなければなりません。したがって、 p4broker を実行するユーザ(通常はサービスユーザ)はPerforceサーバのフィンガープリントを認識する P4TRUST ファイルを( p4 trust を使用して)作成する必要があります。また、そのファイルへのパスを指定する P4TRUST を設定する必要があります( ブローカーの定義 P4TRUST )はブローカコンフィギュレーションファイルでは指定できません。

ブローカ情報

p4 info を実行して、ブローカに接続されているかどうかを知ることができます。ブローカに接続されると、出力に Broker address と Broker version が表示されます。

ブローカに接続されると、 p4 broker コマンドを使用してブローカ情報の簡略レポートを表示させることができます。

ブローカとプロテクション

ブローカユーザのワークステーションのIPアドレスをプロテクションテーブルに対して適用するには、ワークステーションのIPアドレスの先頭に proxy- という文字列を追加します。

例えば、 192.168.10.0/24 というサブネット上のワークステーションでリモート開発を行っている組織を考えてみます。この組織には、ローカル開発を行っている中央オフィスもあり、この中央オフィスは 10.0.0.0/8 というサブネット上に存在しています。Perforceサービスは 10.0.ブローカーの定義 0.0/8 のサブネット上にあり、ブローカは 192.168.10.0/24 のサブネット上にあります。リモートサイトのユーザは remotedev グループに属しており、時々中央オフィスにアクセスします。各サブネットには、対応するIPv6アドレスのセットも存在しています。

1行目では、 192.168.10.0/24 のサブネット上のワークステーションからブローカを使用せずPerforceにアクセスしようと試みた場合に、 remotedev グループのすべてのユーザに対して list アクセスが拒否されます。2行目では、IPV6のサブネット [2001:db8:16:81::]/48 からアクセスしようとした場合に、1行目と同じ方法でアクセスが拒否されます。

3行目では、 192.168.ブローカーの定義 10.0/24 のサブネット上のワークステーションから作業していて、ブローカを使用している場合に、 remotedev グループのすべてのユーザに対して write アクセスが許可されます。リモートサイトにあるワークステーションのユーザは、ブローカを使用しなければなりません。(ブローカ自体がこのサブネット内に存在している必要はありません。例えば、 192.168.20.0 に存在していても構いません。)4行目では、IPV6 [2001:db8:16:81::ブローカーの定義 ブローカーの定義 ]/48 サブネットからアクセスが試みられた場合に、同様にアクセスが拒否されます。

同様に、5行目と6行目では、中央オフィスのサブネット( 10.0.0.0/8 と [2001:db8:1008::]/32 )上のワークステーションからブローカの使用を試みた場合、 remotedev ユーザに対して list アクセスが拒否されます。7行目と8行目では、中央オフィスのサブネット上のワークステーションから直接Perforceサーバにアクセスする remotedev ユーザに対して、書き込みアクセス権が許可されます。 remotedev グループのユーザがローカルサイトにアクセスする場合は、Perforceサーバに直接アクセスする必要があります。

Perforceサービスがプロテクションテーブルのエントリを評価する際に、 dm.proxy.protects 構成も評価されます。

dm.proxy.protects デフォルトを 1 に設定すると、媒介(プロキシ、ブローカ、またはエッジサーバ)を経由して接続するすべてのクライアントホストアドレスの先頭に、プレフィックス proxy- が追加されます。これは、接続が直接でないことを示します。

dm.proxy.protects を 0 に設定すると、 proxy- プレフィックスが削除され、プロテクションエントリを1セット書き込むことができます。これは、直接接続しているクライアントと媒介を経由して接続しているクライアントの両方に適用されます。これは便利ですが、媒介を経由して接続することに問題がある場合、安全性が低下します。この設定を使用する場合は、すべての媒介がリリース2012.1以降になっている必要があります。

事前定義された定数

RD_KAFKA_CONSUMER ( integer ) RD_KAFKA_OFFSET_BEGINNING ( integer ) kafkaパーティションキューの最初からの消費を開始する: 最も古いメッセージ。 RD_KAFKA_OFFSET_END ( integer ) kafkaパーティションキューの最後から消費を開始する: 最も新しいメッセージ。 RD_KAFKA_OFFSET_STORED ( integer ) オフセットストアから取り出されたオフセットから消費を開始する。 RD_KAFKA_PARTITION_UA ( integer ) 割り当てられていないパーティションは、設定されたあるいはデフォルトのパーティショナーを使ってパーティションされなければならないメッセージのために、プロデューサAPIによって使われます。 RD_KAFKA_PRODUCER ( integer ) RD_KAFKA_VERSION ( integer ) RD_KAFKA_RESP_ERR__BEGIN ( integer ) RD_KAFKA_RESP_ERR__BAD_MSG ( integer ) ローカル: 有効ではないメッセージ形式 RD_KAFKA_RESP_ERR__BAD_COMPRESSION ( integer ) ローカル: 無効な圧縮されたデータ RD_KAFKA_RESP_ERR__DESTROY ( integer ) ローカル: ブローカーのハンドルが破棄された RD_KAFKA_RESP_ERR__FAIL ( integer ) ローカル: ブローカーとの通信エラー RD_KAFKA_RESP_ERR__TRANSPORT ( integer ) ローカル: ブローカーの転送エラー RD_KAFKA_RESP_ERR__CRIT_SYS_RESOURCE ( integer ) ローカル: 致命的なシステムのリソース障害 RD_KAFKA_RESP_ERR__RESOLVE ( integer ) ローカル: ホストの解決の失敗 RD_KAFKA_RESP_ERR__MSG_TIMED_OUT ( integer ) ローカル: メッセージのタイムアウト RD_KAFKA_RESP_ERR__PARTITION_EOF ( integer ) ブローカー: もうメッセージが無い ブローカーの定義 RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION ( integer ) ローカル: 不明なパーティション RD_KAFKA_RESP_ERR__FS ( integer ) ローカル: ファイルまたはファイルシステムのエラー RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC ( integer ) ローカル: 不明なトピック RD_KAFKA_RESP_ERR__ALL_BROKERS_DOWN ( integer ) ローカル: 全てのブローカーの接続がダウン RD_KAFKA_RESP_ERR__INVALID_ARG ( integer ) ローカル: 無効な引数または設定 RD_KAFKA_RESP_ERR__TIMED_OUT ( integer ) ローカル: タイムアウト RD_KAFKA_RESP_ERR__QUEUE_FULL ( integer ) ローカル: ブローカーの定義 キューが一杯 RD_KAFKA_RESP_ERR__ISR_INSUFF ( integer ) ローカル: ISR のカウントが不十分 RD_KAFKA_RESP_ERR__NODE_UPDATE ( integer ) ローカル: ブローカーのノードが更新された RD_KAFKA_RESP_ERR__SSL ( integer ) ローカル: SSL エラー RD_KAFKA_RESP_ERR__WAIT_COORD ( integer ) ブローカーの定義 ブローカーの定義 ブローカーの定義 ローカル: コーディネーター待ち RD_KAFKA_RESP_ERR__UNKNOWN_GROUP ( integer ) ローカル: 不明なグループ RD_KAFKA_RESP_ERR__IN_PROGRESS ( integer ) ローカル: 進行中のオペレーション RD_KAFKA_RESP_ERR__PREV_IN_PROGRESS ( integer ) ローカル: 進行中の以前のオペレーション RD_KAFKA_RESP_ERR__EXISTING_SUBSCRIPTION ( integer ) ローカル: 既存の購読 RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS ( integer ) ローカル: パーティションの割り当て RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS ( integer ) ローカル: パーティションの取り消し RD_KAFKA_RESP_ERR__CONFLICT ( integer ) ローカル: 使用の衝突 RD_KAFKA_RESP_ERR__STATE ( integer ) ローカル: 誤った状態 RD_KAFKA_RESP_ERR__UNKNOWN_PROTOCOL ( integer ) ブローカーの定義 ローカル: 不明なプロトコル RD_KAFKA_RESP_ERR__NOT_IMPLEMENTED ( integer ) ローカル: 未実装 RD_KAFKA_RESP_ERR__AUTHENTICATION ( integer ) ローカル: ブローカーの定義 ブローカーの定義 認証失敗 RD_KAFKA_RESP_ERR__NO_OFFSET ( integer ) ローカル: オフセットが格納されていない RD_KAFKA_RESP_ERR__END ( integer ) RD_KAFKA_RESP_ERR_UNKNOWN ( integer ) ブローカーの定義 不明なブローカーのエラー RD_KAFKA_RESP_ERR_OFFSET_OUT_OF_RANGE ( integer ) ブローカー: オフセットが範囲外 RD_KAFKA_RESP_ERR_INVALID_MSG ( integer ) ブローカー: 無効なメッセージ RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART ( integer ) ブローカー: 不明なトピックあるいはパーティション RD_KAFKA_RESP_ERR_INVALID_MSG_SIZE ( integer ) ブローカー: 無効なメッセージのサイズ RD_KAFKA_RESP_ERR_LEADER_NOT_AVAILABLE ( ブローカーの定義 ブローカーの定義 integer ) ブローカー: リーダーが利用不可 RD_KAFKA_RESP_ERR_NOT_LEADER_FOR_PARTITION ( integer ) ブローカー: パーティションについてのリーダーでは無い RD_KAFKA_RESP_ERR_REQUEST_TIMED_OUT ( integer ) ブローカー: リクエストのタイムアウト RD_KAFKA_RESP_ERR_BROKER_NOT_AVAILABLE ( integer ) ブローカー: ブローカーが利用不可 RD_KAFKA_RESP_ERR_REPLICA_NOT_AVAILABLE ( integer ) ブローカー: レプリカが利用不可 RD_KAFKA_RESP_ERR_MSG_SIZE_TOO_LARGE ( integer ) ブローカー: メッセージサイズが長すぎる RD_KAFKA_RESP_ERR_STALE_CTRL_EPOCH ( integer ) ブローカー: StaleControllerEpochCode RD_KAFKA_RESP_ERR_OFFSET_METADATA_TOO_LARGE ( integer ) ブローカー: オフセットのメタデータ文字列が長すぎる RD_KAFKA_RESP_ERR_NETWORK_EXCEPTION ( integer ) ブローカー: 応答が受け取られる前にブローカーが切断された RD_KAFKA_RESP_ERR_GROUP_LOAD_IN_PROGRESS ( integer ) ブローカー: グループのコーディネータがロードを進行中 RD_KAFKA_RESP_ERR_GROUP_COORDINATOR_NOT_AVAILABLE ( integer ) ブローカー: グループコーディネータが利用不可 RD_KAFKA_RESP_ERR_NOT_COORDINATOR_FOR_GROUP ( integer ) ブローカー: グループについてのコーディネータでは無い RD_KAFKA_RESP_ERR_TOPIC_EXCEPTION ( integer ) ブローカー: 無効なトピック RD_KAFKA_RESP_ERR_RECORD_LIST_TOO_LARGE ( integer ) ブローカー: メッセージのバッチが設定されたサーバセグメントのサイズより大きい RD_KAFKA_RESP_ERR_NOT_ENOUGH_REPLICAS ( integer ) ブローカー: 十分なin-syncレプリカが無い RD_KAFKA_RESP_ERR_NOT_ENOUGH_REPLICAS_AFTER_APPEND ( integer ) ブローカー: 不十分な数のin-syncレプリカにメッセージが書き込まれた ブローカーの定義 RD_KAFKA_RESP_ERR_INVALID_REQUIRED_ACKS ( integer ) ブローカー: 無効なacks値の要求 RD_KAFKA_RESP_ERR_ILLEGAL_GENERATION ( integer ) ブローカー: 指定されたグループの生成idが無効 RD_KAFKA_RESP_ERR_INCONSISTENT_GROUP_PROTOCOL ( ブローカーの定義 integer ) ブローカー: 矛盾したグループ プロトコル RD_KAFKA_RESP_ERR_INVALID_GROUP_ID ( integer ) ブローカー: 無効なgroup.id RD_KAFKA_RESP_ERR_UNKNOWN_MEMBER_ID ( integer ) ブローカー: 不明なメンバー RD_KAFKA_RESP_ERR_INVALID_SESSION_TIMEOUT ( integer ) ブローカー: 無効なセッションのタイムアウト RD_KAFKA_RESP_ERR_REBALANCE_IN_PROGRESS ( integer ) ブローカー: グループのリバランスが進行中 RD_KAFKA_RESP_ERR_INVALID_COMMIT_OFFSET_SIZE ( integer ) ブローカー: コミットしたオフセットのデータサイズが無効 RD_KAFKA_RESP_ERR_TOPIC_AUTHORIZATION_FAILED ( integer ) ブローカー: トピックに認証が失敗 RD_KAFKA_RESP_ERR_GROUP_AUTHORIZATION_FAILED ( integer ) ブローカー: グループの認証が失敗 RD_KAFKA_RESP_ERR_CLUSTER_AUTHORIZATION_FAILED ( integer ) ブローカー: ブローカーの定義 クラスタの認証が失敗 RD_KAFKA_CONF_UNKNOWN ( integer ) RD_KAFKA_CONF_INVALID ( integer ) RD_KAFKA_CONF_OK ( integer ) RD_KAFKA_MSG_PARTITIONER_RANDOM ( integer ) ランダムなパーティショナー。これはlibrdkafka 0.8ではデフォルトのパーティショナーでした。パーティションをランダムに割り当てます。 RD_KAFKA_MSG_PARTITIONER_CONSISTENT ( integer ) 首尾一貫したパーティショナー。全く同じキーを全く同じパーティションにマップするために一貫性のあるハッシュを使う。ハッシュ関数としてCRC32を使う。キーが無い、あるいは空のキーを持つメッセージは常に同じパーティションに割り当てられる。 RD_KAFKA_LOG_PRINT ( integer ) ロガーの出力。メッセージをstderrに出力する。 RD_KAFKA_LOG_SYSLOG ( integer ) syslogロガー。メッセージをsyslogに送信する。 RD_KAFKA_LOG_SYSLOG_PRINT ( integer ) syslog-print パーティショナー。メッセージをsyslogに送信し、それらをstderrに出力する。

Wireless・のおと

MQTT とは
MQTT はブローカー型のメッセージ伝達・再分配プロトコルで、その起源は意外に古く ブローカーの定義 ブローカーの定義 1999 年に IBM と Eurotech 社で開発されたものと言われます。IBM の MQ プロトコルを母体として開発されたため MQ Telemetry Transport の略で MQTT と名付けられたとも言われていますが、MQTT という名前自体には大した意味はありません。そもそも MQTT にはメッセージを溜める(Queue)機能はなく、MQTT という名前は「名が体を現わさない」妙なことになっています。

古典的なクライアント・サーバ型システムの場合、データの発信者と受信者は直接接続していました。これは WEB ブラウザから Amazon だとか Google に接続する場合には問題になりませんが、センサネットワークのように数百数千ものデータソースが存在する場合は問題です。「2階第3会議室の南側の窓の開閉センサーを管理しているノードの IP アドレスは何だ?」のように、クライアントはセンサーノードの数だけ IP アドレスを検出管理しなければなりません。一方、サーバ側では接続数が多くなると処理や消費メモリの負荷が上がり、「何が起きたとき誰に伝えれば良いか?」というデータ配布条件の設定も複雑になる傾向がありました。

mqtt01.jpg

クライアント・サーバモデル
サーバ数が少ない場合は単純

mqtt02.jpg

クライアント・サーバモデル
サーバ台数が増えると級数的に複雑度が増す

一方、「ブローカー型」というのは、データの発信者(Publisher / パブリッシャー)は再分配サーバー(Broker ブローカー)にデータを送り付けるだけでよく、そのデータをどんな条件で誰に再配布するのかはブローカーが処理する形態のシステムです。データの受け取り手はサブスクライバー(Subscriber)と呼ばれます。厄介事をブローカーがまとめて引き受ける中央集権型のシステムですが、ブローカーをクラウドサーバとして解釈するとわかりやすいかと思います。

mqtt03.jpg

ブローカーモデル
接続組み合わせの複雑度はブローカーが引き受ける

MQTT は (SOAP や AJAX のような) HTTP 上の相乗りではなく、独自の通信ポート(TCP 1883, TLS 8883)を使って動作します。プロトコル仕様も HTTP/HTML とは全く異なるバイト単位のバイナリフォーマットで、十数バイト程度の短いメッセージを交換する場合にデータ効率が優れることも特長です。


トピックとメッセージ

さて、データ伝達の基本は「誰」に「何」を伝えるかです。「何」は更に「それを識別する名前」と「その中身」から構成されます。MQTT において「何」は「トピック(Topic)」という文字列で識別されます。トピックはいわゆるファイルシステムのパス構造に似て、/ から始まる任意の階層の名前を付けることができます。MQTT のトピック名「/ から始まる Unicode UTF-8 文字列であること」「全長 65535 バイト以下に収まること」「ヌル文字を含まないこと」「$, #, + は予約語として特別な機能が与えられる」という程度しか既定がなく、非常に自由度が高い特徴があります(※註)。

※註:もっとも原仕様で既定していないというだけの話で、実装系によって異なる既定や上限がある可能性はあります。

MQTT において、トピックとパブリッシャーの間に直接の関係はありません。複数のパブリッシャーが1つのトピックにメッセージを送ることも可能です(※註)。メッセージがどのパブリッシャーから送られたのか MQTT は一切関知しませんし、複数パブリッシャーから「ほぼ同時」にメッセージが送られてきた場合の優先度や到着順序は管理も保証もしません。

※註:誰彼構わずメッセージを送られると困るような場合、ユーザ名とパスワードを使ってトピックへのアクセス条件を制限するようにブローカーを実装することは可能です。これは「パーミッション(Permission)」機能と呼ばれ多くの MQTT ブローカーに実装されていますが、MQTT 仕様は「ユーザ名とパスワードが指定可能である」という枠組みを設けているだけで、それをどのように利用してパーミッションを実現するかは実装に任されています。

データの「中身」については、MQTT は「既定しないこと」を既定しています(※註)。たとえば温度 25 ℃を伝えるのにバイナリの 0x00 0x19 でも単位なし文字列の "25" でも、あるいは単位付き文字列の "25C" でも "77F" ブローカーの定義 でも "298K" でも、アプリケーションが解釈できればそれで良いというのです。従来のメッセージ型プロトコルが何らかのデータ型(整数や文字列)を持っていたのに対し、この自由度の高さは異様にすら思えます。とはいえ、本当にパブリッシャー毎にバラバラのメッセージを送られると破綻してしまうので、おそらく現実的には XML や JSON など、既に WEB 世界で用いられているフォーマットが使用されるでしょう。なお MQTT のメッセージ長はちょっと変わったエンコード形式を採用しており、表現可能な最大長は 256M バイトになります。

※註:仕様書原文では "The content and format of the data is application specific".

データを「誰に」伝えるかについては、MQTT はセッションをもって「誰」を識別します。つまり MQTT の受信側(サブスクライバー)側はつなぎっ放しで使うことを前提としており、例えば e-mail のように切断状態にあった「誰か」がログインして溜まっていたメッセージをまとめて受信するような運用は想定されていません(※註)。「MQTT という名前に反して Queue 機能はない」と冒頭に書いた通りです。

※註:ただし、トピックに送られた最後のメッセージを1つだけ溜める「リテイン(Retain)」という機能はオプション仕様として既定されています。

サブスクライバーはブローカーに対し、自分が受信したいトピックを指定します。そのトピックに対して(パブリッシャーから)メッセージが送られると、メッセージは全てのサブスクライバーに再配布されます。メッセージ配送システムにありがちな、ビットマスクや AND/OR 条件を組み合わせた配布条件フィルタのような難しい機能はありません(※註)。

※註:これも、ユーザ名に紐づけてメッセージの再配布条件を設定する実装は可能です。それを実装するかどうか、どれだけ複雑な条件設定を可能にするかは実装と運用に任されます。

MQTT のサブスクライバー側には、複数のトピックをまとめて受信する「ワイルドカード」という仕組みがあります。これは上で「予約語として特別な機能が与えられる」とした + と # の組み合わせで指定されます。
MQTT のトピックにおいて + は単一階層の任意一致、# は「それ以降の全ての一致」を示します。ワイルドカードは階層単位で用いられ、文字列の部分一致には用いられません。「/bedroom/#」というトピックは「/bedroom/ で始まる全てのトピック」、「/+/light」は「2階層で2層目が light の全てのトピック」を対象とします。「/+room」だとか「/bed#」のように文字列と組み合わせて使うことはできません。

ワイルドカードを使った場合、サブスクライバーは(当然ながら)複数の異なるトピックからのメッセージを受信することになります。しかし MQTT ではメッセージの優先度や到着順序は管理も保証もしませんし、それどころかメッセージがどのトピックから送られたかも示してくれません。この辺も「アプリケーション依存」なので、「メッセージにトピック情報を添付することにする」とか「そもそもワイルドカードには頼らない」とか、システムとして何らかの解決法を定める必要があります。

MQTT を使ってみる
MQTT には Python や JavaScript や Erlang といった「IT 屋さん言語」で書かれた実装も多く、ネット上の MQTT 解説にはそれらを駆使したものが多いのですが、今回は「組み込み屋さん」らしくベタの C 言語で書かれた mosquitto というパッケージを使ってました。バージョンは 1.4.ブローカーの定義 9 ですが、バージョンが問題になるほど難しいことはやりません。

mosquitto のソースをダウンロードして make すると、src/ 下にブローカーである mosquitto が、client/ 下にパブリッシャーの ブローカーの定義 mosquitto_pub とサブスクライバーの mosquitto_sub が生成されるはずです。
まず最初にブローカーを起動します。-v オプションを付けて接続や送受信の情報を逐一表示させるようにすると、何がどう動いているのかわかりやすいでしょう。

$ ./src/mosquitto -v
1470848533: mosquitto version ブローカーの定義 1.4.9 (build date 2016-08-09 09:39:33-0700) starting
1470848533: Using default config.
1470848533: Opening ipv4 listen socket on port 1883.
1470848533: Opening ipv6 listen socket on port 1883.

次に別ウィンドウを開けてサブスクライバーを起動します。-h は IP アドレスないしホスト名、-t はトピックを指定します。

次にもう一つ別ウィンドウを開けてパブリッシャーを起動します。-h と -t はサブスクライバーと同じで、-m がメッセージを示します。

MQTT の簡単な動作例は以上です. これだけ?!そう、これだけ。このように、MQTT はとても単純なプロトコルです。進化の過程で(※註) QoS とか Retain とか Will とかのオプション機能も追加されてきたのですが、その辺を全く使わなくとも、もっとも単純なかたちで「とりあえず動かしてみる」ことができるのが MQTT の魅力の一つです。

※註:記事執筆時点で MQTT 仕様の最新バージョンは 3.1.1 ですが、前バージョンの 3.1 からかなり大幅な改訂が行われ直接互換性の無い部分すらあり少々の混乱を招いたようです。何で 3.2 とか 4.0 にせず 3.1.1 にしたんでしょうかね?


MQTT とセキュリティ

現実的には、素の TCP 1883 ポートで MQTT を動かすことはまず無いでしょう。クラウド上で稼動させるなら特に、TLS セキュリティ層を挟んで少なくとも片方向(ブローカー/サーバ側)の認証と暗号化を行う運用がほぼ必須になると思います。パブリッシャーやサブスクライバーの認証は TLS 暗号回線上で ブローカーの定義 Username/Password を用いて行うことになると思われますが、クライアント証明書を用いた TLS の双方向認証を必須とすることも可能で、このへんは使用する実装系と運用上の要件に応じたインテグレーションが必要になります。

TLS を用いると接続・切断のたびに証明書の交換と検証が発生し、これは通信時間と消費電力の増大を招きます。バッテリ駆動で間欠的なデータ発行を行うセンサノードでは大問題で、ここをどう工夫するかがインテグレーターに問われることになります。データ送信間隔が短い場合は下手に切断・再接続するより、TLS 回線を接続しっ放しで省電力モードに入れたほうが効率的かも知れません。データ送信間隔が充分に長いなら切断・電源遮断して毎回再起動・再接続したほうが効率的かも知れません。何をもって「短い」とか「長い」と判断するかは待機時消費電力と再接続時・再認証時の消費電力との兼ね合いで、使用する MCU の性能や証明書の鍵長にも左右されるので一概には言えません。TLS を常時通電のアップリンクルータにトンネルとして実装して、末端ノードとアップリンクルータ間はデータリンク層のセキュリティ機能(WiFi WPA2 など)に頼ることが正解になるかも知れません。原理が単純で自由度が高いだけに、使いこなすにはそれなりにノウハウが要求されるのも MQTT の特徴ではないかと思います。


まとめ

以上、MQTT について簡単にまとめてみました。コマンドやパケットフォーマットの詳細にはあえて踏み込んでいませんが、MQTT は日本でも盛んに実装が行われていて、開発者による充実した日本語の(ホンネの)情報もネットで読むことができます。日本語情報が少ないうえ、往々にして内容が古かったり誤解混じりだったりする Bluetooth とは大違いです。

MQTT はとにかく「アホみたいに単純」なプロトコルで、メッセージフォーマットすら既定せず、運用で直面するであろう多くの課題を「アプリケーション依存」として実装/運用者に丸投げしている印象を受けます。MUST, MUST NOT, SHOULD, SHOULD NOT でガンジガラメにされた過保護管理主義な最近の RFC 仕様にくらべると、何だか3桁時代の RFC を見ているような気になります。こういう仕様が IETF/RFC の枠外から出てきて市場に受け入れつつあるというのは象徴的ですね。

「IPv6 over Bluetooth のはなし」では Bluetooth LE の IPSP を実働させて「スループットは 10Kbit/sec くらい」「こんなので HTTPS を通すのはかなり無謀」と書きましたが、MQTT はこういった低速ネットワークに向くかも知れません。とはいえセキュリティ層に TLS を使用して毎回接続・認証すれば毎回数キロバイトの証明書交換手続きが入るので、HTTP と MQTT のヘッダ長差なんて大した違いではなくなります。MQTT の特長を活かしたシステムとして稼動させるには要求条件と使用するコンポーネントの特性を把握し、利害得失を判断して適切なセッティングを選ぶインテグレーターの手腕が問われることに変わりはないでしょう。

ブローカーの定義

本稿では、韓国の低熟練外国人労働者の受入れ制度である雇用許可制(Employment Permit ブローカーの定義 System:EPS)に関して、国内外から高い評価を受ける「ブローカーの排除に成功した」という点について、これまで日本語文献ではほとんど扱われてきていない韓国現地をはじめとする海外における調査・統計等から示唆される実態を整理する。
※なお、本稿以外の観点も含む、韓国・雇用許可制の実態の把握と日本への示唆については、以下のレポートを参照されたい。

1. 雇用許可制が評価されるポイント

韓国では、2003年以前まで、日本の技能実習制度をベンチマークした産業研修制度を運用していた。だが、韓国国内での人権侵害、劣悪な労働環境等が問題となった結果、2003年の大統領選では与野党候補ともに同制度の廃止と新制度の設立を公約に掲げた。その結果、2004年から実習・研修といった建前をやめ、外国人を名実とも労働者として扱い、外国人労働者の雇用を希望する企業に政府が雇用許可を与える制度(雇用許可制)を開始した。
雇用許可制の制度詳細は別稿を参照されたいが(佐野 2017、労働政策研究・研修機構2018、三菱UFJリサーチ&コンサルティング 2019)、雇用許可制で就労する外国人労働者数は、2020年末時点で約23.7万人おり、長期在留者の14.9%、外国人労働者の29.6%(2020年5月15日時点)を占め、韓国における主要なグループを形成している。国籍は、多い順にカンボジア(3.ブローカーの定義 ブローカーの定義 ブローカーの定義 3万人)、ネパール(3.1万人)、ベトナム(3.1万人)、インドネシア(2.4万人)、フィリピン(2.1万人)でそれぞれ全体の10-15%程度を占めている(法務部2020a、2020b)。 雇用許可制は国際的に高い評価が与えられている。2007年には国際移住機構(IOM)のマッキンリー事務総長が「雇用許可制は良いシステムで多くの国にとって良いモデルになる」と評価し、2011年には国連の「公共行政における腐敗の防止との戦い」分野における最も権威のある賞である「国連公共行政大賞」を受賞した。
特に評価されているポイントが「ブローカーの排除に成功した」という点である。日本では、特に技能実習生がブローカーを利用し、多額の借金を背負って来日する事例が問題視されている一方、韓国の雇用許可制では、送出しから受入れまでの過程を政府間(Government to Government)で行う、いわゆる「G-to-G」の形のため、ブローカーの介在を阻止し、過剰な仲介斡旋費用はかからず、借金を背負った状態での入国は起きえないとされる。
この点について、国内外の先行研究においても、「ブローカーによる中間搾取が排除されている」(指宿 2018:92)、「営利的事業者(ブローカー)の仲介プロセスは排されている」(宮島 2019:62)とされ、「雇用許可制下での労働者が負担する仲介斡旋費用は極めて小さい」(ADBI・OECD・ILO 2019:32)、「中間搾取を取り除くことに成功」(澤田 2020:261)しているなどと評価されている。

2. 実態はどうなっているのか

図表1 雇用許可制で韓国入国までにかかった費用(2010年、2013年、2015年)

グラフ 雇用許可制で韓国入国までにかかった費用

(出所)韓国産業人力公団(2015)、法務部(2013)、法務部(2010)をもとに作成
(出所注)1)各項目のケースの数と平均は0と欠損値を除いた有効回答のみ算出したもの。ただし、総費用は各項目の合計であり、全ケースが含まれる。2)すべての項目、F値はp <0.05レベルで有意。
(注)調査対象年の雇用許可制下で在留する外国人労働者を対象とした調査結果(2015年:n=1,975、2013年:n=1,234、2010年:n=654)

また、世界銀行の移住に関するシンクタンクであるKNOMAD(The World Bank’s Global Knowledge Partnership ブローカーの定義 on Migration and Development)は、2014年から数年間にわたり「移住コスト研究プロジェクト」を実施し、パイロット調査として、ベトナム・インドネシア・タイから韓国へ雇用許可制で入国した119名の労働者に対するインタビュー調査を行った(Abella & Martin 2014)。
その結果をみると、1)雇用許可制では認められていない仲介斡旋費用を支払っている者が27名(約23%)おり、その金額は900USドルから2,200USドルまで開きがあり、特にベトナム出身者の総額の散らばりが大きい。また、2)韓国入国・就労のために借金をした人は、47名(約40%)おり、最高8,000USドルの借金を背負い韓国に入国していることが明らかになっている(下記図表参照)。

図表2 韓国入国時点の借金総額、調査時点の残りの借金(単位:USドル)

ブローカーの定義
韓国入国時点の借金総額 調査時点での残りの借金総額
平均値 1,973 886
中央値 1,551 337
最小値 19 0
最大値 8,000 4,850
標準偏差 1,732 1,248
件数(人) 47 46

図表3 雇用許可制で働くベトナム人労働者のインタビュー抜粋

  • 韓国に来るために、 ブローカーに支払わなければならない費用がとても高いです。私が来るときは、10,000ドルでした。 …その個人が出した10,000ドルのうち、500ドルが地方の人材紹介会社の分け前になります。残り9,500ドルのうち5000ドルは、中央労働部に行き、4500ドルは、地方労働部がもらいました。… もしハノイから離れた地方で申請する場合、さらなるブローカーや送出会社の段階を経る必要があります。 そのようなステップが複数回あるほど多くのお金が必要になります。
  • ベトナムでブローカーを介さず韓国に来られる方法はありません。 ブローカー費用は少なくても6〜700万ウォン(筆者注:約60~70万円)、通常は1,000万ウォン(筆者注:約100万円)以上です。 もし個人的に、ベトナムの労働部に直接申請をしようとすれば、はなから申請を受け付けてくれないか、申請を受け付けても処理をしてくれません。製造業でも、農業でも、漁業でも同様です。ブローカーは「出国するとき、空港で、お金をいくら必要だったか聞かれたら、1,000ドルだったと答えろ。そうでなければ出国できない。」と言います。だからみんな、 実際に支払った費用を隠すでしょう。

3. 調査結果からの示唆

韓国・旧労働部(2007)の調査によれば、旧産業研修制度時代の2001年の平均入国費用が3,509USドルであったが、その後2007年には平均1,097USドルへ減少しており、こうした結果に基づき雇用許可制は国内外で一定の評価がなされてきた。ただし、この数値は全体平均値であり、また、本当の金額は労働者本人が隠している可能性も示唆されていることを踏まえると、政府間による「G-to-G」の送出し・受入れが、すべての問題を解決するわけではないといえる。
また、今回みたいくつかの調査結果から示唆されることとして、入国前の仲介斡旋費用やブローカーの発生、さらには借金の有無については、送出し国による違いが大きいことが指摘できる。
前掲の図表1では、雇用許可制で働く外国人労働者が韓国入国までにかかった費用を整理したが、国によってブローカーや非公式費用の発生有無、金額のばらつきが異なっていた。弊社が2020年秋に日本において介護分野で働く外国人労働者に対して行ったアンケート調査でも、来日費用の工面方法として、借金をしている割合が国によって大きく異なっている(下記図表4)。特に、ミャンマー(47.1%)、ベトナム(31.1%)では費用工面方法として借金をしている割合が高い。反対にフィリピンでは14.5%にとどまっているが、背景には、送出し機関が移住労働者本人から仲介斡旋費用を徴収することを、フィリピン政府が原則禁止していることが影響していると考えられる(借金の14.ブローカーの定義 ブローカーの定義 5%は航空チケット等の実費が中心と推察される)。

図表4 介護分野で働く外国人労働者の来日費用の工面方法

グラフ 介護分野で働く外国人労働者の来日費用の工面方法

さらに、海外におけるDilip Ratha & Genesh Seshan (2018)による研究では、主にアジア各国(ベトナム、フィリピン、インド、ネパール等)から中東やマレーシアへ向かう労働者の移住費用とそのなかで借金の占める割合を調査しており、ここでも、同じ目的国であっても出身国によって借金の割合が異なる実態が明らかになっている。特にベトナムからマレーシアへの移動ルートでは借金の割合が調査対象国中最大であり、ベトナム人労働者の8割弱(内訳は無利子の借金49%、有利子の借金29%)が借金を背負った状態で移動していることがわかっている。
ベトナムにおける労働力の送出し事情について、筆者らが行った研究に基づくと、一口に「送出し機関」といっても、1)国営の送出し機関、2)民間の大規模な送出し機関(自力で人材募集・訓練が可能)、3)民間の小規模の送出し機関(自力では人材募集・訓練ができず、ブローカーや外部語学学校と提携)、4)違法状態の送出し機関(政府認可の送出し機関ライセンスが得られないため、ライセンスを有する別の送出し機関に人材を紹介して仲介斡旋費用を得る)などバリエーションがあり、どの機関・ルートを使うかよって、目的地が同じでも最終的にかかる費用総額には大きな違いが生じることが明らかになっている(是川他 2020)。 ブローカーの定義
つまり、移住労働に伴うブローカーや借金の発生は、受入れ国の制度だけでなく、送出し国側の制度も反映して決まるといえる。そのため、受入れ側の日本の制度自体の見直しと平行して、送出し国側の制度や実態にも目を向け、各国の移住の構造や、仲介斡旋費用が発生するメカニズムを詳細に把握する作業が求められる 1 。

Gigamon

既存ネットワークシステムの複雑化、運用負荷の増大、セキュリティ製品やモニタリング製品の投資コスト増加を解消するソリューションを提供しています。

イメージ画像

Gigamonの基本機能

トラフィックコピー

トラフィックコピー

アグリゲーション

アグリゲーション

トラフィックフィルタ

トラフィックフィルタ

負荷分散 & フェイルオーバー

負荷分散 & フェイルオーバー

Gigamonの拡張機能

Gigamonの拡張機能

【Pick Up】ソリューション

Operations Bridge はマルチクラウドおよびオンプレミスの自動検出、監視、修正を自動化するフルスタックの AIOps ソリューションです。

関連記事

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次
閉じる