Thrift_简介(基于C#)

/*
 * Thrift的RPC调用的一个完整流程:
 * 首先是通过Thrift的编译器生成的客户端,将调用信息(方法名,参数信息)以指定的协议进行封装,
 * 而传输层TTransport是对协议层的封装进行处理(比如封装成帧frame),并通过网络发送出去。
 * 服务端这边流程跟客户端相反,收到客户端发过来的数据后,首先经过传输层对传过来的数据进行处理,
 * 然后使用特定的协议(跟客户端是一一对应的)进行解析,然后再通过生成的Processor调用用户编写的代码,
 * 如果有返回值的话,返回值以逆向的顺序,即通过协议层封装,然后传输层处理对数据进行发送,
 * 到了客户端那边就是对服务端返回的数据进行处理,使用特定协议进行解析,然后得到一个调用个的结果。
 * 
 *  基本类型
 *  bool:布尔值(true或者false)
 *  byte:8位的有符号字节(byte类型)
 *  i16:16位的有符号整数(short类型)
 *  i32:32位的有符号整数(int类型)
 *  i64:64位的有符号长整型(long类型)
 *  double:一个64位的浮点数(double类型)
 *  string: 一个utf8编码的字符串文本(String) 
 *  
 *  集合类型
 *  list:一个有序的元素列表。元素可以重复。
 *  set:一个无序的元素集合,集合中元素不能重复。
 *  map:一个键值对的数据结构,相当于Java中的HashMap。
 * 
 *  异常类型Exceptions
 *  Thrift的异常类型,除了是继承于静态异常基类以外,其他的跟struct是类似的。表示的是一个异常对象。
 *  
 *  服务类型Services Server: 4.服务层, 整合上述组件, 提供网络模型(单线程/多线程/事件驱动), 最终形成真正的服务.
 *  Thrift 的service类型相当于定义一个面向对象编程的一个接口。Thrift的编译器会根据这个接口定义来生成服务端和客户端的接口实现代码。
 *  
 *  Thrift的传输格式(协议层)1.protocol: 协议层, 定义数据传输格式,可以为二进制或者XML等
 *  TBinaryProtocol: 二进制格式。效率显然高于文本格式
 *  TCompactProtocol:压缩格式。在二进制基础上进一步压缩。
 *  TJSONProtocol:JSON格式。
 *  TSimpleJSONProtocol:提供JSON只写协议(缺少元数据信息),生成的文件很容易用过脚本语言解析。
 *  TDebugProtocol:使用易懂的刻度文本格式,以便于调试。
 *  
 *  Thrift的数据传输方式(传输层) 2. Transport: 传输层,定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等
 *  TSocket:阻塞式socket。
 *  TFramedTransport:以frame为单位进行传输,非阻塞式服务中使用。
 *  TFileTransport:以文件形式进行传输。
 *  TMemoryTransport:将内存用于I/O,Java是现实内部实际使用了简单的ByteArrayOutputStream。
 *  TZlibTransport:使用zlib进行压缩,与其他传输方式联合使用。当前无java实现。
 *  
 *  Thrift的服务模型 Processor: 3. 处理层, 这部分由定义的idl来生成, 封装了协议输入输出流, 并委托给用户实现的handler进行处理.
 *  TSimpleServer: 简单的单线程服务模型,常用于测试。只在一个单独的线程中以阻塞I/O的方式来提供服务。所以它只能服务一个客户端连接,其他所有客户端在被服务器端接受之前都只能等待。
 *  TNonblockingServer: 它使用了非阻塞式I/O,使用了java.nio.channels.Selector,通过调用select(),它使得程序阻塞在多个连接上,而不是单一的一个连接上。TNonblockingServer处理这些连接的时候,要么接受它,要么从它那读数据,要么把数据写到它那里,然后再次调用select()来等待下一个准备好的可用的连接。通用这种方式,server可同时服务多个客户端,而不会出现一个客户端把其他客户端全部“饿死”的情况。缺点是所有消息是被调用select()方法的同一个线程处理的,服务端同一时间只会处理一个消息,并没有实现并行处理。
 *  THsHaServer:(半同步半异步server) 针对TNonblockingServer存在的问题,THsHaServer应运而生。它使用一个单独的线程专门负责I/O,同样使用java.nio.channels.Selector,通过调用select()。然后再利用一个独立的worker线程池来处理消息。只要有空闲的worker线程,消息就会被立即处理,因此多条消息能被并行处理。效率进一步得到了提高。
 *  TThreadedSelectorServer: 它与THsHaServer的主要区别在于,TThreadedSelectorServer允许你用多个线程来处理网络I/O。它维护了两个线程池,一个用来处理网络I/O,另一个用来进行请求的处理。
 *  TThreadPoolServer: 它使用的是一种多线程服务模型,使用标准的阻塞式I/O。它会使用一个单独的线程来接收连接。一旦接受了一个连接,它就会被放入ThreadPoolExecutor中的一个worker线程里处理。worker线程被绑定到特定的客户端连接上,直到它关闭。一旦连接关闭,该worker线程就又回到了线程池中。 这意味着,如果有1万个并发的客户端连接,你就需要运行1万个线程。所以它对系统资源的消耗不像其他类型的server一样那么“友好”。此外,如果客户端数量超过了线程池中的最大线程数,在有一个worker线程可用之前,请求将被一直阻塞在那里。 如果提前知道了将要连接到服务器上的客户端数量,并且不介意运行大量线程的话,TThreadPoolServer可能是个很好的选择
 *  
 *  cmd命令:
 *  thrift-0.9.1.exe -help
 *  thrift-0.9.1.exe -r -gen java data.thrift
 *  thrift-0.9.1.exe -r -gen py data.thrift
 *  thrift-0.9.1.exe -r -gen csharp  data.thrift
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Threading.Tasks;
using System.Collections;
using Thrift.Transport;
using Thrift.Server;
using Thrift.Protocol;

namespace TestThriftProject
{
    public partial class FrmTest : Form
    {
        public FrmTest()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {

            if (textBox1.Text != null)
            {
                TTransport transport = new TSocket("127.0.0.1", 8090, 3000);
                TProtocol protocol = new TBinaryProtocol(transport);//协议要和服务端一致     
                HelloWorldService.Client client = new HelloWorldService.Client(protocol);

                try
                {
                    transport.Open();
                    String result = client.SayHello(textBox1.Text.Trim());
                    Console.WriteLine("Thrift client result =: " + result);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                }
                finally
                {
                    if (transport != null)
                    {
                        transport.Close();
                    }
                }
            }
        }

        private void FrmTest_Load(object sender, EventArgs e)
        {
            new Task(new Action(() =>
            {

                try
                {
                    TServerSocket serverTransport = new TServerSocket(8090, 0, false);
                    HelloWorldService.Processor processor = new HelloWorldService.Processor(new HelloWroldImpl());
                    TServer server = new TSimpleServer(processor, serverTransport);
                    server.Serve();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                }
            })).Start();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace TestThriftProject
{
    public class HelloWroldImpl : HelloWorldService.Iface
    {
        public string SayHello(string username)
        {
            return  string.Format("{0:yyyy/MM/dd hh:mm:ss} hello: {1}", DateTime.Now, username);
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/ingstyle/p/9953347.html