golang实现kafka的消息推送
Kafka的安装与启动
kafka中涉及的名词
- 消息记录:由一个key,一个value和一个时间戳构成,消息最终存储在主题下的分区中,记录在生产中称为生产者记录,在消费者中称为消费记录。Kafka集群保持了所有发布的消息,直到它们过期,无论消息是否被消费了,在一个可配置的时间段内,Kafka集群保留了所有发布的消息。比如消息的保存策略被设置为2天,那么在一个消息被发布的两天时间内,它都是可以被消费的。Kafka的性能是和数据量无关的常量级的,所以保留太多数据并不是问题
- 生成者:生产者用于发布消息
- 消费者:消费者用于订阅消息
- 消费者组:相同的groupID的消费者将视为同一个消费者组,每个消费者都需要设置一个组id,每条消息只能被consumer group中的一个Consumer消费,但是可以被多个consumer group消费
- 主题(topic):消息的一种逻辑分组,用于对消息分门别类,每一类消息称之为一个主题,相同主题的消息放在一个队列中
- 分区(partition):消息的一种物理分组,一个主题被拆成多个分区,每一个分区就是一个顺序的,不可变的消息队列,并且可以持续添加,分区中的每个消息都被分配了一个唯一的id,称之为偏移量(offset),在每个分区中偏移量都是唯一的。每个分区对应一个逻辑log,有多个segment组成
- 偏移量:分区中每个消息都有一个唯一的Id,称之为偏移量,代表已经消费的位置
- 代理(broker):一台kafka服务器称之为一个broker
- 副本(replica):副本只是一个分区(partition)的备份。副本不读取或写入数据。它们用于防止数据丢失
- 领导者:leader是负责给定分区的所有读取和写入的节点
- 追随者:跟随领导者指令的节点被称为Follower。
- zookeeper:Kafka代理是无状态的,所以它们使用Zookeeper来维护它们的集群状态。Zookeeper用于管理和协调Kafka代理
kafka功能
- 发布订阅:生产者生产消息(数据流),将消息发送给kafka指定的主题队列中,也可以发送到topic中的指定分区中,消费者从kafka的指定队列中获取消息,然后来处理消息
一. Mac版安装
brew install kafka
安装kafka需要依赖zookeeper的,所以安装kafka的时候也会包含zooker
- kafka的安装目录:/usr/local/Cellar/kafka
- kafka的配置文件目录:/usr/local/etc/kafka
- kafka服务的配置文件:/usr/local/etc/kafka/server.properties
- zookeeper配置文件:/usr/local/etc/kafka/zookeeper.properties
server.properties中重要配置
- broker.id=0
- listeners=PLAINTEXT://:9092
- advertised.listeners=PLAINTEXT://127.0.0.1:9092
- log.dirs=/usr/local/var/lib/kafka-logs
zookeeper.properties重要配置
- dataDir=/usr/local/var/lib/zookeeper
- clientPort=2181
- maxClientCnxns=0
二. 启动zookeeper
新创建终端启动zookeeper
- cd /usr/local/Cellar/kafka/2.1.0
- ./bin/zookeeper-server-start /usr/local/etc/kafka/zookeeper.properties
- 打印台显示:INFO Reading configuration from: /usr/local/etc/kafka/zookeeper.properties (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
- ...即是启动成功
三.启动kafka
新创建终端启动kafka(启动kafka之前必须先启动zookeeper)
- cd /usr/local/Cellar/kafka/2.1.0
- ./bin/kafka-server-start /usr/local/etc/kafka/server.properties
- 打印台显示:INFO Registered kafka:type=kafka.Log4jController MBean (kafka.utils.Log4jControllerRegistration$)
- ...即启动成功
- 启动了kafka之后,zookeeper端会报一些Error:KeeperErrorCode = NoNode for /config/topics/test之类的错误,这个是没有问题的,这是因为kafka向zookeeper发送了关于该路径的一些请求信息,但是不存在,所以这是没有问题的
四.创建topic
新创建终端
- cd /usr/local/Cellar/kafka/2.1.0
- 创建一个名为“test”的主题:./bin/kafka-topics --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
- 查看所有的topic:./bin/kafka-topics --list --zookeeper localhost:2181
- 查看某个topic的信息,比如test:./bin/kafka-topics --describe --zookeeper localhost:2181 --topic test
五.发送消息
新创建一个终端,作为生产者,用于发送消息,每一行就是一条信息,将消息发送到kafka服务器
- cd /usr/local/Cellar/kafka/2.1.0
- ./bin/kafka-console-producer --broker-list localhost:9092 --topic test
- send one message
- send two message
六.消费消息(接受消息)
新创建一个终端作为消费者,接受消息
- cd /usr/local/Cellar/kafka/2.1.0
- ./bin/kafka-console-consumer --bootstrap-server localhost:9092 --topic test --from-beginning
- send one message
- send two message(这些便是从生产者获得的消息)
注意:发送消息与接受消息必须启动kafka与zookeeper
GoLang实现kafka的信息发布与订阅
生产者
import (
"fmt"
"github.com/Shopify/sarama"
)
func main() {
config := sarama.NewConfig()
// 等待服务器所有副本都保存成功后的响应
config.Producer.RequiredAcks = sarama.WaitForAll
// 随机的分区类型:返回一个分区器,该分区器每次选择一个随机分区
config.Producer.Partitioner = sarama.NewRandomPartitioner
// 是否等待成功和失败后的响应
config.Producer.Return.Successes = true
// 使用给定代理地址和配置创建一个同步生产者
producer, err := sarama.NewSyncProducer([]string{"localhost:9092"}, config)
if err != nil {
panic(err)
}
defer producer.Close()
//构建发送的消息,
msg := &sarama.ProducerMessage {
//Topic: "test",//包含了消息的主题
Partition: int32(10),//
Key: sarama.StringEncoder("key"),//
}
var value string
var msgType string
for {
_, err := fmt.Scanf("%s", &value)
if err != nil {
break
}
fmt.Scanf("%s",&msgType)
fmt.Println("msgType = ",msgType,",value = ",value)
msg.Topic = msgType
//将字符串转换为字节数组
msg.Value = sarama.ByteEncoder(value)
//fmt.Println(value)
//SendMessage:该方法是生产者生产给定的消息
//生产成功的时候返回该消息的分区和所在的偏移量
//生产失败的时候返回error
partition, offset, err := producer.SendMessage(msg)
if err != nil {
fmt.Println("Send message Fail")
}
fmt.Printf("Partition = %d, offset=%d\n", partition, offset)
}
}
消费者
import (
"fmt"
"github.com/Shopify/sarama"
"sync"
)
var (
wg sync.WaitGroup
)
func main() {
// 根据给定的代理地址和配置创建一个消费者
consumer, err := sarama.NewConsumer([]string{"localhost:9092"}, nil)
if err != nil {
panic(err)
}
//Partitions(topic):该方法返回了该topic的所有分区id
partitionList, err := consumer.Partitions("test")
if err != nil {
panic(err)
}
for partition := range partitionList {
//ConsumePartition方法根据主题,分区和给定的偏移量创建创建了相应的分区消费者
//如果该分区消费者已经消费了该信息将会返回error
//sarama.OffsetNewest:表明了为最新消息
pc, err := consumer.ConsumePartition("test", int32(partition), sarama.OffsetNewest)
if err != nil {
panic(err)
}
defer pc.AsyncClose()
wg.Add(1)
go func(sarama.PartitionConsumer) {
defer wg.Done()
//Messages()该方法返回一个消费消息类型的只读通道,由代理产生
for msg := range pc.Messages() {
fmt.Printf("%s---Partition:%d, Offset:%d, Key:%s, Value:%s\n", msg.Topic,msg.Partition, msg.Offset, string(msg.Key), string(msg.Value))
}
}(pc)
}
wg.Wait()
consumer.Close()
}
kafka使用场景
kafka的应用很广泛,在这里简单介绍几种
服务解耦
比如我们发了一个帖子,除了写入数据库之外还有很多联动操作,比如给关注这个用户的人发送通知,推送到首页的时间线列表,如果用代码实现的话,发帖服务就要调用通知服务,时间线服务,这样的耦合很大,并且如果增加一个功能依赖发帖,除了要增加新功能外还要修改发帖代码。
解决方法:引入kafka,将发完贴的消息放入kafka消息队列中,对这个主题感兴趣的功能就自己去消费这个消息,那么发帖功能就能够完全独立。同时即使发帖进程挂了,其他功能还能够使用,这样可以将bug隔离在最小范围内
流量削峰
流量削峰在消息队列中也是常用场景,一般在秒杀或团购活动中使用比较广泛。当流量太大的时候达到服务器瓶颈的时候可以将事件放在kafka中,下游服务器当接收到消息的时候自己去消费,有效防止服务器被挤垮
- 消息通讯
消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯中,比如客户端A跟客户端B都使用同一队列进行消息通讯,客户端A,客户端B,客户端N都订阅了同一个主题进行消息发布和接受不了实现类似聊天室效果
golang实现kafka的消息推送的更多相关文章
- Knative 实战:基于 Kafka 实现消息推送
作者 | 元毅 阿里云智能事业群高级开发工程师 导读:当前在 Knative 中已经提供了对 Kafka 事件源的支持,那么如何基于 Kafka 实现消息推送呢?本文作者将以阿里云 Kafka 产品为 ...
- 用kafka实现消息推送
一个人知道的Topic是单点推送,大家都知道Topic是广播. kafka消息消费机制: 1.广播消费:通过定义topic前缀来标识属于广播的消息(例如:topicname:gonggao153568 ...
- 利用Kafka的Assign模式实现超大群组(10万+)消息推送
引言 IM即时通信场景下,最重要的一个能力就是推送:在线的直接通过长连接网关服务转发,离线的通过APNS或者极光等系统进行推送. 本文主要是针对在线用户推送场景来进行总结和探讨:如何利用Kafka ...
- 异步tcp通信——APM.Server 消息推送服务的实现
消息推送服务 服务器推送目前流行就是私信.发布/订阅等模式,基本上都是基于会话映射,消息对列等技术实现的:高性能.分布式可以如下解决:会话映射可采用redis cluster等技术实现,消息对列可使用 ...
- 实现websocket 主动消息推送,用laravel+Swoole
近来有个需求:想实现一个可以主动触发消息推送的功能,这个可以实现向模板消息那个,给予所有成员发送自定义消息,而不需要通过客户端发送消息,服务端上message中监听传送的消息进行做相对于的业务逻辑. ...
- 我有 7种 实现web实时消息推送的方案,7种!
技术交流,公众号:程序员小富 大家好,我是小富- 我有一个朋友- 做了一个小破站,现在要实现一个站内信web消息推送的功能,对,就是下图这个小红点,一个很常用的功能. 不过他还没想好用什么方式做,这里 ...
- SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)
SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=>提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/si ...
- 【原创分享·微信支付】C# MVC 微信支付之微信模板消息推送
微信支付之微信模板消息推送 今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...
- 基于SignalR的消息推送与二维码描登录实现
1 概要说明 使用微信扫描登录相信大家都不会陌生吧,二维码与手机结合产生了不同应用场景,基于二维码的应用更是比较广泛.为了满足ios.android客户端与web短信平台的结合,特开发了基于Singl ...
随机推荐
- scvmm sdk之powershell(一)
shell表示计算机操作系统中的壳层,与之相对的是内核,内核不能与用户直接交互,而是通过shell为用户提供操作界面,shell分为两类,一种提供命令行界面,一种提供图形界面.windows powe ...
- ffmpeg学习(一)——在window7下编译ffmpeg
FFmpeg是一个开源免费跨平台的视频和音频流项目,它提供了录制.转换以及流化音视频的完整解决方案.本文作者将尝试使用该库实现一个可适应复杂网络环境的, 支持标准rtsp协议的流媒体服务器.由于Vis ...
- linux free命令下 cached占用很大
# 背景 使用free -h命令,展示如下: # 解决方法 先执行sync命令,同步数据 然后执行 echo 1 > /proc/sys/vm/drop_caches echo 2 > / ...
- Net系列框架-Dapper+AutoFac 基于接口
Net系列框架-Dapper+AutoFac 基于接口 工作将近6年多了,工作中也陆陆续续学习和搭建了不少的框架,后续将按由浅入深的方式,整理出一些框架源码,所有框架源码本人都亲自调试通过,如果有问题 ...
- Java50道经典习题-程序9 求完数
题目:一个数如果恰好等于它的因子之和,这个数就称为"完数".例如6=1+2+3.编程找出1000以内的所有完数. public class Prog9 { public stati ...
- Java50道经典习题-程序18 乒乓球赛
题目:两个乒乓球队进行比赛,各出三人.甲队为a,b,c三人,乙队为x,y,z三人.已抽签决定比赛名单.有人向队员打听比赛的名单. a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单.分析: ...
- 【Oracle 12c】最新CUUG OCP-071考试题库(55题)
55.(13-3) choose the best answer: Which statement is true regarding the SESSION_PRIVS dictionary vie ...
- 玩PHP必了解的PHP常用符号和函数
原文:http://y312ff.blog.163.com/blog/static/12701109420119119575812/ 近在写PHP程序的时候发现了一些特殊的PHP符号,例如连续小于符号 ...
- canvas图像绘制过程中的注意
特别来记录一下canvas绘制图像,要在图片加载完后,才会将其显示在canvas画布之上,否则会显示不出来:深刻体会,愣是找不到问题... var c=document.getElementById( ...
- python3.6使用scrapy报错
用python做爬虫的,肯定熟悉scrapy,不过新手安装总是会遇到各种奇葩错误. 错误一:building 'twisted.test.raiser' extensionerror: Microso ...