kafka redis验证码实战 | 青训营

246 阅读3分钟

生产者代码

  1. 引入库:使用了gin库来构建Web服务器,confluent-kafka-go库来与Kafka通信,以及redis库来与Redis交互。
  2. 初始化Redis客户端:连接到本地的Redis服务。
  3. 定义主函数
    • 创建一个Gin引擎来处理HTTP请求。
    • 定义一个POST路由/sendCode,当接收到该请求时会触发验证码的生成和发送到Kafka的操作。
    • 从请求中获取电子邮件地址。
    • 生成验证码。
    • 创建一个Kafka生产者并连接到本地Kafka服务器。
    • 将验证码作为消息发送到Kafka的特定主题(在此例中,主题是电子邮件地址)。
    • 返回一个成功的JSON响应。
    • 开始运行服务器,监听8080端口。
  4. 定义生成验证码的函数:这里可以添加您自己的验证码生成逻辑。

消费者代码

  1. 引入库:与生产者相似,但不包括gin
  2. 初始化Redis客户端:连接到本地的Redis服务。
  3. 定义主函数
    • 创建一个Kafka消费者并连接到本地Kafka服务器,设置消费组ID等。
    • 订阅所有主题(使用正则表达式^.*)。
    • 无限循环读取Kafka的消息。
    • 当接收到消息时,将其打印出来。
    • 调用发送电子邮件的函数,并将验证码存储在Redis中。
    • 如果出现错误,则打印错误。
    • 关闭消费者。
  4. 定义发送电子邮件的函数
    • 定义SMTP服务器的凭据和地址。
    • 创建邮件正文。
    • 使用SMTP协议发送电子邮件。
    • 如果发送失败,则打印错误。

技术用法

  • Gin:用于构建Web服务器,处理HTTP请求和响应。
  • Kafka:用作消息队列,以异步方式传输验证码。生产者将验证码发送到队列,消费者从队列中获取并处理。
  • Redis:用作数据存储,存储验证码,以便以后进行验证或其他用途。
  • SMTP:用于发送电子邮件验证码。可以与各种电子邮件服务提供商一起使用。

生产者(发送验证码)

package main

import (
	"github.com/gin-gonic/gin"                 // 导入Gin框架
	"github.com/go-redis/redis/v8"             // 导入Redis库
	"gopkg.in/confluentinc/confluent-kafka-go.v1/kafka" // 导入Kafka库
	"net/http"
	"context"
)

var redisClient *redis.Client

func init() {
	redisClient = redis.NewClient(&redis.Options{ // 初始化Redis客户端
		Addr: "localhost:6379",
	})
}

func main() {
	r := gin.Default() // 创建Gin引擎

	// 定义POST路由来接收验证码发送请求
	r.POST("/sendCode", func(c *gin.Context) {
		email := c.PostForm("email")      // 获取邮箱地址
		code := generateCode()            // 生成验证码

		p, err := kafka.NewProducer(&kafka.ConfigMap{"bootstrap.servers": "localhost"}) // 创建Kafka生产者
		if err != nil {
			panic(err)
		}

		defer p.Close()

		// 将验证码作为消息发送到Kafka队列
		p.Produce(&kafka.Message{
			TopicPartition: kafka.TopicPartition{Topic: &email, Partition: kafka.PartitionAny},
			Value:          []byte(code),
		}, nil)

		c.JSON(http.StatusOK, gin.H{"message": "验证码发送成功"}) // 返回成功的响应
	})

	r.Run(":8080") // 运行服务器,监听8080端口
}

func generateCode() string { // 生成验证码的函数
	// 这里添加生成验证码的逻辑
	return "123456"
}

消费者(接收验证码并发送)

package main

import (
	"context" // 导入上下文库
	"fmt"
	"github.com/go-redis/redis/v8" // 导入Redis库
	"gopkg.in/confluentinc/confluent-kafka-go.v1/kafka" // 导入Kafka库
	"net/smtp" // 导入SMTP库
	"os"
)

var redisClient *redis.Client
var ctx = context.Background()

func init() {
	redisClient = redis.NewClient(&redis.Options{ // 初始化Redis客户端
		Addr: "localhost:6379",
	})
}

func main() {
	// 创建Kafka消费者
	c, err := kafka.NewConsumer(&kafka.ConfigMap{
		"bootstrap.servers": "localhost",
		"group.id":          "myGroup",
		"auto.offset.reset": "earliest",
	})

	if err != nil {
		panic(err)
	}

	c.SubscribeTopics([]string{"^.*"}, nil) // 订阅所有主题

	// 循环读取Kafka的消息
	for {
		msg, err := c.ReadMessage(-1)
		if err == nil {
			fmt.Printf("Received message on %s: %s\n", msg.TopicPartition, string(msg.Value))
			sendEmail(*msg.TopicPartition.Topic, string(msg.Value)) // 调用发送邮件的函数
			redisClient.Set(ctx, *msg.TopicPartition.Topic, string(msg.Value), 0).Err() // 将验证码存储在Redis中
		} else {
			fmt.Printf("Consumer error: %v (%v)\n", err, msg)
		}
	}

	c.Close() // 关闭消费者
}

func sendEmail(to string, code string) { // 发送邮件的函数
	from := "your-email@example.com"
	password := "your-password"

	body := "Subject: Verification Code\n\n" + "Your verification code is: " + code

	smtpHost := "smtp.example.com"
	smtpPort := "587"

	auth := smtp.PlainAuth("", from, password, smtpHost) // 创建SMTP认证

	// 使用SMTP发送邮件
	err := smtp.SendMail(smtpHost+":"+smtpPort, auth, from, []string{to}, []byte(body))
	if err != nil {
		fmt.Println("Failed to send email:", err)
	}
}

生产者部分负责接收来自Web客户端的请求,生成验证码,并将其发送到Kafka队列。消费者部分从Kafka队列读取验证码,并通过电子邮件发送给用户,然后将验证码存储在Redis中。