RPC 组件
srpc Simple RPC 简单易用的 rpc 组件
特性
- 轻量级、用法简单
- 无框架依赖、可与其他框架集成
- tcp 协议,性能还不错
- 支持服务自动发现 (
nacos) - 支持
token验证
快速使用
先搭建一个 api 模块,用于提供 rpc 接口定义
xml
<dependency>
<groupId>org.winterfell</groupId>
<artifactId>srpc</artifactId>
<version>1.1.0-SNAPSHOT</version>
</dependency>java
public interface PersonService {
PersonDTO find(String name);
String plus(String a, String b);
}java
@Data
@Accessors(chain = true)
@ToString
public class PersonDTO implements Serializable {
private static final long serialVersionUID = 7702920534629457322L;
private String name;
private Integer age;
private Map attributes;
}接着搭建服务端和客户端模块:
TIP
为了演示方便,这里把服务端和客户端都放在一个工程里,实际场景里是分开的。
引入 api 和一些必要依赖:
xml
<dependency>
<groupId>org.winterfell</groupId>
<artifactId>srpc-sample-api</artifactId>
<version>1.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.12</version>
</dependency>服务端实现:
java
public class RpcSampleProvider {
public static void main(String[] args) {
RpcProviderFactory providerFactory = RpcProviderFactory.builder()
.accessToken("whosyourdaddy")
.corePoolSize(10)
.maxPoolSize(64)
.port(5555) // 服务监听 5555 端口
.build();
providerFactory.start(new AsyncResultHandler() {
@Override
public void complete(Object result) {
System.out.println("rpc server 启动成功!");
providerFactory.addService(PersonService.class.getName(), new PersonServiceImpl());
}
@Override
public void failed(Throwable error) {
System.err.println("rpc server 启动失败");
}
});
}
}java
public class PersonServiceImpl implements PersonService {
@Override
public PersonDTO find(String name) {
return new PersonDTO().setAge(RandomUtil.randomInt(20,50)).setName(name);
}
@Override
public String plus(String a, String b) {
return String.format("%s %s %s", a, b, RandomUtil.randomInt(20,50));
}
}客户端实现:
java
public class RpcSampleConsumer {
public static void main(String[] args) {
RpcConsumerFactory consumerFactory = RpcConsumerFactory.builder()
.address("127.0.0.1:5555")
.accessToken("whosyourdaddy")
.build();
PersonService personService = consumerFactory.getObject(PersonService.class);
int count = 40;
for (int i = 0; i < count; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.err.println(e.getLocalizedMessage());
}
PersonDTO person = personService.find(RandomUtil.randomString(4));
if (!Objects.isNull(person)) {
System.out.printf("num: %d, response: %s \n", i, person.toString());
}
}
}
}分别启动 RpcSampleProvider 和 RpcSampleConsumer ,可以看到服务调用结果。
集成 springboot
使用
springboot中使用会更加方便,引入下面的依赖:
xml
<dependency>
<groupId>org.winterfell</groupId>
<artifactId>srpc-spring-boot-starter</artifactId>
<version>1.1.0-SNAPSHOT</version>
</dependency>服务端实现:
java
@RpcProvider
public class PersonServiceImpl implements PersonService {
@Override
public PersonDTO find(String name) {
return new PersonDTO().setAge(RandomUtil.randomInt(20,50)).setName(name);
}
@Override
public String plus(String a, String b) {
return String.format("%s %s %s", a, b, RandomUtil.randomInt(20,50));
}
}服务端配置:
yaml
srpc:
server:
port: 5555
access-token: YNKM45sMDafV客户端调用:
java
@CrossOrigin
@RestController
@RequestMapping("/api")
public class IndexController {
@RpcInject
private PersonService personService;
@GetMapping("/plus/{a}/{b}")
public String getPlus(@PathVariable String a, @PathVariable String b) {
return personService.plus(a, b);
}
}客户端配置:
yaml
srpc:
providers:
- address: 127.0.0.1:5555
access-token: YNKM45sMDafV # 和服务端保持一致
request-timeout: 600000注解说明
@RpcProvider
注解某个 rpc 接口的实现类,以便在 spring 启动时,provideFactory 可以扫描并注册该类, 在 rpc 服务端使用
TIP
该注解包含 @Service 注解
@RpcInject
自动注入 rpc 的接口类并在 spring 容器内注册,在rpc客户端使用
TIP
使用此接口, 无需使用 @AutoWried