Thrift 快速入门实战

[一]、基本概念

1.数据类型

  • 基本类型:
    • bool:布尔值,true 或 false,对应 Java 的 boolean
    • byte:8 位有符号整数,对应 Java 的 byte
    • i16:16 位有符号整数,对应 Java 的 short
    • i32:32 位有符号整数,对应 Java 的 int
    • i64:64 位有符号整数,对应 Java 的 long
    • double:64 位浮点数,对应 Java 的 double
    • string:utf-8编码的字符串,对应 Java 的 String
  • 结构体类型:
    • struct:定义公共的对象,类似于 C 语言中的结构体定义,在 Java 中是一个 JavaBean
  • 容器类型:
    • list:对应 Java 的 ArrayList
    • set:对应 Java 的 HashSet
    • map:对应 Java 的 HashMap
  • 异常类型:
    • exception:对应 Java 的 Exception
  • 服务类型:
    • service:对应服务的类

2.服务端编码基本步骤:

  • 实现服务处理接口impl
  • 创建TProcessor
  • 创建TServerTransport
  • 创建TProtocol
  • 创建TServer
  • 启动Server

3.客户端编码基本步骤:

  • 创建Transport
  • 创建TProtocol
  • 基于TTransport和TProtocol创建 Client
  • 调用Client的相应方法

4.数据传输协议

  • TBinaryProtocol : 二进制格式.
  • TCompactProtocol : 压缩格式
  • TJSONProtocol : JSON格式
  • TSimpleJSONProtocol : 提供JSON只写协议, 生成的文件很容易通过脚本语言解析

tips:客户端和服务端的协议要一致

[二]、实例演示

1. thrift生成代码

thrift-0.11.0.exe 是官网提供的windows下编译工具,运用这个工具生成相关代码:

2. maven 导入相关的jar

 目前用的最新版本0.11.0

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

3.先从最传统的io服务端简单的单线程服务模型写起

/**
 * @blog https://blog.csdn.net/qq_33283716
 * @author ll
 * @date 2018年5月19日14:52:03
 * @Description 服务端简单的单线程服务模型
 */
public class BioServerApp {
    private static Logger logger = Logger.getLogger(BioServerApp.class);  
    public final static int SERVER_PORT = 7098; //服务端的port
    private static String SERVER_IP = "localhost"; //服务端的地址
    
    public void startServer() {
        try {
        	
            TServerSocket serverTransport = new TServerSocket(SERVER_PORT); //create socket
            TServer.Args args = new TServer.Args(serverTransport);
	     //TMultiplexedProcessor 类通过该类,可以注册多个接口的服务实现类
	     //TMultiplexedProtocol 类它来帮助客户端区别调用哪个接口
            TMultiplexedProcessor multiplexedProcessor = new TMultiplexedProcessor();
            TProcessor process = new AppEvent.Processor((AppEvent.Iface) new AppEventServiceImpl());
            TProcessor browserProcess = new ClientDeviceData.Processor((ClientDeviceData.Iface) 
            		new BrowserHistoryInfoServiceImpl());
            multiplexedProcessor.registerProcessor("AppEvent", process);
            multiplexedProcessor.registerProcessor("ClientDeviceData", browserProcess);
            
            TBinaryProtocol.Factory portFactory = new TBinaryProtocol.Factory(true, true);
            args.processor(multiplexedProcessor);
            args.protocolFactory(portFactory);
            logger.info("ServerApp Server start...");

	     //使用传统阻塞式BIO,服务端和客户端需要指定数据传输的方式
            TServer server = new TSimpleServer(args);
            server.serve();
        } catch (Exception e) {
        	System.out.println("ServerApp error...");
        	logger.error(e.getMessage());
        }
    }


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

  client端

/**
 * @blog https://blog.csdn.net/qq_33283716
 * @author ll
 * @date 2018年5月19日14:52:03
 * @Description 服务端简单的单线程服务模型Client
 */

public class AppEventBioClient {
    public static final int SERVER_PORT = 7098;
    public static final String SERVER_IP = "localhost";

    public void startClient() {
        TTransport tTransport = null;
        try {
            tTransport = new TSocket(SERVER_IP, SERVER_PORT);
            //协议要和服务端一致
            TProtocol protocol = new TBinaryProtocol(tTransport);
            TMultiplexedProtocol multiplexedProtocol = new TMultiplexedProtocol(protocol, "AppEvent");
            AppEvent.Client client = new AppEvent.Client(multiplexedProtocol,multiplexedProtocol); 
            tTransport.open();

            for (int i = 0; i <=15; i++) {
                AppEventInfo appEventInfo = new AppEventInfo();
                appEventInfo.event_id = 38386689+i;
                appEventInfo.sdk = 23;
                appEventInfo.m = "vivo 1606";
                appEventInfo.app = "calf";
                appEventInfo.os = "android";
                appEventInfo.lo = 106.888621;
                appEventInfo.l = "in";
                appEventInfo.v = 2400;
                appEventInfo.b = "vivo";
                appEventInfo.c = "GooglePlay";
                appEventInfo.t = 1432349188;
                appEventInfo.pn = "" ;
                appEventInfo.la = -6.171863;
                appEventInfo.r = "6.0.1";
                appEventInfo.refer = "";
                appEventInfo.ip="100.86.123.056";
                appEventInfo.account_id =0;
                appEventInfo.customer_id = 0;
                appEventInfo.imei = "866845035845370";
                appEventInfo.gaid = "11ef5c4f-8252-4253-bcef-e8170025075e";
                appEventInfo.android_id = "3344c770161f29be";
                boolean result = client.save(appEventInfo);
                System.out.println(result);
			}
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
    	AppEventBioClient client = new AppEventBioClient();
        client.startClient();
    }
}

首先把服务端的Main函数启动;

然后启动Client

运行结果:


此demo是通过rpc通信实时传输数据.然后数据落地Write File方式.最终数据落地Elasticsearch 或者 hive数据仓库;

4.线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求



/**
 * @blog https://blog.csdn.net/qq_33283716
 * @author ll
 * @date 2018年5月19日14:52:03
 * @Description 服务模型线程池服务模型 使用标准的阻塞式IO,预先创建一组线程处理请求
 */
public class ThreadServerApp {

	private static Logger logger = Logger.getLogger(ThreadServerApp.class);

	public final static int SERVER_PORT = 7098;

	public void startServer() {
		try {

            TProcessor process = new AppEvent.Processor((AppEvent.Iface) new AppEventServiceImpl());

            TMultiplexedProcessor multiplexedProcessor = new TMultiplexedProcessor();
            multiplexedProcessor.registerProcessor("AppEvent", process);

			 TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
			 TThreadPoolServer.Args ttpsArgs = new TThreadPoolServer.Args(
			 serverTransport);
			 ttpsArgs.processor(multiplexedProcessor);
			 ttpsArgs.protocolFactory(new TBinaryProtocol.Factory());
			 
			// 线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求。
			 TServer server = new TThreadPoolServer(ttpsArgs);
			 logger.info("Thrift  ThreadServerApp start ....");
			 server.serve();

		} catch (Exception e) {
			// TODO: handle exception
        	logger.error("ThreadServerApp error... ",e);
        }

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

看了下源码

import java.util.concurrent.ExecutorService;

默认的方式是:  核心线程数为5,最大线程数为10。超时时间为60秒

ThreadPoolExecutor executor = new ThreadPoolExecutor(5, (2^31-1), 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());

Client端不变.与上面的BIO Client一致

5.使用非阻塞式IO,服务端和客户端需要指定 TFramedTransport 数据传输的方式。

Server端:


/**
 * @blog https://blog.csdn.net/qq_33283716
 * @author ll
 * @date 2018年5月19日14:52:03
 * @Description  非阻塞式NIO 服务端
 */
public class NioServerApp {
	private static Logger logger = Logger.getLogger(NioServerApp.class);
	public final static int SERVER_PORT = 7098;
	public void startServer() {
		try {
			TProcessor tprocessor = new AppEvent.Processor((AppEvent.Iface) new AppEventServiceImpl());
			TNonblockingServerSocket tnbSocketTransport = new TNonblockingServerSocket(
					SERVER_PORT);
			TNonblockingServer.Args tnbArgs = new TNonblockingServer.Args(
					tnbSocketTransport);
            TMultiplexedProcessor multiplexedProcessor = new TMultiplexedProcessor();
            multiplexedProcessor.registerProcessor("AppEvent", tprocessor);
            
			tnbArgs.processor(multiplexedProcessor);
			tnbArgs.transportFactory(new TFramedTransport.Factory());
			tnbArgs.protocolFactory(new TCompactProtocol.Factory());

			// 使用非阻塞式IO,服务端和客户端需要指定TFramedTransport数据传输的方式
			logger.info("Thrift  TNonblockingServer start ....");
			TServer server = new TNonblockingServer(tnbArgs);
			server.serve();
		} catch (Exception e) {
			// TODO: handle exception
        	logger.error("NioServerApp error... ",e);
        }
	}
    public static void main(String[] args) {
    	NioServerApp server = new NioServerApp();
        server.startServer();
    }
}

Client端:

/**
 * blog https://blog.csdn.net/qq_33283716
 * @author ll
 * @date 2018年5月19日14:52:03
 * @Description  非阻塞式NIO Client
 */
public class AppEventNioClient {
	public static final int SERVER_PORT = 7098;
	public static final String SERVER_IP = "localhost";

	public void startClient() {
		TTransport tTransport = null;
		try {
			tTransport = new TFramedTransport(new TSocket(SERVER_IP, SERVER_PORT));
			// 协议要和服务端一致
			TProtocol protocol = new TCompactProtocol(tTransport);

			TMultiplexedProtocol multiplexedProtocol = new TMultiplexedProtocol(protocol, "AppEvent");
			AppEvent.Client client = new AppEvent.Client(multiplexedProtocol, multiplexedProtocol);
			tTransport.open();

			AppEventInfo appEventInfo = new AppEventInfo();

			for (int i = 0; i <= 150000; i++) {

				appEventInfo.event_id = 10000;
				appEventInfo.sdk = 23;
				appEventInfo.m = "vivo 1606";
				appEventInfo.app = "calf";
				appEventInfo.os = "android";
				appEventInfo.lo = 106.888621;
				appEventInfo.l = "in";
				appEventInfo.v = 2400;
				appEventInfo.b = "vivo";
				appEventInfo.c = "GooglePlay";
				appEventInfo.t = 1432349188;
				appEventInfo.pn = "";
				appEventInfo.la = -6.171863;
				appEventInfo.r = "6.0.1";
				appEventInfo.refer = "";
				appEventInfo.ip = "100.86.123.056";
				appEventInfo.account_id = 0;
				appEventInfo.customer_id = 0;
				appEventInfo.imei = "866845035845370";
				appEventInfo.gaid = "11ef5c4f-8252-4253-bcef-e8170025075e";
				appEventInfo.android_id = "3344c770161f29be";

				boolean result = client.save(appEventInfo);
				System.out.println(result);

			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		} finally {
			tTransport.close();
		}
	}

	public static void main(String[] args) {
		AppEventNioClient client = new AppEventNioClient();
		client.startClient();
	}
}

大致内容都一致 只是协议要和服务端一致 还有半同步半异步的服务端模型,需要指定为: TFramedTransport 数据传输的方式

希望对你们有帮助

猜你喜欢

转载自blog.csdn.net/qq_33283716/article/details/80374462