一、rpc知识
1、概念
rpc:(Remote Procedure Call)远程过程调用,是一个计算机通信协议的泛称。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程调用或远程方法调用。
远程过程调用是一个分布式计算的客户端-服务器(Client/Server)的例子,它简单而又广受欢迎。远程过程调用总是由客户端对服务器发出一个执行若干过程请求,并用客户端提供的参数。执行结果将返回给客户端。由于存在各式各样的变体和细节差异,对应地派生了各式远程过程调用协议,而且它们并不互相兼容。
从通信协议的层面,大致可以分为:
基于HTTP协议的(例如基于文本的SOAP(XML)、Rest(JSON),基于二进制Hessian(Binary))
基于TCP协议的(通常会借助Mina、Netty等高性能网络框架)
从不同的开发语言和平台层面,分为:
单种语言或平台特定支持的通信技术(例如Java平台的RMI、.NET平台Remoting)
支持跨平台通信的技术(例如HTTP Rest、Thrift等)
从调用过程来看,分为:
同步通信调用(同步RPC)
异步通信调用(MQ、异步RPC)
常见的几种通信方式
1. 远程数据共享(例如:共享远程文件,共享数据库等实现不同系统通信)
2. 消息队列
3. RPC(远程过程调用)
序列化/反序列化
只有二进制数据才能在网络中传输,序列化和反序列化的定义是:
将对象转换成二进制流的过程叫做序列化,
将二进制流转换成对象的过程叫做反序列化
二、json-rpc技术简单介绍
json-rpc是基于json的跨语言远程调用协议。比xml-rpc、webservice等基于文本的协议数据传输格式;相比于hessian、java-rpc等二进制协议更便于调试、实现、扩展,是很优秀的一种远程调用协议。眼下主流语言都已有json-rpc的实现框架,java语言中较好的json-rpc实现框架有jsonrpc4j、jpoxy、json-rpc。三者之中jsonrpc4j既可独立使用。又可与spring无缝集合,比較适合于基于spring的项目开发。
总结下,jsonrpc4j主要优点有:
- 代码编写简单
- 体积小巧
- 与Spring完美整合
1、JSON-RPC协议描写叙述
json-rpc协议很easy,发起远程调用时向服务端数据传输格式例如以下:
{ "method": "sayHello", "params": ["Hello JSON-RPC"], "id": 1}
參数说明:
method: 调用的方法名
params: 方法传入的參数。若无參数则传入 []
id : 调用标识符。用于标示一次远程调用过程
server其收到调用请求,处理方法调用,将方法效用结果效应给调用方;返回数据格式:
{
"result": "Hello JSON-RPC",
"error": null,
"id": 1
}
參数说明:
result: 方法返回值。若无返回值。则返回null。
若调用错误,返回null。
error :调用时错误,无错误返回null。
id : 调用标识符,与调用方传入的标识符一致。
以上就是json-rpc协议规范,很easy,小巧。便于各种语言实现。
三、搭建服务端
添加依赖
<dependency>
<groupId>com.github.briandilley.jsonrpc4j</groupId>
<artifactId>jsonrpc4j</artifactId>
<version>1.5.3</version>
</dependency>
添加配置类JsonRpcConfig
@Configuration
public class JsonRpcConfig {
@Bean
public AutoJsonRpcServiceImplExporter rpcServiceImplExporter(){
return new AutoJsonRpcServiceImplExporter();
}
添加JsonRpc服务接口
@JsonRpcService("rpc/products")
public interface ProductJsonRpcService {
List<Product> findAll(ProductParam param);
Product findOne(String id);
}
添加JsonRpc服务接口实现类
@AutoJsonRpcServiceImpl
@Service
public class ProductJsonRpcServiceImpl implements ProductJsonRpcService {
@Autowired
private ProductService productService;
@Override
public List<Product> findAll(ProductParam param) {
Pageable pageable = PageRequest.of(0,100, Sort.Direction.DESC,"rewardRate");
Page<Product> result = productService.query(param.getIdsList(),param.getNamesList(), param.getMinRewardRate(),
param.getMaxRewardRate(), param.getStatusList(), pageable);
return result.getContent();
}
@Override
public Product findOne(String id) {
productService.findById(id);
return null;
}
}
常见错误: @JsonRpcService("rpc/products")
是正确的,需要注意的是这里不能以/
开始,例如/products
就是错误的。
四、搭建客户端
添加依赖
<dependency>
<groupId>com.github.briandilley.jsonrpc4j</groupId>
<artifactId>jsonrpc4j</artifactId>
<version>1.5.3</version>
</dependency>
配置文件
rpc:
client:
url: http://localhost:8080/manager/ #1
basePackage: com.momo.seller #2
1、请求的服务端地址
2、rpc调用接口的包名,让配置类去扫描
配置类
@Configuration
public class JsonRpcConfig {
private static Logger LOG = LoggerFactory.getLogger(JsonRpcConfig.class);
@Bean
@ConditionalOnProperty(value = {"rpc.client.url","rpc.client.basePackage"})
public AutoJsonRpcClientProxyCreator rpcClientProxyCreator(@Value("${rpc.client.url}") String url, @Value("${rpc.client.basePackage}") String basePackage) {
AutoJsonRpcClientProxyCreator creator = new AutoJsonRpcClientProxyCreator();
try {
creator.setBaseUrl(new URL(url));
} catch (MalformedURLException e) {
LOG.error("创建rpc服务地址错误", e);
}
creator.setScanPackage(basePackage);
return creator;
}
}
客户端接口
@JsonRpcService("rpc/products")
public interface ProductJsonRpcClient {
List<Product> findAll(ProductParam param);
Product findOne(String id);
}
测试
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
ProductJsonRpcClient jsonRpcClient;
@GetMapping("/{id}")
public Product findOne(@PathVariable String id) {
return jsonRpcClient.findOne(id);
}
}
成功调取服务端的内容,测试成功。。。。。
总结
json-rpc调用原理:
根据我们配置的信息去扫描RPC的服务接口,然后去创建代理,执行的时候就是把我们的操作信息转化成json字符串的格式传递到服务端,然后服务端使用json字符串的形式返回来。
另外,其实服务端和客户端的实体类和RPC接口代码上是重复的,可以分别独立抽取出来作为单独的模块,可以减少代码的重复。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。