一.背景
在企业数字化运营与系统集成的大背景下,数据的 “实时接入 - 高效流转 - 可靠存储” 已成为支撑业务响应、数据分析、系统联动的核心诉求。各类业务系统(如前端应用、IoT 设备、第三方服务、内部微服务)产生的实时数据(用户行为、设备状态、交易请求、业务事件等),需要通过标准化接口快速接入,并实时分发至下游系统(如实时计算引擎、数据仓库、监控平台),以满足业务对低延迟、高可靠数据流转的需求。
传统数据接入方案存在明显痛点:一方面,数据接入方式碎片化(如文件上传、定时推送、直连数据库),缺乏统一的接口标准,导致接入成本高、兼容性差;另一方面,数据接收后直接落地数据库或本地文件,无法支撑下游系统的实时消费需求,且单点故障易导致数据丢失,难以满足高可用、高吞吐的业务要求。此外,多源数据的并发写入、峰值流量的缓冲、数据传输的一致性等问题,也让传统方案难以适配规模化的业务场景。
在此背景下,“HTTP/GRPC 接口 + Go + Kafka” 的技术架构成为解决上述痛点的最优选择,各环节形成互补、构建起高效的数据流转闭环:
- 标准化接口作为数据接入层:通过 HTTP/GRPC 等通用接口对外提供统一的数据接收能力,适配不同来源(前端、设备、第三方系统)的接入需求,支持 JSON/Protobuf 等主流数据格式,解决数据接入碎片化问题,降低上游系统的对接成本;
- Go 作为接口服务开发语言:Go 语言具备天生的高并发、低延迟、轻量级特性,能够高效处理海量接口请求,同时拥有完善的网络编程库和 Kafka 客户端生态,可快速实现接口逻辑与 Kafka 生产端的集成;其编译型语言的特性也保障了服务的高性能与稳定性,适配高吞吐的实时数据接入场景;
- Kafka 作为数据分发枢纽:Kafka 凭借高吞吐、高可用、持久化存储、消息分区与副本机制的核心优势,成为实时数据流分发的标准组件。接口接收的数据写入 Kafka 后,可实现数据的缓冲(应对流量峰值)、可靠存储(副本机制避免数据丢失)、多下游消费(支持订阅 - 发布模式),解决了数据实时分发与高可用的核心诉求。
采用 Go 实现 “接口接收数据写入 Kafka” 的方案,本质是构建一套 “统一接入 - 高效处理 - 可靠分发” 的实时数据流转通道。该方案可广泛应用于用户行为数据采集、IoT 设备状态上报、业务事件实时推送、微服务间数据同步等场景:
- 对互联网业务而言,可实时采集用户点击、浏览、下单等行为数据,支撑实时推荐、用户画像更新;
- 对工业物联网场景,可接收设备传感器的实时状态数据,写入 Kafka 后供实时监控、故障预警系统消费;
- 对企业内部系统,可作为跨部门数据交换的统一通道,避免系统间直连带来的耦合与稳定性问题。
此外,Go 语言的跨平台特性、简洁的语法体系,以及 Kafka 成熟的生态工具链(如监控、扩容、数据回溯),也让该方案具备易部署、易维护、可扩展的特性,能够适配从初创业务到大型企业级场景的不同需求,帮助企业打通数据流转的 “最后一公里”,为实时数据驱动的业务决策提供坚实支撑。
二.具体实现
1.创建go工程,创建Http2Kafka.go,并引入依赖
import (
"encoding/json"
"fmt"
"github.com/Shopify/sarama"
"github.com/gin-gonic/gin"
"gopkg.in/yaml.v2"
"io/ioutil"
"net/http"
)
2.定义json转换函数
func MapToJson(param map[string]interface{}) string {
dataType, _ := json.Marshal(param)
dataString := string(dataType)
return dataString
}
3.定义配置文件init.yaml
system:
port: "http端口"
kafka:
addr: 'kafka地址'
topic: 'topic'
4.初始化配置
fmt.Printf("HttpServer start \n")
//读取初始化配置
initConfig := make(map[string]interface{})
file, err := ioutil.ReadFile("init.yaml")
if err != nil {
panic(err)
}
err = yaml.Unmarshal(file, initConfig)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(initConfig)
//进行kafka生产初始化
config := sarama.NewConfig()
//等待服务器所有副本都保存成功后的响应
config.Producer.RequiredAcks = sarama.WaitForAll
//随机向partition发送消息
config.Producer.Partitioner = sarama.NewRandomPartitioner
//是否等待成功和失败后的响应,只有上面的RequireAcks设置不是NoReponse这里才有用.
config.Producer.Return.Successes = true
config.Producer.Return.Errors = true
//设置使用的kafka版本,如果低于V0_10_0_0版本,消息中的timestrap没有作用.需要消费和生产同时配置
//注意,版本设置不对的话,kafka会返回很奇怪的错误,并且无法成功发送消息
config.Version = sarama.V2_1_0_0
5.初始化kafka生产者
fmt.Println("start build producer")
//使用配置,新建一个异步生产者
producer, _ := sarama.NewAsyncProducer([]string{initConfig["kafka"].(map[interface{}]interface{})["addr"].(string)}, config)
6.定义http接口,接收数据并写入kafka
router := gin.Default()
//构建post接口服务
router.POST("/pushAppsflyerData", func(c *gin.Context) {
json := make(map[string]interface{})
c.BindJSON(&json)
//写入kafka
msg := &sarama.ProducerMessage{
Topic: initConfig["kafka"].(map[interface{}]interface{})["topic"].(string),
}
msg.Value = sarama.ByteEncoder(string(MapToJson(json)))
producer.Input() <- msg
select {
case <-producer.Successes():
//fmt.Printf("offset: %d, timestamp: %s", suc.Offset, suc.Timestamp.String())
c.JSON(http.StatusOK, gin.H{
"code": 200,
"data": "",
"info": "成功",
})
case fail := <-producer.Errors():
fmt.Printf("err: %s\n", fail.Err.Error())
c.JSON(http.StatusOK, gin.H{
"code": 500,
"data": fail.Err.Error(),
"info": "失败",
})
}
})
router.Run(":" + initConfig["system"].(map[interface{}]interface{})["port"].(string))
943

被折叠的 条评论
为什么被折叠?



