Lagom框架中的JDBC读侧支持详解

Lagom框架中的JDBC读侧支持详解

lagom Reactive Microservices for the JVM lagom 项目地址: https://gitcode.com/gh_mirrors/la/lagom

概述

在Lagom微服务框架中,读侧(Read-Side)处理是实现CQRS(命令查询职责分离)架构的关键部分。本文将深入讲解Lagom如何通过JDBC支持关系型数据库的读侧处理,包括数据查询和事件处理机制。

读侧数据库查询

服务实现可以通过JDBC从关系型数据库中检索数据,Lagom提供了JdbcSession来简化这一过程。

import com.lightbend.lagom.javadsl.persistence.jdbc.JdbcSession;

public class BlogServiceImpl implements BlogService {
    
    private final JdbcSession jdbcSession;
    
    @Inject
    public BlogServiceImpl(JdbcSession jdbcSession) {
        this.jdbcSession = jdbcSession;
    }
    
    @Override
    public ServiceCall<NotUsed, List<PostSummary>> getPostSummaries() {
        return request -> jdbcSession.withConnection(connection -> {
            try (PreparedStatement ps = connection.prepareStatement(
                "SELECT id, title FROM blogsummary ORDER BY created DESC LIMIT 10")) {
                
                ResultSet rs = ps.executeQuery();
                List<PostSummary> summaries = new ArrayList<>();
                while (rs.next()) {
                    summaries.add(new PostSummary(rs.getString("id"), rs.getString("title")));
                }
                return summaries;
            }
        });
    }
}

关键点说明:

  1. JdbcSession通过依赖注入获取,它管理连接池和事务
  2. withConnection方法处理阻塞JDBC调用,返回CompletionStage以异步执行
  3. 所有JDBC操作都在专用线程池中执行,避免阻塞主线程

读侧更新处理

为了将持久化实体产生的事件转换为可查询的数据库表,我们需要实现ReadSideProcessor

基本结构

import com.lightbend.lagom.javadsl.persistence.jdbc.JdbcReadSide;

public class BlogEventProcessor extends ReadSideProcessor<BlogEvent> {
    
    private final JdbcReadSide jdbcReadSide;
    
    @Inject
    public BlogEventProcessor(JdbcReadSide jdbcReadSide) {
        this.jdbcReadSide = jdbcReadSide;
    }
    
    @Override
    public ReadSideHandler<BlogEvent> buildHandler() {
        // 构建处理器
    }
    
    @Override
    public PSequence<AggregateEventTag<BlogEvent>> aggregateTags() {
        // 返回事件标签
    }
}

事件标签实现

@Override
public PSequence<AggregateEventTag<BlogEvent>> aggregateTags() {
    return BlogEvent.TAG.allTags();
}

构建读侧处理器

使用JdbcReadSide.builder创建处理器构建器:

JdbcReadSide.ReadSideHandlerBuilder<BlogEvent> builder = 
    jdbcReadSide.builder("blogsummaryoffset");

构建器会自动管理事务和读侧偏移量。偏移量存储在Lagom自动创建的read_side_offsets表中,表结构如下:

CREATE TABLE read_side_offsets (
  read_side_id VARCHAR(255), 
  tag VARCHAR(255),
  sequence_offset bigint, 
  time_uuid_offset char(36),
  PRIMARY KEY (read_side_id, tag)
)

全局准备回调

全局准备回调用于创建表和准备初始数据,它在整个集群中只执行一次。

private void createTable(Connection connection) throws SQLException {
    try (PreparedStatement ps = connection.prepareStatement(
        "CREATE TABLE IF NOT EXISTS blogsummary (" +
        "id VARCHAR(64) PRIMARY KEY, " +
        "title VARCHAR(256) NOT NULL, " +
        "created TIMESTAMP NOT NULL)")) {
        ps.execute();
    }
}

注册全局回调:

builder.setGlobalPrepare(this::createTable);

注意事项:

  1. 回调必须是幂等的,可能被多次执行
  2. 失败后会使用指数退避策略重试
  3. 整个集群的读侧处理会等待它成功完成

事件处理器实现

处理PostAdded事件的示例:

private void processPostAdded(Connection connection, PostAdded event) throws SQLException {
    PreparedStatement ps = connection.prepareStatement(
        "INSERT INTO blogsummary (id, title, created) VALUES (?, ?, ?)");
    ps.setString(1, event.getPostId());
    ps.setString(2, event.getContent().getTitle());
    ps.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
    ps.execute();
}

注册事件处理器:

builder.setEventHandler(PostAdded.class, this::processPostAdded);

完成处理器构建

return builder.build();

注册读侧处理器

最后需要在服务实现中注册处理器:

@Inject
public BlogServiceImpl(
    PersistentEntityRegistry persistentEntityRegistry,
    ReadSide readSide,
    JdbcSession jdbcSession) {
    
    this.persistentEntityRegistry = persistentEntityRegistry;
    this.jdbcSession = jdbcSession;
    
    // 注册事件处理器
    readSide.register(BlogEventProcessor.class);
}

最佳实践

  1. 对于生产环境,考虑手动管理表结构而非使用全局回调
  2. 确保所有数据库操作都是幂等的
  3. 合理设计表结构以优化查询性能
  4. 考虑使用批处理提高事件处理效率
  5. 监控读侧处理延迟,确保及时性

通过以上机制,Lagom提供了完整的JDBC读侧支持,使开发者能够轻松实现CQRS架构中的查询部分,同时保证了数据的一致性和系统的可扩展性。

lagom Reactive Microservices for the JVM lagom 项目地址: https://gitcode.com/gh_mirrors/la/lagom

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伍盛普Silas

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值