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


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

    Apache Thrift简介

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

    目前流行的服务调用方式有很多种,例如基于 SOAP 消息格式的 Web Service,基于 JSON 消息格式的 RESTful 服务等。其中所用到的数据传输方式包括 XMLJSON 等,然而 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 官网
  • 相关阅读:
    SQL Server 2008 如何查看与创建约束
    Hibernate的主键生成策略
    sql server的id字段设置为自动生成的,那么该怎么写insert语句呢?
    org.hibernate.AnnotationException: Collection has neither generic type or OneToMany.targetEntity() defined: com.bjsxt.model.Student.courses
    INSERT 语句与 FOREIGN KEY 约束"XXX"冲突。该冲突发生于数据库"XXX",表"XXX", column 'XXX。
    在排序数组中查找符合条件的数
    求二叉树中节点的最大距离
    设计包含min 函数的栈
    寻找链表的倒数第K个节点
    翻转句子中单词的顺序
  • 原文地址:https://www.cnblogs.com/yaoyu126/p/6724718.html
Copyright © 2020-2023  润新知