RRiBbit:开源事件总线EventBus框架

RRiBbit可以作为事件总线Eventbus, 能够让组件之间进行双向通讯,支持远程功能,实现失败恢复 负载平衡, SSL/TLS等支持,这也称为请求-响应总线(Request-Response-Bus).

在一个大型项目中,模块之间的依赖是一个大的挑战,传统思路使用OSGI,实际上OSGI也是一种事件总线框架。

RRiBbit相比其他框架的优点是:
1. 其他框架一般要求监听者实现特定的Listener接口,甚至执行onEvent() or onRequest() 方法,而RRiBbit只需要在方法上标注 @Listener元注解即可

2.其他框架因第一个条件需要改变源码,而RRiBbit没有必要。

3.其他框架监听者不能将结果发回发送者,如果你非要这样做,得做些黑客的工作,比如通过修改参数对象什么的,而RRiBbit的监听者方法能够返回一个POJO给发送者。

4.其他框架并不支持监听者在多个线程中,RRiBbit能够配置运行在不同线程,每个监听对应一个事件。

5.其他框架并不支持远程,只是工作在一个虚拟机中,RRiBbit监听者能够运行在其他机器上,而调用者无需任何变化。

RRiBbit的名字是来自于Request-Response-Bus。

以一个订单为例,当订单完成后,将调用PaymentService支付服务支付,而支付服务将调用MailService邮件服务发送Email,然后邮件服务将请求用户服务获得要发送邮件的邮件地址。

在没有使用事件总线时,几个服务将互相依赖,如下:


public class OrderPage {

private PaymentService paymentService;
private UserService userService;

public void submitOrder() {
Integer userId = 1;
BigDecimal amount = BigDecimal.TEN;

//依赖支付模块的支付服务
paymentService.doPayment(userId, amount);
//依赖用户模块中的用户服务
userService.registerPayment(userId, amount);
}
}


public class PaymentService {

private MailService mailService;

public void doPayment(Integer userId, BigDecimal amount) {
//Do payment...
mailService.sendPaymentEmail(userId, amount);
}
}


public class UserService {

public String getEmailAddress(Integer userId) {
return
"foo@bar.com";
}

public void registerPayment(Integer userId, BigDecimal amount) {
//Register payment in database...
}
}


public class MailService {

private UserService userService;

public void sendPaymentEmail(Integer userId, BigDecimal amount) {
String emailAddress = userService.getEmailAddress(userId);
//Send email...
}
}

虽然你秉承了面向接口编程,但是接口之间依然互相依赖,如果你有成千上万个类这样互相依赖,其维护性是多么可怕的事情。

而使用RRiBbit的事件总线(包括其他产品消息模型)则可以避免这种依赖:


public class OrderPage {

private RequestResponseBus rrb;

public void submitOrder() {
Integer userId = 1;
BigDecimal amount = BigDecimal.TEN;

//发送消息或事件
rrb.send(
"doPayment", userId, amount);
rrb.send(
"registerPayment", userId, amount);
}
}


public class PaymentService {

private RequestResponseBus rrb;

@Listener(hint=
"doPayment")
public void doPayment(Integer userId, BigDecimal amount) {
//Do payment...
rrb.send(
"sendPaymentEmail", userId, amount);
}
}


public class UserService {

@Listener(hint=
"getUserEmail")
public String getEmailAddress(Integer userId) {
return
"foo@bar.com";
}

@Listener(hint=
"registerPayment")
public void registerPayment(Integer userId, BigDecimal amount) {
//Register payment in database...
}
}


public class MailService {

private RequestResponseBus rrb;

@Listener(hint=
"sendPaymentEmail")
public void sendPaymentEmail(Integer userId, BigDecimal amount) {
String emailAddress = rrb.send(
"getUserEmail", userId);
//Send email...
}
}

文档介绍Introduction

BTW:和JdonFramework一样强大,但是JF只限于一个JVM,与其配合可以跨多个机器。
[该贴被banq于2012-07-16 09:19修改过]

弄这类 事件总线 是为了异步吧? 那假如
//依赖支付模块的支付服务
paymentService.doPayment(userId, amount);
//依赖用户模块中的用户服务
userService.registerPayment(userId, amount);

registerPayment要等到doPayment正常返回后才进行,咋办呢?

2012-07-17 10:43 "@lostalien"的内容
registerPayment要等到doPayment正常返回后才进行 ...

通过业务分析切割,找出业务上可异步并发的服务使用这样技术来实现,参考:无堵塞的并发编程

2012-07-17 11:01 "@banq"的内容
通过业务分析切割,找出业务上可异步并发的服务使用这样技术来实现 ...

明白了,要根据业务的特点来选择性的使用不同的技术