1. Introduction
As an RPC framework, thrift solves the problem of Cross-language invocation and provides flexible and efficient transmission and server mode. In practical applications, personally think that thrift more is used for system decoupling, responsible for communication between modules, so that each module can be independently developed, tested and released, and so on, in general, do not need to worry about cross language invocation and transmission performance problems, and the external call is biased towards more universal HTTP REST. In this post, we understand the remote invocation of thrift by writing a basic example. 2. Preparatory work
First use Manven to create a Java Project and add thrift dependencies
<dependencies>
<dependency>
<groupId>org.apache.thrift</groupId>
< artifactid>libthrift</artifactid>
<version>0.9.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12< /artifactid>
<version>1.7.12</version>
</dependency>
</dependencies>
3. Preparation of thrift documents
Thrift provides us with IDL (Interface Definition Language) to write common service interface files (files with a suffix of thrift) and to compile the template code for the corresponding language to solve the problem of cross-language invocation. For example, we are using Java, then generate Java files, using node, that will generate JS files.
If we query a cinema information system for a movie's data, we need an interface to get the movie information, the client passes in the name of the query, and the server returns the detailed data for the movie.
First we need a movie entity to load the relevant data, as shown in the following code.
Moviemodel.thrift
Defines the Java namespace, corresponding to the value of package
namespace Java com.thrift.simple.model
struct Movie {1:string
chname//Chinese name
2:string enname//English name
3:string type//Type
4:string Digital//number type
5:i64 releasedate//release date
6:I32 Duration//Time long
7:i32 price//Sales
8:map<string, bool> screenings//information, whether there are tickets
The above code involves the data types that IDL supports, interested readers can go to http://thrift.apache.org/docs/types to learn a little bit, we don't add required or optional declarations here, thrift default as Required processing, the difference is that the type of required declaration must be serialized, if you do not assign a value to it, the generated Java code will also set a default value, optional unassigned is not serialized. In addition, IDL supports only basic Java types, and types such as Date are not supported and need to be converted in code.
Next you need a service interface to query movie information, as shown in the following code.
Movieoperator.thrift
namespace Java com.thrift.simple.service
//reference Another thrift file, called by the form "file name. Data type".
include "Moviemodel.thrift"
service movieoperator {
Moviemodel.movie getmovie (1:string chname)
So we need the thrift file is ready, enter the following command to generate the corresponding Java files.
Add-r option to generate include file
thrift-r--gen java movieoperator.thrift
Put the generated Java file into the project corresponding to the package, you can start to use, the first simple analysis of the generated movie and Movieoperator classes.
Movie Class
Figure 3-1 is a partial method of the movie class, and you can see that, in addition to the read and write methods itself for transmission, the Equals and hashcode of set and Get,object and even CompareTo methods are written for you, In this case, we can use it directly as a movie entity.
Figure 3-1
Movieoperator class
The code for this class looks a lot, but the structure is simple, and the main members are shown in Figure 3-2. Where Iface is the interface we have just defined, the client and processor are used for clients and services, which encapsulate the request and receive methods of the remote invocation, and the Getmovie_args and Getmovie_ are used during the invocation. The result method to obtain parameters and return values, respectively. The last 3 async methods are used for asynchronous processing, and this example is not described in detail.
Figure 3-2
4. Client Implementation
Now formally write code, first create the client's Thriftclient class, the code looks like this.
public class Thriftclient {public
static void Main (string[] args) {
//Java sockets are encapsulated to define the basic method
of transmission Ttransport Basetrans = new Tsocket ("localhost", 6060, Watts);
Further encapsulation, using the mode of frame transfer, the server must use Non-blocking type
ttransport Frametrans = new Tframedtransport (Basetrans);
Using binary protocol, the service-side agreement must be consistent
tprotocol protocol = new Tbinaryprotocol (Frametrans);
The configuration is passed into the client object
movieoperator.client client = new Movieoperator.client (protocol);
try {
//tsocket initializes and creates a socket connection
frametrans.open ();
Calls the Getmovie method remotely and gets the return value
Movie Movie = Client.getmovie ("The Spy Shadow 5");
SYSTEM.OUT.PRINTLN ("Get remote info---->" + movie.tostring ());
} catch (Texception e) {
e.printstacktrace ();
} finally {
//Don't forget to close the connection
frametrans.close ();
}
}
}
5. Interface Service Implementation
Write the implementation class for the Iface interface, which is what the client does to find the service-side, as shown in the code below.
public class Movieoperatorimpl implements Movieoperator.iface {@Override public Movie Getmovie (String chname) thr
OWS texception {//Create entity object Movie Movie = new Movie ();
This example is not retrieved from the database, directly into a test data movie.setenname ("Jason Bourne");
Movie.setchname (Chname);
Movie.setprice (49);
Movie.setdigital ("original 3D");
Movie.setduration (123);
Movie.setreleasedate (Datetrans ("2016-08-23"));
Movie.settype ("English");
map<string, boolean> map = new hashmap<string, boolean> ();
Map.put ("18:15", false);
Map.put ("22:30", true);
Movie.setscreenings (map);
return movie;
Private Long Datetrans (String date) {long defaulttime = 0;
DateFormat format = new SimpleDateFormat ("Yyyy-mm-dd");
try {defaulttime = format.parse (date). GetTime ();
catch (ParseException e) {e.printstacktrace ();
return defaulttime; }
}
6. Service-Side Implementation
Finally write the service-side Thriftserver class, as shown in the code below.
public class Thriftserver {public static final int serveport = 6060;
public static void Main (string[] args) {movieoperator.iface operator = new Movieoperatorimpl ();
The object of the implementation class is placed in the processor to be maintained, and when requested by the client, it is mapped to the specific execution method Tprocessor processor = new movieoperator.processor<> (operator); try {//Create a Non-blocking transport object that encapsulates the ServerSocket tnonblockingservertransport niosocket = new Tnonblo
Ckingserversocket (Serveport);
Tnonblockingserver.args Nonblockingargs = new Tnonblockingserver.args (niosocket);
Put the process in place and set the type of transport and protocol, pay attention to the corresponding nonblockingargs.processor (processor);
Nonblockingargs.transportfactory (New Tframedtransport.factory ());
Nonblockingargs.protocolfactory (New Tbinaryprotocol.factory ());
Instantiating the server object Tserver Server = new Tnonblockingserver (Nonblockingargs);
SYSTEM.OUT.PRINTLN ("service start at" + Serveport); Start and monitorListen to Server.serve ();
catch (Texception e) {e.printstacktrace (); }
}
}
The only place where the above code has doubts is the internal class args of Tnonblockingserver, why not instantiate the Tnonblockingserver directly, but use the parameters needed for the configuration.
Let's see figure 6-1,tnonblockingserver only provides a constructor that takes Abstractnonblockingserverargs as a parameter, so you must first create its static internal class args object.
Figure 6-1
We continue to look at the inheritance structure of the args, as shown in Figure 6-2.
Figure 6-2
Tracing the parent class to Tserver, it is found that the basic data required by the server is defined in Abstractserverargs: transport, process, and protocol, which is the parameter properties that have just been configured, as shown in Figure 6-3.
Figure 6-3
See here, we already understand the general design method, Tserver as the parent class of all server types, in addition to defining the underlying attributes and operating standards, also provides an abstract args class for parameter configuration and management, subclasses inherit and extend the class as needed, This is how tthreadpoolserver is done, as often used. So when you instantiate another server, you simply create and configure the corresponding args object, which reflects the encapsulation and extensibility of the code.
To this code is done, we look at the results of the run, the results are as follows.
Get remote Info----> Movie (chname: Spy Shadow 5, Enname:jason Bourne, type: English, Digital: original, releasedate:1471881600000, Duration:123, price:49, Screenings:{18:15=false, 22:30=true})
Process finished with exit code 0
7. Summary
Finally, we'll start by using the IDL provided by thrift to write two thrift files, one for the movie entity and the other for Movieoperator to provide a service interface to generate Java code from the command. After the client has specified the transport mode and transport protocol, it invokes the Movieoperator client to interact with the server. The service side first realizes the Movieoperator Iface interface, compiles the concrete realization code MOVIEOPERATORIMPL, then puts the Movieoperatorimpl into the Movieoperator processor management, It then specifies the server type, transfer mode, and transport protocol corresponding to the client and instantiates the server object, finally starting the service and listening on the specified port.
This example source download http://download.csdn.net/detail/roderick2015/9613104
Tips:
If you put the thrift generated code into the project, the following figure shows the problem, your JDK compiled version is too low, in 1.5 does not really use this.
You can refer to the following two pictures, change to a higher version of the line.