zoukankan      html  css  js  c++  java
  • 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接口高效

    
    
  • 相关阅读:
    Linux基础知识
    oracle用户及表空间基础
    渗透测试之目录扫描-Dirbuster
    oracle自定义函数身份证15位和18位的转换
    linux 网络带宽和延时测试
    LNMP(linux+nginx+mysql+php)服务器环境配置
    使用Medusa美杜莎暴力破解SSH密码
    暴力密码在线破解工具
    在linux下搭建NFS服务器实现文件共享
    Nginx是做什么的
  • 原文地址:https://www.cnblogs.com/energy1010/p/10381215.html
Copyright © 2011-2022 走看看