在 http://developers.facebook.com/thrift/thrift-20070401.pdf 7.1节有如下内容,
Thrift services implemented in PHP have also been embedded into the Apache web server, provid- ing transparent backend access to many of our frontend constructs using a THttpClient implementation of the TTransport inter- face.
但Thrift没有把service嵌入到Servlet中的实现。搜索了以下,有人解决了这个问题。
参见: http://www.google.com/codesearch/p?hl=en&sa=N&cd=1&ct=rc#vusEaWnOsAk/thrift/TServlet.java&q=TServlet
我只做了一点修改,其中把com.facebook.thrift改为org.apache.thrift。测试了一下,可以正常运行。
修改后的TServlet.java
package servlet; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.thrift.TException; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TIOStreamTransport; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.TTransportFactory; /** * <p> * A servlet for exposing Thrift services over HTTP. To use, create a subclass * that supplies a {@link TProcessor}. For example, * </p> * * <pre> * public class CalculatorTServlet extends TServlet { * public CalculatorTServlet() { * super(new Calculator.Processor(new CalculatorHandler())); * } * } * </pre> * <p> * This code is based heavily on {@link org.apache.thrift.server.TSimpleServer}. * </p> * * @author Tom White */ public class TServlet extends HttpServlet { protected TProcessor processor_ = null; protected TTransportFactory inputTransportFactory_ = new TTransportFactory(); protected TTransportFactory outputTransportFactory_ = new TTransportFactory(); protected TProtocolFactory inputProtocolFactory_ = new TBinaryProtocol.Factory(); protected TProtocolFactory outputProtocolFactory_ = new TBinaryProtocol.Factory(); public TServlet(TProcessor processor) { processor_ = processor; } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter w = response.getWriter(); w.write("This is a thrift service!"); w.close(); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/x-thrift"); InputStream in = request.getInputStream(); OutputStream out = response.getOutputStream(); TTransport client = new TIOStreamTransport(in, out); TProcessor processor = null; TTransport inputTransport = null; TTransport outputTransport = null; TProtocol inputProtocol = null; TProtocol outputProtocol = null; try { processor = processor_; inputTransport = inputTransportFactory_.getTransport(client); outputTransport = outputTransportFactory_.getTransport(client); inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); outputProtocol = outputProtocolFactory_ .getProtocol(outputTransport); while (processor.process(inputProtocol, outputProtocol)) { } } catch (TTransportException ttx) { // Client died, just move on } catch (TException tx) { tx.printStackTrace(); } catch (Exception x) { x.printStackTrace(); } if (inputTransport != null) { inputTransport.close(); } if (outputTransport != null) { outputTransport.close(); } } }
写一个实现自己service的servlet
UserServiceServlet.java
package servlet; import myserver.UserServiceHandler; import mytest.thrift.gen.UserService; public class UserServiceServlet extends TServlet { public UserServiceServlet() { super(new UserService.Processor(new UserServiceHandler())); } }
修改web.xml
加入如下内容
<servlet> <servlet-name>UserServiceServlet</servlet-name> <servlet-class>servlet.UserServiceServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>UserServiceServlet</servlet-name> <url-pattern>/UserService</url-pattern> </servlet-mapping>
启动tomcat
Java客户端测试
把client.java中的
TTransport transport = new TSocket("localhost", 9090);
改为
transport = THttpClient.THttpClient("http://localhost:8080/UserService")
Python客户端测试
把client.py中的
transport = TSocket.TSocket('localhost', 9090)
改为
transport = THttpClient.THttpClient("http://localhost:8080/UserService")
最后,尽管http的方式是可以工作的,这样说明了Thrift的传输协议是很容易改变的。但我想需要注意的是服务的并发能力受到了tomcat的限制。如果要追求并发能力,就要使用nonblock的传输方式。