基于Apache Thrift的公路涵洞数据交互实现原理

Apache Thrift简介

Apache Thrift(以下简称为“Thrift”) 是 Facebook 实现的一种高效的、支持多种编程语言的远程服务调用的框架。

目前流行的服务调用方式有很多种,例如基于 SOAP 消息格式的 Web Service,基于 JSON 消息格式的 RESTful 服务等。其中所用到的数据传输方式包括 XML,JSON 等,然而 XML 相对体积太大,传输效率低,JSON 体积较小,新颖,但还不够完善。本文将介绍由 Facebook 开发的远程服务调用框架 Apache Thrift,它采用接口描述语言定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码生成引擎可以在多种语言中,如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 等创建高效的、无缝的服务,其传输数据采用二进制格式,相对 XML 和 JSON 体积更小,对于高并发、大数据量和多语言的环境更有优势。

Thrift 架构

Thrift 包含一个完整的堆栈结构用于构建客户端和服务器端。下图描绘了 Thrift 的整体架构。

图 1. 架构图

如图所示,图中黄色部分是用户实现的业务逻辑,褐色部分是根据 Thrift 定义的服务接口描述文件生成的客户端和服务器端代码框架,红色部分是根据 Thrift 文件生成代码实现数据的读写操作。红色部分以下是 Thrift 的传输体系、协议以及底层 I/O 通信,使用 Thrift 可以很方便的定义一个服务并且选择不同的传输协议和传输层而不用重新生成代码。

Thrift 服务器包含用于绑定协议和传输层的基础架构,它提供阻塞、非阻塞、单线程和多线程的模式运行在服务器上,可以配合服务器 / 容器一起运行。

服务端和客户端具体的调用流程如下:

图 2. Server 端启动、服务时序图

该图所示是 HelloServiceServer 启动的过程以及服务被客户端调用时,服务器的响应过程。从图中我们可以看到,程序调用了 TThreadPoolServer 的 serve 方法后,server 进入阻塞监听状态,其阻塞在 TServerSocket 的 accept 方法上。当接收到来自客户端的消息后,服务器发起一个新线程处理这个消息请求,原线程再次进入阻塞状态。在新线程中,服务器通过 TBinaryProtocol 协议读取消息内容,调用 HelloServiceImpl 的 helloVoid 方法,并将结果写入 helloVoid_result 中传回客户端。

图 3. Client 端调用服务时序图

该图所示是 HelloServiceClient 调用服务的过程以及接收到服务器端的返回值后处理结果的过程。从图中我们可以看到,程序调用了 Hello.Client 的 helloVoid 方法,在 helloVoid 方法中,通过 send_helloVoid 方法发送对服务的调用请求,通过 recv_helloVoid 方法接收服务处理请求后返回的结果。

Thrift环境准备

  1下载Thrift

    当前版本为Thrift-0.10.0

  2. 编译或下载Thrift编译器

    windows下可以直接下载已经编译好的编译器Thrift-0.10.0.exe

涵洞数据交互实例:

1. 定义Thrift文件

exception GenericError {

}

enum SlabCulvertType {

}

struct CommonResult{

}

struct SlabCulvert {

}

service EngineerService {

CommonResult slabCulvert_add(1: Context context,2: SlabCulvertType slabCulvertType,3: SlabCulvert slabCulvert) throws (1:GenericError e)

CommonResult slabCulvert_modify(1: Context context,2: SlabCulvertCondition slabCulvertCondition,3: SlabCulvertType slabCulvertType,4: SlabCulvert slabCulvert) throws (1:GenericError e)

CommonResult slabCulvert_remove(1: Context context,2: SlabCulvertCondition slabCulvertCondition) throws (1:GenericError e)

SlabCulvertResult slabCulvert_query(1: Context context,2: SlabCulvertCondition slabCulvertCondition) throws (1:GenericError e)

}

2. 使用Thrift编译器编译Thrift文件

thrift --gen <language> <Thrift filename>

3. 编写服务端代码

#!/usr/bin/env python
# -*- coding:utf-8 -*- import glob
import sys
sys.path.append('gen-py')
sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) from tutorial import EngineerService from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer class EngineerServiceHandler:
def __init__(self):
self.log = {} def slabCulvert_add(self, context, slabCulvertType, slabCulvert):
pass def slabCulvert_modify(self, context, slabCulvertCondition, slabCulvertType, slabCulvert):
pass def slabCulvert_remove(self, context, slabCulvertCondition):
pass def slabCulvert_query(self, context, slabCulvertCondition):
pass if __name__ == '__main__':
handler = EngineerServiceHandler()
processor = EngineerService.Processor(handler)
transport = TSocket.TServerSocket(port=9090)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory() server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) print('Starting the server...')
server.serve()
print('done.')

4. 客户端使用框架代码调用远程服务

#!/usr/bin/env python
# -*- coding:utf-8 -*- import sys
import glob
sys.path.append('gen-py')
sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) from tutorial import EngineerService
from tutorial.ttypes import InvalidOperation, slabCulvertType from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol def main():
# Make socket
transport = TSocket.TSocket('localhost', 9090) # Buffering is critical. Raw sockets are very slow
transport = TTransport.TBufferedTransport(transport) # Wrap in a protocol
protocol = TBinaryProtocol.TBinaryProtocol(transport) # Create a client to use the protocol encoder
client = EngineerService.Client(protocol) # Connect!
transport.open() try:
context = ...
slab_culvert_type = ...
slab_culvert = slabCulvert(...)
res = client.slabCulvert_add(context, slab_culvert_type, slab_culvert)
print(res)
except InvalidOperation as e:
print('InvalidOperation: %r' % e) # Close!
transport.close() if __name__ == '__main__':
try:
main()
except Thrift.TException as tx:
print('%s' % tx.message)

参考资料:

  1. Apache Thrift - 可伸缩的跨语言服务开发框架
  2. Apache Thrift 官网

基于Apache Thrift的公路涵洞数据交互实现原理的更多相关文章

  1. Apache Thrift学习之二(基础及原理)

    Apache Thrift 是 Facebook 实现的一种高效的.支持多种编程语言的远程服务调用的框架.本文将从 Java 开发人员角度详细介绍 Apache Thrift 的架构.开发和部署,并且 ...

  2. 基于Apache POI 从xlsx读出数据

    [0]写在前面 0.1) these codes are from 基于Apache POI 的从xlsx读出数据 0.2) this idea is from http://cwind.iteye. ...

  3. 基于Apache POI 向xlsx写入数据

    [0]写在前面 0.1) these codes are from 基于Apache POI 的向xlsx写入数据 0.2) this idea is from http://cwind.iteye. ...

  4. 基于Apache Hudi构建分析型数据湖

    为了有机地发展业务,每个组织都在迅速采用分析. 在分析过程的帮助下,产品团队正在接收来自用户的反馈,并能够以更快的速度交付新功能. 通过分析提供的对用户的更深入了解,营销团队能够调整他们的活动以针对特 ...

  5. 基于ssh框架的highcharts前后台数据交互实例

    Highcharts 是一个用纯JavaScript编写的一个图表库, 能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,并且免费提供给个人学习.个人网站和非商业用途使用.HighCh ...

  6. 基于Xen实现一种domain0和domainU的应用层数据交互高效机制 - 2

    继续昨天的思路,今天先google了类似的实现domain0和domainU之间数据传输的方案 [Xen-devel] XenStore as a data transfer path?  这篇帖子讨 ...

  7. Apache Thrift 跨语言服务开发框架

    Apache Thrift 是一种支持多种编程语言的远程服务调用框架,由 Facebook 于 2007 年开发,并于 2008 年进入 Apache 开源项目管理.Apache Thrift 通过 ...

  8. Apache Thrift - 可伸缩的跨语言服务开发框架

    To put it simply, Apache Thrift is a binary communication protocol 原文地址:http://www.ibm.com/developer ...

  9. 【转】Apache Thrift - 可伸缩的跨语言服务开发框架

    Apache Thrift - 可伸缩的跨语言服务开发框架 Apache Thrift 是 Facebook 实现的一种高效的.支持多种编程语言的远程服务调用的框架.本文将从 Java 开发人员角度详 ...

随机推荐

  1. JAVA 构建使用 Native 库

    Java 使用Native文件,一般分解为下面几个步骤: 在Java代码中使用native关键字声明一个本地方法 运行javah,获得包含该方法声明的C语言头文件(使用jni编程中的C函数名通常是相关 ...

  2. ASP.NET MD5加密

    protected void Button1_Click(object sender, EventArgs e) { string pwd = TextBox2.Text.Trim(); Respon ...

  3. 利用Putty/Plink通过ssh tunnel端口转发实现FireFox和Chrome的加密代理访问

    如果需要使用远端服务器的DNS:在Firefox中about:config设置 network.proxy.socks_remote_dns ==> true 参考原文:http://think ...

  4. 【转载】IDEA的这八条配置你一定要改!

    引言 坦白说,我很少写这种操作类型的文章.因为这种文章没啥新意,大家操作步骤肯定是一样的.然而,我答应了我的同事小阳,给她出一篇!毕竟人家打算从Eclipse转IDEA了,于是以示鼓励,写一篇给她!那 ...

  5. scrapy-redis使redis不止保存url

    先看scrapy-redis源码 class RedisMixin(object): """Mixin class to implement reading urls f ...

  6. [转载]Linux内存高,触发oom-killer问题解决

    最近遇到两起Linux的内存问题,其一是触发了oom-killer导致系统挂 首先确认该系统的版本是32位 #uname -a Linux alarm 2.6.9-67.ELsmp #1 SMP We ...

  7. npm命令及解释

    npm是Node Package Manager,也就是长说的NPM包管理器. 一般安装node.js就会一起安装. npm install npm install XXX    //表示安装模块, ...

  8. CodeForces 245C-Game with Coins

    题意:给你一个n,紧接着n个正数,然后有一种操作:选择一个x满足(x*2+1<=n)一次可以把下标为  x,2*x,2*x+1的三个数同时减一: 问,最少几次操作可以使n个数字变为零(已经是0的 ...

  9. String使用方式详细总结

    1.用双引号创建 2.用new String方式创建 3.双引号相加创建 4.两个new String相加时 5.两个引用相加时 6.双引号加new String创建或者new String加双引号创 ...

  10. Git 基础教程 之 撤销修改

    Git跟踪并管理的是修改,而非文件.每次修改,如果不用git add到暂存区,那就不会加入到commit中, 要么全部改完后,再add → commit :要么改一点,就add → commit. 撤 ...