著者:重松 亜夢
今回は、「gRPC」という通信プロトコルを使った、Webアプリケーションの作成方法を紹介します。gRPCを使うことで、通信量が減らせます。最近注目のマイクロサービスの連携にも活用できます。
シェルスクリプトマガジン Vol.72は以下のリンク先でご購入できます。![]()
![]()
図3 「pb/picture.proto」ファイルに記述する内容
syntax = "proto3";
option go_package = "example.com/user_name/sample/pb/go/picture";
package picture;
service Picture {
rpc GetPictures (GetPicturesRequest) returns (GetPicturesReply) {}
}
message GetPicturesRequest {
uint32 num = 1;
}
message GetPicturesReply {
repeated bytes pictures = 1;
}
図4 「pb/protoc-web/Dockerfile」ファイルに記述する内容
FROM node:15-buster
WORKDIR /pb
RUN npm i rimraf -g
RUN curl -L -O https://github.com/protocolbuffers/protobuf/releases/download/v3.15.8/protoc-3.15.8-linux-x86_64.zip
RUN curl -L -O https://github.com/grpc/grpc-web/releases/download/1.2.1/protoc-gen-grpc-web-1.2.1-linux-x86_64
RUN unzip protoc-3.15.8-linux-x86_64.zip && cp ./bin/protoc /usr/local/bin/. && chmod +x /usr/local/bin/protoc
RUN cp protoc-gen-grpc-web-1.2.1-linux-x86_64 /usr/local/bin/protoc-gen-grpc-web && chmod +x /usr/local/bin/protoc-gen-grpc-web
図5 「pb/scripts/picture-compile.sh」ファイルに追記する内容
docker build protoc-web -t streaming-protoc-web
mkdir -p js/picture
docker run -v "$(pwd):/pb" -w /pb --rm streaming-protoc-web \
protoc --proto_path=. picture.proto \
--js_out=import_style=commonjs:js/picture \
--grpc-web_out=import_style=typescript,mode=grpcwebtext:js/picture
mkdir -p ../services/client/src/pb
cp -r ./js/* ../services/client/src/pb/
図6 「Makefil e」ファイルの変更内容
proto: pb/js/picture/picture_pb.js
# make .proto
pb/js/picture/picture_pb.js: pb/picture.proto
bash ./pb/scripts/picture-compile.sh
図8 「docker-compose.yaml」ファイルに追加する内容
proxy:
container_name: sample-proxy-container
image: envoyproxy/envoy-dev:1f642ab20b8975654482411537a6bdc5e2f6c4f6
ports:
- "8080:8080"
volumes:
- ./services/proxy/envoy.yaml:/etc/envoy/envoy.yaml
図9 「services/client/src/components/Picture.tsx」ファイルの内容
import { useState } from 'react';
import { GetPicturesRequest, GetPicturesReply } from "../pb/picture/picture_pb";
import { PictureClient } from "../pb/picture/PictureServiceClientPb";
import { Error } from 'grpc-web';
export const Picture = () => {
const [num, setNumber] = useState(1); // 枚数の指定
const [pictures, setPictures] = useState<JSX.Element[]>([]);
const jspb = require('google-protobuf');
const client = new PictureClient(http://${window.location.hostname}:8080/server, {}, {});
const getPictures = () => {
if (num <= 0) return;
const request = new GetPicturesRequest();
request.setNum(num);
client.getPictures(request, {}, (err: Error, response: GetPicturesReply) => {
if (err || response === null) { throw err; }
setPictures(jspb.Message.bytesListAsB64(response.getPicturesList())
.map((images: string, index: number) => (
<img key={${index}} width="200px"
src={data:image/jpg;base64,${window.atob(images)}}
alt="pictures" />
)));
});
}
const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const n = event.target.valueAsNumber;
if (!isNaN(n)) { setNumber(n); }
};
return (
<div>
<input type="number" min="1" defaultValue="1" onChange={onChange} />
<button onClick={getPictures}>GetPictures</button>
<div className="getPictures">{pictures}</div>
</div>
);
}
図10 「services/client/src/App.tsx」ファイルに記述する内容
import {Picture} from './components/Picture'
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<Picture/>
</header>
</div>
);
}
export default App;
