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

  • 相关阅读:
    Java Spring Boot VS .NetCore (十) Java Interceptor vs .NetCore Interceptor
    Java Spring Boot VS .NetCore (九) Spring Security vs .NetCore Security
    IdentityServer4 And AspNetCore.Identity Get AccessToken 问题
    Java Spring Boot VS .NetCore (八) Java 注解 vs .NetCore Attribute
    Java Spring Boot VS .NetCore (七) 配置文件
    Java Spring Boot VS .NetCore (六) UI thymeleaf vs cshtml
    Java Spring Boot VS .NetCore (五)MyBatis vs EFCore
    Java Spring Boot VS .NetCore (四)数据库操作 Spring Data JPA vs EFCore
    Java Spring Boot VS .NetCore (三)Ioc容器处理
    Java Spring Boot VS .NetCore (二)实现一个过滤器Filter
  • 原文地址:https://www.cnblogs.com/wenjingu/p/3522026.html
Copyright © 2011-2022 走看看