当前位置: 首页 > 知识库问答 >
问题:

Google Cloud PubSub将消息发送给多个用户(在同一订阅中)

吕宸
2023-03-14
private final static int ACK_DEAD_LINE_IN_SECONDS = 30;
private static final long POLLING_PERIOD_MS = 250L;
private static final int WINDOW_MAX_SIZE = 1000;
private static final Duration WINDOW_MAX_TIME = Duration.ofSeconds(1L);

@Autowired
private PubSubAdmin pubSubAdmin;

@Bean
public ApplicationRunner runner(PubSubReactiveFactory reactiveFactory) {
    return args -> {
        createSubscription("subscription-id", "topic-id", ACK_DEAD_LINE_IN_SECONDS);
        reactiveFactory.poll(subscription, POLLING_PERIOD_MS) // Poll the PubSub periodically
            .map(msg -> Pair.of(msg, getMessageValue(msg))) // Extract the message as a pair
            .bufferTimeout(WINDOW_MAX_SIZE, WINDOW_MAX_TIME) // Create a buffer of messages to bulk process 
            .flatMap(this::processBuffer) // Process the buffer
            .doOnError(e -> log.error("Error processing event window", e))
            .retry()
            .subscribe();
    };
}

private void createSubscription(String subscriptionName, String topicName, int ackDeadline) {
    pubSubAdmin.createTopic(topicName);
    try {
        pubSubAdmin.createSubscription(subscriptionName, topicName, ackDeadline);
    } catch (AlreadyExistsException e) {
        log.info("Pubsub subscription '{}' already configured for topic '{}': {}", subscriptionName, topicName, e.getMessage());
    }
}

private Flux<Void> processBuffer(List<Pair<AcknowledgeablePubsubMessage, PreparedRecordEvent>> msgsWindow) {
    return Flux.fromStream(
        msgsWindow.stream()
            .collect(Collectors.groupingBy(msg -> msg.getRight().getData())) // Group the messages by same data
            .values()
            .stream()
    )
    .flatMap(this::processDataBuffer);
}

private Mono<Void> processDataBuffer(List<Pair<AcknowledgeablePubsubMessage, PreparedRecordEvent>> dataMsgsWindow) {
    return processData(
        dataMsgsWindow.get(0).getRight().getData(),
        dataMsgsWindow.stream()
            .map(Pair::getRight)
            .map(PreparedRecordEvent::getRecord)
            .collect(Collectors.toSet())
    )
    .doOnSuccess(it ->
        dataMsgsWindow.forEach(msg -> {
            log.info("Mark msg ACK");
            msg.getLeft().ack();
        })
    )
    .doOnError(e -> {
        log.error("Error on PreparedRecordEvent event", e);
        dataMsgsWindow.forEach(msg -> {
            log.error("Mark msg NACK");
            msg.getLeft().nack();
        });
    })
    .retry();
}

private Mono<Void> processData(Data data, Set<Record> records) {
    // For each message, make calculations over the records associated to the data
    final DataQuality calculated = calculatorService.calculateDataQualityFor(data, records); // Arithmetic calculations
    return this.daasClient.updateMetrics(calculated) // Update DB record with a DaaS to wrap DB access
        .flatMap(it -> {
            if (it.getProcessedRows() >= it.getValidRows()) {
                return finish(data);
            }
            return Mono.just(data);
        })
        .then();
}

private Mono<Data> finish(Data data) {
    return dataClient.updateStatus(data.getId, DataStatus.DONE) // Update DB record with a DaaS to wrap DB access
        .doOnSuccess(updatedData -> pubSubClient.publish(
            new Qa0DonedataEvent(updatedData) // Publis a new event in other topic
        ))
        .doOnError(err -> {
            log.error("Error finishing data");
        })
        .onErrorReturn(data);
}

根据官方文档,一旦消息被发送给订阅者,pub/sub就会尝试不将其传递给同一订阅的任何其他订阅者(app2实例是同一订阅的订阅者):

一旦消息被发送到订阅服务器,订阅服务器应该确认该消息。消息一旦发送出去并在订阅者确认之前被视为未完成。pub/sub将反复尝试传递任何未被确认的消息。然而,当一条消息对订阅者来说是未完成的时,Pub/Sub会尝试不将它传递给同一订阅中的任何其他订阅者。订阅服务器有一个可配置的、有限的时间--称为ackDeadline--来确认未完成的消息。一旦截止日期过去,消息不再被认为是未完成的,并且pub/sub将尝试重新传递消息

暂时还没有答案

 类似资料:
  • 找到要发消息的订阅号-“群发消息”-新建群发消息 1)根据内容选择发送图文消息、文字消息、图片消息和文件消息。 2)选择群发范围,全部用户或部分用户,选择部分用户时支持选择组织机构或成员。 3)支持从素材库中选择,或直接新建图文消息。以“新建图文消息”为例: 备注:“保存”只是保存在“素材管理”里,没有发送出去,如果既要保存又要发送,请点击“保存并发送”。 4)除了图文、图片、文字消息,订阅号还可

  • 首先,我知道这里已经有一个类似问题的答案了,但我仍然不能确定这是因为RabbitMQ的不可能,还是因为我研究得不够。 我来自事件pub/sub模式是这样工作的JS/Node背景:当许多消费者用pub/sub模式订阅同一个主题时,无论何时某个生产者发布它,所有人都应该得到相同的消息。 我希望用消息代理实现相同的模式。 例如: 生产者%1发布到主题 生产者2发布到主题 RabbitMQ的实际操作(根据

  • 微信文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.addTemplate.html 组合模板并添加至帐号下的个人模板库 $tid = 563; // 模板标题 id,可通过接口获取,也可登录小程序后台查看获取 $kidLi

  • 开普勒消息目前分为三大类:公告,告警和通知。 通知中根据不同的操作事件类型,分为十几个事件。每个事件都跟项目操作相关。便于接收项目操作变更的通知。 分类 事件 公告 Alarm 告警 Proclaim 通知 Build,Apply,Audit,Delete,Rollback,Logging,Reboot,Command,Storage,Extend... 订阅界面: 用户中心,点击头像,下拉菜单→

  • 我是新的数据流和发布子工具在GCP。 需要将prem过程中的电流迁移到GCP。 当前流程如下: 我们有两种类型的数据馈送 Full Feed–其adhoc作业–完整XML的大小约为100GB(单个XML–非常复杂的一个–完整的数据–ETL作业处理此XML并将其加载到约60个表中) 单独的ETL作业用于处理完整提要。ETL作业过程完全馈送并创建负载就绪文件,所有表将被截断并重新加载 源系统每30分钟

  • 如何在一条消息中发送多个嵌入?像这样发送多个: 输出: 我找不到任何关于发送多个嵌入的文档,在discord.js文件中提到了它,发送了一个嵌入列表。虽然我试过这个,但它也不起作用。