【问题标题】:Perform service multiplexing with Apache Thrift and TServlet使用 Apache Thrift 和 TServlet 执行服务多路复用
【发布时间】:2014-07-26 15:40:06
【问题描述】:

我有一个系统(带有 Spring 框架的 Java),它使用 TServlet 类通过 HTTP 公开 7 个不同的 Apache Thrift servlet。目前,它们都需要自己的 Servlet、ServletMappings、处理器、处理程序等,因此实现客户端还必须为不同服务保留所有各种 URL 的内部列表。

我知道 Apache Thrift 在使用 TServer 及其衍生产品时支持多路复用 TMultiplexingProcessor,但是由于我使用的是 Spring,并且我的 Servlet、Handler 和 Processor 都是 Spring Bean,它们会自动连接到彼此中,所以我'我不确定如何继续。

以下是其中一项服务如何连接的示例:

UserServiceHandler.java

@Component
public class UserServiceHandler implements UserService.Iface {
    @Override
    public User getUser(String userId) throws TException {
        // implementation logic goes here
    }
}

UserServiceProcessor.java

@Component
public class UserServiceProcessor extends UserService.Processor<UserServiceHandler> {

    private UserServiceHandler handler;

    @Autowired
    public UserServiceProcessor(UserServiceHandler iface) {
        super(iface);
        handler = iface;
    }

    public UserServiceHandler getHandler() {
        return handler;
    }

    public void setHandler(UserServiceHandler handler) {
        this.handler = handler;
    }

}

UserServiceServlet.java

@Component
public class UserServiceServlet extends TServlet {
    private UserServiceProcessor processor;

    @Autowired
    public UserServiceServlet(UserServiceProcessor p) {
        super(p, new TBinaryProtocol.Factory());
        processor = p;
    }
}

Servlet 注册

ServletRegistration.Dynamic userService = servletContext.addServlet("UserServiceServlet", (UserServiceServlet) ctx.getBean("userServiceServlet"));
userService.setLoadOnStartup(1);
userService.addMapping("/api/UserService/*");
// This same block repeated 7 times for each *ServiceServlet with different mappings

我想让所有 7 个服务处理程序都映射到单个 URL,例如 /api/*。这甚至可能吗?我想我必须创建一个 servlet 和处理器,但我不确定它们应该是什么样子。我的处理器扩展 UserService.Processor 等。

【问题讨论】:

    标签: java spring servlets thrift


    【解决方案1】:

    好的,想通了。可能不是最好的方法,所以我欢迎批评。

    这是我的粗略步骤:

    1. 保持处理程序类原样。
    2. 创建一个扩展TMultiplexedProcessor的新类
    3. 创建一个扩展TServlet的新类
    4. 所有处理器(例如 UserServiceProcessor 具有 handler 属性和相应的 getter 和 setter

    这是我的ApiMultiplexingProcessor

    @Component
    public class ApiMultiplexingProcessor extends TMultiplexedProcessor {
    
        UserServiceHandler userServiceHandler;
        ReportServiceHandler reportServiceHandler;
        // ... more service handlers can go here
    
        @Autowired
        public ApiMultiplexingProcessor(UserServiceProcessor userServiceProcessor, ReportServiceProcessor reportServiceProcessor) {
            this.registerProcessor("UserService", userServiceProcessor);
            this.registerProcessor("ReportService", reportServiceProcessor);
            // add more registerProcessor lines here for additional services
    
            userServiceHandler = userServiceProcessor.getHandler();
            reportServiceHandler = reportServiceProcessor.getHandler();
            // set any additional service handlers here
        }
    
        // getters and setters for the handlers
    
        public UserServiceHandler getUserServiceHandler() {
            return userServiceHandler;
        }
    
        public void setUserServiceHandler(UserServiceHandler userServiceHandler) {
            this.userServiceHandler = userServiceHandler;
        }
    
        public ReportServiceHandler getReportServiceHandler() {
            return reportServiceHandler;
        }
    
        public void setReportServiceHandler(ReportServiceHandler reportServiceHandler) {
            this.reportServiceHandler = reportServiceHandler;
        }
    }
    

    所以稍微解释一下,如果你添加任何额外的服务,你需要在这个类上添加 *ServiceHandler 类作为字段,并创建 getter 和 setter 等。

    现在我们有了它,我们可以创建一个新的单个 servlet,将其添加到 servlet 上下文中。

    这是我的ApiServlet

    @Component
    public class ApiServlet extends TServlet {
        private ApiMultiplexingProcessor processor;
    
        @Autowired
        public ApiServlet(ApiMultiplexingProcessor p) {
            super(p, new TBinaryProtocol.Factory());
            processor = p;
        }
    }
    

    然后您只需像以前一样将此 servlet 添加到 servlet 上下文(来自 bean):

    ServletRegistration.Dynamic api = servletContext.addServlet("ApiServlet", (ApiServlet) ctx.getBean("apiServlet"));
    api.setLoadOnStartup(1);
    api.addMapping("/api/*");
    // yay now we have a single URL and a single servlet
    

    这一切都可能对我这种情况的其他人有所帮助,所以享受吧!

    附:确保在调整客户端时使用TMultiplexedProtocol,以便在与服务器通信时传递服务名称,例如

    TTransport transport = new THttpClient(new Uri("https://myapp.com/api/"));
    TProtocol protocol = new TBinaryProtocol(transport);
    TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "UserService");
    UserService.Client userServiceClient = new UserService.Client(mp);
    

    【讨论】:

      猜你喜欢
      • 2013-11-06
      • 1970-01-01
      • 2017-07-23
      • 1970-01-01
      • 2018-06-08
      • 2014-06-03
      • 1970-01-01
      • 2021-09-12
      • 2014-02-26
      相关资源
      最近更新 更多