一、概念java
rpc:(Remote Procedure Call)遠程過程調用,是一個計算機通訊協議的泛稱。該協議容許運行於一臺計算機的程序調用另外一臺計算機的子程序,而程序員無需額外地爲這個交互做用編程。若是涉及的軟件採用面向對象編程,那麼遠程過程調用亦可稱做遠程調用或遠程方法調用。git
遠程過程調用是一個分佈式計算的客戶端-服務器(Client/Server)的例子,它簡單而又廣受歡迎。遠程過程調用老是由客戶端對服務器發出一個執行若干過程請求,並用客戶端提供的參數。執行結果將返回給客戶端。因爲存在各式各樣的變體和細節差別,對應地派生了各式遠程過程調用協議,並且它們並不互相兼容。程序員
從通訊協議的層面,大體能夠分爲:github
基於HTTP協議的(例如基於文本的SOAP(XML)、Rest(JSON),基於二進制Hessian(Binary))web
基於TCP協議的(一般會藉助Mina、Netty等高性能網絡框架)spring
從不一樣的開發語言和平臺層面,分爲:數據庫
單種語言或平臺特定支持的通訊技術(例如Java平臺的RMI、.NET平臺Remoting)編程
支持跨平臺通訊的技術(例如HTTP Rest、Thrift等)json
從調用過程來看,分爲:服務器
同步通訊調用(同步RPC)
異步通訊調用(MQ、異步RPC)
常見的幾種通訊方式
1. 遠程數據共享(例如:共享遠程文件,共享數據庫等實現不一樣系統通訊)
2. 消息隊列
3. RPC(遠程過程調用)
序列化/反序列化
只有二進制數據才能在網絡中傳輸,序列化和反序列化的定義是:
將對象轉換成二進制流的過程叫作序列化,
將二進制流轉換成對象的過程叫作反序列化
json-rpc是基於json的跨語言遠程調用協議。比xml-rpc、webservice等基於文本的協議數據傳輸格式;相比於hessian、java-rpc等二進制協議更便於調試、實現、擴展,是很優秀的一種遠程調用協議。眼下主流語言都已有json-rpc的實現框架,java語言中較好的json-rpc實現框架有jsonrpc4j、jpoxy、json-rpc。三者之中jsonrpc4j既可獨立使用。又可與spring無縫集合,比較適合於基於spring的項目開發。
總結下,jsonrpc4j主要優勢有:
一、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(); }
@JsonRpcService("rpc/products") public interface ProductJsonRpcService { List<Product> findAll(ProductParam param); Product findOne(String id); }
@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
一、請求的服務端地址
二、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接口代碼上是重複的,能夠分別獨立抽取出來做爲單獨的模塊,能夠減小代碼的重複。