JSON-RPC轻量级远程调用协议介绍及使用

Nirvana

一、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);
    }
}

clipboard.png
成功调取服务端的内容,测试成功。。。。。

总结

json-rpc调用原理:
根据我们配置的信息去扫描RPC的服务接口,然后去创建代理,执行的时候就是把我们的操作信息转化成json字符串的格式传递到服务端,然后服务端使用json字符串的形式返回来。
另外,其实服务端和客户端的实体类和RPC接口代码上是重复的,可以分别独立抽取出来作为单独的模块,可以减少代码的重复。

阅读 13.1k

整个体系复杂对我而言又陌生,每次学习对自己的脑力与知识体系都是一个巨大的挑战,也需要克服巨大的惰...

29 声望
4 粉丝
0 条评论

整个体系复杂对我而言又陌生,每次学习对自己的脑力与知识体系都是一个巨大的挑战,也需要克服巨大的惰...

29 声望
4 粉丝
文章目录
宣传栏