[一]、基本概念
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 数据传输的方式
希望对你们有帮助