文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C#怎么使用远程服务调用框架Apache Thrift

2023-07-02 12:57

关注

这篇“C#怎么使用远程服务调用框架Apache Thrift”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C#怎么使用远程服务调用框架Apache Thrift”文章吧。

Apache Thrift 是 Facebook 实现的一种高效的、支持多种编程语言的远程服务调用的框架。和其它RPC框架相比,它主要具有如下连个特点:

正因为如此,Thrift对于高并发、大数据量和多语言的环境是非常有优势的,本文就简单的介绍一下如何使用它。

使用Thrift和传统的Corba之类的RPC框架并无太大差异,主要分为如下三个部分:

和传统RPC框架一样,Thrift框架提供数据传输的服务,服务端和客户端只需要关注业务即可;这一系列流程并没有多大新颖的地方。

准备工作:

需要在Thrift官网下载两个文件:

下载完后,由于Thrift类库是以源码形式提供的,因此需要自己编译。为了简单,这里以C#为例,打开 "\lib\csharp\src\Thrift.sln" 工程文件,直接编译即可生成Thrift.dll文件。官方说.net版本.net 3.5及以上即可。

示例项目:

Thrift本身提供了多多种语言的支持,这里示例项目仍以官网的CSharp Tutorial为例来介绍一下如何在C#中使用Thrift。

首先下载接口定义文件 tutorial.thrift 和shared.thrift 。官方的文档中加了一大堆注释,实际上还是比较简单的,主体部分如下:

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()}

主要就是定义了一个这样的接口,提供了四个接口。以及一些相关的结构体的定义。定义好接口后,调用Thrift.exe将其编译成C#的代码:

thrift -r --gen csharp tutorial.thrift

编译完后,会生成一个gen-csharp文件夹,里面就是相关的结构体和接口的定义,和一些框架的实现,具体的后续再讲。这个文件夹里的文件大部分都是服务端和客户端都要用的,为了简单起见,大可以建立一个ShareProject(低版本的VS不支持的话可以建立一个独立的类库项目),以方便客户端和服务端引用。

客户端:

首先还是来看看客户端代码(运行这段代码需要加上前面编译的Thrift.dll和编译idl文件生成的一堆C#代码):

using System;using Thrift;using Thrift.Protocol;using Thrift.Server;using Thrift.Transport;namespace CSharpTutorial{    public class CSharpClient    {        public static void Main()        {            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);            }        }    }}

官方的例子简化一下后如下:

    using (TTransport transport = new TSocket("localhost", 9090))    using (TProtocol protocol = new TBinaryProtocol(transport))    using (Calculator.Client client = new Calculator.Client(protocol))    {        transport.Open();        int sum = client.add(1, 1);        Console.WriteLine("1+1={0}", sum);    }

主要就设计到了三个类:TTransport、TProtocol和Calculator.Client,其中TTransport、Tprotocol是用于传输控制的,和业务无关,是在Thrift.dll中定义的。而Calculator.Client则是客户端的Proxy,用于执行RPC,和业务相关,是由idl文件编译生成。客户端无需编写代码,即可拥有RPC能力。(这个特效基本上所有RPC框架都具有)

服务端:

服务端示例代码如下: 

using System;using System.Collections.Generic;using Thrift.Server;using Thrift.Transport;namespace CSharpTutorial{    public class CalculatorHandler : Calculator.Iface    {        Dictionary<int, SharedStruct> log;        public CalculatorHandler()        {            log = new Dictionary<int, SharedStruct>();        }        public void ping()        {            Console.WriteLine("ping()");        }        public int add(int n1, int n2)        {            Console.WriteLine("add({0},{1})", n1, n2);            return n1 + n2;        }        public int calculate(int logid, Work work)        {            Console.WriteLine("calculate({0}, [{1},{2},{3}])", logid, work.Op, work.Num1, work.Num2);            int val = 0;            switch (work.Op)            {                case Operation.ADD:                    val = work.Num1 + work.Num2;                    break;                case Operation.SUBTRACT:                    val = work.Num1 - work.Num2;                    break;                case Operation.MULTIPLY:                    val = work.Num1 * work.Num2;                    break;                case Operation.DIVIDE:                    if (work.Num2 == 0)                    {                        InvalidOperation io = new InvalidOperation();                        io.What = (int)work.Op;                        io.Why = "Cannot divide by 0";                        throw io;                    }                    val = work.Num1 / work.Num2;                    break;                default:                    {                        InvalidOperation io = new InvalidOperation();                        io.What = (int)work.Op;                        io.Why = "Unknown operation";                        throw io;                    }            }            SharedStruct entry = new SharedStruct();            entry.Key = logid;            entry.Value = val.ToString();            log[logid] = entry;            return val;        }        public SharedStruct getStruct(int key)        {            Console.WriteLine("getStruct({0})", key);            return log[key];        }        public void zip()        {            Console.WriteLine("zip()");        }    }    public class CSharpServer    {        public static void Main()        {            try            {                CalculatorHandler handler = new CalculatorHandler();                Calculator.Processor processor = new Calculator.Processor(handler);                TServerTransport serverTransport = new TServerSocket(9090);                TServer server = new TSimpleServer(processor, serverTransport);                // Use this for a multithreaded server                // server = new TThreadPoolServer(processor, serverTransport);                Console.WriteLine("Starting the server...");                server.Serve();            }            catch (Exception x)            {                Console.WriteLine(x.StackTrace);            }            Console.WriteLine("done.");        }    }}

官方代码基本上包括两个部分:接口实现和服务的启动,简化后如下:

    public class CalculatorHandler : Calculator.Iface    {        public void ping()        {        }        public int add(int n1, int n2)        {            return n1 + n2;        }        public int calculate(int logid, Work work)        {            throw new InvalidOperation();        }        public SharedStruct getStruct(int key)        {            return new SharedStruct();        }        public void zip()        {        }    }

接口实现依赖于IDL生成的Calculator.Iface接口,这里我就实现了一个add接口。再来看看服务端 

    static void Main(string[] args)    {        CalculatorHandler handler = new CalculatorHandler();        Calculator.Processor processor = new Calculator.Processor(handler);        TServerTransport serverTransport = new TServerSocket(9090);        TServer server = new TSimpleServer(processor, serverTransport);        Console.WriteLine("Starting the server...");        server.Serve();    }

服务端主要的功能就是将刚才的接口作为服务加载起来,并启动服务,也是比较常规的做法,没有太多需要介绍的地方

从这个Demo来看,主要过程和其它RPC框架的流程倒也没有太大区别。一个比较出彩的地方是Thrift是提供了原生的.net运行库的(前面编译的Thrift.dll),作为一个跨语言的框架不用Pinvoke非常给力,给部署带来不少方便。本来高性能才是它的主要特点,后续有空再测试一下。

以上就是关于“C#怎么使用远程服务调用框架Apache Thrift”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯