首页 > 其他分享 >JQueue一个实现Outbox模式的库

JQueue一个实现Outbox模式的库

时间:2022-10-29 16:13:17浏览次数:78  
标签:架构 队列 模式 JQueue new Outbox conn 事件

    为了提高系统吞吐率,也就是提高生产效率,核心观点如下,系统设计也是如此

image

      在微服务或任何其他基于事件的架构(event-driven-architecture)中,在一些用例中,一个服务可能需要我们对他们自己的本地数据库进行修改,同时发布一个事件。然后,该事件会被其他服务所消费。为了拥有一个一致的软件系统,这两个动作必须以原子方式执行。这两个动作都需要成功完成,或者都不需要完成。不应该有其他方法。 电商网站的事件驱动型架构(event-driven-architecture)示例。此架构使网站能够对需求峰值期间的各种来源变动做出反应,而不会导致应用程序崩溃或过度预置资源:

1-SEO-Diagram_Event-Driven-Architecture_Diagram.b3fbc18f8cd65e3af3ccb4845dce735b0b9e2c54

     解决这个问题的一个优雅方法是使用收件箱模式(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运行器,以所需的频率来保持队列为空。

该运行器使用 "select for update skip locked "SQL语句,这是一些关系型数据库实现的一种新功能,用于(除其他外)在关系型表中实现队列。这是目前使JQueue在PostgreSQL v9.5+和MySQL 8.0+中工作的原因之一(JQueue对Oracle和MS SQL的支持即将到来,因为它们都支持跳过锁定功能)。

现在让我们来展示一些例子,说明你如何在本地事务中推送事件。假设你的服务创建了用户,当这种情况发生时,你需要发布NewUserEvent。 如果你的服务使用的是普通的JDBC,你可以做这样的事情:

Connection conn = connection();
try {
  conn.setAutoCommit(false);
  //your business logic first
  final PreparedStatement st = conn.prepareStatement(
         "insert into user(id, user_name, pwd, email) values(108,  'user1','anyPassword','[email protected]')");
  st.executeUpdate();

//then push an event
  JTxQueue.queue(conn)
      .push(new NewUserEvent(108, "user1", "[email protected]").toJson());

conn.commit();
} catch (SQLException | JQueueException e) {
  try {
    conn.rollback();
    throw new RuntimeException(e);
  } catch (SQLException e1) {
     throw new RuntimeException(e1);
  }
} finally {
  try {
    conn.setAutoCommit(true);
    conn.close();
  } catch (SQLException e) {
    throw new RuntimeException(e);
  }

}

而且,如果你的服务使用Spring,你可以这样做:

@RestController
@RequestMapping("/api/users")
public class UserController {
   @Autowired
   private UserRepository userRepository;

  @Autowired
   private DataSource dataSource;

  @PostMapping
   @ResponseStatus(HttpStatus.CREATED)
   @Transactional
   public User create(@RequestBody User user) throws SQLException {
     //your business logic first
     User u = userRepository.save(user);
     //then push an event
     JTxQueue.queue(dataSource)
         .push(new NewUserEvent(u.id(), u.getUserName(), u.email()).toJson());
     return u;
   }
}

在上面所有的例子中,事务包裹了你的业务逻辑,加上推入队列。

JQueue的灵感来自于Yii2 Queue这个优秀的PHP库。希望这有助于使Outbox模式的实现变得更容易和简单。


今天先到这儿,希望对云原生,技术领导力, 企业管理,系统架构设计与评估,团队管理, 项目管理, 产品管管,团队建设 有参考作用 , 您可能感兴趣的文章:
领导人怎样带领好团队
构建创业公司突击小团队
国际化环境下系统架构演化
微服务架构设计
视频直播平台的系统架构演化
微服务与Docker介绍
Docker与CI持续集成/CD
互联网电商购物车架构演变案例
互联网业务场景下消息队列架构
互联网高效研发团队管理演进之一
消息系统架构设计演进
互联网电商搜索架构演化之一
企业信息化与软件工程的迷思
企业项目化管理介绍
软件项目成功之要素
人际沟通风格介绍一
精益IT组织与分享式领导
学习型组织与企业
企业创新文化与等级观念
组织目标与个人目标
初创公司人才招聘与管理
人才公司环境与企业文化
企业文化、团队文化与知识共享
高效能的团队建设
项目管理沟通计划
构建高效的研发与自动化运维
某大型电商云平台实践
互联网数据库架构设计思路
IT基础架构规划方案一(网络系统规划)
餐饮行业解决方案之客户分析流程
餐饮行业解决方案之采购战略制定与实施流程
餐饮行业解决方案之业务设计流程
供应链需求调研CheckList
企业应用之性能实时度量系统演变

如有想了解更多软件设计与架构, 系统IT,企业信息化, 团队管理 资讯,请关注我的微信订阅号:

MegadotnetMicroMsg_thumb1_thumb1_thu[2]

作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 该文章也同时发布在我的独立博客中-Petter Liu Blog。

标签:架构,队列,模式,JQueue,new,Outbox,conn,事件
From: https://www.cnblogs.com/wintersun/p/16838947.html

相关文章

  • 状态模式
    一、前言自然界所有事物都有自己的存在状态,比如水有固态、液态、气态,三种不同的心态有着完全不一样的外在特性,我们将事物所处的某一种形态称为状态。二、状态模式概念状态模......
  • 设计模式之装饰模式
    概述装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为。在现实生活中,这种情况也到处存在,例如一张照片,可以不改变照片本身,给它增加一个相框,使得它具有......
  • 【Vue2.0学习】—路由的两种工作模式(六十六)
    【Vue2.0学习】—路由的两种工作模式(六十六)对于一个url来说,什么是hash值?#以及后面的内容就是hash值hash值不会包含在HTTP请求中,即:hash值不会带给服务器hash模式:地址中永远带......
  • 设计模式九(命令模式、解释器模式、迭代器模式、中介者模式)
    命令模式(CommandPattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传......
  • 实现云原生模式​
    云原生基础架构由应用程序来维护,而云原生应用则由基础架构来维护,两者密不可分。这就要求基础架构和应用程序设计必须是简单的。如果一个应用程序比较复杂,则应该采用微服务模......
  • 实现云原生模式
    云原生基础架构由应用程序来维护,而云原生应用则由基础架构来维护,两者密不可分。这就要求基础架构和应用程序设计必须是简单的。如果一个应用程序比较复杂,则应该采用微服务......
  • flink集群安装-Standalone模式
    1、节点规划JobManager:192.168.23.151TaskManager:192.168.23.152TaskManager:192.168.23.153TaskManager:192.168.23.1542、安装配置1)首先在一台机器上安装flink,参......
  • Python RabbitMQ pika的安装及direct路由模式的使用
    RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件,RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有......
  • 浅谈PHP设计模式的观察者模式
    简介观察者模式是行为型模式的一种,定义了对象间一对多的关系。当对象的状态发生变化时候,依赖于它的对象会得到通知。适用场景类似触发钩子事件,可做消息通知、框架底层......
  • js一键切换dark模式 -
    js一键切换dark模式//初始化$(function(){lettheme=$.cookie('theme');if(theme=="dark"){$("body").addClass('dark');$("#theme").add......