写在前面
最近了解到了 gRPC 的相关内容, 这一篇就写在用法和概念上的相关东西,以 Dart 语言来做代码示例。
内容
从一个示例开始
配置环境
- 安装 Dart SDK 或是 Flutter SDK,然后配置它们的环境变量
- 安装 protobuf
- brew 安装
brew install protobuf
- 压缩包安装
- 有遇到过上面的 brew 安装失败,于是可以直接去官方 GitHub,下载对应的压缩包,如我是 mac,就下载 osx-x86_64.zip。然后解压该压缩包,将 bin 路径写入到 PATH 即可。
- 安装protoc_plugin
pub global activate protoc_plugin
- 在 bash_profile (M1的话应该是 zshrc里)下添加
export PATH="$PATH":"$HOME/.pub-cache/bin"
- 我使用的是 IDEA 进行开发,可以安装一个叫 Protocol Buffer Editor 的插件,来帮助我们更好地编辑 .proto 文件。
Demo
让我们新建一个 Dart 工程,在其pusepc.yaml
里添加依赖:
dependencies:
protobuf: ^2.0.0
grpc: ^3.0.0
然后我们就可以开始了。
在 lib 文件夹下创建 protos (名称随意)文件夹,然后创建helloworld.proto
用于写我们的代码:
// helloworld.proto
syntax = "proto3";
package helloworld;
service Greeter{
rpc SayHello(HelloRequest) returns (HelloReply){}
}
message HelloRequest{
string name = 1;
}
message HelloReply{
string message = 1;
}
开头我们声明了使用的是 proto3 版本,然后定义了Greeter
服务,并声明了一个 rpc 接口SayHello
,请求的参数是HelloRequest
,返回的参数是HelloReply
。
在 lib 目录下,我们新建一个 src/generated 文件夹,用于存放我们待会要生成的文件。
然后命令行进入我们的 lib 目录下,执行命令:
protoc --dart_out=grpc:src/generated -Iprotos protos/helloworld.proto
这样 generated 文件夹下就会生成相应的文件:
helloworld.pbjson.dart
helloworld.pbgrpc.dart
helloworld.pbenum.dart
helloworld.pb.dart
同样地在 lib 目录下我们创建 src/bin 目录来写我们的客户端和服务端。
客户端:
// client.dart
import 'package:grpc/grpc.dart';
import 'package:grpc_learning/src/generated/helloworld.pbgrpc.dart';
void main() async {
final channel = ClientChannel(
'localhost',
port: 50051,
options: ChannelOptions(
credentials: ChannelCredentials.insecure(),
codecRegistry:
CodecRegistry(codecs: const [GzipCodec(), IdentityCodec()]),
),
);
final stub = GreeterClient(channel);
final name = 'world';
try {
final response = await stub.sayHello(HelloRequest()..name = name);
print('Greeter client received: ${response.message}');
} catch (e) {
print('error = ${e.toString()}');
}
await channel.shutdown();
}
服务端:
// server.dart
import 'package:grpc/grpc.dart';
import 'package:grpc/src/server/call.dart';
import 'package:grpc_learning/src/generated/helloworld.pbgrpc.dart';
class GreeterService extends GreeterServiceBase {
@override
Future<HelloReply> sayHello(ServiceCall call, HelloRequest request) async {
return HelloReply()..message = 'I got it ${request.name}';
}
}
void main() async {
final server = Server([GreeterService()]);
await server.serve(port: 50051);
print('Server listening on port ${server.port}...');
}
接下来我们就可以开启两个终端,来分别运行客户端和服务端了,使用dart server.dart
和dart client.dart
来执行。
执行结果:
// 服务端
Server listening on port 50051...
// 客户端
Greeter client received: I got it world
这样就完成了一个 gRPC 的客户端与服务端通信的 Demo。