zoukankan      html  css  js  c++  java
  • [转载] Thrift.net介绍和使用

    一、 什么是 RPC

    Restful 采用 Http 进行通讯,优点是开放、标准、简单、兼容性升级容易;

    缺点是性能略低。在 QPS 高或者对响应时间要求苛刻的服务上,可以用 RPC(Remote Procedure Call),RPC 由于采用二进制传输、TCP 通讯,所以通常性能更好。

    .Net Core 下的 RPC(远程方法调用)框架有 gRPC、Thrift 等,都支持主流的编程语言。

    RPC 虽然效率略高,但是耦合性强,如果兼容性处理不好的话,一旦服务器端接口升级,客户端就要更新,即使是增加一个参数,而 rest 则比较灵活。

    最佳实践:对内一些性能要求高的场合用 RPC,对内其他场合以及对外用 Rest。比如 web 服务器和视频转码服务器之间通讯可以用 restful 就够了,转账接口用 RPC 性能会更高一些。

    Thrift架构

    img

    图中,TProtocol(协议层),定义数据传输格式,例如:

    • TBinaryProtocol:二进制格式(默认传输格式);
    • TCompactProtocol:压缩格式;
    • TJSONProtocol:JSON格式;
    • TSimpleJSONProtocol:提供JSON只写协议, 生成的文件很容易通过脚本语言解析;
    • TDebugProtocol:使用易懂的可读的文本格式,以便于debug

    TTransport(传输层),定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库。

    • TSocket:阻塞式socker;
    • TFramedTransport:以frame为单位进行传输,非阻塞式服务中使用;
    • TFileTransport:以文件形式进行传输;
    • TMemoryTransport:将内存用于I/O,java实现时内部实际使用了简单的ByteArrayOutputStream;
    • TZlibTransport:使用zlib进行压缩, 与其他传输方式联合使用,当前无java实现;

    Thrift支持的服务模型

    • TSimpleServer:简单的单线程服务模型,常用于测试;
    • TThreadPoolServer:多线程服务模型,使用标准的阻塞式IO;
    • TNonblockingServer:多线程服务模型,使用非阻塞式IO(需使用TFramedTransport数据传输方式);

    二、 Thrift 基本使用

    参考资料:https://www.cnblogs.com/focus-lei/p/8889389.html

    1、 下载thrift http://thrift.apache.org/

    把thrift-***.exe解压到磁盘,改名为thrift.exe(用起来方便一些)

    2、 编写一个UserService.thrift文件(IDL)

    namespace csharp RuPeng.ThriftTest1.Contract
    
    service UserService{
       SaveResult Save(1:User user)     
       User Get(1:i32 id)     
       list<User> GetAll()
    } 
    
    enum SaveResult {     
      SUCCESS = 0,  
      FAILED = 1,  
    }  
    
    struct User {
        1: required i64 Id;
        2: required string Name;
        3: required i32 Age;
        4: optional bool IsVIP;
        5: optional string Remark;
    }
    

    service定义的是服务类,enum 是枚举,struct是传入或者传出的复杂数据类型(支持对象级联)。

    语法规范 http://thrift.apache.org/docs/idl

    根据thrift语法生成C#代码

    cmd -> thrift.exe -gen csharp UserService.thrift
    

    创建一个类库项目 ThriftTest1.Contract,作为客户端和服务器之间的共用协议,把上一步生成的代码放进项目。

    3、 创建服务器端项目 ThriftTest1.Server,建一个控制台项目(放到 web 项目中或者在 Linux中用守护进程运行起来(SuperVisor等,类似Windows下的“Windows服务”)也可以)。

    ThriftTest1.Server项目引用ThriftTest1.Contract

    创建项目:ApplicationExtenssion.cs

    编写实现类 UserServiceImpl.cs

    public class UserServiceImpl : UserService.Iface
    {
        public User Get(int id)
        {
            User u = new User();
            u.Id = id;
            u.Name = "用户" + id;
            u.Age = 6; return u;
        }
    
        public List<User> GetAll()
        {
            List<User> list = new List<User>();
            list.Add(new User { Id = 1, Name = "yzk", Age = 18, Remark = "hello" });
            list.Add(new User { Id = 2, Name = "rupeng", Age = 6 });
            return list;
        }
    
        public SaveResult Save(User user)
        {
            Console.WriteLine($"保存用户,{user.Id}"); return SaveResult.SUCCESS;
        }
    }
    

    修改Program下的Main函数 启动服务器端

    TServerTransport transport = new TServerSocket(8800);//监听8800端口
    var processor = new RuPeng.ThriftTest1.Contract.UserService.Processor(new UserServiceImpl());//设置实现类
    TServer server = new TThreadPoolServer(processor, transport);
    server.Serve();
    

    监听8800端口

    通过比较TSimpleServer、TThreadedServer、TThreadPoolServer,发现TSimpleServer只能同时响应一个客户端,TThreadedServer则维护了一个clientQueue,clientQueue最大值是100,TThreadPoolServer则用的是用线程池响应多个客户请求,生产环境绝不能用TSimpleServer。

    4、创建客户端项目也引用ThriftTest1.Contract项目

    调用方法

    using (TTransport transport = new TSocket("localhost", 8800))
        using (TProtocol protocol = new TBinaryProtocol(transport))
        using (var clientUser = new UserService.Client(protocol))
    {
        transport.Open();
        User u = clientUser.Get(1);
        Console.WriteLine($"{u.Id},{u.Name}");
    }
    

    三、一个服务器中放多个服务

    0.9.1之前只支持一个服务器一个服务,这也是建议的做法。之后支持多路服务在thrift中增加一个服务

    修改UserService.thrift文件 添加以下内容 然后重新生成替换

    service CalcService{ 
         i32 Add(1:i32 i1,2:i32 i2)
    }
    

    服务器:

    1.创建CalcServiceImpl文件实现CalcService服务

    2.修改Main方法如下:

    TServerTransport transport = new TServerSocket(8800);
    var processorUserService = new RuPeng.ThriftTest1.Contract.UserService.Processor(new UserServiceImpl())
    var processorCalcService = new RuPeng.ThriftTest1.Contract.CalcService.Processor(new CalcServiceImpl());
    var processorMulti = new TMultiplexedProcessor();
    processorMulti.RegisterProcessor("userService", processorUserService);
    processorMulti.RegisterProcessor("calcService", processorCalcService);
    TServer server = new TThreadPoolServer(processorMulti, transport);
    server.Serve();
    

    客户端:

    using (TTransport transport = new TSocket("localhost", 8800))
        using (TProtocol protocol = new TBinaryProtocol(transport))
        using (var protocolUserService = new TMultiplexedProtocol(protocol, "userService"))
        using (var clientUser = new UserService.Client(protocolUserService))
        using (var protocolCalcService = new TMultiplexedProtocol(protocol,"calcService"))
        using (var clientCalc = new CalcService.Client(protocolCalcService))
    {
        transport.Open();
        User u = clientUser.Get(1);
        Console.WriteLine($"{u.Id},{u.Name}");
        Console.WriteLine(clientCalc.Add(1, 2));
    }
    

    原文地址:https://blog.csdn.net/qq_18145031/article/details/82802158

  • 相关阅读:
    P2602 [ZJOI2010]数字计数
    P2657 [SCOI2009] windy 数
    Gym
    B
    Problem E The League of Sequence Designers
    C. Vladik and fractions
    hdu6069
    hdu 6096
    30道经典面试题,靠它我在一线拿到了20k的前端开发工程师岗位
    【面经分享】互联网寒冬,7面阿里,终获Offer!
  • 原文地址:https://www.cnblogs.com/ghhjanes/p/11211880.html
Copyright © 2011-2022 走看看