Catalog
I. Preface
Because of the need of work, when using thrift to realize rpc, considering that the cost of creating and destroying connections is relatively large, I think of making a connection pool for thrift clients. Each time I use thrift clients, I only need to get a connection from the pool, and then put it back when I use up, so that the program can reuse a few connections without creating and destroying connections every time I visit To improve system performance.
On the Internet, there are some ways to build a thrift client connection pool with org.apache.commons.pool2. Because I am not familiar with springboot, I have some difficulties in integrating the three. Fortunately, I solved them at the end. Here is a record.
2, thrift server
This part of the content is relatively simple, there are many online tutorials, here is a brief mention.
First, write a thrift file
struct DebugResponse{ 1: required i32 code; 2: required string message; } service DebugService{ DebugResponse debug(1:string id,2:string data); }
Then use thrift.exe to automatically generate java files, put them in the project, and write business logic
public class DebugServiceImpl implements DebugService.Iface { private Logger logger = LoggerFactory.getLogger(DebugServiceImpl.class); @Override public DebugResponse debug(String id, String data) throws TException { //Realize your business logic here logger.info("get a new request"); return new DebugResponse(0, id + "*-*-*" + data); } }
Then write the server startup program
public static void main(String[] args) { try { TProcessor tProcessor = new DebugService.Processor<DebugService.Iface>(new DebugServiceImpl()); TNonblockingServerSocket socket = new TNonblockingServerSocket(6868); TThreadedSelectorServer.Args args = new TThreadedSelectorServer.Args(socket); args.processor(tProcessor); args.transportFactory(new TFramedTransport.Factory()); args.protocolFactory(new TBinaryProtocol.Factory()); TServer server = new TThreadedSelectorServer(args); } catch (Exception e) { } System.out.println("debug server start..."); server.serve(); }
3, thrift client connection pool
The methods on the Internet are similar. I've added some features of springboot
Introducing pom dependency
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.5.0</version> </dependency>
Objects that need to be pooled
The object to be pooled is thrift's TTransport.
Object factory
To create a factory, you only need to inherit BasePooledObjectFactory and override some functions.
Because each time you create TTransport, you need to specify parameters such as ip and port, so here you use the automatic injection function @ ConfigurationProperties(prefix = "debug.thrift") of springboot. In this way, you don't need to write the configuration in the code. You can complete the configuration by adding debug.thrift.host=XX.XX.XX.XX in the configuration file app.properties.
@ConfigurationProperties(prefix = "debug.thrift") @Component public class DebugConnectionFactory extends BasePooledObjectFactory<TTransport> { private String host = "localhost"; private int port = 6868; private int timeOut = 10000; public void setHost(String host) { this.host = host; } public void setPort(int port) { this.port = port; } public void setTimeOut(int timeOut) { this.timeOut = timeOut; } @Override public TTransport create() throws Exception { TTransport tTransport = new TFramedTransport(new TSocket(host, port, timeOut)); if (!tTransport.isOpen()) { tTransport.open(); } return tTransport; } @Override public boolean validateObject(PooledObject<TTransport> p) { return p.getObject().isOpen(); } @Override public PooledObject<TTransport> wrap(TTransport tTransport) { return new DefaultPooledObject<>(tTransport); } @Override public void destroyObject(PooledObject<TTransport> p) throws Exception { //The function here is to ensure that when the client is shut down, the server will not report an error if (p.getObject().isOpen()) { p.getObject().close(); } } }
app.properties configuration file
debug.thrift.host=XX.XX.XX.XX debug.thrift.port=12321 debug.thrift.timeOut=30000
Object pool
It inherits GenericObjectPool directly, because the object we pooled is TTransport, and we prefer to get the Client, so we add two methods of getting and recycling
public class DebugConnectionPool extends GenericObjectPool<TTransport> { public DebugConnectionPool(PooledObjectFactory<TTransport> factory) { super(factory); } public DebugConnectionPool(PooledObjectFactory<TTransport> factory, GenericObjectPoolConfig config) { super(factory, config); } public DebugConnectionPool(PooledObjectFactory<TTransport> factory, GenericObjectPoolConfig config, AbandonedConfig abandonedConfig) { super(factory, config, abandonedConfig); } //Get public DebugService.Client getClient() throws Exception { TTransport tTransport = this.borrowObject(); TProtocol tProtocol = new TBinaryProtocol(tTransport); return new DebugService.Client(tProtocol); } //recovery public void releaseConnection(DebugService.Client client) { TTransport tTransport = client.getInputProtocol().getTransport(); // TTransport tTransport = client.getOutputProtocol().getTransport(); //Because when we declare it is new DebugService.Client(tProtocol), the two protocols here are the same. Choose one this.returnObject(tTransport); } }
Configuration class of object pool
From the above construction method, we can see that in addition to passing in a factory, the object pool can also pass in a configuration class, so I inherited the GenericObjectPoolConfig object pool configuration class
@ConfigurationProperties(prefix = "debug.pool") @Component public class PoolConfig extends GenericObjectPoolConfig { }
As before, because @ ConfigurationProperties(prefix = "debug.pool") is added, configuration can be added to the configuration file app.properties. When writing the configuration file, the idea will also prompt us which properties can be configured.
Spring configuration class
To use DebugConnectionPool as an object pool in Spring, you need to add a configuration class and declare @ Bean
@Configuration public class PoolAutoConfiguration { @Bean public DebugConnectionPool debugConnectionPool(PoolConfig poolConfig, DebugConnectionFactory debugConnectionFactory) { //This must be set here. Otherwise, spring boot will report an error that a bean has been registered poolConfig.setJmxEnabled(false); return new DebugConnectionPool(debugConnectionFactory, poolConfig); } }
Four, use
At this point, all the preparations are completed. To use it, just inject DebugConnectionPool
@Autowired DebugConnectionPool debugConnectionPool; @Test public void testPool() throws Exception { DebugService.Client client = debugConnectionPool.getClient(); DebugResponse debug = client.debug("test_id", "data"); System.out.println(debug.toString()); debugConnectionPool.releaseConnection(client); }
Five, summary
In fact, many people have written a tutorial about thrift client connection pool, but I just want to use the spring boot auto injection configuration feature in my mind, so I spent the whole afternoon tossing about, and the final result is satisfied though the function is simple.
I seldom write blog myself. Please point out the wrong place.