使用RxJava / Jersey2的异步RestAPI。线程问题?

时间:2015-01-27 05:00:29

标签: java asynchronous jersey-2.0 reactive-programming rx-java

我们正在使用反应式编程对REST API进行原型设计。 如图所示,我们保留3层与我们在上一代同步API设计中使用的相同;

enter image description here http://oi59.tinypic.com/339hhki.jpg

  1. 使用Jersey2实现的API层,它将处理请求/反序列化JSON并切换到服务层。
  2. 实现业务逻辑的服务层。使用反应式编程实现(RxJava)
  3. Dao Layer,用于Service Layer的持久化操作。由于我们使用CouchBase,这将使用CouchBase RxClient。
  4. 根据我的理解,流程如下:

    a) HTTP请求到来,Jersery将处理来自"容器线程池"的RequestThread内的请求/解析JSON /反序列化请求模型。

    b)使用Jersey2异步支持,RequestThread将返回Container Thread Pool,服务层将在Schedulers.computation()调度程序中执行。

    @Path("/resource")
    public class AsyncUserResource {
        @GET
        public void asyncGet(@Suspended final AsyncResponse asyncResponse) {
     
           Observable<User> user = userService.getUser(...); //this is executed using Schedulers.computation() inside Service implementation
    
    
           user.subscribe(new Observer<User>() {
    
                @Override
                public void onCompleted() { 
    
                }
    
                @Override
                public void onError(Throwable e) {
                    //handle error using ExceptionMappers
    
                }
    
                @Override
                public void onNext(User user) {
                   asyncResponse.resume(user); 
    
                }});
        }        
    
    
    }
    

    c) DAO中的任何IO操作都将使用Schedulers.io()在单独的线程中运行这些长处理操作。

    我的问题是:

    1. 在实施DAO /服务时,我是否应该在实现中隐藏正在使用的日程表(线程)。
    2. 例如Dao:

      public interface UserDao {
        public Observable<User> getUser();
      }
      

      在实施中,最好是如下指定计划;

      public Observable<User> getUser() {
      
              Observable<User> ret = Observable.create((subscriber)->{
                  try {
      
                       //Do DB call
                       User u = null;
                       subscriber.onNext(u);
                       subscriber.onCompleted();
      
                  }catch (Exception e) {
                      subscriber.onError(e);  
                  }
      
              });
              return ret.subscribeOn(Schedulers.io());
      }
      

      或者简单地返回Observable是否更好,而上层将相应地使用特定的Schedular?

      1. 由于DAO主要接受io /网络呼叫,我认为应该使用Schedulars.io()。 服务层一侧的业务逻辑怎么样?它们应该在Schedulers.computation()(事件循环)中执行吗?

      2. JVM中有两个线程池。一个是#34;容器线程池&#34;另一个是&#34; RxThread Pool&#34;由Schedulers.io()使用。 如何配置RxJava的池设置/大小?

1 个答案:

答案 0 :(得分:1)

1)在RxJava本身中,如果方法需要调度程序,我们会创建两个重载:一个没有Scheduler参数,另一个带有它。前者然后使用合理的默认调度程序委托后者。这样,API使用者可以选择接受默认值或使用自己的默认值。

2)这取决于你的计算。如果计算花费相同的时间等待IO,则可以将计算移动到计算调度程序中,从而释放IO中的缓存工作线程以执行更多阻塞。否则,您可以在同一个调度程序上执行业务逻辑。

3)您目前无法在RxJava中配置池大小。计算将始终使用Runtime.availableProcessors(),IO将始终充当无限制的缓存线程池。如果您可以使用事件线程跳转(意思是:它们保证是串行的,但是一个事件可以在线程1和后续的线程2上执行),您可以通过Schedulers.from()使用您自己的ExecutorServices。