gRPC基本使用(一)--java与go之间的相互调用
gRPC是一个高性能、开源、通用的RPC框架,面向移动和HTTP/2设计。gRPC 默认使用 protocol buffers,这是 Google 开源的一套成熟的结构数据序列化机制。
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
简介
本文只是根据gRPC相关资料文档编写的Java Spring Boot 与 Golang 语言相关调用的示例。
详细内容
编写proto文件
使用proto3语法。文件user_provider.proto。
需要使用proto文件,来自动生成不同语言的相关接口、类、对象等。
// user service provider
// proto语法版本
syntax = "proto3";
// 可选参数 设置java package
option java_package = "cn.lpe234.grpc.grpcdemo.grpc";
// 定义对外暴露的服务
service UserProvider {
// 根据用户id获取用户信息的服务(具体服务/函数)
rpc getByUserId(UserIdRequest) returns (UserVoReplay) {}
}
// 请求
message UserIdRequest {
uint64 id = 1; // 用户id 类型为Long
}
// 响应
message UserVoReplay {
uint64 id = 1; // 用户id
string username = 2; // 用户名称
}
Java Spring Boot 相关
使用Maven作为项目的依赖管理及编译构建工具。当前使用Maven插件,在编译时根据proto文件自动生成服务编写时所需的Class类。
需要将*.proto放置在 xxProject/src/main/proto文件夹下,才能被插件读取到。也就是proto文件夹需要跟java、resources文件夹并列才行(或许可通过修改配置信息修改proto文件存储位置,未做深究~)。
Maven配置
项目精简的pxm.xml配置文件。
<!-- grpc 依赖版本 -->
<properties>
<grpc.version>1.14.0</grpc.version>
</properties>
<!-- grpc 依赖jar包 -->
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${grpc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-core</artifactId>
<version>${grpc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
</dependencies>
<!-- grpc build 插件 -->
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.4.1.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
理论上,此时执行 mvn -DskipTests=true compile,即可正常生成gRPC相关的Class类。
target
├── generated-sources
│ ├── annotations
│ └── protobuf
│ ├── grpc-java
│ │ └── cn
│ │ └── lpe234
│ │ └── grpc
│ │ └── grpcdemo
│ │ └── grpc
│ │ └── UserProviderGrpc.java
│ └── java
│ └── cn
│ └── lpe234
│ └── grpc
│ └── grpcdemo
│ └── grpc
│ └── UserProviderOuterClass.java
gPPC服务提供编写
使用注解(@net.devh.springboot.autoconfigure.grpc.server.GrpcService)的方式对外提供服务,类似Dubbo服务中的注解方式。
package cn.lpe234.grpc.grpcdemo.grpcprovider;
import cn.lpe234.grpc.grpcdemo.grpc.UserProviderGrpc;
import cn.lpe234.grpc.grpcdemo.grpc.UserProviderOuterClass;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.springboot.autoconfigure.grpc.server.GrpcService;
/**
* Grpc服务暴露
*
* @author lpe234
* @datetime 2018/11/24 14:36
*/
@Slf4j
@GrpcService(UserProviderGrpc.class)
public class UserProvider extends UserProviderGrpc.UserProviderImplBase {
@Override
public void getByUserId(UserProviderOuterClass.UserIdRequest request, StreamObserver<UserProviderOuterClass.UserVoReplay> responseObserver) {
// super.getByUserId(request, responseObserver);
// 获取请求数据
long userId = request.getId();
log.debug("grpc request: userId=" + userId);
// 构造返回数据
UserProviderOuterClass.UserVoReplay.Builder userVoReplayBuild = UserProviderOuterClass.UserVoReplay.newBuilder();
userVoReplayBuild.setId(userId);
userVoReplayBuild.setUsername("hello world");
UserProviderOuterClass.UserVoReplay userVoReplay = userVoReplayBuild.build();
// 做出响应
responseObserver.onNext(userVoReplay);
responseObserver.onCompleted();
}
}
gRPC对外服务暴露相关配置
application.xml文件。需配置绑定的地址和监听的端口。
# grpc
grpc:
server:
address: 0.0.0.0
port: 10081
运行
如果一切顺利的话,启动Spring Boot项目。可看到控制台日志输出:
2018-11-24 16:51:16.999 INFO 60266 --- [ main] n.d.s.a.g.server.NettyGrpcServerFactory : Registered gRPC service: UserProvider, bean: userProvider, class: cn.lpe234.grpc.grpcdemo.grpcprovider.UserProvider
2018-11-24 16:51:17.124 INFO 60266 --- [ main] n.d.s.a.grpc.server.GrpcServerLifecycle : gRPC Server started, listening on address: 0.0.0.0, port: 10081
2018-11-24 16:51:17.141 INFO 60266 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 10080 (http) with context path ''
2018-11-24 16:51:17.145 INFO 60266 --- [ main] c.l.grpc.grpcdemo.GrpcDemoApplication : Started GrpcDemoApplication in 2.246 seconds (JVM running for 2.721)
可看到:gRPC Server started, listening on address: 0.0.0.0, port: 10081。说明服务启动正常~
Golang相关
新建项目 grpc-demo并 创建子文件夹 grpc-demo/proto,然后将 最开始的user_provider.proto拷贝进去(由于proto文件定义了RPC调用的所有细节,即所有服务提供或调用均需要保持版本的相同。拷贝似乎有些不妥~)。
生成Golang gRPC调用相关文件
该步骤,需要一些相关依赖~
protoc --go_out=plugins=grpc:. user_provider.proto
执行成功后,会在该文件夹下生成 user_provider.pb.go 文件。
服务调用
在项目的 src目录下,新建main.go文件。
备注: 地址直接硬编码毕竟是不好的,暂不考虑服务注册发现相关内容,知道这块应该有更好的解决方案即可~
package main
import (
"google.golang.org/grpc"
pb "proto"
"context"
"log"
)
func main() {
// java spring boot 暴露的grpc服务接口
const addr = "127.0.0.1:10081"
// 连接服务
conn, err := grpc.Dial(addr, grpc.WithInsecure())
if err != nil {
log.Panic(err)
}
// 确保连接最终被关闭
defer conn.Close()
// 建立远程调用客户端
client := pb.NewUserProviderClient(conn)
reply, err := client.GetByUserId(context.Background(), &pb.UserIdRequest{Id: 1})
if err != nil {
log.Panic(err)
}
// 输出结果
log.Println("user info:", reply.Id, reply.Username)
}
运行
执行后,可分别在服务调用和提供者日志中看到如下内容:
# Golang
2018/11/24 17:10:12 user info: 1 hello world
# Spring Boot
2018-11-24 17:10:12.123 DEBUG 60266 --- [ault-executor-1] c.l.g.g.grpcprovider.UserProvider : grpc request: userId=1
完结
至此,已完成了Java提供服务,Golang调用服务。
关注公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
这可能是搭建Zookeeper集群介绍最全的文章
1.搭建 怎么搭建单机无安全校验的就不说了,百度一搜一大堆。这里我就说说怎么搭建一个生产环境可用的Zookeeper集群 Zookeeper 3.4.13下载地址 Docker方式不太建议,要考虑的东西比较多,如果要用Docker方式还是比较建议自建镜像,假如是Docker专家可以忽略本句。 以下介绍的都是Linux服务器下搭建(Winserver服务器的也是雷同)先操作单机,再copy到其他机器。下载完Zookeeper(下称zk)后,进入zk解压目录下的conf文件夹,zoo_sample.cfg是zk的配置文件实例,Copy一个出来命名为zoo.cfg zk默认会读这个配置。 配置详解: tickTime :心跳发送的间隔时间,用于判定Client是否断开(默认2000ms) dataDir :zk数据文件保存目录,zk是基于文件来存储配置的 clientPort :这个端口就是客户端连接 zk 服务器的端口,zk 会监听这个端口,接受客户端的访问请求。 initLimit:初始化Client时的重试次数(默认5次),判断Client是否连接成功就是发initLimit次心跳,每...
-
下一篇
c++命名空间 namespace学习
我们为什么需要命名空间? 我们假设一下这种情况,在A班中,有一名同学叫小明,在B班中,也有一名同学叫小明,现在两个班的同学一起聚会,老师找A班的小明,这时候他在人群中喊一声小明肯定两个小明都过来了,这个时候B班小明就白跑一趟了,为了避免这种尴尬,老师只要喊“A班的小明过来一下就行了”。在c++已经其他某些语言中,也是这个道理,在很多大型项目中,由于可能多人一起开发,难免出现相同名字的变量,这个时候我们就需要namespace了,在调用同名变量时,另外加上它的namespace,这样就避免了出错。 1.命名空间实例 //namespace study #include<iostream> using namespace std; namespace first_space{ void func(){ cout<<"my first_space"<<endl; } } namespace second_space{ void func(){ cout<<"my second_space"<<endl; } ...
相关文章
文章评论
共有0条评论来说两句吧...

微信收款码
支付宝收款码