`
mncc
  • 浏览: 52947 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Thrift基础(一)Hello World

阅读更多

昨天写的 thrift 基础的例子


1、thrift 是什么:

thrift 是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。thrift 最初由 facebook 开发,07年四月开放源码,08年5月进入apache孵化器。(这段话是百度的
现在的官方网站:http://thrift.apache.org/ 最新版0.9.2


2、开发简单的例子
实际上thrift就是生成一个各个语言下都能通用的Entity类,Service接口和通讯协议。
首先要到官网上下载thrift的可执行程序,用于生成上边写的Entity和Service接口。
下载地址:http://thrift.apache.org/download
下载 Thrift compiler 即可,我是 windows 直接改名称为 thrift.exe 放到了系统的 windows 目录下。所以到时候命令行直接执行命令即可(懒得配单独的环境变量啊)。

 

开发:
使用的是Java
先是maven的配置

<dependency>
  <groupId>org.apache.thrift</groupId>
  <artifactId>libthrift</artifactId>
  <version>0.9.2</version>
</dependency>

 
PS:话说才发现 storm 里也有 thrift 的包不过包名怎么都改成了 org.apache.thrift7 了。

首先是Entity类和Service接口:
随便找个文本文件管理器比如Notepad++或者SublimeText之类的写一个文件,文件名helloworld.thrift
内容:

namespace java com.nanxiaoqiang.test.thrift.demo1// java下的包路径
// 生成方式 bash:thrift -r -gen java helloworld.thrift
struct Helloworld{
    1:i32 id;
    2:string name;
}

service HelloworldService{
    bool insertHelloworld(1:Helloworld helloworld),
    bool removeHelloworld(1:i32 id),
    Helloworld getHelloworld(1:i32 id)
}

 
然后命令行下 thrift -r -gen java helloworld.thrift 即可生成两个文件:Helloworld.javaHelloworldService.java

 

PS:关于这个IDL类型的文件到底应当怎么写,下边的是参考文档:

http://thrift.apache.org/docs/types 官方文档

http://wiki.apache.org/thrift/ Wiki百科

http://www.cnblogs.com/tianhuilove/archive/2011/09/05/2167669.html    tianhuilove的博客


接着是具体Service的实现,模拟了一个类似于CURD的方法内容

package com.nanxiaoqiang.test.thrift.demo1;

import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.thrift.TException;

import com.nanxiaoqiang.test.thrift.demo1.HelloworldService.Iface;

/**
 * Handler 数据处理接口
 *
 * @author nanxiaoqiang
 *
 * @version 0.1
 *
 * @since 2015年3月21日
 *
 */
public class HelloworldServiceImpl implements Iface {

    private static Logger logger = LogManager
            .getLogger(HelloworldServiceImpl.class.getName());

    ConcurrentHashMap<Integer, Helloworld> map = new ConcurrentHashMap<>();

    public HelloworldServiceImpl() {
        Helloworld h = new Helloworld();
        h.setId(0);
        h.setName("NULL");
        map.put(h.getId(), h);
        logger.info("constructor HelloworldServiceImpl:add new Helloworld,now map size is "
                + map.size());
    }

    @Override
    public boolean insertHelloworld(Helloworld helloworld) throws TException {
        if (helloworld == null || helloworld.getId() == 0) {
            logger.info("error object of Helloworld. map size is " + map.size());
            return false;
        } else {
            logger.info(ToStringBuilder.reflectionToString(helloworld,
                    ToStringStyle.MULTI_LINE_STYLE));
            map.put(helloworld.getId(), helloworld);
            logger.info("insert complete. map size is " + map.size());
            return true;
        }
    }

    @Override
    public boolean removeHelloworld(int id) throws TException {
        if (id == 0) {
            logger.info("can not remove with id 0. map size is " + map.size());
            return false;
        } else if (map.containsKey(id)) {
            logger.info(ToStringBuilder.reflectionToString(map.get(id),
                    ToStringStyle.MULTI_LINE_STYLE));
            map.remove(id);
            logger.info("removed complete with id " + id + ". map size is "
                    + map.size());
            return true;
        } else {
            logger.info("can not find object with id " + id + ". map size is "
                    + map.size());
            return false;
        }
    }

    @Override
    public Helloworld getHelloworld(int id) throws TException {
        if (map.containsKey(id)) {
            Helloworld h = map.get(id);
            logger.info(ToStringBuilder.reflectionToString(h,
                    ToStringStyle.MULTI_LINE_STYLE));
            return h;
        } else {
            logger.info("can not find object with id " + id + ". map size is "
                    + map.size());
            return null;
        }
    }

}

 

接着是 Server 端:

package com.nanxiaoqiang.test.thrift.demo1;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;

/**
 * 一个基本的Thrift的例子,Server 服务模型,线程安全
 * 
 * @author nanxiaoqiang
 * 
 * @version 0.1
 * 
 * @since 2015年3月21日
 *
 */
public class Server {
	private static Logger logger = LogManager.getLogger(Server.class.getName());

	public static final int SERVER_PORT = 9999;

	public Server() {
	}

	public void startServer() {
		logger.info("准备启动TProcessor");
		TProcessor tprocessor = new HelloworldService.Processor<HelloworldService.Iface>(
				new HelloworldServiceImpl());

		// 简单的单线程服务模型,一般用于测试
		try {
			// 支持的服务模型
			// TSimpleServer – 简单的单线程服务模型,常用于测试
			// TThreadedServer - 多线程服务模型,使用阻塞式IO,每个请求创建一个线程。
			// TThreadPoolServer – 线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求。
			// TNonblockingServer – 多线程服务模型,使用非阻塞式IO(需使用TFramedTransport数据传输方式)
			// 处理大量更新的话,主要是在TThreadedServer和TNonblockingServer中进行选择。
			// TNonblockingServer能够使用少量线程处理大量并发连接,但是延迟较高;
			// TThreadedServer的延迟较低。
			// 实际中,TThreadedServer的吞吐量可能会比TNonblockingServer高,
			// 但是TThreadedServer的CPU占用要比TNonblockingServer高很多。
			TServerSocket serverTransport = new TServerSocket(SERVER_PORT);

			TServer.Args tArgs = new TServer.Args(serverTransport);

			tArgs.processor(tprocessor);

			// 支持的传输格式
			// TBinaryProtocol – 二进制格式.
			// TCompactProtocol – 压缩格式
			// TJSONProtocol – JSON格式
			// TSimpleJSONProtocol –提供JSON只写协议, 生成的文件很容易通过脚本语言解析。
			// TDebugProtocol – 使用易懂的可读的文本格式,以便于debug
			tArgs.protocolFactory(new TBinaryProtocol.Factory());// 传输格式,二进制
			// tArgs.protocolFactory(new TCompactProtocol.Factory()); // 传输格式,压缩
			// tArgs.protocolFactory(new TJSONProtocol.Factory());// 传输格式,JSON
			TServer server = new TSimpleServer(tArgs);
			server.serve();
			logger.info("启动完成.");

		} catch (TTransportException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		Server server = new Server();
		server.startServer();
	}

}

 

Client 端:

package com.nanxiaoqiang.test.thrift.demo1;

import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

public class Client {

    private static Logger logger = LogManager.getLogger(Client.class.getName());

    public static final String SERVER_IP = "localhost";
    public static final int SERVER_PORT = 9999;
    public static final int TIMEOUT = 30000;// 超时

    public Client() {
    }

    public void startclient() {
        // 支持的通信方式(数据传输方式)(Transport)
        // TFileTransport:文件(日志)传输类,允许client将文件传给server,允许server将收到的数据写到文件中。
        // THttpTransport:采用Http传输协议进行数据传输
        // TSocket:采用TCP Socket进行数据传输
        // TZlibTransport:压缩后对数据进行传输,或者将收到的数据解压
        // 下面几个类主要是对上面几个类地装饰(采用了装饰模式),以提高传输效率。
        // TBufferedTransport:对某个Transport对象操作的数据进行buffer,即从buffer中读取数据进行传输,或者将数据直接写入buffer
        // TFramedTransport:以frame为单位进行传输,非阻塞式服务中使用。同TBufferedTransport类似,也会对相关数据进行buffer,同时,它支持定长数据发送和接收。
        // TMemoryBuffer:从一个缓冲区中读写数据
        TTransport transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT);
        // 协议要和服务端一致
        TProtocol protocol = new TBinaryProtocol(transport);
        // TProtocol protocol = new TCompactProtocol(transport);
        // TProtocol protocol = new TJSONProtocol(transport);
        HelloworldService.Client client = new HelloworldService.Client(protocol);

        try {
            transport.open();

            // 测试1
            Helloworld h1 = null;
            boolean b1 = client.insertHelloworld(h1);
            logger.info("传输一个null值进行insertHelloworld方法,返回结果:" + b1);
            TimeUnit.SECONDS.sleep(1);

            // 测试2
            Helloworld h2 = new Helloworld();
            h2.setId(1);
            h2.setName("Hello World!Thrift!");
            boolean b2 = client.insertHelloworld(h2);
            logger.info("传输一个Helloworld对象进行insertHelloworld方法,返回结果:" + b2);
            TimeUnit.SECONDS.sleep(1);

            // 测试3
            Helloworld h3 = client.getHelloworld(0);
            logger.info("通过方法getHelloworld得到id为0的Helloworld对象,返回结果:"
                    + ToStringBuilder.reflectionToString(h3,
                            ToStringStyle.MULTI_LINE_STYLE));
            TimeUnit.SECONDS.sleep(1);

            // 测试4
            Helloworld h4 = client.getHelloworld(1);
            logger.info("通过方法getHelloworld得到id为1的Helloworld对象,返回结果:"
                    + ToStringBuilder.reflectionToString(h4,
                            ToStringStyle.MULTI_LINE_STYLE));
            TimeUnit.SECONDS.sleep(1);

            // 测试5
            // 此段会报错!不能返回null对象
            // 报错内容:org.apache.thrift.TApplicationException: getHelloworld failed: unknown result
            // Helloworld h5 = client.getHelloworld(2);
            // logger.info("通过方法getHelloworld得到id为2的Helloworld对象,返回结果:"
            // + ToStringBuilder.reflectionToString(h5,
            // ToStringStyle.MULTI_LINE_STYLE));
            // TimeUnit.SECONDS.sleep(1);

            // 测试6
            boolean b6 = client.removeHelloworld(0);
            logger.info("通过方法removeHelloworld删除id为0的Helloworld对象,返回结果:" + b6);
            TimeUnit.SECONDS.sleep(1);

            // 测试7
            boolean b7 = client.removeHelloworld(1);
            logger.info("通过方法removeHelloworld删除id为1的Helloworld对象,返回结果:" + b7);
            TimeUnit.SECONDS.sleep(1);

            // 测试8
            boolean b8 = client.removeHelloworld(2);
            logger.info("通过方法removeHelloworld删除id为2的Helloworld对象,返回结果:" + b8);
            TimeUnit.SECONDS.sleep(1);
           
        } catch (TTransportException e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        } catch (TException e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        } catch (InterruptedException e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        } finally {
            if (transport != null)
                transport.close();
            logger.info("transport关闭");
        }

    }

    public static void main(String[] args) {
        Client c = new Client();
        c.startclient();
    }

}

 

然后分别运行Server和Client即可返回执行结果。

PS:

  1. 因为是测试,所以用的是单线程的Server,实际上最好用TNonblockingServer。
  2. null值是不能返回做交互的。会抛出org.apache.thrift.TApplicationException: getHelloworld failed: unknown result。

参考(受益良多):
http://www.cnblogs.com/mumuxinfei/p/3873709.html             Thrift 个人实战--初次体验Thrift
http://blog.csdn.net/amuseme_lu/article/details/6262572     Apache Thrift的简单使用
http://gemantic.iteye.com/blog/1199214                               thrift的使用介绍





 

分享到:
评论

相关推荐

    【Thrift之C++远程调用helloworld菜鸟教程】

    【Thrift之C++远程调用helloworld菜鸟教程】

    c# thrift demo

    thrift应用, c#实现,代码简洁清晰,一看就会。。。分布式技术必掌握之一

    thrift基础文档

    thrift基础教学文档,适合新手入门学习,大家可以下载下来学习!

    thrift-laravel:Apache Thrift 教程 Hello World(服务器中的 Laravel + Python)

    教程在: 技术包括: 阿帕奇节俭 Laravel 4.2 Python 概念: BROWSERS WEB SERVER Apache Thrift | | | | hello? | | |--------------&gt;... | | Hello World! | | |&lt;--------------|

    thrift java hello

    thrift java hello 具体见 http://blog.csdn.net/stonexmx/article/details/51613962

    thrift入门

    thrift基础入门,讲解thrift基本语法

    基于thrift的rpc框架,在thrift基础上增加负载均衡,连接池,性能监控.zip

    基于thrift的rpc框架,在thrift基础上增加负载均衡,连接池,性能监控.zip

    thrift 源码(一种可伸缩的跨语言服务的发展软件框架)

    thrift是一种可伸缩的跨语言服务的发展软件框架。它结合了功能强大的软件堆栈的代码生成引擎,以建设服务,工作效率和无缝地与C + +,C#,Java,Python和PHP和Ruby结合。thrift是facebook开发的,我们现在把它作为...

    qt 实现thrift的一个例子

    具体文章请看 https://blog.csdn.net/bwangk/article/details/83017030 thrift实现一个客户端和服务端c++ 语言的RPC连接例子

    thrift-Demo

    thrift一个实例

    Learning.Apache.Thrift.178588274

    Learn to make your services ready for real-world applications by using stepwise examples and modifying code from Industry giants. Be a crackerjack at solving Apache Thrift-related issues. Table of ...

    Thrift之C++初体验

    thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, ...

    thrift-0.9.3.exe

    Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, ...

    thrift源码

    thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码...

    thrift安装

    thrift 安装包。

    Thrift框架所用的包

    压缩包中包含四个文件,libthrift-0.9.1.jar,slf4j-...然后将后两个文件放在同一个目录,在控制台中执行如下命令thrift-0.9.3.exe -r -gen java ./demoHello.thrift,将产生一个新的目录,将里面的文件复制到项目中即可

    thrift-0.10.0.exe

    Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, ...

    the programmer's guide to apache thrift

    Apache Thrift is an open source cross language serialization and RPC framework. With support for over 15 programming languages, Apache Thrift can play an important role in a range of distributed ...

    thrift开发入门java程序

    Thrift作为可伸缩的跨语言服务开发框架,网上的资源较少,这里是一个简单的入门小程序,文件中的mylib下包含了依赖的jar包,并且在file目录下放了一个简单的thrift文件和生成thrift-0.9.0.exe工具,直接使用 thrift-...

    Windows下QT使用Thrift的样例

    网上一直搜不到Windows下QT使用thrift的例子,自己整了个 QT版本 5.8.0 Boost版本 boost_1_61_0 Thrift版本 thrift-0.10.0

Global site tag (gtag.js) - Google Analytics