具有单线程执行程序的RESTful Web服务的体系结构?

时间:2014-09-08 16:24:28

标签: java web-services rest lifecycle executor

我想知道什么是具有单线程执行程序的RESTful Web服务的最佳架构。

我的目标:

  1. 调用RESTful Web服务
  2. Web服务在线程队列中添加任务,并按1执行所有任务。
  3. instanciated对象的生命周期非常重要(必须有只有一个线程队列)。我知道RESTful Web服务生命周期是每个请求" (类似于我认为的@RequestScoped),所以我看到了2个选项:

    选项1:

    public class RestService {
        protected final static Executor executor;
        protected final static Implementation1 impl1;
        protected final static Implementation2 impl2;
    
        static {
            executor = Executors.newSingleThreadExecutor();
            impl1 = new Implementation1();
            impl2 = new Implementation2();
        }
    }
    
    @Path("/servicename")
    public class MyService extends RestService {
        @POST
        @Path("/compute")
        public void compute(){
            executor.execute(new Runnable(){
                public void run(){
                    impl1.compute();
                }
            });
        }
    }
    

    选项2:

    @Singleton
    public class RestService {
        private Executor executor;
        private Implementation1 impl1;
        private Implementation2 impl2;
    
        public RestService () {
            executor = Executors.newSingleThreadExecutor();
            impl1 = new Implementation1();
            impl2 = new Implementation2();
        }
    
        public void execute(Runnable run){
            executor.execute(run);
        }
    
        public Implementation1 getImplementation1(){
            return impl1;
        }
    
        public Implementation2 getImplementation2(){
            return impl2;
        }
    
    }
    
    @Path("/servicename")
    public class MyService {
    
        @Inject
        private RestService rs;
    
        @POST
        @Path("/compute")
        public void compute(){
            rs.execute(new Runnable(){
                public void run(){
                    rs.getImplementation1().compute();
                }
            });
        }
    } 
    

    对于选项1,我不确定"生命周期"关于静态领域。我应该使用哪个选项?你会怎么做?

    由于

    编辑: 选项3(由EJB容器处理的线程)和"排序"并不重要:

    @Singleton
    public class RestService {
        private final Executor executor;
        private final Implementation1 impl1;
        private final Implementation2 impl2;
    
        public RestService () {
            executor = Executors.newSingleThreadExecutor();
            impl1 = new Implementation1();
            impl2 = new Implementation2();
        }
    
        public void compute1(){
            executor.execute(new Runnable(){
                public void run(){
                    impl1.compute();
                }
            });
        }
    
        public void compute2(){
            executor.execute(new Runnable(){
                public void run(){
                    impl2.compute();
                }
            });
        }
    
    }
    
    @Path("/servicename")
    public class MyService {
    
        @Inject
        private RestService rs;
    
        @POST
        @Path("/compute1")
        public void compute1(){
            rs.compute1();
        }
    
        @POST
        @Path("/compute2")
        public void compute2(){
            rs.compute2();
        }
    } 
    

    我认为选项3仍然优于选项1& 2。

2 个答案:

答案 0 :(得分:6)

我认为这样做是个坏主意。线程应该由您的容器处理,而不是您的代码。

如果要在Java EE应用服务器上进行部署,则应该让它处理线程。

如果要在Netty或vert.x等非阻塞I / O服务器上进行部署,则应该让它处理线程。

在任何情况下都不应该管理线程。

加载.class时实例化静态字段。它们没有像实例那样的“生命周期”。在类加载器删除.class文件之前,它们不会被清理。

如果你必须有这种行为,我要么使用JMS队列来订购处理,要么使用生产者/消费者deque来管理它。您希望处理是异步的。让REST服务将令牌或收据返回给客户端,让他们回来查看处理完成的时间。如果线条很长,你将无法知道他们的衬衫什么时候准备就绪。收据让他们回来检查他们的结果何时可用。

答案 1 :(得分:0)

如果您使用Spring,然后将业务逻辑分离为单独的组件(bean)并将这些bean注入到服务类中,则只需更改业务的“范围”属性即可有效控制实现的线程模型逻辑豆。

这是description of Spring bean scopes

这种方法可以让您轻松修改/试验您的解决方案,并为您的情况找到最佳选择。

就架构而言,我建议您对系统进行分层(松散耦合,高内聚,关注点分离等)。在这方面,您可能拥有服务层(REST),业务层和数据(dao)层最小值。这些层通过接口相互交互。使用Spring将事物连接在一起(注入依赖关系)。这使您可以灵活地注入不同的实现。示例是为您的业务类注入模拟DAO以进行单元测试。 REST服务所在的服务层将执行请求/响应的转换,一些验证,确定要调用的业务组件以及调用它们。