• rpc服务框架thrift介绍


    rpc服务框架目前主要有 thrift, grpc, dubbo, HSF等

    这里主要介绍thrift框架

    git地址  :https://github.com/apache/thrift/tree/0.9.1

    1. 接口定义 tutorial.thrift

    include "shared.thrift"
    
    /**
     * Thrift files can namespace, package, or prefix their output in various
     * target languages.
     */
    
    namespace cl tutorial
    namespace cpp tutorial
    namespace d tutorial
    namespace dart tutorial
    namespace java tutorial
    namespace php tutorial
    namespace perl tutorial
    namespace haxe tutorial
    namespace netcore tutorial
    namespace netstd tutorial
    
    /**
     * Thrift lets you do typedefs to get pretty names for your types. Standard
     * C style here.
     */
    typedef i32 MyInteger
    
    /**
     * Thrift also lets you define constants for use across languages. Complex
     * types and structs are specified using JSON notation.
     */
    const i32 INT32CONSTANT = 9853
    const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}
    
    /**
     * You can define enums, which are just 32 bit integers. Values are optional
     * and start at 1 if not supplied, C style again.
     */
    enum Operation {
      ADD = 1,
      SUBTRACT = 2,
      MULTIPLY = 3,
      DIVIDE = 4
    }
    
    /**
     * Structs are the basic complex data structures. They are comprised of fields
     * which each have an integer identifier, a type, a symbolic name, and an
     * optional default value.
     *
     * Fields can be declared "optional", which ensures they will not be included
     * in the serialized output if they aren't set.  Note that this requires some
     * manual management in some languages.
     */
    struct Work {
      1: i32 num1 = 0,
      2: i32 num2,
      3: Operation op,
      4: optional string comment,
    }
    
    /**
     * Structs can also be exceptions, if they are nasty.
     */
    exception InvalidOperation {
      1: i32 whatOp,
      2: string why
    }
    
    /**
     * Ahh, now onto the cool part, defining a service. Services just need a name
     * and can optionally inherit from another service using the extends keyword.
     */
    service Calculator extends shared.SharedService {
    
      /**
       * A method definition looks like C code. It has a return type, arguments,
       * and optionally a list of exceptions that it may throw. Note that argument
       * lists and exception lists are specified using the exact same syntax as
       * field lists in struct or exception definitions.
       */
    
       void ping(),
    
       i32 add(1:i32 num1, 2:i32 num2),
    
       i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),
    
       /**
        * This method has a oneway modifier. That means the client only makes
        * a request and does not listen for any response at all. Oneway methods
        * must be void.
        */
       oneway void zip()
    
    }
    

    2. 根据接口定义文件生成相应的服务接口

    thrift -r --gen py tutorial.thrift 根据thrift接口定义生成服务接口
    执行完后会在当前目录生成 gen-py文件夹, 下面包含 tutorial shared两个子文件夹

    主要文件就是Calulator.py 定义了相应语言的接口协议

    3. 根据接口,实现接口功能,提供服务

    这步是最重要的,开始实现接口功能, 上面由接口定义文件service可知, 定义了4个功能: ping  add  caculate zip

    这里用python实现上述接口, PythonServer.py

    import glob
    import sys
    sys.path.append('gen-py')
    sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0])
    
    from tutorial import Calculator
    from tutorial.ttypes import InvalidOperation, Operation
    
    from shared.ttypes import SharedStruct
    
    from thrift.transport import TSocket
    from thrift.transport import TTransport
    from thrift.protocol import TBinaryProtocol
    from thrift.server import TServer
    
    
    class CalculatorHandler:
        def __init__(self):
            self.log = {}
    
        def ping(self):
            print('ping()')
    
        def add(self, n1, n2):
            print('add(%d,%d)' % (n1, n2))
            return n1 + n2
    
        def calculate(self, logid, work):
            print('calculate(%d, %r)' % (logid, work))
    
            if work.op == Operation.ADD:
                val = work.num1 + work.num2
            elif work.op == Operation.SUBTRACT:
                val = work.num1 - work.num2
            elif work.op == Operation.MULTIPLY:
                val = work.num1 * work.num2
            elif work.op == Operation.DIVIDE:
                if work.num2 == 0:
                    x = InvalidOperation()
                    x.whatOp = work.op
                    x.why = 'Cannot divide by 0'
                    raise x
                val = work.num1 / work.num2
            else:
                x = InvalidOperation()
                x.whatOp = work.op
                x.why = 'Invalid operation'
                raise x
    
            log = SharedStruct()
            log.key = logid
            log.value = '%d' % (val)
            self.log[logid] = log
    
            return val
    
        def getStruct(self, key):
            print('getStruct(%d)' % (key))
            return self.log[key]
    
        def zip(self):
            print('zip()')
    
    
    if __name__ == '__main__':
        handler = CalculatorHandler()
        processor = Calculator.Processor(handler)
        transport = TSocket.TServerSocket(host='127.0.0.1', port=9090)
        tfactory = TTransport.TBufferedTransportFactory()
        pfactory = TBinaryProtocol.TBinaryProtocolFactory()
    
        server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
    

     python PythonServer.py 然后可以看到rpc对外开始提供服务, 这里注意host, port

    4.实现客户端,连接rpc服务接口

    PythonClient.py

    import sys
    import glob
    sys.path.append('gen-py')
    sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0])
    
    from tutorial import Calculator
    from tutorial.ttypes import InvalidOperation, Operation, Work
    
    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 = Calculator.Client(protocol)
    
        # Connect!
        transport.open()
    
        client.ping()
        print('ping()')
    
        sum_ = client.add(1, 1)
        print('1+1=%d' % sum_)
    
        work = Work()
    
        work.op = Operation.DIVIDE
        work.num1 = 1
        work.num2 = 0
    
        try:
            quotient = client.calculate(1, work)
            print('Whoa? You know how to divide by zero?')
            print('FYI the answer is %d' % quotient)
        except InvalidOperation as e:
            print('InvalidOperation: %r' % e)
    
        work.op = Operation.SUBTRACT
        work.num1 = 15
        work.num2 = 10
    
        diff = client.calculate(1, work)
        print('15-10=%d' % diff)
    
        log = client.getStruct(1)
        print('Check log: %s' % log.value)
    
        # Close!
        transport.close()
    

     启动客户端,连接rpc服务

    可以看到,已经能get到结果了,通过rpc,可以实现,接口实现与使用的分离, 使用不同语言,而且效率远比restful接口高效

    
    
  • 相关阅读:
    idea中pom.xml相关操作
    Java集合1-集合与数组的区别
    idea中各种图标的含义
    testng之多线程执行(并发执行)
    testng之DataProvider参数化
    fastjson将java对象与json字符串相互转换
    testng -依赖测试
    testng- 异常测试
    转-selenium3 webdriver启动火狐、chrome、edge、Safari浏览器的方法
    浏览器兼容性测试
  • 原文地址:https://www.cnblogs.com/energy1010/p/10381215.html
Copyright © 2020-2023  润新知