热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

jsonrpc2.0java_使用JSONRPC2.0规范解决多语言RPC交互的方案

转载注明出处动机最近做的一个项目比较大,分了许多模块,但是由于不同的开源技术使用的语言不同,不同模块使用的语言可能不同,但基

转载注明出处

动机

最近做的一个项目比较大,分了许多模块,但是由于不同的开源技术使用的语言不同,不同模块使用的语言可能不同,但基本上是使用Java和Python实现的。当各模块需要进行交互的时候,问题就出现了,模块不能像Jar包或者Python模块那样引入,Java有它的JVM,Python有它的解释器,单机调用只能是用native方案。但native明显与os有关,换个环境又不知道会有什么兼容问题出现。

具体问题还是要具体分析,考虑的因素有很多。在该实际项目中,关于效率需要考虑的因素有:

单输入文本的处理时间

网络传输时间

机器的配置

经过测试,单输入文本处理时间>>网络传输时间,而且没有很高配置的机器,如果用native方法,需要跑几个模块,机器可能负荷不了,所以考虑构建成分布式,以提高效率。

设计分布式系统需要考虑机器间如何交互。最简单的又通用的就是使用互联网协议,如http协议,由于它是个应用层协议,所以效率肯定不会高,但为了简单起见,而且在网络传输效率基本可以忽略不计的情况下,我们还是选用了这个应用层协议。

http协议只是作为通信协议,但是数据传输的格式还是要规范的,传统的有xml和一些序列化方案,近年流行更加轻量级和通用的json格式,它被广泛用于web数据传输。本文选用的就是json格式。

于是朝着这个方向去调研,找到了json-rpc 2.0规范。

JSON-RPC 2.0简介

JSON-RPC is a stateless, light-weight remote procedure call (RPC) protocol. Primarily this specification defines several data structures and the rules around their processing. It is transport agnostic in that the concepts can be used within the same process, over sockets, over http, or in many various message passing environments. It uses JSON (RFC 4627) as data format.

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

好了,此处关键词:JSON、HTTP。

既然是规范,应当被很多人应用,而且有详尽文档,就不需要自己傻乎乎地去写详细的交互文档。

下面介绍一下规范中定义的对象必须有的成员:

jsonrpc

A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".

method

A String containing the name of the method to be invoked. Method names that begin with the word rpc followed by a period character (U+002E or ASCII 46) are reserved for rpc-internal methods and extensions and MUST NOT be used for anything else.

params

A Structured value that holds the parameter values to be used during the invocation of the method. This member MAY be omitted.

id

An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null [1] and Numbers SHOULD NOT contain fractional parts [2]

The Server MUST reply with the same value in the Response object if included. This member is used to correlate the context between the two objects.

当发起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管理页面:

5b66aca61745

Flask-jsonrpc API管理界面

交互方法

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

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

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

总结

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

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

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

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



推荐阅读
  • Hadoop2.6.0 + 云centos +伪分布式只谈部署
    3.0.3玩不好,现将2.6.0tar.gz上传到usr,chmod-Rhadoop:hadophadoop-2.6.0,rm掉3.0.32.在etcp ... [详细]
  • 本文介绍了Python语言程序设计中文件和数据格式化的操作,包括使用np.savetext保存文本文件,对文本文件和二进制文件进行统一的操作步骤,以及使用Numpy模块进行数据可视化编程的指南。同时还提供了一些关于Python的测试题。 ... [详细]
  • 解决java.lang.IllegalStateException: ApplicationEventMulticaster not initialized错误的方法和原因
    本文介绍了解决java.lang.IllegalStateException: ApplicationEventMulticaster not initialized错误的方法和原因。其中包括修改包名、解决service name重复、处理jar包冲突和添加maven依赖等解决方案。同时推荐了一个人工智能学习网站,该网站内容通俗易懂,风趣幽默,值得一看。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 开发笔记:spring boot项目打成war包部署到服务器的步骤与注意事项
    本文介绍了将spring boot项目打成war包并部署到服务器的步骤与注意事项。通过本文的学习,读者可以了解到如何将spring boot项目打包成war包,并成功地部署到服务器上。 ... [详细]
  • 本文介绍了在sqoop1.4.*版本中,如何实现自定义分隔符的方法及步骤。通过修改sqoop生成的java文件,并重新编译,可以满足实际开发中对分隔符的需求。具体步骤包括修改java文件中的一行代码,重新编译所需的hadoop包等。详细步骤和编译方法在本文中都有详细说明。 ... [详细]
  • 本文介绍了使用FormData对象上传文件同时附带其他参数的方法。通过创建一个表单,将文件和参数添加到FormData对象中,然后使用ajax发送POST请求进行文件上传。在发送请求时,需要设置processData为false,告诉jquery不要处理发送的数据;同时设置contentType为false,告诉jquery不要设置content-Type请求头。 ... [详细]
  • Struts2+Sring+Hibernate简单配置
    2019独角兽企业重金招聘Python工程师标准Struts2SpringHibernate搭建全解!Struts2SpringHibernate是J2EE的最 ... [详细]
  • JVM:33 如何查看JVM的Full GC日志
    1.示例代码packagecom.webcode;publicclassDemo4{publicstaticvoidmain(String[]args){byte[]arr ... [详细]
author-avatar
闲看云天的快乐生活
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有