Java跨语言调用实现方案

简介:

Java 跨语言实现方案

背景:

在大型分布式 java 应用中,为了方便开发者,通常底层的 rpc 框架都会做一些调用的封装,让应用层开发人员在开发服务的时候只用编写简单的 pojo 对象就可以了,如流行的 spring remoting , jboss remoting 等等,都有这样的效果。

随着业务的需要,可能上层应用希望采用非 java 技术,如 php , ruby on rails ,而由于 java gc 和内存模型的限制,可能有的底层服务又需要采用更高性能和更加灵活的技术,如果 c++ , python 等。

这时候就会考虑跨语言的问题了,在如何不改动原有 pojo 实现的 rpc 框架,而让系统实现跨语言,这个难题摆在了中间件开发者的头上。

问题 :

现在我们不妨把上面说涉及的问题提取出来:

1)  不能改变原有的 java rpc 服务的发布方式,仍然采用 pojo 。

2)  上层非 java 应用可以调用到由 server 端 pojo 形式发布的服务。

3)  底层非 java 应用,如 c++ , python 等可以发布格式和 pojo service 一样的服务

4)  提供优雅的借口给应用开发者。

业界考察:

好在我们并不是第一个遇到这个问题的人,那我们来看看在我们业界的前辈们都给我们留下了哪些宝贵的财富(主要是互联网行业)。

Google protocol buffers  Google 大神总是早人一步,在 google 架构的初期就意识到了跨语言的重要性,在构建 bigtable , GFS 的同一时期就是定制出了一套跨语言方案。那就是 google protocol buffers ,不过直到 08 年, google protocl buffers 才开源出来,正所谓国之利器不可以示人,我们所看到的, google protocl buffers 其实是阉割版,如没有 map 的支持 ( 根据一些资料表明, google 内部是有这个东西的) , python 的 native c 性能优化,不包括 rpc service ,虽然后面补了一个,但是可用性差强人意,不能多参,不能抛异常。不过在这方面我们确实不应该报太大的希望,因为 google 自己都说了 protocol buffers – a language-neutral, platform-neutral, extensible way of serializing structured data ,好吧,他只是一个序列化格式,而和 hessian , java 序列化有所不同的是, protocol buffers 可以用通过定义好数据结构的 proto ( IDL )文件产生目标语言代码,大大了减少了开发量,不过遗憾的是生成的代码有很强的侵入性,并不能产生我们需要的pojo java 对象。

不过即使是这样,我们也从 google  protocol buffers 身上学到了很多东西。

  1. 编码的压缩,采用 Base 128 Varints 序列化数字,减少网络传输开销。
  2. 非自描述数据, protocol buffers 将每个数据结构的描述信息嵌入到代码中,因此只需要传输数据过来,就可以反序列化出来该数据结构的实例了。
  3. Immutable object , protocol buffers 在生成的 java 代码中采用 builder&message 模式, message 是一个不能变的对象,即只有getter ,没有 setter ,而每一个 message 的生成由一个对应的 builder 来完成,从这点可以看出, google 已经用上了函数式编程。
  4. Rpc 异步话,虽然 protocol buffers 的 rpc 很简陋,但是一开始就只提供异步 callback 调用形式,可见 google 已经实现异步话,如果在互联网行业的人会知道,这点是相当不容易。

Facebook thrift  4 月 1 号,呵呵,没错, thrift 是 Facebook 于 07 年愚人节开源出来的,有点 google 的作风。 Thrift 是facebook 自己的一套跨语言实现。有人会问这个和 protocol buffers 有啥区别。 Ok ,先看看它的定义吧。

Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml.

说得很清楚是一个跨语言的服务开发框架。包括的功能有 code generation (代码生成, protocol buffers 也有), cross-language (跨语言, protocol buffers 也有), service development (好吧,这个 protocol buffers 也有)。晕倒,这样看起来,它和 google protocol buffers 完全是同一个领域的东西,而其有点重复发明轮子的味道。

刚开始,我们也有这样一个疑惑,好吧,接着往下看, here we go 。其实除了这些共同性以外(都是解决跨语言问题嘛), thrift 还是和protocol buffers 有很大不同的。不同点如下:

1)  提供一个完整的 service stack ,定义了一整套的 rpc 服务框架栈,这个 protocol buffers 是没有,这个绝对是 thrift 的利器,如果你想要开发一个服务, thrift 甚至有个栈层的实现,我靠,爽。

2)  Ok ,在 thrift 论文有这样一句话。 Thrift enforces a certain messaging structure when transporting data, but it is agnostic to the protocol encoding in use. 嗯哼,我懂了,它是不会管,你到底采用哪种序列化方式的,hessian ,xml 甚至是protocol buffers 。Oh ,my god 。

3)  接下来不得不膜拜一下thrift 的service 接口的强大了,多参,异常,同步,异步调用的支持,这正是我们想要的, 瞬间给protocol buffers 比下去了。

4)  多集合的支持 map , set 都有,让你爽歪歪。 Protocol buffers 颤抖吧。

这时候我们亲爱的读者就会问了,那我们的问题不就解决了吗,就是 thrift 。我笑而不语 , 虽然 thrift 是如此的强大,但是它仍然不是我们想要的, thrift 生成的代码也是强侵入性的,这样 pojo 的对象是无法发布服务的。还有一个硬伤是虽然 thrift 的 stack 很强大,当时这和我们原有系统的 stack 肯定是不兼容的,如 jboss remoting , spring remoting ,它们都会加一些 header 信息,而 thrift 已有实现的传输中式没有header 信息的。值得一提的是现有的 thrift service 实现中,不是线程安全的,考虑到有些语言没有对线程很好的支持,尤其是 Facebook 最常用的 PHP 语言,所以现有的实现中没有线程安全 Client 的实现。这样就会造成 client 端 connection 不能复用的问题,相当于短连接了。( ps :其实短连接就真的比长连接性能差吗?这是个问题。)

总结一下从 Facebook thrift 学到的东西:

1)              同步,异步都支持,这个很强悍,一般的做法是对性能要求高的服务器端采用异步方式开发,对易用性有要求的客户端采用同步方式调用,是比较完美的。

2)              从现有的非线程安全的实现看, Facebook 很有可能自己有一套更高效的线程安全的实现,估计考虑到和 thrift 关系不到,或者是核心技术,所以没有放出来,其实想自己做,也不是太难。

3)              Thrift 对很多脚本语言都进行了 native c 的性能优化,如 python 端,采用 native c 以后性能提高 20 倍。 Protocol buffers 一直在做这方面的优化,打算在 2.4 中加入,不过 protocol buffers 就像 jdk 7 一样难产,跟让人崩溃的是,前不久在论坛爆出做这块优化的哥们已经离开了 google ,不再负责了,好吧,我关心的是他去哪儿了,泪奔。

Apache Hadoop avro  Avro is a data serialization system. Avro provides functionality similar to systems such as Thrift, Protocol Buffers, etc. 好吧它自己都承认了,我们就不去纠结了。

简单介绍一下, avo 是 hadoop 项目下面用来传输数据的一个架构。也是一个跨语言解决方案。不过 avro 有自己的亮点。 1 , Dynamic typing, 2 , Untagged data , 3 , . No manually-assigned field Ids 

眼前一亮, Dynamic typing , oh , my god 。没错, avro 通过将 metadata 放在一个叫 schema 的对象里面,然后可以序列化对应的 pojo兑现。这个正是我想要的,至于其他的特性,的确没有咋仔细看 avro ,感觉上比 thrift ,和 protocol buffers 跟难学习,有熟悉的读者可以给我科普一下。

解决方案:

好了,到了这里,读者大概心里也有数了, protocol buffers , thrift , avro 都有我们想要的和我们不想要的。要解决我们的问题,我们只需要扬长避短就可以了。揉揉就是我们的东西了。方案如下:

1)  采用 protocol buffers 的 message 序列化格式和代码生成。

2)  采用 thrift 的 service 生成格式,以及实现兼容 jboss remoting 或者 spring remoting 的 thrift ( jboss remoting ) stack 。

3)  原有的 pojo 对象采用 avro 的 schema 方式序列化和反序列化该对象。

Ok 了,一切看起来是那样的完美。呵呵,不要被迷惑,还有很多 detail 的事情需要解决,时候不早,吃碗泡面,洗洗睡了,有时间,再把具体实现 detail 分享给大家。

相关文章
|
小程序 数据可视化 Java
Java+后端Spring boot 开发的全套UWB定位方案,0.1米高精度定位系统源码
UWB定位系统由硬件定位设备、定位引擎和应用软件组成。该定位系统应用软件支持PC端和移动端访问,并提供位置实时显示、历史轨迹回放、人员考勤、电子围栏、行为分析、智能巡检等功能。定位精度高达10cm,同时具备高动态、高容量、低功耗的优点。应用场景包括:隧道、化工、工厂、煤矿、工地、电厂、养老、展馆、整车、机房、机场等。
217 8
|
12天前
|
机器学习/深度学习 JSON Java
Java调用Python的5种实用方案:从简单到进阶的全场景解析
在机器学习与大数据融合背景下,Java与Python协同开发成为企业常见需求。本文通过真实案例解析5种主流调用方案,涵盖脚本调用到微服务架构,助力开发者根据业务场景选择最优方案,提升开发效率与系统性能。
144 0
|
1月前
|
Cloud Native 前端开发 Java
WebAssembly 与 Java 结合的跨语言协作方案及性能提升策略研究
本文深入探讨了WebAssembly与Java的结合方式,介绍了编译Java为Wasm模块、在Java中运行Wasm、云原生集成等技术方案,并通过金融分析系统的应用实例展示了其高性能、低延迟、跨平台等优势。结合TeaVM、JWebAssembly、GraalVM、Wasmer Java等工具,帮助开发者提升应用性能与开发效率,适用于Web前端、服务器端及边缘计算等场景。
89 0
|
22天前
|
缓存 监控 Kubernetes
Java虚拟机内存溢出(Java Heap Space)问题处理方案
综上所述, 解决Java Heap Space溢出需从多角度综合施策; 包括但不限于配置调整、代码审查与优化以及系统设计层面改进; 同样也不能忽视运行期监控与预警设置之重要性; 及早发现潜在风险点并采取相应补救手段至关重要.
176 17
|
12天前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
|
2月前
|
缓存 Java 数据库
Java 项目分层架构实操指南及长尾关键词优化方案
本指南详解基于Spring Boot与Spring Cloud的Java微服务分层架构,以用户管理系统为例,涵盖技术选型、核心代码实现、服务治理及部署实践,助力掌握现代化Java企业级开发方案。
146 2
|
2月前
|
JavaScript Java Go
Go、Node.js、Python、PHP、Java五种语言的直播推流RTMP协议技术实施方案和思路-优雅草卓伊凡
Go、Node.js、Python、PHP、Java五种语言的直播推流RTMP协议技术实施方案和思路-优雅草卓伊凡
172 0
|
3月前
|
安全 Java Docker
Docker 部署 Java 应用实战指南与长尾优化方案
本文详细介绍了Docker容器化部署Java应用的最佳实践。首先阐述了采用多阶段构建和精简JRE的镜像优化技术,可将镜像体积减少60%。其次讲解了资源配置、健康检查、启动优化等容器化关键配置,并演示了Spring Boot微服务的多模块构建与Docker Compose编排方案。最后深入探讨了Kubernetes生产部署、监控日志集成、灰度发布策略以及性能调优和安全加固措施,为Java应用的容器化部署提供了完整的解决方案指南。文章还包含大量可落地的代码示例,涵盖从基础到高级的生产环境实践。
175 3
|
3月前
|
前端开发 数据可视化 Java
开发 JavaFX 与 Java Swing 桌面应用的实用技巧与实践方案
本文介绍了Java桌面应用开发的技术选型与JavaFX实战方案。首先对比了JavaFX和Swing的特点,推荐JavaFX更适合现代UI需求。重点讲解了JavaFX 19+的技术升级,包括模块化开发(module-info.java配置)和响应式UI设计(CSS样式管理)。在数据访问层展示了JDBC 4.3的集成和异步加载实现。高级UI组件部分演示了自定义表格和图表可视化的开发方法。最后介绍了MVVM架构的实现,包括视图模型的数据绑定和FXML控制器的集成,为开发者提供了完整的JavaFX桌面应用开发解决方案。
220 0
|
5月前
|
数据采集 自然语言处理 JavaScript
Playwright多语言生态:跨Python/Java/.NET的统一采集方案
随着数据采集需求的增加,传统爬虫工具如Selenium、Jsoup等因语言割裂、JS渲染困难及代理兼容性差等问题,难以满足现代网站抓取需求。微软推出的Playwright框架,凭借多语言支持(Python/Java/.NET/Node.js)、统一API接口和优异的JS兼容性,解决了跨语言协作、动态页面解析和身份伪装等痛点。其性能优于Selenium与Puppeteer,在学术数据库(如Scopus)抓取中表现出色。行业应用广泛,涵盖高校科研、大型数据公司及AI初创团队,助力构建高效稳定的爬虫系统。
289 2
Playwright多语言生态:跨Python/Java/.NET的统一采集方案