Springboot集成Brpc
本文代码可在总结处自取。
1、为什么要写这篇文章
最近自己做的业务在和C++团队对接,双方需要指定接口与传输协议。原本是直接使用http协议传输json数据,对双方来说都比较简单可接受。但是json数据传输效率实在令人堪忧,导致我们不得不另寻其道。因此,商量过后决定使用Brpc协议传输protobuf数据。
这对对方来说轻而易举,分分钟就搞定了。咱们搞Java的如果是第一次接触的话,还是需要一些时间调研的。
最开始想的是能有一篇手把手搭建Springboot集成Brpc的文章,但是浏览了一堆就没一个靠谱的`( >﹏< )′。于是自己只能不断查阅github兄弟上的wiki、遇到问题找StackOverflow大哥,最终才成功搭建起来基于Brpc协议的C++客户端与Java服务端。
想着自己踩坑不少,有必要记录一下整个搭建过程,不仅方便日后自己查阅,也能帮助兄弟们少走弯路。
2、Java服务端搭建
由于现在Java已经差不多和Spring/SpringBoot划上等号了(bushi),因此本小节仅介绍SpringBoot集成Brpc的工程搭建。
Baidu已经为我们开源了brpc-java的项目,chrome上输入关键词brpc java,第一个搜索词条便是baidu/starlight(感谢Google)。
想要搭建一个点对点对接的工程,我们可以直接看这个仓库->wiki->快速开始->2. SpringBoot场景(类似Spring MVC)这个锚点的内容。
2.1、Springboot工程搭建
这个相信大家都轻车熟路了,我就不再费太多口舌了。不过要注意的是,springboot的版本要在2.x,我们原先的工程就是1.x的Springboot,导致容器每次都启动失败。具体原因当时没有深入研究,后续有机会再给补上(主要原因还是打工人想早点干完活🤣)。
2.2、添加starlight依赖
截止写这篇文章的时候,mvnrepository仅有下面一个版本的仓库,所以可以不用去找了,就用下面的吧。
<dependency>
<groupId>com.baidu.cloud</groupId>
<artifactId>spring-cloud-starter-baidu-starlight</artifactId>
<version>2022.2.0</version>
</dependency>
记得还要添加一个httpclient依赖,这里就添加apache httpclient了。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
2.3、工程代码
因为是搭建启动demo,代码量非常少,这里就一起说完了。
整个工程的组织结构如下所示:
- Application:Springboot启动类,没啥好说的
- domain包:这个包下的类主要是brpc服务的请求和响应,设计这些请求和响应是为了C++侧更好的设计proto数据。
- service包:暴露出去的服务接口和服务实现。
- application.yaml:starlight配置
domain包下的类:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EchoRequest {
private String message;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EchoResponse {
private String message;
}
service包下的类:
public interface EchoService {
EchoResponse echo(EchoRequest request);
}
// @RpcService注解指定了该service以brpc协议暴露出去,starlight支持一个接口同时暴露brpc和http协议,具体可以参考wiki
@RpcService
public class EchoServiceImpl implements EchoService {
@Override
public EchoResponse echo(EchoRequest request) {
System.out.println(request.getMessage());
return new EchoResponse("Success");
}
}
Application类:
@SpringBootApplication
@StarlightScan // 扫描@RpcService注解暴露的服务
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
application.yaml:brpc服务将被暴露再8777端口
starlight:
server:
enable: true
port: 8777
启动Application,如果没有问题就表示Java服务端已经搭建完成了。
3、C++客户端搭建
其实这一小节没有太大必要,我们搭建好了服务后直接让C++侧的同学对接你的服务进行测试就行了。
但想着为了搭建一个可靠的服务,咱们可以现在本地搭建一个C++ brpc client进行测试下,确保咱们的服务端没问题后再和C++客户端侧对接,这样不显得你更加靠谱么。
3.1、安装、编译brpc
在安装brpc之前需要安装依赖的环境:
- 安装git、g++、make、libssl-dev。(还是喜欢一个一个安装,在安装失败的时候就不用到处找日志了)
sudo apt-get install git
sudo apt-get install g++
sudo apt-get install make
sudo apt-get install libssl-dev
- 安装gflags、protobuf、leveldb
sudo apt-get install realpath
sudo apt-get install libgflags-dev
sudo apt-get install libprotobuf-dev
sudo apt-get install libprotoc-dev
sudo apt-get install protobuf-compiler
sudo apt-get install libleveldb-dev
- 下载brpc源码
git clone https://github.com/brpc/brpc.git
- 使用config_brpc.sh编译brpc
cd brpc
sh config_brpc.sh --headers=/usr/include --libs=/usr/lib
make
- 测试是否编译成功
cd example/echo_c++
make
./echo_server & ./echo_client
- 访问localhost:8080,如果能够出现如下页面,说明使用已经没问题了。
3.2、与Java服务端联调测试
为了简单起见,我们直接使用EchoClient进行测试。
首先我们需要修改echo.proto文件,我们需要把C++客户端的数据协议与Java服务端对齐,修改后的文件如下所示,主要有两点修改:
- package,包改成了EchoService所在包名路径
- EchoService.echo,方法首字母改成小写,与Java端对齐。当然也可以改成大写,让Java端与C++端对齐。
syntax="proto2";
package org.chubxu.brpc.service;
option cc_generic_services = true;
message EchoRequest {
required string message = 1;
};
message EchoResponse {
required string message = 1;
};
service EchoService {
rpc echo(EchoRequest) returns (EchoResponse);
};
改完后需要重新编译proto文件。
protoc --cpp_out=./ echo.proto
因为proto文件改变,客户端源码也必须做出相应改变,有以下几点需要改变
EchoService_Stub
的名称空间EchoRequest
、EchoResponse
的名称空间- stub的方法名
其实改变的地方就是对应proto文件改变的地方。
org::chubxu::brpc::service::EchoService_Stub stub(&channel);
org::chubxu::brpc::service::EchoRequest request;
org::chubxu::brpc::service::EchoResponse response;
stub.echo(&cntl, &request, &response, NULL);
改完后重新编译一下。
make
之后就可以发起请求了,观察client.cpp源码,可知客户端使用gflag接收了几个命令行参数,其中就有server参数指定brpc服务端的ip和port,因此我们执行下面的命令就可以成功发起请求了。
./echo_client --server=host:8777
服务端日志
客户端日志
4、总结
到这里,整个搭建和联调过程就结束了,还算是比较详细吧。其中对接的数据只是非常简单的message,且只有一个。如果是复杂数据的话,proto文件和Java bean需要设计的非常规范,否则非常容易出现protostuff反序列化异常问题。这个有机会就下次再说啦。
ps:本文全部代码在 👉 springboot04-brpc,有需要的可以自取哈。
转载自:https://juejin.cn/post/7177191380194689080