一个分布式异步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处理流程,我们能委托操作到分离的其他线程,也能分离到其他服务器节点,实现分布式微服务框架原型。
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。