プラットフォームを共有していただきありがとうございます-http://bjbsair.com/2020-04-10/tech-info/53317.html
この時点で、「gRPC」について聞いたことがあるはずです(少なくともタイトルで1回)。この記事では、マイクロサービス間の通信媒体としてgRPCを使用する利点に焦点を当てます。
最初に、アーキテクチャの進化の歴史を簡単に紹介します。次に、RESTの使用(媒体として)と考えられる問題に焦点を当てます。3番目に、gRPCが起動します。最後に、例として開発ワークフローを使用します。
アーキテクチャ開発の簡単な歴史
このセクションでは、各アーキテクチャの長所と短所をリストして説明します(Webベースのアプリケーションに焦点を当てています)。
モノリシック
すべてが1つのパッケージに含まれています。
利点:
· 容易上手
・単一のコードベースですべてのニーズを満たすことができます
短所:
・拡張が難しい(部分的)
・サーバーの読み込み(サーバー側レンダリング)
・ユーザーエクスペリエンスが悪い(読み込み時間が長い)
・拡張が難しい開発チーム
モノリスアーキテクチャ
モノリスアーキテクチャの内部
Monolith v2(フロントエンド)
フロントエンドロジックとバックエンドロジックの明確な分離。バックエンドはまだ巨大です。
利点:
・チームはフロントエンドとバックエンドに分けることができます
・ユーザーエクスペリエンスの向上(クライアントのフロントエンドロジック(アプリケーション))
短所:
・[まだ]拡張が難しい(部分的)
・[まだ]開発チームを拡張するのは難しい
フロントエンド-バックエンドアーキテクチャ
マイクロサービス
すべてがサービス(パッケージ)です。ネットワークを使用して、各ソフトウェアパッケージ間の通信を行います。
利点:
・拡張可能なコンポーネント
・スケーラブルチーム
・柔軟な言語選択(標準の通信方法を使用している場合)
・各パッケージを個別に展開/修復する
短所:
・ネットワークの問題を紹介する(通信の間隔を空ける)
・サービス間の通信に必要なドキュメントとプロトコル
・共有データベースを使用する場合、エラーを特定することは困難です
共有データベースを備えたマイクロサービスアーキテクチャ
サービスごとにスタンドアロンデータベースを備えたマイクロサービスアーキテクチャ
REST(媒体として)と考えられる問題
REST(HTTPベースのJSON)は、その使いやすさから、サービス間の最も一般的な通信方法です。RESTを使用すると、各サービスに任意の言語を使用できる柔軟性が得られます。
典型的なREST呼び出し
ただし、柔軟性にはいくつかの落とし穴があります。開発者には非常に厳密な合意が必要です。次のスケッチは、通常開発中に発生する非常に一般的なシナリオを示しています。
開発者Aは開発者Bにサービスを作って欲しい
要求の形式が正しくありません
期待と実際
問題:
・人間の同意に依存する
・依存関係のドキュメント(メンテナンス/更新が必要)
・プロトコルからプロトコルへ(両方のサービス)、多くの「フォーマット、解析」が必要
・ほとんどの開発時間は、ビジネスロジックではなく、プロトコルとフォーマットに費やされます
gRPCの起動
gRPCは、あらゆる環境で実行できる最新のオープンソースの高性能RPCフレームワークです。
RPCとは何ですか?RPCはリモートプロシージャコールの略です。これは、ネットワークの詳細を知らなくても、プログラムを使用してネットワーク上の別のコンピューター上のプログラムにサービスを要求できるプロトコルです。
リモートプロシージャコール
RESTを使用したRPC
サービス作成者が提供するRPCクライアント/ライブラリを使用すると、サービスを呼び出すときに正確さが保証されます。RPCとRESTを媒体として使用する場合、開発者Bは開発者Aが使用するクライアントコードを記述する必要があります。開発者Bが両方とも異なる言語を使用する場合、これは開発者Bにとって大きな問題です。これは、彼が慣れていない別の言語でPRCクライアントを作成する必要があるためです。さらに、さまざまなサービスがサービスBを使用する必要がある場合、開発者Bはさまざまな言語でRPCクライアントを作成するために多くの時間を費やさなければならず、それを維持する必要があります。
原生動物?
プロトコルバッファは、構造化データをシリアル化するためのGoogleの言語に依存せず、プラットフォームに依存しない拡張可能なメカニズムです。gRPCは、データ構造とサービスを定義するための言語としてprotobufを使用します。RESTサービスの厳密なドキュメントと比較できます。Protobuf構文は非常に厳密であるため、マシンをコンパイルできます。
次のコードブロックは、通信のための単純なTo Doサービスとデータ構造を記述する単純な元のファイルです。
データ構造を定義するために使用される「メッセージ」キーワード
サービスを定義するための「サービス」キーワード
「rpc」キーワード。サービス機能を定義するために使用されます
syntax = "proto3";
package gogrpcspec;
message Employee {
string name = 1;
}
message Task {
Employee employee = 1;
string name = 2;
string status = 3;
}
message Summary {
int32 todoTasks = 1;
int32 doingTasks = 2;
int32 doneTasks = 3;
}
message SpecificSummary {
Employee employee = 1;
Summary summary = 2;
}
service TaskManager {
rpc GetSummary(Employee) returns (SpecificSummary) {}
rpc AddTask(Task) returns (SpecificSummary) {}
rpc AddTasks(stream Task) returns(Summary) {}
rpc GetTasks(Employee) returns (stream Task) {}
rpc ChangeToDone(stream Task) returns (stream Task) {}
}
元のコードをサーバーコードにコンパイルする
protobufは非常に厳密であるため、「protoc」を使用してprotoファイルをサーバーコードにコンパイルできます。コンパイル後、実際のロジックを実装する必要があります。
protoc --go_out = plugins = grpc:。$ {pwd} / proto / *。proto
--proto_path = $ {pwd}
元のコードをクライアントコードにコンパイルする
protoファイルを使用すると、「protoc」を使用してクライアントコードを多くの一般的な言語にコンパイルできます:C#、C ++、Dart、Go、Java、javascript、Objective-C、PHP、Python、Rubyなど。
gRPC rpcタイプ
gRPCは複数のrpcタイプをサポートします(ただし、この記事では強調しません)
・単項RPC(要求/応答)
・クライアントストリーミングRPC
・サーバーストリーミングRPC
・双方向ストリーミングRPC
開発プロセス
チーム間でgRPCを採用するには、何かが必要です。
・一元化されたコードベース(サービス間の通信のためのgRPC仕様)
・自動コード生成
・サービスユーザー(顧客)は、たとえば、パッケージマネージャーを介して(選択した言語用に)生成されたコードを使用できます。入手/ポイントインストール
この例のコードは、次のリポジトリにあります。
コードベースの構造
。
HISTORY.md├──
├──Makefileの
├──README.md
├──genpyinit.sh
├──gogrpcspec //ここで生成されたコードを行く
│└──...
├──プロト
│└──todo.proto
├──pygrpcspec //ここにPythonで生成されたコード
│├──...
└──setup.py
gitフック
送信する前にコンテンツを自動生成するようにgithookを設定します。必要に応じて、CI(ドローン/ gitlab / jenkins / ...)を使用できます。(githookを使用するデメリットは、すべての開発者が最初にgithookを構成する必要があることです)
コミット前のスクリプトを保持するには、ディレクトリ(フォルダ)が必要です。「.githooks」と呼んでいます
$ mkdir .githooks
$ cd .githooks/
$ cat <<EOF > pre-commit
#!/bin/sh
set -e
make generate
git add gogrpcspec pygrpcspec
EOF
$ chomd +x pre-commit
pre-commitスクリプトはMakefileをトリガーし、gitは2つのディレクトリ(gogrpcsepc、pygrpcspec)を追加します。
githooksが正しく機能するためには、開発者は次のgit configコマンドを実行する必要があります。
$ git config core.hooksPath .githooks
このコマンドをMakefileに追加して、開発者がこのコマンドを簡単に実行できるようにしました(「make init」と呼ばれます)。Makefileの内容は次のようになります。
# content of: Makefile
init:
git config core.hooksPath .githooks
generate:
# TO BE CONTINUE
コードを生成する
Makefile( "make generate")を実行するためのgithookを設定しました。コードを自動的に生成するコマンドについて詳しく見ていきましょう。この記事では、Pythonの2つの言語に焦点を当てます。
Goコードを生成する
protocを使用して.protoファイルをgoコードにコンパイルできます。
protoc --go_out=plugins=grpc:. ${pwd}/proto/*.proto
\--proto_path=${pwd}
代わりにdocker via protocを使用します(開発者の便宜のため)
docker run --rm -v $ {CURDIR}:$ {CURDIR} -w $ {CURDIR} \
znly / protoc \
--go_out = plugins = grpc:。\
$ {CURDIR} / proto / *。Proto \
--proto_path = $ {CURDIR}
以下の生成コマンドを見てください(コードを削除して生成し、適切なフォルダーに移動します)。
# content of: Makefile
init:
git config core.hooksPath .githooks
generate:
# remove previously generated code
rm -rf gogrpcspec/*
# generate go code
docker run --rm -v ${CURDIR}:${CURDIR} -w ${CURDIR} \
znly/protoc \
--go_out=plugins=grpc:. \
${CURDIR}/proto/*.proto \
--proto_path=${CURDIR}
# move generated code into gogrpcspec folder
mv proto/*.go gogrpcspec
コードが生成された後、サーバーまたはクライアントスタブのコードを使用してサービスを呼び出すユーザー(開発者)は、go getコマンドを使用してダウンロードできます。
get -u github.com/redcranetech/grpcspec-example
次に使用します
import pb "github.com/redcranetech/grpcspec-example/gogrpcspec"
Pythonコードを生成する
protocを使用して.protoファイルをPythonコードにコンパイルできます。
protoc --plugin = protoc-gen-grpc = / usr / bin / grpc_python_plugin \
--python_out =。/ pygrpcspec \
--grpc_out =。/ pygrpcspec \
$ {pwd} / proto / *。proto \
--proto_path = $ {pwd}
代わりにdocker via protocを使用します(開発者の便宜のため)
docker run --rm -v $ {CURDIR}:$ {CURDIR} -w $ {CURDIR} \
znly / protoc \ --plugin = protoc-gen-grpc = / usr / bin / grpc_python_plugin \
--python_out =。/ pygrpcspec \
--grpc_out =。/ pygrpcspec \
$ {CURDIR} / proto / *。Proto \
--proto_path = $ {CURDIR}
生成されたコードがpipを介してインストールするpythonパッケージに入るようにするには、追加の手順を実行する必要があります。
・setup.pyを作成します
・生成されたコードを変更します(生成されたコードはフォルダー名を使用してインポートされますが、相対名に変更しました)
・生成されたコードを公開するには、フォルダーに「init.py」が含まれている必要があります
次のテンプレートを使用して、setup.pyファイルを作成します。
# content of: setup.py
from setuptools import setup, find_packages
with open('README.md') as readme_file:
README = readme_file.read()
with open('HISTORY.md') as history_file:
HISTORY = history_file.read()
setup_args = dict(
name='pygrpcspec',
version='0.0.1',
description='grpc spec',
long_description_content_type="text/markdown",
long_description=README + '\n\n' + HISTORY,
license='MIT',
packages=['pygrpcspec','pygrpcspec.proto'],
author='Napon Mekavuthikul',
author_email='[email protected]',
keywords=['grpc'],
url='https://github.com/redcranetech/grpcspec-example',
download_url=''
)
install_requires = [
'grpcio>=1.21.0',
'grpcio-tools>=1.21.0',
'protobuf>=3.8.0'
]
if __name__ == '__main__':
setup(**setup_args, install_requires=install_requires)
init .pyを生成する
pygrpcspecフォルダのinitの.pyでなければなりません
# content of: pygrpspec/__init__.py
from . import proto
__all__ = [
'proto'
]
そしてpygrpcspec /プロトフォルダの初期化の.pyでなければなりません
# content of: pygrpspec/proto/__init__.py
from . import todo_pb2
from . import todo_pb2_grpc
__all__ = [
'todo_pb2',
'todo_pb2_grpc',
]
開発者が.protoファイルを追加してinit .py を自動的に生成できるようにするために、単純なシェルスクリプトでこの問題を解決できます
# content of: genpyinit.sh
cat <<EOF >pygrpcspec/__init__.py
from . import proto
__all__ = [
'proto'
]
EOF
pyfiles=($(ls pygrpcspec/proto | sed -e 's/\..*$//'| grep -v __init__))
rm -f pygrpcspec/proto/__init__.py
for i in "${pyfiles[@]}"
do
echo "from . import $i" >> pygrpcspec/proto/__init__.py
done
echo "__all__ = [" >> pygrpcspec/proto/__init__.py
for i in "${pyfiles[@]}"
do
echo " '$i'," >> pygrpcspec/proto/__init__.py
done
echo "]" >> pygrpcspec/proto/__init__.py
生成されたコードを変更する
(Pythonモジュールに慣れていない場合は、この読み物をスキップできます)
それぞれの「インポート元」から「インポート元」に変更したい。インポート "。これの背後にある理由は、データタイプとサービススタブを同じディレクトリに配置し、モジュールの外部でモジュールを呼び出すために、各内部参照が相対である必要があるためです。
sed -i -E 's/^from proto import/from . import/g' *.py
この時点で、Makefileは次のようになります。
# content of: Makefile
init:
git config core.hooksPath .githooks
generate:
# remove previously generated code
rm -rf gogrpcspec/*
# generate go code
docker run --rm -v ${CURDIR}:${CURDIR} -w ${CURDIR} \
znly/protoc \
--go_out=plugins=grpc:. \
${CURDIR}/proto/*.proto \
--proto_path=${CURDIR}
# move generated code into gogrpcspec folder
mv proto/*.go gogrpcspec
# remove previously generated code
rm -rf pygrpcspec/*
# generate python code
docker run --rm -v ${CURDIR}:${CURDIR} -w ${CURDIR} \
znly/protoc \
--plugin=protoc-gen-grpc=/usr/bin/grpc_python_plugin \
--python_out=./pygrpcspec \
--grpc_out=./pygrpcspec \
${CURDIR}/proto/*.proto \
--proto_path=${CURDIR}
# generate __init__.py
sh genpyinit.sh
# modify import using sed
docker run --rm -v ${CURDIR}:${CURDIR} -w ${CURDIR}/pygrpcspec/proto \
frolvlad/alpine-bash \
bash -c "sed -i -E 's/^from proto import/from . import/g' *.py"
コードが生成された後、サーバーまたはクライアントスタブのコードを使用してサービスを呼び出すユーザー(開発者)は、pipコマンドを使用してダウンロードできます。
pip install -e git + https://github.com/redcranetech/grpcspec-example.git#egg=pygrpcspec
次に使用します
from pygrpcspec.proto import todo_pb2_grpc
from pygrpcspec.proto import todo_pb2
要約すると、protobufの厳密な構文はgRPCをさまざまな言語のクライアントコードにコンパイルできるため、gRPCはマイクロサービス間の通信に優れた方法です。
この記事のすべてのコード: