首页天道酬勤,

,

张世龙 05-13 12:03 115次浏览

转载注明出处

动机

最近进行的项目很大,分为许多模块,但由于开源技术使用的语言不同,模块使用的语言可能不同,但基本上是使用Java和Python实现的。 如果每个模块都需要交互,就会出现问题。 模块不能像Jar包或Python模块那样部署。 Java有其JVM,Python有其解释器,独立调用只能使用朴素方案。 但是,native显然与操作系统有关,不知道改变环境会产生什么样的兼容性问题。

具体问题还是要具体分析,需要考虑的因素很多。 在这个实际项目中,要考虑效率的因素如下。

单输入文本的处理时间

网络传输时间

机器配置

经过测试,输入文本处理时间的网络传输时间,而且没有高配置的机器,如果使用朴素方法,可能需要跑一些模块,机器可能不会负荷,所以考虑分布式构建提高效率。

设计分布式系统需要考虑机器之间的交互。 最简单、最常见的是使用互联网协议,如http协议。 虽然这是一个APP应用层协议,可能并不高效,但是为了简单起见,如果网络传输效率几乎可以忽略,我们选择了此APP应用层协议。

虽然http协议仅用作通信协议,但数据传输格式仍需规范。 传统上有xml和几种序列化方式,近年来流行更轻量通用的json格式,广泛用于web数据传输。 在本文中,选择json格式。

于是我朝着这个方向调查,找到了json-rpc 2.0标准。

JSON-RPC 2.0概述

JSON-RPC is a stateless, 轻型远程处理模块呼叫(RPC )。protocol.primarilythisspecificationdefinesseveraldatastructuresandtherulesaroundatastructures nosticinthanage ceptscanbeusedwithinthesameprocess,over sockets,over http,orinmanyvariousmessagepassingenvironments.ituses

JSON-RPC是一种无状态、轻量级的远程过程调用(RPC )协议。 本规范主要围绕其处理方法定义了一些数据结构和规则。 此概念可用于在同一进程、套接字或HTTP之间或许多其他消息传递环境中传输数据。 将JSON(RFC4627 )用作数据格式。

那么,这里关键词: JSON,HTTP。

既然是规范,就应该被很多人应用,因为有详细的文档,所以不需要自己写详细的交互式文档。

说明规格中定义的对象所需的成员。

jsonrpc

astringspecifyingtheversionofthejson-RPC协议. must be exactly ' 2.0 '。

方法

astringcontainingthenameofthemethodtobeinvoked.methodnamesthatbeginwithewordrpcfollowedbyaperiodcharacter (u 002 EOR ascii 46 ) thodsandextensionsandmustnotbeusedforanythingelse。

参数化

astructuredvaluethatholdstheparametervaluestobeusedduringtheinvocationofthemethod.thismembermaybeomitted。

id

anidentifierestablishedbytheclientthatmustcontainastring,Number,ornullvalueifincluded.ifitisnotincludeditisassssumedtobeanatobeanananated

theservermustreplywiththesamevalueintheresponseobjectifincluded.thismemberisusedtocorrelatethecontextbetweeenthetwooobjects。

rpc调用启动时,服务器必须返回响应(通知除外)。 将显示响应

成一个单一的对象,包含下列的成员:

jsonrpc

指定JSON-RPC版本的字符串,它必须是“2.0”。

result

当调用成功时,该成员是必须的。

如果调用方法出现错误时,必须不包含该成员。

该成员的值由服务器上调用的方法决定。

error

当调用发生错误时,该成员是必须的。

在调用期间如果没有错误产生,必须不包含该成员。

该成员的值必须是一个5.1节定义的对象。

id

该成员是必须的。

它的值必须与请求对象中的id成员的值相同。

如果检查请求对象中的id时发生错误(如:转换错误或无效的请求),它必须为Null。

必须包含result或error成员,但是两个成员都必须不能同时包含。

Java Server

既然是使用http协议,那就需要一个web容器是装载。(不装载也可以,自己去实现一个http容器咯,或者去找开源的,其实也挺大的)

Java有一段时间没用了,以前用Java是做web开发,用经典的Spring框架做对象管理,SpringMVC管理整个web框架,数据层框架用Hibernate或者JPA等。听说最近有个框架很火,叫Spring Boot,它能够快速地构建web应用,而且配置纯Java化,通过一个函数即可启动,像Python的Flask那样的方便,实质它默认使用的底层容器还是Tomcat,简化了我们的操作而已。

用传统的web应用构建方式的成本跟学习Spring Boot框架的成本之间衡量了一下,选择了后者,因为前者再用也是没有什么收益,后者却能体验到新框架,而且现在的框架网站上的Quick Start都很容易实现。但是提高效率的方法不应是单个单个地学习,而是联系起来学习,所以我直接去github上找java jsonrpc的项目。于是定位到了一个叫jsonrpc4j的开源项目,Star299,肯定没找错了。

直接看它的Wiki,还真有Spring Boot的Quick Start。

这里省点力,直接贴:

Server

Configuration

To get the entire system working, you need to define the AutoJsonRpcServiceImplExporter bean in your @Configuration class:

package example.jsonrpc4j.springboot;

import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImplExporter;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class ApplicationConfig {

@Bean

public static AutoJsonRpcServiceImplExporter autoJsonRpcServiceImplExporter() {

AutoJsonRpcServiceImplExporter exp = new AutoJsonRpcServiceImplExporter();

//in here you can provide custom HTTP status code providers etc. eg:

//exp.setHttpStatusCodeProvider();

//exp.setErrorResolver();

return exp;

}

}

Service

Then create your service interface. My example is a simple calculator endpoint:

package example.jsonrpc4j.springboot.api;

import com.googlecode.jsonrpc4j.JsonRpcParam;

import com.googlecode.jsonrpc4j.JsonRpcService;

@JsonRpcService("/calculator")

public interface ExampleServerAPI {

int multiplier(@JsonRpcParam(value = "a") int a, @JsonRpcParam(value = "b") int b);

}

And implement your interface like this:

package example.jsonrpc4j.springboot.api;

import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImpl;

import org.springframework.stereotype.Service;

@Service

@AutoJsonRpcServiceImpl

public class ExampleServerAPIImpl implements ExampleServerAPI {

@Override

public int multiplier(int a, int b) {

return a * b;

}

}

测试:

curl -H "Content-Type:application/json" -d '{"id":"1","jsonrpc":"2.0","method":"multiplier","params":{"a":5,"b":6}}' http://localhost:8080/calculator

Python Server

这里我使用Flask-jsonrpc模块,直接pip安装。

有点尿急,也直接贴吧:

Create your application and initialize the Flask-JSONRPC.

from flask import Flask

from flask_jsonrpc import JSONRPC

app = Flask(__name__)

jsonrpc = JSONRPC(app, '/api')

Write JSON-RPC methods.

@jsonrpc.method('App.index')

def index():

return u'Welcome to Flask JSON-RPC'

All code of example run.py.

$ python run.py

* Running on http://0.0.0.0:5000/

Test:

$ curl -i -X POST \

-H "Content-Type: application/json; indent=4" \

-d '{

"jsonrpc": "2.0",

"method": "App.index",

"params": {},

"id": "1"

}' http://localhost:5000/api

HTTP/1.0 200 OK

Content-Type: application/json

Content-Length: 77

Server: Werkzeug/0.8.3 Python/2.7.3

Date: Fri, 14 Dec 2012 19:26:56 GMT

{

"jsonrpc": "2.0",

"id": "1",

"result": "Welcome to Flask JSON-RPC"

}

如果是Python调用它,可以

>>> from flask_jsonrpc.proxy import ServiceProxy

>>> server = ServiceProxy('http://localhost:5000/api')

>>>

>>> server.App.index()

{'jsonrpc': '2.0', 'id': '91bce374-462f-11e2-af55-f0bf97588c3b', 'result': 'Welcome to Flask JSON-RPC'}

Flask-jsonrpc有一个优点就是它有一个api管理页面:

Flask-jsonrpc API管理界面

交互方法

以上我们可以看到我们已经可以通过http协议,加上一些json字符串就可以实现调用了。

在实际项目中,我们只需要实现客户端使用语言的jsonrpc 2.0规范的http调用方法即可,如上一节中的Python使用ServiceProxy对象调用。

还有一定值得注意的是,交互的对象必须要能转为json格式,否则需要自己写转json字符串的方法。

总结

总感觉这是个笨笨的方法,是因为http协议笨重吗?

反正我觉得比native好,少侵入代码,又能形成分布式,而且有个好处就是,前端应用可以直接用js调用。

其实RPC调用就是一个将模块服务化的过程,一个模块能够向多个模块提供服务,例如可以想一些公共功能服务化,就不需要重复代码。

由于分布式知识有限,不能进行更多方法的对比,日后如果有所学习,一定会更新。

eth改算法,java实现rpc调用 rpc系统,grpc protobuf