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

  1. 高性能。 它采用的是二进制序列化,并且用的是长连接。比传统的使用XML,SOAP,JSON等短连接的解决方案要快得多。
  2. 多语言支持。 它对提供了对C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk等多种常用语言的支持

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

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

  1. 使用IDL定义提供的服务:主要用于服务接口和数据传输对象(DTO)并且有一套自己的语法, Thrift中命名为thirft文件,并且有一套自己的语法。
  2. 将IDL编译成框架代码
  3. 客户端使用框架代码调用远程服务
  4. 服务端使用框架代码实现接口,并提供服务

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

准备工作:

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

  1. IDL编译工具。官方本身提供了Windows的exe版本:thrift-0.9.2.tar.gz
  2. 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(:i32 num1, :i32 num2),
i32 calculate(:i32 logid, :Work w) throws (: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", );
TProtocol protocol = new TBinaryProtocol(transport);
Calculator.Client client = new Calculator.Client(protocol); transport.Open();
try
{
client.ping();
Console.WriteLine("ping()"); int sum = client.add(, );
Console.WriteLine("1+1={0}", sum); Work work = new Work(); work.Op = Operation.DIVIDE;
work.Num1 = ;
work.Num2 = ;
try
{
int quotient = client.calculate(, work);
Console.WriteLine("Whoa we can divide by 0");
}
catch (InvalidOperation io)
{
Console.WriteLine("Invalid operation: " + io.Why);
} work.Op = Operation.SUBTRACT;
work.Num1 = ;
work.Num2 = ;
try
{
int diff = client.calculate(, work);
Console.WriteLine("15-10={0}", diff);
}
catch (InvalidOperation io)
{
Console.WriteLine("Invalid operation: " + io.Why);
} SharedStruct log = client.getStruct();
Console.WriteLine("Check log: {0}", log.Value); }
finally
{
transport.Close();
}
}
catch (TApplicationException x)
{
Console.WriteLine(x.StackTrace);
} }
}
}

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

    using (TTransport transport = new TSocket("localhost", ))
using (TProtocol protocol = new TBinaryProtocol(transport))
using (Calculator.Client client = new Calculator.Client(protocol))
{
transport.Open();
int sum = client.add(, );
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 = ;
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 == )
{
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();
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();
TServer server = new TSimpleServer(processor, serverTransport); Console.WriteLine("Starting the server...");
server.Serve();
}

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

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

最后,本文只是一个简单的入门体验,如果需要更多信息,请参看Thrift的官方网站,另外,IBM Developer works网站上的一篇文章Apache Thrift - 可伸缩的跨语言服务开发框架介绍得比较详细,强烈推荐。

Apache Thrift使用简介的更多相关文章

  1. 《精通并发与Netty》学习笔记(06 - Apache Thrift使用简介)

    一.概述 Apache Thrift 是 Facebook 实现的一种高效的.支持多种编程语言的远程服务调用的框架.Thrift是由Facebook开发的,并在2008年捐给了Apache基金会,成为 ...

  2. Netty学习——Apache Thrift 简介和下载安装

    Netty学习——Apache Thrift 简介和下载安装 Apache Thrift 简介 本来由Facebook开发,捐献给了Apache,成了Apache的一个重要项目 可伸缩的,跨语言的服务 ...

  3. Apache Thrift - 可伸缩的跨语言服务开发框架

    To put it simply, Apache Thrift is a binary communication protocol 原文地址:http://www.ibm.com/developer ...

  4. Apache Thrift的简单使用

    Apache Thrift的简单使用 ---------------------- 1. 简介 Thrift是Facebook的一个开源项目,主要是一个跨语言的服务开发框架.它有一个代码生成器来对它所 ...

  5. golang高性能RPC:Apache Thrift安装使用完全攻略

    在企业应用中RPC的使用可以说是十分的广泛,使用该技术可以方便的与各种程序交互而不用考虑其编写使用的语言. 如果你对RPC的概念还不太清楚,可以点击这里. 现今市面上已经有许多应用广泛的RPC框架,比 ...

  6. 【Java】分布式RPC通信框架Apache Thrift 使用总结

    简介 Apache Thrift是Facebook开源的跨语言的RPC通信框架,目前已经捐献给Apache基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于th ...

  7. 基于Apache Thrift的公路涵洞数据交互实现原理

    基于Apache Thrift的公路涵洞数据交互实现原理 Apache Thrift简介 Apache Thrift(以下简称为“Thrift”) 是 Facebook 实现的一种高效的.支持多种编程 ...

  8. Apache Thrift 的魅力

    WhyApacheThrift 因为最近在项目中需要集成进来一个Python编写的机器学习算法,但是我的后端主要使用的是SpringCloud技术栈. 于是面临着异构语言之间的通信实现方式的抉择. 因 ...

  9. apache thrift 入门(一)

    1.简介 Apache Thrift软件框架,是用来开发可扩展的跨语言的软件服务.通过软件堆栈和代码生成引擎相结合的方式来构建服务,使C++, Java, Python, PHP, Ruby, Erl ...

随机推荐

  1. ActiveMQ-如何使用JMS API?

    JMS编程模型 JMS定义了Java中访问消息中间件的一组接口,主要包括ConnectionFactory.Connection.Session.Destination.MessageProducer ...

  2. Ubuntu 各版本的几个国内更新源

    Ubuntu 国内更新源(各版本通用) 前言:为了下载更方便,速度更快,我们在使用Linux系列系统时修改 apt源 为国内的源 1.复制源文件备份,以防万一 修改文件sources.list,在目录 ...

  3. xshell 映射带跳板机服务器的端口到本地

    1.配置xshell连接跳板机服务器: 2. 3.可用navicate等同过端口连接远程数据库.

  4. CentOS系统yum源配置修改、yum安装软件包源码包出错解决办法apt.sw.be couldn't connect to host

    yum安装包时报错: Could not retrieve mirrorlist http://mirrorlist.repoforge.org/el6/mirrors-rpmforge error  ...

  5. Makefile的使用方法

    转自:http://blog.chinaunix.net/uid-403164-id-2407545.html 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Wind ...

  6. 专题-Delphi/C++ Builder多线程编程与调试

    [目录] Delphi.C++ Builder多线程程序编码调试的一点经验谈 多线程程序的填坑笔记和多线程编程应该遵循的规则(天地弦) 多线程编程中死锁问题的跟踪与解决 临界.多重读独占写多线程同步测 ...

  7. python collection系列

    collection系列 不常用功能,需要进行模块功能导入: import collection Counter 常用方法测试: #!/usr/local/env python3 ''' Author ...

  8. loadrunner 分用户日志

    loadrunner 分用户日志 loadrunner在run脚本时,模拟多用户并发场景下,通常需要分别关注每个用户的脚本执行日志,可以按照以下操作进行: 在“Run Load Tests”中选择需要 ...

  9. Ubuntu编译安装nginx,php,mysql

    摘要: 整理的Ubuntu编译安装nginx,php,mysql的步骤,主要来自对驻云的sh-1.4.1中脚本的整理,随时代进步,内容中的软件或者命令请自行更新 目录准备 创建用户 userdel w ...

  10. 洛谷P1088 火星人 [STL]

    题目传送门 火星人 格式难调,题面就不放了. 分析: 这道题目不得不又让人感叹,还是$STL$大法好!!! $C++$的$algorithm$库中自带有$next\_permutation()$和$p ...