为了提高系统吞吐率,也就是提高生产效率,核心观点如下,系统设计也是如此
在微服务或任何其他基于事件的架构(event-driven-architecture)中,在一些用例中,一个服务可能需要我们对他们自己的本地数据库进行修改,同时发布一个事件。然后,该事件会被其他服务所消费。为了拥有一个一致的软件系统,这两个动作必须以原子方式执行。这两个动作都需要成功完成,或者都不需要完成。不应该有其他方法。 电商网站的事件驱动型架构(event-driven-architecture)示例。此架构使网站能够对需求峰值期间的各种来源变动做出反应,而不会导致应用程序崩溃或过度预置资源:
解决这个问题的一个优雅方法是使用收件箱模式(Outbox Pattern)。它通过使用一个数据库表(如果你的服务使用关系型数据库),通常称为发件箱表,来存储这些事件。在这种情况下,你能够将事件的插入SQL语句纳入用例本地事务。另一个运行器可以定期检查收件箱表是否为空,并通过将事件发布到消息代理中来处理这些事件。社区已经实现了一个Java库,称之为JQueue,它使这种模式的实现更加容易。JQueue使用关系型数据库表实现了一个FIFO数据结构,所以目前,如果你的服务的数据库是关系型的,它就可以工作。
JQueue有两个模块,推送模块和运行器模块。要把一个事件(或任务)推入队列,你可以这样做:
JTxQueue.queue(/*a JDBC Data Source or a JDBC Connection */)
.push(
"{/"type/": /"job_type1/", /"event/":{/"id/": /"an id/", /"value/": /"/" }}");
请注意,作为一个参数,你必须传递当前在你的本地事务中正在使用的数据源或连接。在这种情况下,如果你的事务被提交,推送也将被提交。如果任何事情失败了,一切都会被回滚。你推入队列的事件或任务可以是任何文本。然后,为了从队列中消费事件或任务,你必须写一些类似这样的东西:
JQueueRunner.runner(/* a JDBC DataSource */)
.executeAll(new Job() {
@Override
public void run(String data) {
//do something with data
}
});
上面的代码将在一个循环中逐一处理队列中的所有条目,直到它是空的。它将读取队列数据并调用Job接口的一个实例,你必须提供该实例来做你需要的任何数据。这可能是将一个消息推送到消息代理中,或者只是调用任何其他的外部服务API。你可以使用任何调度器库(比如Quartz)来安排JQueue运行器,以所需的频率来保持队列为空。
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/293333.html