Node-REDでgRPC：1000x10回の処理時間をhttpと比較

# gRPC
gRPCはHTTP/2通信でRPC(remote procedure callができるフレームワークです。.protoファイルというインタフェースを定義をサーバとクライアントで共有して、フレームワークがパラメータのチェックなどしてくれます。
他の言語だとOpenAPI/Swaggerのようにコード生成が必要ですが、node.jsではコード生成が不要で、さらにNode-REDを使えばほとんど設定だけで簡単に実装できます。開発中のソフトのエミュレータやテストスタブ/ドライバとして便利に使うことができます。
gRPCはバイナリを送ることやストリーム通信も可能であるなどのメリットがあるのですが、普通の通信でもHTTP/2によって早くなっているはずです。使い慣れたNode-REDがどのくらい早くなるか気になったので、速度を測定してみました。

# 評価方法
今回はhttpのPOSTとの比較を1000回呼び出しを10セット行って処理時間を比較しました。
なお、今回はWSL(V1)のNode-RED内のローカル通信で行いました。「こんなものかな」という雰囲気をお楽しみください。環境だけでなく、パラメータのデータ形式や通信方式など、評価としては不十分な点も多々ありますので、気になる方はフローを修正してご自身で試していただけたらと思います。

# 結果：
3倍弱の速度が出ているようです。

|        | HTTP | gRPC |
|-------:|-----:|-----:|
| 1回目  |  6523|  2640|
| 2回目  |  5987|  2133|
| 3回目  |  5716|  2168|
| 4回目  |  5870|  1852|
| 5回目  |  5987|  1784|
| 6回目  |  5614|  1763|
| 7回目  |  5396|  1745|
| 8回目  |  5441|  1889|
| 9回目  |  5500|  1775|
|10回目  |  5858|  1827|
|平均(秒)|5.7892|1.9576|

# フロー
![Screenshot 2021-12-24 at 07-54-11 Node-RED.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147007/44ac5dd0-9d3c-d2b8-6ecb-0294d50e64c5.png)

# コード
読み込んで使ってください
<div class="highlight"><pre><code>
[{"id":"f6d68618250ca67f","type":"tab","label":"HTTPとgRPC","disabled":false,"info":"","env":[]},{"id":"e95f41214660dee0","type":"inject","z":"f6d68618250ca67f","name":"","props":[{"p":"payload"},{"p":"topic","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"id\":123456,\"name\":\"test\"}","payloadType":"json","x":130,"y":80,"wires":[["0d5edbe239b1896a"]]},{"id":"f81476510ec5f8e4","type":"debug","z":"f6d68618250ca67f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":660,"y":220,"wires":[]},{"id":"5fb1c2df8eae1e12","type":"http in","z":"f6d68618250ca67f","name":"","url":"/http","method":"post","upload":false,"swaggerDoc":"","x":170,"y":300,"wires":[["37be881fb460ae59"]]},{"id":"0e9cc56c988dc971","type":"http response","z":"f6d68618250ca67f","name":"","statusCode":"","headers":{"Content-Type":"application/json"},"x":620,"y":300,"wires":[]},{"id":"b1f8b6a64988d025","type":"http request","z":"f6d68618250ca67f","name":"","method":"POST","ret":"obj","paytoqs":"ignore","url":"http://localhost:1880/http","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":450,"y":140,"wires":[["4e87001263af2e43"]]},{"id":"a71e4f38fcaca3d3","type":"change","z":"f6d68618250ca67f","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"id\":123456,\"name\":\"test\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":250,"y":140,"wires":[["b1f8b6a64988d025"]]},{"id":"4e87001263af2e43","type":"function","z":"f6d68618250ca67f","name":"","func":"msg.counter = msg.counter+1\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":640,"y":140,"wires":[["6c52fd1ba44a5aef"]]},{"id":"6c52fd1ba44a5aef","type":"switch","z":"f6d68618250ca67f","name":"","property":"counter","propertyType":"msg","rules":[{"t":"lt","v":"1000","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":310,"y":220,"wires":[["a71e4f38fcaca3d3"],["c4a1a4474f7478bf"]]},{"id":"1f023ef9fb240d3f","type":"debug","z":"f6d68618250ca67f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":660,"y":540,"wires":[]},{"id":"88a6762b8302f60f","type":"change","z":"f6d68618250ca67f","name":"","rules":[{"t":"set","p":"counter","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":400,"wires":[["d3739dc3caf9689f"]]},{"id":"0b16db712fc56de0","type":"function","z":"f6d68618250ca67f","name":"","func":"msg.counter = msg.counter+1\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":460,"wires":[["90cd9e63946ba227"]]},{"id":"90cd9e63946ba227","type":"switch","z":"f6d68618250ca67f","name":"","property":"counter","propertyType":"msg","rules":[{"t":"lt","v":"1000","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":290,"y":540,"wires":[["d3739dc3caf9689f"],["0709b9bb353b5616"]]},{"id":"0699e370b014662e","type":"grpc-response","z":"f6d68618250ca67f","name":"","x":610,"y":620,"wires":[]},{"id":"f130b9ebdb4402b9","type":"grpc-register-function","z":"f6d68618250ca67f","name":"","server":"8cb71b4d968ba4f2","service":"Greeter","method":"SayHello","x":180,"y":620,"wires":[["a57a172ef664a814"]]},{"id":"d3739dc3caf9689f","type":"grpc-call","z":"f6d68618250ca67f","name":"","server":"8cb71b4d968ba4f2","service":"Greeter","method":"SayHello","chain":"","key":"","x":230,"y":460,"wires":[["0b16db712fc56de0"]]},{"id":"2e42051c498d3367","type":"inject","z":"f6d68618250ca67f","name":"","props":[{"p":"payload"},{"p":"topic","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"id\":123456,\"name\":\"test\"}","payloadType":"json","x":140,"y":400,"wires":[["88a6762b8302f60f"]]},{"id":"37be881fb460ae59","type":"change","z":"f6d68618250ca67f","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"message\":\"OK!\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":300,"wires":[["0e9cc56c988dc971"]]},{"id":"a57a172ef664a814","type":"change","z":"f6d68618250ca67f","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"message\":\"OK!\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":390,"y":620,"wires":[["0699e370b014662e"]]},{"id":"c4a1a4474f7478bf","type":"function","z":"f6d68618250ca67f","name":"","func":"msg.payload = Date.now() -msg.topic;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":220,"wires":[["f81476510ec5f8e4"]]},{"id":"0709b9bb353b5616","type":"function","z":"f6d68618250ca67f","name":"","func":"msg.payload = Date.now() -msg.topic;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":540,"wires":[["1f023ef9fb240d3f"]]},{"id":"0d5edbe239b1896a","type":"change","z":"f6d68618250ca67f","name":"","rules":[{"t":"set","p":"counter","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":290,"y":80,"wires":[["a71e4f38fcaca3d3"]]},{"id":"cb132ac35c2e449c","type":"comment","z":"f6d68618250ca67f","name":"HTTP呼出し1000回","info":"","x":140,"y":40,"wires":[]},{"id":"bdc6dfb867aa2128","type":"comment","z":"f6d68618250ca67f","name":"HTTPサーバ","info":"","x":110,"y":260,"wires":[]},{"id":"58d487f0614a7632","type":"comment","z":"f6d68618250ca67f","name":"GRPC呼出し1000回","info":"","x":140,"y":360,"wires":[]},{"id":"a7711b6a35746825","type":"comment","z":"f6d68618250ca67f","name":"GRPCサーバ","info":"","x":120,"y":580,"wires":[]},{"id":"8cb71b4d968ba4f2","type":"grpc-server","port":"5001","name":"","server":"localhost","protoFile":"syntax = \"proto3\";\npackage hello;\n \nservice Greeter {\n  rpc SayHello(HelloRequest) returns (HelloReply) {}\n}\n \nmessage HelloRequest {\n  int32 id = 1;\n  string name = 2;\n}\n \nmessage HelloReply {\n  string message = 1;\n}","ca":"","chain":"","key":"","mutualTls":false,"localServer":true}]
</code></pre></div>

# 参考文献
参考にさせていただきました。ありがとうございます。
* [node-red-contrib-grpc](https://flows.nodered.org/node/node-red-contrib-grpc)
* [Node.jsでgRPCを動かそう](https://qiita.com/tomsan96/items/34093c5af6e02c59f8e4)
* [Node.jsではじめるgRPC [@grpc/proto-loader]](https://noumenon-th.net/programming/2019/07/05/grpc/)

# おまけ
設定の方法がわからない方は以下をご覧ください。
[Node-REDでgRPC：はじめ方](https://qiita.com/sakaba37/items/a9028bfe61284e00fa68)