一个分布式异步RESTful框架原型案例代码

  介绍一个异步和分布式JAX-RS的RESTful实现案例,Jersey已经实现JAX-RS 2.0中异步分布式规范,这里使用Jersey和Spring综合如何具体实现,概念如下:

1. 不同于传统将请求分发到JAX-RS元注释的服务方法上,反而是以某种方式暂停这个操作,取代之是返回一个201或200 HTTP响应,也可以说202(表示接受)响应。

2.在响应中使用http头部中的Location设置一个重定向URL。

3.被暂停的操作应该以一种异步方式被委托执行,也就是在另外一个线程执行,一旦执行完成,响应资源应该在前面提到重定向URL中创建,以便该URL能够获得这个异步响应。

4.客户端将需要对重定向URL做一个HTTP GET操作,以获得异步响应内容,也可能是204或404,这一来请求处理的情况,如果在这段来回时间内,异步处理还没有处理结束,那么需要设置客户端人为等待几秒,或者增大服务器端处理能力。不管如何,出现错误时是可以提醒管理员或被监控检测到的。

下面我们看看关键的异步方法委托,被暂停的调用将被异步分发到一个另外一个组件处理,从JAX-RS规范来看,这个处理组件将通过反射机制调用一个普通Java类的被元注释标注的方法,也可能将查询或路径参数或其他内容作为参数传送给它。

如果我们使用一个数据网格平台建立这样一个普通Java类的提供者,那么我们能分发请求数据(包括参数请求细节和Id标识),而接受方成员将根据这些请求参数实现真正调用,响应内容也被存储在数据网格中,根据Id标识为key存储。标识Id将作为重定向URL的一部分会发回客户端。

这里的数据网格我们使用Hazelcast为案例,这是一个分布式的Map模型,它提供本地监听器监听Map,当对map进行put/get/remove操作时会触发这个监听器,这样,无论是什么请求数据加入put到这个分布式map,监听器会被触发,接受的数据将被委托给处理的组件,分发到JAX-RS标注的服务方法上。

下面是调用顺序解释:

  • 一个HTTP服务器组件将会将RESTful URI 映射到一个方法调用(REST Listener)

    • 拦截 HTTP 请求并分析请求参数和内容

    • 准备序列化请求数据结构

    • 产生 HTTP response

  • 发现组件会自动发现和注册用JAX-RS标注的元素或方法(RequestDispatcher)
    • 自动发现的 JAX-RS元注释,准备被标注的方法调用元数据(反射)
    • 映射方法调用元数据到uri匹配
    • 执行方法调用
  • Hazelcast组件能够注册本地Map的监听器,执行分布式map操作(HazelcastService)
    • 注册监听器回调函数,用于分发map操作事件。
    • 提供一个管理器,基于数据网格映射操作

使用这样的异步RESTful处理流程,我们能委托操作到分离的其他线程,也能分离到其他服务器节点,实现分布式微服务框架原型。

源代码见: GitHub

REST监听器是Netty-based 库包 Webbit,该项目作为一个原型有一些限制,主要是实现JAX RS 2.0规范的小子集:

  • 只有 JSON request/response 被消费/生产
  • 只支持 GET/POST/DELETE
  • 对于异步服务器 API AsyncResponse, 不是所有操作都支持,细节文本在 code.

 

下面是异步REST服务的一段案例,真正方法调用被委托给另外一个线程,也可能是分离的另外一个JVM异步执行:

@GET
@Path("/async")
//第一个参数必须是 @Suspended AsyncResponse 类型
//可选的第二个蚕食,是解析已经序列化的JSON请求内容
public void helloAsync(@Suspended AsyncResponse asynResponse)
{
  
  //该方法将自动在分离的线程或JVM或服务器中执行
  Object returned = invokeMySuperHeavyService();
  asynResponse.resume(returned);
  //响应已经提交,以JSON方式可以使用了
}

代码中 asyncResponse.resume(),使得响应内容提供给了重定向的URL。

 

微服务专题

异步专题

REST专题