关于Ebay的架构之一Asynchrony Everywhere

13-08-30 jhr820520
各位jdon的老大,小弟新手一名,最近在学习一些架构方面的知识,在看到一篇关于Ebay技术架构的文章,其中关于Asynchrony Everywhere这一点,至于说优点是提高了系统的可用性和伸缩性,我能明白,但是关于如何实现的?我苦苦思索了几天以及查相关的资料,都未能找到答案,所以想请教下jdon的各位高手。

举例:
比如我公司目前为运营商做的终端商城项目,其中用户下单的流程:

用户下单请求 <-> 前端控制层 <-> 业务逻辑层 <-> 同步调用 <-> 订单接口服务 <-> 数据层

以上即为目前用户下单的处理流程,业务逻辑层使用同步的方式调用接口服务,直到订单接口服务响应或者超时。
查看了很多资料说加入消息队列的机制,即可实现异步。首先将用户的下单请求添加消息队列中,然后接口服务从消息队列中获取请求消息进行处理。我不明白的是:
1、前端系统在将请求添加到队列后,是一直在等待响应,还是返回处理结果,如果是等待,那和同步的本质上没区别,如果是返回结果,那下单是否成功也不得而知。
2、接口服务如何将处理结果返回给前端系统,还是将响应消息放入消息队列中实现吗?还有就是异步的缘故,如何将响应与请求对应起来?

由于小弟不擅长于文档描述,有点小乱,请各位将就下,谢谢!!!












jhr820520
2013-08-30 14:30
呼叫banq,带动下气氛

banq
2013-08-30 15:14
2013-08-30 12:26 "@jhr820520
"的内容
前端系统在将请求添加到队列后,是一直在等待响应,还是返回处理结果,如果是等待,那和同步的本质上没区别,如果是返回结果,那下单是否成功也不得而知。 ...


这里面有一个误解,认为异步就慢于同步,异步后才能并行并发,利用多CPU的并行并发处理要比同步串联处理无疑性能要提升多。

消息加入队列后,是等待返回处理结果,假设后面的处理步骤分三步,如果是同步,那么轮流等这1 2 3三步依次串联处理完成才返回结果,而后面处理三个步骤如果并行并发同时处理,无疑快得多。

只有能够加入异步的地方,才有可能实现并行并发。这应该是到处异步的核心意义,主要目的是从设计上解耦,从执行顺序上进行切分。

jhr820520
2013-08-30 16:26
多谢banq的回复!

是不是我对这个异步的理解上有误区啊?
我起初认为的异步方式,如ajax的异步请求,浏览器发送请求,无需锁定用户操作,异步返回结果后接着处理。
据banq大大的回复中说,异步处理也是要请求方一直等待响应的,那么异步主要是实现了将请求进行切分,进行并发处理(请求拆分成多个消息,放到消息队列中,然后消费者一个个快速的读取出消息,使用多线程进行并发处理,最后将结果再合并,最终返回)吗?
我对细节上仍有很多不明白的地方?
banq或者其他朋友,请问大家是否有DEMO或者现成的案例提供下?我想学习下。

banq
2013-08-30 16:56
2013-08-30 16:26 "@jhr820520
"的内容
请求拆分成多个消息,放到消息队列中,然后消费者一个个快速的读取出消息,使用多线程进行并发处理,最后将结果再合并,最终返回 ...


将一个请求放在队列中,多个消费者同时读取各自并行处理即可,案例参考Disruptor,或者本站Jdon框架的应用案例:http://www.jdon.com/jdonframework/app.htm

jhr820520
2013-09-03 14:54
2013-08-30 16:56 "@banq
"的内容
将一个请求放在队列中,多个消费者同时读取各自并行处理即可,案例参考Disruptor,或者本站Jdon框架的应用案例:http://www.jdon.com/jdonframework/app.htm ...


banq老师,不好意思,由于最近工作上事太多,没及时回复您。
今天下载了jdonMVC+CQRS+ES的例子。
其中ES的代码片段如下:

@[author][author]Send[/author][/author]("created")
public DomainMessage created(UserCreatedEvent event) {
	return new DomainMessage(event);
}

@[author][author]Send[/author][/author]("updated")
public DomainMessage updated(UserUpdatedEvent event) {
	return new DomainMessage(event);
}
<p class="indent">

调用ES的代码片段

public void update(UserUpdatedEvent userUpdatedEvent) {
	if (!userUpdatedEvent.getNewUserDTO().getUserId().equals(this.userId)) {
		System.err.print("update not this user");
		return;
	}
	this.name = userUpdatedEvent.getNewUserDTO().getName();
	this.email = userUpdatedEvent.getNewUserDTO().getEmail();
	this.es.updated(userUpdatedEvent);
}
<p class="indent">

想请教您的问题是:
这个例子中的异步事件处理都是没有返回值的情况,如:this.es.updated(userUpdatedEvent);
当然,jdon的框架如此强大,支持异步事件处理有返回值必然不在话下的。
如上面的代码改为:

Object result = this.es.updated(userUpdatedEvent);
......
......
return result;
<p class="indent">

那么在result返回之前,当前处理应该是wait的状态,直到结果返回后再继续执行后面的代码,类似于线程的wait和notify机制。
这里我厚颜做回伸手党,想请banq老师讲讲,jdon的异步事件框架是如何处理的?
1、当前的处理如何进入wait状态?wait超时怎么处理?
2、事件event放到消息队列后等待处理,多个消费者不停的读取并行处理,那么就会产生很多的结果,结果是否会放在另外一个消息队列中?由于是异步处理,结果如何能够正确的返回给对应的请求?
麻烦banq老师提供点具体实现的代码或是将实现的原理讲讲。谢谢!!






jhr820520
2013-09-04 09:11
banq老师,看过来看过来看过来,这里的小弟在等待!!!

banq
2013-09-04 11:18
2013-09-03 14:54 "@jhr820520
"的内容
这个例子中的异步事件处理都是没有返回值的情况,如:this.es.updated(userUpdatedEvent); ...


返回值也是使用一个Disruptor实现的,也就是消息队列,这实际类似ErLang或Scala的进程信箱。

Model producer ==>队列===> consumer
返回值:
Model consumer <===队列 <===consumer/producer

但是由于模型有自己的逻辑处理顺序,不能在某个地方永久堵塞等待返回结果,这里有一个值,大概默认5秒。如果超过5秒等不到返回值,下次再取,取到后在自己对象状态内保存起来,可以参考JdonMVC+JDON案例中懒赋值显示图片的过程。

希望能够帮到你。

[该贴被banq于2013-09-04 11:19修改过]

jhr820520
2013-09-04 11:40
2013-09-04 11:18 "@banq
"的内容
返回值也是使用一个Disruptor实现的,也就是消息队列,这实际类似ErLang或Scala的进程信箱。 ...


一直在等待您的回复,呵呵。
我会按照您提供的思路,试着去实现看看,多谢banq老师!!