java版gRPC实战之四:客户端流

  • 双击下图红框中的task即可生成java代码:

在这里插入图片描述

  • 生成下图红框中的文件:

在这里插入图片描述

  • 接下来开发服务端;

开发服务端应用

  • 在父工程grpc-turtorials下面新建名为client-stream-server-side的模块,其build.gradle内容如下:

// 使用springboot插件

plugins {

id ‘org.springframework.boot’

}

dependencies {

implementation ‘org.projectlombok:lombok’

implementation ‘org.springframework.boot:spring-boot-starter’

// 作为gRPC服务提供方,需要用到此库

implementation ‘net.devh:grpc-server-spring-boot-starter’

// 依赖自动生成源码的工程

implementation project(‘:grpc-lib’)

// annotationProcessor不会传递,使用了lombok生成代码的模块,需要自己声明annotationProcessor

annotationProcessor ‘org.projectlombok:lombok’

}

  • 配置文件application.yml:

spring:

application:

name: client-stream-server-side

gRPC有关的配置,这里只需要配置服务端口号

grpc:

server:

port: 9900

  • 启动类ClientStreamServerSideApplication.java的代码就不贴了,普通的springboot启动类而已;

  • 重点是提供grpc服务的GrpcServerService.java,请结合前面小结的第五点来阅读代码,咱们要做的就是给上层框架返回一个匿名类,至于里面的onNext、onCompleted方法何时被调用是上层框架决定的,另外还准备了成员变量totalCount,这样就可以记录总数了:

package com.bolingcavalry.grpctutorials;

import com.bolingcavalry.grpctutorials.lib.AddCartReply;

import com.bolingcavalry.grpctutorials.lib.CartServiceGrpc;

import com.bolingcavalry.grpctutorials.lib.ProductOrder;

import io.grpc.stub.StreamObserver;

import lombok.extern.slf4j.Slf4j;

import net.devh.boot.grpc.server.service.GrpcService;

@GrpcService

@Slf4j

public class GrpcServerService extends CartServiceGrpc.CartServiceImplBase {

@Override

public StreamObserver addToCart(StreamObserver responseObserver) {

// 返回匿名类,给上层框架使用

return new StreamObserver() {

// 记录处理产品的总量

private int totalCount = 0;

@Override

public void onNext(ProductOrder value) {

log.info(“正在处理商品[{}],数量为[{}]”,

value.getProductId(),

value.getNumber());

// 增加总量

totalCount += value.getNumber();

}

@Override

public void onError(Throwable t) {

log.error(“添加购物车异常”, t);

}

@Override

public void onCompleted() {

log.info(“添加购物车完成,共计[{}]件商品”, totalCount);

responseObserver.onNext(AddCartReply.newBuilder()

.setCode(10000)

.setMessage(String.format(“添加购物车完成,共计[%d]件商品”, totalCount))

.build());

responseObserver.onCompleted();

}

};

}

}

开发客户端应用

  • 在父工程grpc-turtorials下面新建名为client-stream-server-side的模块,其build.gradle内容如下:

plugins {

id ‘org.springframework.boot’

}

dependencies {

implementation ‘org.projectlombok:lombok’

implementation ‘org.springframework.boot:spring-boot-starter’

implementation ‘org.springframework.boot:spring-boot-starter-web’

implementation ‘net.devh:grpc-client-spring-boot-starter’

implementation project(‘:grpc-lib’)

}

  • 配置文件application.yml,设置自己的web端口号和服务端地址:

server:

port: 8082

spring:

application:

name: client-stream-client-side

grpc:

client:

gRPC配置的名字,GrpcClient注解会用到

client-stream-server-side:

gRPC服务端地址

address: ‘static://127.0.0.1:9900’

enableKeepAlive: true

keepAliveWithoutCalls: true

negotiationType: plaintext

  • 启动类ClientStreamClientSideApplication.java的代码就不贴了,普通的springboot启动类而已;

  • 正常情况下我们都是用StreamObserver处理服务端响应,这里由于是异步响应,需要额外的方法从StreamObserver中取出业务数据,于是定一个新接口,继承自StreamObserver,新增getExtra方法可以返回String对象,详细的用法稍后会看到:

package com.bolingcavalry.grpctutorials;

import io.grpc.stub.StreamObserver;

public interface ExtendResponseObserver extends StreamObserver {

String getExtra();

}

  • 重头戏来了,看看如何远程调用客户端流类型的gRPC接口,前面小结提到的2、3、4点都会涉及到,代码中已经添加详细注释:

package com.bolingcavalry.grpctutorials;

import com.bolingcavalry.grpctutorials.lib.AddCartReply;

import com.bolingcavalry.grpctutorials.lib.CartServiceGrpc;

import com.bolingcavalry.grpctutorials.lib.ProductOrder;

import io.grpc.stub.StreamObserver;

import lombok.Getter;

import lombok.extern.slf4j.Slf4j;

import net.devh.boot.grpc.client.inject.GrpcClient;

import org.springframework.stereotype.Service;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.TimeUnit;

@Service

@Slf4j

public class GrpcClientService {

@GrpcClient(“client-stream-server-side”)

private CartServiceGrpc.CartServiceStub cartServiceStub;

public String addToCart(int count) {

CountDownLatch countDownLatch = new CountDownLatch(1);

// responseObserver的onNext和onCompleted会在另一个线程中被执行,

// ExtendResponseObserver继承自StreamObserver

ExtendResponseObserver responseObserver = new ExtendResponseObserver() {

String extraStr;

@Override

public String getExtra() {

return extraStr;

}

private int code;

private String message;

@Override

public void onNext(AddCartReply value) {

log.info(“on next”);

code = value.getCode();

message = value.getMessage();

}

@Override

public void onError(Throwable t) {

log.error(“gRPC request error”, t);

extraStr = "gRPC error, " + t.getMessage();

countDownLatch.countDown();

}

@Override

public void onCompleted() {

log.info(“on complete”);

extraStr = String.format(“返回码[%d],返回信息:%s” , code, message);

countDownLatch.countDown();

}

};

// 远程调用,此时数据还没有给到服务端

StreamObserver requestObserver = cartServiceStub.addToCart(responseObserver);

for(int i=0; i<count; i++) {

// 发送一笔数据到服务端

requestObserver.onNext(build(101 + i, 1 + i));

}

// 客户端告诉服务端:数据已经发完了

requestObserver.onCompleted();

try {

// 开始等待,如果服务端处理完成,那么responseObserver的onCompleted方法会在另一个线程被执行,

// 那里会执行countDownLatch的countDown方法,一但countDown被执行,下面的await就执行完毕了,

// await的超时时间设置为2秒

countDownLatch.await(2, TimeUnit.SECONDS);

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

如果觉得本文对你有帮助的话,不妨给我点个赞,关注一下吧!

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!
以上Java开发知识点,真正体系化!**

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

如果觉得本文对你有帮助的话,不妨给我点个赞,关注一下吧!

[外链图片转存中…(img-5zWNATmL-1712029805095)]

[外链图片转存中…(img-BxyjKSMI-1712029805095)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

  • 13
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值