【复杂gRPC之Java调用go】

2023-12-14 13:57:49

1 注意点

一般上来说如果java调用java的话,我们可以使用springcloud来做,而面对这种跨语言的情况下,gRPC就展现出了他的优势。
代码放在这了,请结合前面的go服务器端一起使用
https://gitee.com/guo-zonghao/java-client-grpc

// 这些是在java端生成时候的配置
 option java_multiple_files = true;
 //生成文件所属的包
 option java_package = "com.iq50.client.routeguide";
 option java_outer_classname = "RouteGuideProto";

在运行插件的时候我们需要运行以下两个命令
在这里插入图片描述
之后我们会获得:
在这里插入图片描述

2 如何编写客户端代码

package com.iq50.client.routeguide;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.netty.NegotiationType;
import io.grpc.netty.NettyChannelBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class RouteGuideClient {
    //socket通道管理
    private final ManagedChannel channel;
    //负责普通调用和服务端到客户端的流调用
    private final RouteGuideGrpc.RouteGuideBlockingStub blockingStub;
    //负责双向流调用和客户端到服务端的流调用
    private final RouteGuideGrpc.RouteGuideStub asyncStub;
    
    public RouteGuideClient(){
        this(ManagedChannelBuilder.forAddress("127.0.0.1", 50051).usePlaintext());
    }
    private RouteGuideClient(ManagedChannelBuilder<?> channelBuilder) {
        this.channel = channelBuilder.build();
        this.blockingStub = RouteGuideGrpc.newBlockingStub(channel);
        this.asyncStub = RouteGuideGrpc.newStub(channel);
    }
    public RouteGuideGrpc.RouteGuideBlockingStub getRPCMethods(){
        return this.blockingStub;
    }
    public RouteGuideGrpc.RouteGuideStub getRPCAsyncMethods(){
        return this.asyncStub;
    }
}

3 如何调用具体的方法

3.1 普通调用和服务端流式调用

so easy!
通过获取stub之后直接调用即可。

package com.iq50.client.service.impl;

import com.iq50.client.routeguide.Feature;
import com.iq50.client.routeguide.Point;
import com.iq50.client.routeguide.Rectangle;
import com.iq50.client.routeguide.RouteGuideClient;
import com.iq50.client.service.RouteGuideService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Iterator;

@Service
public class RouteGuideServiceImpl implements RouteGuideService {
    @Autowired
    RouteGuideClient routeGuideClient;
    @Override
    public Feature GetFeature(Point point) {
        return routeGuideClient.getRPCMethods().getFeature(point);
    }
    @Override
    public Iterator<Feature>  ListFeatures(Rectangle rectangle) {
        return routeGuideClient.getRPCMethods().listFeatures(rectangle);
    }
}

3.2 客户端流式调用

在这个代码中我们需要使用SettableFuture来进行异步操作的通知,以及重写一个观察者的方法来方便进行异步的回调操作。

在这个方法体中,我们返回了一个匿名 StreamObserver 实例,其中我们:

  • 覆写了 onNext() 方法,每次客户端写入一个 Point 到消息流时,拿到特性和其它信息。 覆写了 onCompleted()
  • 方法(在 客户端 结束写入消息时调用),用来填充和构建我们的 RouteSummary。然后我们用 RouteSummary调用方法自己的的响应观察者的 onNext(),
  • 之后调用它的 onCompleted() 方法,结束服务器端的调用。
   		List<Feature> features = new ArrayList<Feature>();
        features.add(Feature.newBuilder().setLocation(Point.newBuilder().setLatitude(1200000).setLongitude(12000).build()).setName("asd").build());
        features.add(Feature.newBuilder().setLocation(Point.newBuilder().setLatitude(2200000).setLongitude(12000).build()).setName("asdf").build());
        features.add(Feature.newBuilder().setLocation(Point.newBuilder().setLatitude(3200000).setLongitude(12000).build()).setName("ewfew").build());
        features.add(Feature.newBuilder().setLocation(Point.newBuilder().setLatitude(4200000).setLongitude(12000).build()).setName("rtgr").build());
        features.add(Feature.newBuilder().setLocation(Point.newBuilder().setLatitude(5200000).setLongitude(12000).build()).setName("wer").build());
        int numPoints = features.size();
        //=========================
        //用来控制异步操作
        final SettableFuture<Void> finishFuture = SettableFuture.create();
        StreamObserver<RouteSummary> responseObserver = new StreamObserver<RouteSummary>() {
            @Override
            public void onNext(RouteSummary summary) {
                try {
                    System.out.printf("Finished trip with %d points. Passed %d features. Travelled %d meters. It took %d seconds.\n",
                            summary.getPointCount(), summary.getFeatureCount(), summary.getDistance(), summary.getElapsedTime());

                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public void onError(Throwable t) {
                //表示操作已经出错,进行通知
                finishFuture.setException(t);
            }

            @Override
            public void onCompleted() {
                //表示操作已经完成
                finishFuture.set(null);
            }
        };
        //获得一个请求的观察者对象
        StreamObserver<Point> requestObserver = routeGuideClient.getRPCAsyncMethods().recordRoute(responseObserver);

        try {
            // 随机挑选节点发送给服务器
            StringBuilder numMsg = new StringBuilder();
            Random rand = new Random();
            for (int i = 0; i < numPoints; ++i) {
                int index = rand.nextInt(features.size());
                Point point = features.get(index).getLocation();
                System.out.printf("Visiting point %d, %d\n", point.getLatitude(),point.getLongitude());
                //将点发送给服务器
                requestObserver.onNext(point);
                // Sleep for a bit before sending the next one.
                Thread.sleep(rand.nextInt(1000) + 500);
                if (finishFuture.isDone()) {
                    break;
                }
            }
            System.out.println(numMsg.toString());
            //告诉服务器端客户端以及发送完全部信息
            requestObserver.onCompleted();
            //等待服务器端完成处理
            finishFuture.get();
            System.out.println("Finished RecordRoute\n");
        } catch (Exception e) {
            requestObserver.onError(e);
            System.out.printf("RecordRoute Failed\n", e);
        }

        return "调用成功";

3.3 双向流式调用

    @GetMapping("/routeChat")
    public String routeChat() {
        final SettableFuture<Void> finishFuture = SettableFuture.create();
        StreamObserver<RouteNote> requestObserver = routeGuideClient.getRPCAsyncMethods().routeChat(new StreamObserver<RouteNote>() {
            @Override
            public void onNext(RouteNote note) {
                System.out.println("========");
                System.out.printf("Got2 message \"{%s}\" at {%d}, {%d}\n", note.getMessage(), note.getLocation().getLatitude(), note.getLocation().getLongitude());
            }

            @Override
            public void onError(Throwable t) {
                finishFuture.setException(t);
            }

            @Override
            public void onCompleted() {
                finishFuture.set(null);
            }
        });

        try {
            RouteNote[] requests =
                    {
                            RouteNote.newBuilder().setMessage("First message").setLocation(Point.newBuilder().setLongitude(0).setLatitude(0).build()).build(),
                            RouteNote.newBuilder().setMessage("Second message").setLocation(Point.newBuilder().setLongitude(0).setLatitude(1).build()).build(),
                            RouteNote.newBuilder().setMessage("Third message").setLocation(Point.newBuilder().setLongitude(1).setLatitude(0).build()).build(),
                            RouteNote.newBuilder().setMessage("Fourth message").setLocation(Point.newBuilder().setLongitude(1).setLatitude(1).build()).build(),
                            RouteNote.newBuilder().setMessage("Fifth message").setLocation(Point.newBuilder().setLongitude(1).setLatitude(1).build()).build(),
                    };

            for (RouteNote request : requests) {
                System.out.println("========");
                System.out.printf("Got message \"{%s}\" at {%d}, {%d}\n", request.getMessage(), request.getLocation().getLatitude(), request.getLocation().getLongitude());
                //发送请求
                requestObserver.onNext(request);
                //线程休眠0.5。这样从结果中才能体现出双向流的调用
                Thread.sleep(500);
            }
            //发送完成
            requestObserver.onCompleted();
            //等待服务器完成
            finishFuture.get();
            System.out.println("Finished RouteChat");
        } catch (Exception t) {
            requestObserver.onError(t);
            System.out.println("RouteChat Failed");
        }

        return "";
    }

结果如下:确实体现出了双向流
在这里插入图片描述

文章来源:https://blog.csdn.net/qq_45467608/article/details/134863944
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。