読者です 読者をやめる 読者になる 読者になる

AlpineコンテナでNode.jsからgRPCを利用する場合、libc6-compatが必要

Node.jsでgRPCを利用するアプリケーションを書いてるのだが、Alpine LinuxベースのDockerコンテナで運用する場合、ld-linux-x86-64.so.2 が無くて死ぬという備忘。

Error: Error loading shared library ld-linux-x86-64.so.2: No such file or directory (needed by /nodeapp/node_modules/grpc/src/node/extension_binary/grpc_node.node)
    at Error (native)
    at Object.Module._extensions..node (module.js:597:18)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/nodeapp/node_modules/grpc/src/node/src/grpc_extension.js:38:15)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/nodeapp/node_modules/grpc/src/node/src/client.js:55:12)

これはNodeのgRPCのモジュールに含まれる grpc_node.node のバイナリで共有ライブラリとして ld-linux-x86-64.so.2 に依存していることに起因する。

イメージを軽くするため、基本的にAlpineのDockerイメージはスリム化されており、(https://github.com/nodejs/docker-node)も例外ではない。

解決策

Alpine3.3系以降であれば、apkで libc6-compat をインストールすると解決できる。

RUN apk --update add libc6-compat

これを対象のイメージに仕込んでおく。gRPCの利用例もどんどん増えてきてるのでAlpineのベースコンテナにはもはやおまじないのようにインストールしておいた方が良さそう。

gRPCとServer-Sent Eventsでサーバプッシュできるplasmaを公開しました

この度OpenFRESHプロジェクト(生放送動画配信プラットフォーム FRESH!オープンソースプロジェクト)は、plasmaというプロダクトを公開しました。

f:id:a-yamada:20170403023140p:plain

plasmaとは

plasmaとは何ぞやという話ですが、gRPC streamとServer Sent Event(SSE)を用いた汎用的なServer Pushミドルウェア

github.com

f:id:a-yamada:20170405113205p:plain

Plasmaにイベントデータ(イベントタイプとPayload)を投げると、それを購読(SUBSCRIBE)しているクライアントに通知される。gRPC Streamを使っているので、基本的にgRPC対応言語で書かれたクライアントであれば利用可能。

WebフロントエンドはServer Sent Eventを利用することで購読が可能。SSEに関してはPolyfill(Yaffle/EventSource)があるのでこれを利用すると良い。

また、Dockerイメージも提供している。Plasmaの利用にはRedisが必要だが、docker-compose も用意してあるのですぐに試すことができる。

モチベーション

世の中のWebアプリやスマートフォンアプリはもちろん、サーバ間通信をするアプリケーションは目的の情報の状態変化を知るために定期的にポーリングして変化を検知するという手法が使われてきたが、変化を知るためだけに延々と同じようなリクエストを送り続けるのはリソースの無駄遣いすぎるのでやめたかった。とにかくこれに尽きる。

構想については自分が温めていたものを、3月からプロジェクトにやってきた徳の高い女性声優好きのインターン生 がほぼ一人で実装した感じ。インターン生のミッションとしてはちょうど良いと思いません?

plasmaのユースケース

SUBSCRIBE型のミドルウェアなので、多くのクライアントが特定のイベントを注視したいといったケースで力を発揮する。例えばFRESH!でいえば、番組のViewが放送前→放送開始になるといったケースでの利用を想定している(他にも色々ある)。

また、Microservices間でのイベント通知にも有効的な使い方できる。サービス間をgRPCで繋いでいるようなシステムであれば、似たようなことをしているケースもあるかと思われる。

イベントでPublishされるPayloadはそのままの中身でSubscribeしているクライアントに到達するので、接続しているクライアントによって返すPayloadを変えたい!みたいなケースには基本的に向いていないが、イベントだけ拾ってクライアントに別途APIで取りに行かせるという手法で回避ができる。

今後のアレコレ

性能的にはProductionで使えるレベルであることを確認しているので、今はplasmaを様々な箇所に投入やっていき〜💪なフェーズ。汎用的なミドルウェアとして作っているので、Payload部分だけが型の恩恵に預かれてないので今後どうしていこうかなぁと思いを馳せているところ。

plasmaだけではないけど、FRESH!としては今後も様々なプロダクトを野ざらしにしていく予定であります。