grpc基本实践(一)

        此篇中主要简单实现了,grpc的4种交互,包括普通请求,客户端流,服务端流,和双向流。其中服务端采用go语言实现,客户端将采用java实现。

        在此篇中基本可以了解到protobuf的基本知识,以及多文件编译上的一些问题。以及在grpc请求上,对一些基本数据的发送和返回。其中你可以通过两种形式拿到自己想要的list数据。

        需要注意的是此篇中用到的grpc为版本1.10。这个版本的context依然用的是golang.org/x/net/context中的,所以大家想用grpc一定要翻墙把这个下好。

        首先我们先看一下proto文件。

        

        此次练习实践,主要包含了两个proto文件,包含user_server.proto和user_vo.proto。一方面是对数据方法和服务方法进行分离,另一方面也是为了可以用到多文件编译。这样做还能在编译安卓用到的文件时遇到的不支持服务的问题(当然你也可以直接用java的生成代码)。

        接下来让我们看一下, 在user_vo.proto中所定义的一些基本数据:

syntax = "proto3";

package testg;

message Empty{}

message UserList{
    repeated User u = 1;
}

message User{
    string user_id = 1;
    string user_name = 2;
    int32 age = 3;
    Msg msg = 4;
}

message Msg{
    string msg = 1;
}

            首先头部的syntax="proto3"是必须的,否则他将按proto2编译。其次因为grpc无论是否有数据要发送返回,你都必须定义发送数据和返回数据。所以我们在这里定义了一个空的数据以方便我们在不需要传数据时使用。

            protobuf在使用中只有基本类型,如果数据时一个list,你则需要用到repeatred这个关键字,他代表你的这个数据是不定的,可以是0个,1个或者更多。

            oneof :可以让你包裹的几个字段只能有一个被赋值。


            在proto2中的关键字,在proto3中已经删除:

            required : 表示此字段必填。此字段需要小心设置因为如果忘记设置带有此关键字的字段,你的数据将被拒绝解析。

            optional :  可选字段。(在proto3中默认就是可选的)


        接下来让我们看看user_server.proto:

syntax = "proto3";

package testg;

import "testg/user_vo.proto";

service UserServer {
    rpc GetUserById(User) returns (User);
    rpc GetList(Empty) returns (UserList);
    rpc GetListStream(Empty) returns (stream User);
    rpc SetUserStream(stream User) returns (UserList);
    rpc Chat(stream User) returns (stream User);
}

        在这个文件中,主要是定义了grpc的服务和方法,其中我们通过使用import来引用我们要使用的其他文件的方法数据。在这里我们引用了user_vo.proto的数据类型。

        数据和服务都定义好后,我们就可以开始编译了,在编译上,单文件和多文件编译时一样的,但是这里会有个小坑,如果不注意还是很头疼的。在编译一个文件时,我们基本不会遇到什么问题。但是多文件编译我们必须把所引用到的文件都一起编译,多个proto文件使用空格隔开。

        如果我们一个一个编译的话,在go中你会遇到找不到某方法或数据的问题,而在java中会发现缺少某文件。

        在此篇中go的编译为:

        protoc --go_out=plugins=grpc:.   ./user_vo.proto  ./user_server.proto

        在java的编译为:

        1.通过 protoc --java_out=./ ./user_vo.proto  ./user_server.proto生成proto文件的java版

        2.通过 protoc --plugin=protoc-gen-grpc-java.exe --grpc-java_out=./ ./user_vo.proto  ./user_server.proto生成grpc服务的和客户端文件

         在多文件编译中,java版会额外生成一个UserServerOuterClass.java,即对某个文件的额外引用文件。如果一个一个编译你将会缺少这个文件。

         所以大家在编译的时候一定要记住把所以引用到的proto文件都编译上,不要分开编译。

         

        编译成功后,我们就可以开始代码的正式编写了。

        作为服务端,我们首先需要实现所以 的接口。否则你将不能使用grpc服务。

        其中具体要实现那些接口,大家可以在自己生成的grpc服务文件中找到,在此次中我们需要实现的接口有:

        

        接下来就是定义一个空结构体来实现这五个方法:

func (u *UserServer) GetUserById(c context.Context,user *testg.User) (*testg.User, error) {
	userId := user.UserId
	if userId == "" {
		return nil, nil
	}
	fmt.Println("userId:", userId)
	ul := testListFunc()
	for i:=0;i<len(ul.U);i++{
		if ul.U[i].UserId == user.UserId {
			return ul.U[i], nil
		}
	}
	return nil, nil
}

           这个方法通过客户端拿到传过来的参数,返回一个user的对象。

    

func (u *UserServer) GetList(c context.Context,e *testg.Empty) (*testg.UserList, error) {
	return testListFunc(),nil
}

            在这个方法中我们返回了list,这也是第一种返回list的方法,主要是利用了定义数据中的repeatred,让我们可以把user对象拿到一个list。

            同时这两个方法都是对基础grpc服务的实现,即没有用到流,都是一问一答。在客户端发来请求后,服务端给客户端一个应答。

           

func (u *UserServer) GetListStream(e *testg.Empty, us testg.UserServer_GetListStreamServer) error {
	ul := testListFunc()
	for i:=0;i<len(ul.U);i++{
		us.Send(ul.U[i])
	}
	return nil
}

            这个方法中,我们实现了服务端流,即在客户端发来一个请求后,服务端以流的形式持续返回数据给客户端,通过方法看到,服务端流中有一个send的发送方法, 它允许我们不断给客户端发送数据。通过这个方法我们就实现第二种获得list的方法,每次 发送一个user对象,不间断发送直到没有数据可发。

                  

func (u *UserServer) SetUserStream(us testg.UserServer_SetUserStreamServer) error {
	for {
		user,err := us.Recv()
		if err == io.EOF {
			return us.SendAndClose(testListFunc())
		}
		if err != nil {
			return err
		}
		fmt.Println("user", user)
	}
	return nil
}

          这个方法中我们实现了客户端流,即客户端会持续发送数据,当发送完成后,客户端会给服务端一个eof错误,服务端在拿到eof就关闭通道并发送返回数据给客户端。其中通过us.Recv()拿到客户端发来的数据。

            

func (u *UserServer) Chat(us testg.UserServer_ChatServer) error {
	for {
		user,err := us.Recv()
		if err == io.EOF {
			return nil
		}
		fmt.Println("user",user)
		us.Send(user)
	}
	return nil
}

        这个方法就是实现双向流的,我们通过Recv()方法拿到客户端数据,服务端通过Send()方法发送数据给客户端。这个基本就是客户端流和服务端流的结合。


        在下一篇中,我们将讲关于客户端的基本实现。


        大家也可以去GitHub下载我的练习源码:

        https://github.com/aixinaxc/grpcserver (服务端)

        https://github.com/aixinaxc/grpcclient-golang (客户端)

            





  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
要实现 grpc Java 的一元异步调用,可以按照以下步骤进行: 1. 定义 proto 文件,并使用 protobuf 编译器生成 Java 类。 2. 在服务端实现 proto 文件中定义的服务接口,并启动服务。 3. 在客户端创建一个 Channel 和 Stub 对象,用于连接服务端并调用服务。 4. 使用 Stub 对象创建一个异步调用请求,并设置回调函数处理服务端返回的响应结果。 下面是一个简单的示例代码: ```java // 引入 grpc 相关库 import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.stub.StreamObserver; // 创建 Channel ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8080).usePlaintext().build(); // 创建 Stub MyServiceGrpc.MyServiceStub stub = MyServiceGrpc.newStub(channel); // 创建请求消息 MyRequest request = MyRequest.newBuilder().setParam("param").build(); // 发送异步请求 stub.myMethod(request, new StreamObserver<MyResponse>() { @Override public void onNext(MyResponse response) { // 处理服务端返回结果 } @Override public void onError(Throwable t) { // 处理请求出错 } @Override public void onCompleted() { // 请求完成 } }); ``` 在上面的代码中,我们首先创建了一个 Channel 对象,用于连接服务端。然后创建了一个 Stub 对象,用于调用服务端的 `myMethod` 方法。接着创建了一个请求消息对象,并调用 Stub 的 `myMethod` 方法发送异步请求。最后,我们设置了一个回调函数,用于处理服务端返回的响应结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值