tech|再探grpc
11211 ワード
date:2019-04-25 22:16:01 title:tech|再探grpc
grpcを振り回すのは何度もあって、すべて大規模な使うことがなくて、熟知の程度は多く公式サイトのhelloworldの上で滞在して、原理に対する理解は深くなくて、だからいつも引っかかります.
grpc|python実戦grpc
ここで私が引っかかった点を紹介します.公式サイトのquick startドキュメントに従います. phpを使用する:PHPを構成する環境が面倒で、特に . go:golangパッケージをインストールし、壁にぶつかることが多い(gogetに失敗) 最後にpythonをサボって走ったが、最大の収穫はgrpcが一方向要求のほかに双方向通信(stream、ストリーミング通信)があり、環境の問題を迂回してdemo に通じたことだ.
PHPerからの魂は「環境を解決するか、grpcを使えないか」と尋ねた.
この問題に陥って、ずっと迂回できなかった.しかしgrpcの基本原理を理解し、考え方を変えると、非常に簡単であることがわかる.
公式文書の解読
grpc - quickstart - php: https://grpc.io/docs/quickstart/php/
公式php quickstartで説明する手順: grpc環境 ext-grpc が自動的に生成される.
protobuf環境 protoファイルIDLファイルに基づいてサービスを定義し、現在proto 3文法(文法は簡単で、15分以内に見ることができる) を使用している. protoc,protobuf compile,protoファイルコンパイラは、protoファイルが異なる開発言語に基づいて翻訳されていることを理解することができる protobuf runtime、protobufフォーマットの実行時サポート、protobufシーケンス化後の情報、protobuf runtime が必要
誤読されやすい点は2つあります.順序:protobuf環境を理解してからgrpc を構築する公式サイトが自動的に生成したコードは、grpcサービス呼び出しに通じるだけだ.しかし、現実的には、rpcサービスは、マイクロサービス など、一連のサービスフレームワークをサポートする必要があります.
理解grpc
いくつかの基礎的な点からgrpc.を少しずつ見てみましょう. protobuf:シーケンス化、符号化の基礎知識 rpc,tcpベースの通信:tcp通信はなぜプロトコルが必要なのか、プロトコル設計は簡単 grpcの通信プロトコル詳細 protobuf
protobuf環境: protoファイルIDLファイルに基づいてサービスを定義し、現在proto 3文法(文法は簡単で、15分以内に見ることができる) を使用している. protoc,protobuf compile,protoファイルコンパイラは、protoファイルが異なる開発言語に基づいて翻訳されていることを理解することができる protobuf runtime、protobufフォーマットの実行時サポート、protobufシーケンス化後の情報、protobuf runtime が必要
時系列的に理解する: protoファイル->protcコンパイル->異なる言語を自動的に生成するコード gen code+protobuf runtime->情報シーケンス化/逆シーケンス化 補足すると、情報のシーケンス化/逆シーケンス化は、符号化の知識に関連し、進数変換->文字セット(なぜ文字化されないのか)->大端シーケンス/小端シーケンス/ネットワークシーケンス(php pack()/unpack()関数)を含む.
具体的にPHPでは、公式サイトのhelloworldを例に挙げます. protoファイル protoc protobuf runtime
PHPの中で実はとても簡単な
ここまで、protobufという部分の内容をすべて解決しました.以下は生成の例です. client.php:tcp協程client プロトコル処理に加えて、簡単なプロトコルは構成を変更するだけで を実現することができる.
grpc = http2 + protobuf
grpcはhttp 2プロトコルに基づいて通信を行い、上記の基礎知識を理解し、grpcが使用するhttp 2プロトコルの通信の詳細を見ると、完全に簡単に実現することができる.
ここには4つの部分が含まれています. .protoファイルで定義されたgrpcサービス名: になる. HelloRequest/HelloReply: .ptotoファイル+protoc自動生成protobuf自動解析ファイル serverのサンプルコードがあり、clientはswoole http 2コヒーレントclientを使用してパッケージ化することもできます.
最後に書く
ここまで、基本的にgrpcの簡単な原理は、上に書いた例に示されていて、自分が以前蓄積した知識を融通して貫通することができて、喜びの気持ちが湧き出ています!
特筆すべき点
最初は原理を舍ててdemoを走って、绝えず环境を振り回して、コードを振り回して自动的に生成して、公式サイトdemoの上でますます远くなります.前に出会った例をもう一度挙げて、啓発してほしい.
alipay ILLEGAL_SIGNエラー解決:https://www.jianshu.com/p/28585a6454b2
呼び出しリンク全体が非常に長く、debug問題の前後にtraceが長く、できる限り様々な試みをしたが、本質に戻った:httpプロトコル
だから、「http権威ガイド」を開いて、よく調べてみると、httpプロトコルの中でcharsetに影響を与えるのは2つの場所だけです.クライアント: サービス: 補足&&その他 のみを見ることをお勧めします. protobufの実践について、私の前のblog:サーバー開発シリーズ1 nginxによるgrpcのサポート:https://www.nginx.com/blog/nginx-1-13-10-grpc/ 極客時間-深入浅出grpc:https://time.geekbang.org/column/intro/75
詳細: grpcシーケンス化メカニズム&grpcセキュリティ設計 swoft 2でgrpcの を簡単に使用する方法
grpcを振り回すのは何度もあって、すべて大規模な使うことがなくて、熟知の程度は多く公式サイトのhelloworldの上で滞在して、原理に対する理解は深くなくて、だからいつも引っかかります.
grpc|python実戦grpc
ここで私が引っかかった点を紹介します.公式サイトのquick startドキュメントに従います.
grpc/grpc
コードライブラリがgrpc_php_plugin
をコンパイルするステップPHPerからの魂は「環境を解決するか、grpcを使えないか」と尋ねた.
この問題に陥って、ずっと迂回できなかった.しかしgrpcの基本原理を理解し、考え方を変えると、非常に簡単であることがわかる.
公式文書の解読
grpc - quickstart - php: https://grpc.io/docs/quickstart/php/
公式php quickstartで説明する手順:
github.com/grpc/grpc
ソースライブラリからgrpc_php_plugin
がコンパイルされ、protocと連携するコード誤読されやすい点は2つあります.
理解grpc
いくつかの基礎的な点からgrpc.を少しずつ見てみましょう.
protobuf環境:
時系列的に理解する:
具体的にPHPでは、公式サイトのhelloworldを例に挙げます.
syntax = "proto3";
package grpc;
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string greeting = 1;
}
message HelloResponse {
string reply = 1;
}
# alpine linux , linux ,
apk add protobuf
protoc --version # protoc
# protoc
protoc --php_out=grpc/ game.proto # --php_out , PHP
PHPの中で実はとても簡単な
ext-protobuf / google/protobuf package
、2は1を選びます// ext-protobuf
pecl install protobuf
// google/protobuf
composer require google/protobuf
ここまで、protobufという部分の内容をすべて解決しました.以下は生成の例です.
// proto
message HelloRequest {
string greeting = 1;
}
grpc.HelloRequest
*/ class HelloRequest extends \Google\Protobuf\Internal\Message { /** * Generated from protobuf fieldstring greeting = 1;
*/ private $greeting = ''; public function __construct() { \GPBMetadata\Hello::initOnce(); parent::__construct(); } /** * Generated from protobuf fieldstring greeting = 1;
* @return string */ public function getGreeting() { return $this->greeting; } /** * Generated from protobuf fieldstring greeting = 1;
* @param string $var * @return $this */ public function setGreeting($var) { GPBUtil::checkString($var, True); $this->greeting = $var; return $this; } }
rpc, tcp 基础上的通信
tcp/ip 4 层网络通信:
- 物理层/数据链路层: 网线/路由器/交换机/网卡 -> mac地址
- ip 层: ip 地址, 4 种网络地址类型
- tcp/udp层: 端口, 端口上绑定的服务
- 协议层: 各种熟悉的协议, http/ftp
为什么需要协议: tcp 是流式(stream)传输数据的, 需要协议来确定数据边界
简单协议设计: EOF结束符 / 固定包头
swoole wiki - 网络通信协议设计: https://wiki.swoole.com/wiki/page/484.html
有了 swoole, tcp 通信, 编程十分简单:
- server.php: tcp 协程 server
=v4.0
$s = new Server('0.0.0.0', '9502', SWOOLE_BASE, SWOOLE_TCP);
$s->set([
'worker_num' => 4,
'daemonize' => true,
'backlog' => 128,
]);
$s->on('connect', 'on_connect');
$s->on('receive', 'on_receive');
$s->on('close', 'on_close');
$s->start();
connect('127.0.0.1', '9502');
$c->send('hello');
echo $c->recv();
$c->close();
set([
'open_length_check' => 1,
'package_length_type' => 'N',
'package_length_offset' => 0, // N
'package_body_offset' => 4, //
'package_max_length' => 2000000, //
]);
$c->connect('127.0.0.1', '9502');
$c->send('hello');
echo $c->recv();
$c->close();
grpc = http2 + protobuf
grpcはhttp 2プロトコルに基づいて通信を行い、上記の基礎知識を理解し、grpcが使用するhttp 2プロトコルの通信の詳細を見ると、完全に簡単に実現することができる.
set([
'open_http2_protocol' => true,
]);
$http->on('workerStart', function (\Swoole\Http\Server $server) {
echo "workerStart
";
});
$http->on('request', function (\Swoole\Http\Request $request, \Swoole\Http\Response $response) {
// request_uri proto rpc : /{package}.{service}/{rpc}
$path = $request->server['request_uri'];
if ($path == '/grpc.HelloService/SayHello') {
// decode, rpc
$request_message = \Grpc\Parser::deserializeMessage([HelloRequest::class, null], $request->rawContent());
// encode, rpc
$response_message = new HelloReply();
$response_message->setMessage('Hello ' . $request_message->getName());
$response->header('content-type', 'application/grpc');
$response->header('trailer', 'grpc-status, grpc-message');
$trailer = [
"grpc-status" => "0",
"grpc-message" => ""
];
foreach ($trailer as $trailer_name => $trailer_value) {
$response->trailer($trailer_name, $trailer_value);
}
$response->end(\Grpc\Parser::serializeMessage($response_message));
}
});
ここには4つの部分が含まれています.
\Swoole\Http\Server
:swooleを使用して実装されたhttp 2 server request_uri proto rpc : /{package}.{service}/{rpc}
\Grpc\Parser
:grpc情報の解析クラスは、grpcが使用するhttp 2プロトコルの詳細に基づいてクラスをカプセル化すると\Grpc\Parser
サンプルコード:encode();
} else if (method_exists($data, 'serializeToString')) {
$data = $data->serializeToString();
} else {
/** @noinspection PhpUndefinedMethodInspection */
$data = $data->serialize();
}
return self::pack($data);
}
public static function deserializeMessage($deserialize, string $value)
{
if (empty($value)) {
return null;
} else {
$value = self::unpack($value);
}
if (is_array($deserialize)) {
list($className, $deserializeFunc) = $deserialize;
/** @var $obj Message */
$obj = new $className();
if ($deserializeFunc && method_exists($obj, $deserializeFunc)) {
$obj->$deserializeFunc($value);
} else {
$obj->mergeFromString($value);
}
return $obj;
}
return call_user_func($deserialize, $value);
}
public static function parseToResultArray($response, $deserialize): array
{
if (!$response) {
return ['No response', GRPC_ERROR_NO_RESPONSE, $response];
} else if ($response->statusCode !== 200) {
return ['Http status Error', $response->errCode ?: $response->statusCode, $response];
} else {
$grpc_status = (int)($response->headers['grpc-status'] ?? 0);
if ($grpc_status !== 0) {
return [$response->headers['grpc-message'] ?? 'Unknown error', $grpc_status, $response];
}
$data = $response->data;
$reply = self::deserializeMessage($deserialize, $data);
$status = (int)($response->headers['grpc-status'] ?? 0 ?: 0);
return [$reply, $status, $response];
}
}
}
最後に書く
ここまで、基本的にgrpcの簡単な原理は、上に書いた例に示されていて、自分が以前蓄積した知識を融通して貫通することができて、喜びの気持ちが湧き出ています!
特筆すべき点
最初は原理を舍ててdemoを走って、绝えず环境を振り回して、コードを振り回して自动的に生成して、公式サイトdemoの上でますます远くなります.前に出会った例をもう一度挙げて、啓発してほしい.
alipay ILLEGAL_SIGNエラー解決:https://www.jianshu.com/p/28585a6454b2
呼び出しリンク全体が非常に長く、debug問題の前後にtraceが長く、できる限り様々な試みをしたが、本質に戻った:httpプロトコル
だから、「http権威ガイド」を開いて、よく調べてみると、httpプロトコルの中でcharsetに影響を与えるのは2つの場所だけです.
accept-charset='utf-8'
content-type: text/plain;charset:utf-8
swoole/grpc
:参考になる項目は、swoole/grpc/examples/grpc/greeter_server.php
とswoole/grpc/examples/grpc/greeter_client.php
詳細: