Kafka: 基于 NestJS 的微信小程序问卷系统后端开发实战

实战目标与技术架构


1 ) 核心目标

开发微信小程序后端服务,实现问卷模板获取、结果上报与统计功能,并通过 Kafka Producer 将问卷数据推送至消息队列,供大数据平台实时分析。

2 ) 技术栈:

  • 后端框架:NestJS(替代原 Spring Boot)
  • 消息队列:Kafka
  • 数据传输:HTTPS(微信小程序强制要求)
  • 数据格式:JSON

3 ) 关键流程:

  1. 前端请求问卷模板 → 后端返回动态模板(JSON 格式)。
  2. 用户提交问卷 → 后端通过 Kafka Producer 将结果发送至 Kafka Topic。
  3. 大数据平台(如 Flink/Spark)消费数据并生成统计结果。

注:本实战聚焦 Kafka Producer 集成,统计结果接口暂用本地文件模拟,实际需对接实时计算平台。

接口设计与业务逻辑


三个核心接口(HTTPS 协议):

  1. 获取问卷模板

    • 请求:GET /survey/template
    • 响应:
      {
        "requestId": "UUID",
        "result": {
          "templateId": "T001",
          "questions": [
            {
              "id": "Q1",
              "content": "您最近去过哪些城市?",
              "options": ["北京", "上海", "广州", "深圳"]
            },
            // 更多问题...
          ]
        }
      }
      
  2. 提交问卷结果

    • 请求:POST /survey/submit
    • 参数:
      {
        "templateId": "T001",
        "results": [
          { "questionId": "Q1", "answer": "北京" },
          // 更多答案...
        ]
      }
      
    • 关键动作:数据通过 Kafka Producer 发送至 Topic survey-results
  3. 获取统计结果(模拟实现)

    • 请求:GET /survey/statistics?templateId=T001
    • 响应:
      {
        "requestId": "UUID",
        "result": {
          "templateName": "疫情行程调查",
          "totalSubmissions": 100,
          "details": [
            { "questionId": "Q1", "A": 10, "B": 50, "C": 12, "D": 17 },
            // 更多统计...
          ]
        }
      }
      

工程结构搭建与依赖配置


项目目录:

src/
├── common/              # 公共模块
│   ├── dto/             # 数据传输对象
│   ├── utils/           # 工具类
│   └── filters/         # 过滤器(如跨域处理)
├── survey/              # 问卷业务模块
│   ├── controller/      # 控制器
│   ├── service/         # 服务层 
│   └── kafka/           # Kafka 生产者配置 
└── main.ts              # 入口文件

依赖安装:

# 核心依赖
npm install @nestjs/common @nestjs/core @nestjs/microservices
# Kafka 支持
npm install kafkajs @nestjs/microservices
# 文件操作与 JSON 处理
npm install fs-extra fast-json-stringify

核心代码实现


1 ) 统一响应格式(DTO)

// src/common/dto/base-response.dto.ts 
export class BaseResponseDto<T> {
  requestId: string;  // 请求唯一标识
  result?: T;         // 业务数据
 
  static success<T>(result?: T): BaseResponseDto<T> {
    const response = new BaseResponseDto<T>();
    response.requestId = this.generateRequestId();
    response.result = result;
    return response;
  }
 
  private static generateRequestId(): string {
    return Math.random().toString(36).substring(2, 15);
  }
}

2 ) Kafka 生产者服务

// src/survey/kafka/survey-producer.service.ts
import { Injectable, OnModuleInit } from '@nestjs/common';
import { Kafka, Producer, ProducerRecord } from 'kafkajs';
 
@Injectable()
export class SurveyProducerService implements OnModuleInit {
  private producer: Producer;
 
  async onModuleInit() {
    const kafka = new Kafka({
      brokers: ['localhost:9092'], // Kafka 集群地址
      clientId: 'survey-service',
    });
    this.producer = kafka.producer();
    await this.producer.connect();
  }
 
  async sendSurveyResult(record: ProducerRecord) {
    await this.producer.send(record);
  }
 
  async onApplicationShutdown() {
    await this.producer.disconnect();
  }
}

3 ) 问卷提交接口(集成 Kafka)

// src/survey/controller/survey.controller.ts
import { Body, Controller, Post } from '@nestjs/common';
import { SurveyProducerService } from '../kafka/survey-producer.service';
import { BaseResponseDto } from '../../common/dto/base-response.dto';
 
@Controller('survey')
export class SurveyController {
  constructor(private readonly producer: SurveyProducerService) {}
 
  @Post('submit')
  async submitSurvey(@ // 发送数据至 Kafka
    await this.producer.sendSurveyResult({
      topic: 'survey-results',
      messages: [{ value: JSON.stringify(data) }],
    });
 
    return BaseResponseDto.success();
  }
}

工程示例:Kafka 生产者三种集成方案


1 ) 方案 1:同步发送(确保消息顺序)

// 在 SurveyProducerService 中添加
async sendSync(topic: string, message: any) {
  await this.producer.send({
    topic,
    messages: [{ value: JSON.stringify(message) }],
  });
}

2 ) 方案 2:异步批量发送(高性能)

// 在 SurveyProducerService 中添加
private batchMessages: Array<ProducerRecord> = [];
 
async sendBatch() {
  if (this.batchMessages.length > 0) {
    await this.producer.sendBatch({
      topicMessages: this.batchMessages,
    });
    this.batchMessages = [];
  }
}
 
queueMessage(topic: string, message: any) {
  this.batchMessages.push({
    topic,
    messages: [{ value: JSON.stringify(message) }],
  });
  if (this.batchMessages.length >= 100) { // 批量阈值
    this.sendBatch();
  }
}

3 ) 方案 3:事务性发送(数据一致性)

// 初始化事务生产者
const transactionalProducer = kafka.producer({
  transactionalId: 'survey-transactional-producer',
});
 
await transactionalProducer.connect();
await transactionalProducer.transaction().run(async ({ send }) => {
  await send({
    topic: 'survey-results',
    messages: [{ value: JSON.stringify(data) }],
  });
  // 其他事务操作(如数据库更新)
});

Kafka 运维命令与配置


1 ) 创建 Topic

kafka-topics.sh --create \
  --bootstrap-server localhost:9092 \
  --replication-factor 1 \
  --partitions 3 \
  --topic survey-results

2 ) NestJS 微服务配置(main.ts)

// src/main.ts
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { AppModule } from './app.module';
 
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
 
  // 连接 Kafka
  app.connectMicroservice<MicroserviceOptions>({
    transport: Transport.KAFKA,
    options: {
      client: { brokers: ['localhost:9092'] },
      consumer: { groupId: 'survey-consumer' },
    },
  });
 
  await app.startAllMicroservices();
  await app.listen(3000);
}
bootstrap();

关键优化与注意事项


  1. HTTPS 与域名:

    • 使用 Nginx 反向代理 NestJS 服务,配置 SSL 证书。
    • 微信小程序要求所有接口必须通过 HTTPS 访问。
  2. 数据安全:

    • 敏感字段加密(如用户 ID)。
    • Kafka 启用 SASL/SSL 认证。
  3. 性能优化:

    • Kafka 批量发送 减少网络开销(见方案 2)。
    • 使用 compression.type 参数启用消息压缩(如 gzip)。
  4. 错误处理:

    • 实现 Kafka 消息重试机制:
      await producer.send({
        topic: 'survey-results',
        messages: [...],
        retry: { retries: 3 } // 最多重试 3 次
      });
      

术语解释:

  • Kafka Topic:消息的分类通道(如 survey-results)。
  • Producer:消息生产者,负责向 Kafka 发送数据。
  • Consumer:消息消费者,从 Kafka 读取数据(如 Spark/Flink 作业)。

总结

本文完整实现了基于 NestJS 的微信小程序后端服务,重点集成了 Kafka Producer 实现问卷数据异步上报,并通过三种工程方案(同步、批量、事务)满足不同场景需求。

确保接口符合微信小程序 HTTPS 规范。开发者可扩展统计模块对接实时计算平台(如 Flink),构建完整的数据处理链路

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Wang's Blog

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

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

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

打赏作者

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

抵扣说明:

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

余额充值