zoukankan      html  css  js  c++  java
  • Thrift框架学习

    参考文章:1、http://www.kankanews.com/ICkengine/archives/54084.shtml

    2、http://www.cnblogs.com/liping13599168/archive/2011/09/15/2176836.html

    Golang内置了对RPC支持,但只能适用于go语言程序之间调用。Thrift是一种可伸缩的跨语言服务框架,它支持C++,C#,Java,Python,Go等多种语言。

    thrift允许你定义一个简单的定义文件中的数据类型和服务接口,以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。 

    这种方式与微软的WCF框架以及Android中的AIDL服务的做法很类似。

    1、安装Go语言的thrift包

    参考文章1给出的地址是:go get git.apache.org/thrift.git/lib/go/thrift,但该地址现在似乎不能访问了,请使用下面的命令:

    go get github.com/apache/thrift/lib/go/thrift

    2、下载脚本编译器

    下载地址:http://www.apache.org/dyn/closer.cgi?path=/thrift/0.9.1/thrift-0.9.1.exe

    该编译工具可将thrift脚本文件编译为目标变成语言代码。

    3、创建脚本

    脚本文件采用thrift自带教程github.comapache hrift utorial中的shared.thrift和tutorial.thrift:

    shared.thrift文件如下:

    namespace go shared

    struct SharedStruct {
    1: i32 key
    2: string value
    }

    service SharedService {
    SharedStruct getStruct(1: i32 key)
    }

    tutorial.thrift文件如下:

    include "shared.thrift"

    namespace go tutorial

    typedef i32 MyInteger

    const i32 INT32CONSTANT = 9853
    const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}

    enum Operation {
    ADD = 1,
    SUBTRACT = 2,
    MULTIPLY = 3,
    DIVIDE = 4
    }

    struct Work {
    1: i32 num1 = 0,
    2: i32 num2,
    3: Operation op,
    4: optional string comment,
    }

    exception InvalidOperation {
    1: i32 what,
    2: string why
    }

    service Calculator extends shared.SharedService {

    void ping(),

    i32 add(1:i32 num1, 2:i32 num2),

    i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),

    oneway void zip()

    }

    4、编译脚本

    分别执行 thrift -gen go x:shared.thrift和thrift -gen go x: utorial.thrift  命令,参数go表示生成go代码,可以根据实际情况使用csharp,java,python等参数。

    5、示例代码

    下面我们使用C#语言实现的客户端与Go语言实现的服务端通信,进行跨语言调用。

    将第4步中生成的go代码放到服务端目录下,服务端代码如下:

    main.go文件

    package main

    import (
    "crypto/tls"
    "fmt"
    "github.com/apache/thrift/lib/go/thrift"
    "tutorial"
    )

    func main() {
    protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
    transportFactory := thrift.NewTTransportFactory()
    addr := "localhost:9090"
    secure := false

    if err := runServer(transportFactory, protocolFactory, addr, secure); err != nil {
    fmt.Println("error running server:", err)
    }
    }

    func runServer(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory, addr string, secure bool) error {
    var transport thrift.TServerTransport
    var err error
    if secure {
    cfg := new(tls.Config)
    if cert, err := tls.LoadX509KeyPair("server.crt", "server.key"); err == nil {
    cfg.Certificates = append(cfg.Certificates, cert)
    } else {
    return err
    }
    transport, err = thrift.NewTSSLServerSocket(addr, cfg)
    } else {
    transport, err = thrift.NewTServerSocket(addr)
    }

    if err != nil {
    return err
    }
    fmt.Printf("%T ", transport)
    handler := NewCalculatorHandler()
    processor := tutorial.NewCalculatorProcessor(handler)
    server := thrift.NewTSimpleServer4(processor, transport, transportFactory, protocolFactory)

    fmt.Println("Starting the simple server... on ", addr)
    return server.Serve()
    }

    handler.go文件使用原文件。

    将第4步生成的c#代码加入客户端工程,并引用thrift.dll(该组件的代码可在..github.comapache hrift utorialcsharp下找到),如图所示:

    客户端测试代码如下:

    class Program
        {
            static void Main(string[] args)
            {
                try
                {
                    TTransport transport = new TSocket("localhost", 9090);
                    TProtocol protocol = new TBinaryProtocol(transport);
                    Calculator.Client client = new Calculator.Client(protocol);
    
                    transport.Open();
                    try
                    {
                        client.ping();
                        Console.WriteLine("ping()");
    
                        int sum = client.add(1, 1);
                        Console.WriteLine("1+1={0}", sum);
    
                        Work work = new Work();
    
                        work.Op = Operation.DIVIDE;
                        work.Num1 = 1;
                        work.Num2 = 0;
                        try
                        {
                            int quotient = client.calculate(1, work);
                            Console.WriteLine("Whoa we can divide by 0");
                        }
                        catch (InvalidOperation io)
                        {
                            Console.WriteLine("Invalid operation: " + io.Why);
                        }
    
                        work.Op = Operation.SUBTRACT;
                        work.Num1 = 15;
                        work.Num2 = 10;
                        try
                        {
                            int diff = client.calculate(1, work);
                            Console.WriteLine("15-10={0}", diff);
                        }
                        catch (InvalidOperation io)
                        {
                            Console.WriteLine("Invalid operation: " + io.Why);
                        }
    
                        SharedStruct log = client.getStruct(1);
                        Console.WriteLine("Check log: {0}", log.Value);
    
                    }
                    finally
                    {
                        transport.Close();
                    }
                }
                catch (TApplicationException x)
                {
                    Console.WriteLine(x.StackTrace);
                }
                Console.ReadKey();
            }
        }

    测试结果:

    本文结束。源码下载:thriftserver  thriftclient

  • 相关阅读:
    CSS margin重叠 & CSS BFC(Block Formatting Context)
    require.js
    bind()函数的作用
    JavaScript DOM 总结
    插入排序-直接插入排序、希尔排序
    交换排序-起泡排序、快速排序算法
    JavaScript全局函数
    JavaScript命名空间的理解与实现
    document.documentElement.clientWidth
    Python-删除多级目录
  • 原文地址:https://www.cnblogs.com/wenjingu/p/3522026.html
Copyright © 2011-2022 走看看