You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS-Telegraf开发的Telegram Bot无法处理并发请求问题求助

NestJS-Telegram机器人无法并发处理请求的解决方案

问题原因

问题出在Telegraf默认的更新处理机制:它是串行处理所有 incoming 更新的。哪怕你的onRandom是异步方法,Telegraf的事件循环会等待当前方法内的异步操作完成后,才会处理下一个用户的请求。当asyncRequestToGetData耗时10秒以上时,后续请求会全部排队等待,导致机器人无法并发响应。


解决方案

方案1:开启Telegraf多Worker模式

直接在TelegrafModule的配置中添加launchOptions,指定worker数量,让Telegraf用多线程并行处理请求:

TelegrafModule.forRootAsync({
  imports: [ConfigModule],
  useFactory: (configService: ConfigService) => ({
    token: configService.get<string>('TELEGRAM_BOT_TOKEN'),
    // 开启多worker,数量可根据服务器配置调整
    launchOptions: {
      worker: 4, // 示例:启动4个并行worker
      polling: {
        timeout: 30, // 保持polling配置一致性
      },
    },
  }),
  inject: [ConfigService],
}),

这个方法能直接解决串行阻塞问题,适合IO/CPU密集型场景,无需改动业务代码。

方案2:异步解耦耗时操作(生产环境推荐)

通过任务队列将耗时操作与请求处理解耦,先回复用户“正在处理”,待任务完成后再推送结果:

  1. 安装依赖:
npm install bullmq @nestjs/bull
  1. 在AppModule中注册队列:
import { BullModule } from '@nestjs/bull';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    BullModule.forRoot({
      redis: {
        host: 'localhost',
        port: 6379,
      },
    }),
    BullModule.registerQueue({ name: 'random-task' }),
    TelegrafModule.forRootAsync({ /* 原配置 */ }),
    HttpModule,
  ],
  controllers: [AppController],
  providers: [AppUpdate, RandomTaskProcessor],
})
export class AppModule {}
  1. 创建任务处理器:
import { Processor, Process } from '@nestjs/bull';
import { Job } from 'bullmq';
import { Injectable } from '@nestjs/common';
import { Telegraf } from 'telegraf';

@Processor('random-task')
@Injectable()
export class RandomTaskProcessor {
  constructor(private readonly telegraf: Telegraf) {}

  @Process()
  async handleRandomTask(job: Job) {
    const { chatId, text } = job.data;
    try {
      const resp = await asyncRequestToGetData(text);
      await this.telegraf.telegram.sendMessage(chatId, resp);
    } catch (err) {
      await this.telegraf.telegram.sendMessage(chatId, '处理失败,请重试');
    }
  }
}
  1. 修改AppUpdate中的命令处理逻辑:
import { InjectQueue } from '@nestjs/bull';
import { Queue } from 'bullmq';

@Update()
@Injectable()
export class AppUpdate {
  constructor(@InjectQueue('random-task') private readonly randomQueue: Queue) {}

  @Command('random')
  async onRandom(@Ctx() ctx: Context) {
    // 先回复用户,避免等待感知
    await ctx.reply('正在获取数据,请稍候...');
    // 将任务加入队列异步处理
    await this.randomQueue.add({
      chatId: ctx.chat.id,
      text: ctx.message.text,
    });
  }
}

该方案能实现完全的请求-处理解耦,支持任务重试、失败告警等生产级特性。

方案3:简易后台异步处理(测试/轻量场景)

如果不想引入队列,可直接让耗时操作在后台执行,不阻塞当前请求:

@Command('random')
async onRandom(@Ctx() ctx: Context) {
  await ctx.reply('正在处理,请稍候');
  // 后台执行耗时操作,不等待完成
  (async () => {
    try {
      const resp = await asyncRequestToGetData(ctx.message.text);
      await ctx.reply(resp);
    } catch (err) {
      await ctx.reply('获取数据失败');
    }
  })();
}

注意:该方式无法保证任务持久化,应用重启时未完成的任务会丢失,仅适合简单场景。


内容的提问来源于stack exchange,提问作者Daniil Andreyevich Baunov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 11:46:05