我的应用程序由Apache Thrift连接的PHP客户端和Java后端组成,我遇到了Thrift线程池的问题。 如果我运行PHP测试,通过Thrift向后端发送请求,我得到一个异常
TSocket: timed out reading 4 bytes from localhost:34567
同时我在Java端的日志中看到以下内容:
java.util.concurrent.RejectedExecutionException: Task org.apache.thrift.server.TThreadPoolServer$WorkerProcess@17a0d6f rejected from java.util.concurrent.ThreadPoolExecutor@80080[Running, pool size = 50, active threads = 50, queued tasks = 0, completed tasks = 0]
因此,从我的角度来看,这意味着单线程同步PHP应用程序使用所有已配置的线程(50),这很奇怪。 我使用Apache Thrift 0.9.0,PHP 5.4.13和Java 1.7.0_45
Java服务器代码:
public class ThriftServer implements TransportServer {
private static Logger logger = LoggerFactory.getLogger(ThriftServer.class);
private final TServer server;
private final SprootService service;
private final int port;
public ThriftServer(Integer thriftPort) throws IOException, ThriftException, ConfigurationException, ConfigValidationException {
this.service = new SprootService();
this.port = thriftPort;
try {
TProcessor processor = new TSprootService.Processor<SprootService>(service);
TServerSocket socket = new TServerSocket(port);
TBinaryProtocol.Factory protocolFactory = new TBinaryProtocol.Factory(true, true);
ThreadPoolServerArgs targs = new ThreadPoolServerArgs(socket, processor, protocolFactory, 5, 50);
this.server = new TThreadPoolServer(targs);
} catch (TTransportException tte) {
throw new ThriftException("Exception has occured during attempt to create Thrift server on port " + port, tte);
}
}
public void start() {
logger.info("Thrift server is started on port " + port);
System.out.println("Thrift server is started on port " + port);
server.serve();
}
}
PHP客户端代码:
class SprootClient {
private $thriftClient = null;
private $mappersRegistry = null;
private $tSocket = null;
public function __construct($host, $port) {
$this->thriftClient = $this->initThriftClient($host, $port);
$this->mappersRegistry = new MappersRegistry();
}
public function __destruct() {
$this->tSocket->close();
}
private function initThriftClient($host, $port) {
settype($port, 'integer');
$this->tSocket = new TSocket($host, $port);
$this->tSocket->setRecvTimeout(3000);
try {
$this->tSocket -> open();
$protocol = new TBinaryProtocol($this->tSocket);
return new TSprootServiceClient($protocol);
} catch (Exception $e) {
throw new SprootClientException($e->getMessage()." ".$e->getTraceAsString());
}
}
private function getThriftClient() {
return $this->thriftClient;
}
public function put($cacheName, $key, $domainObject) {
if ($domainObject == null || $key == null) {
throw new SprootClientException("Both key and value cannot be null or empty");
}
try {
$mapper = $this->mappersRegistry->getDomainMapper($cacheName);
$dataObject = $mapper->toTDataObject($domainObject);
$this->getThriftClient()->put($cacheName, $key, $dataObject);
} catch (Exception $e) {
throw new SprootClientException($e->getMessage()." ".$e->getTraceAsString());
}
}