利用Kafka的Assign模式实现超大群组(10万+)消息推送
引言
问题背景


问题分解
1)长连接网关要支持10万+用户在线
2)群ID到成员列表的转换
3)长连接网关之间的路由通信问题
解决方案
1)连接池


2)kafka实现
方式一:使用consumer group



方式二:使用assign,手动订阅所有分区,不使用consumer group

consumer group vs assign模式
- 优点:分区的管理通过group自动实现,不用考虑新分区创建、新消费者加入等等情况。在kafka中还能很方便的看到每一个消费者的消费情况。
- 缺点:受限于云产品的group数量限制,再加上k8s动态启动容器,故需要开发额外的group name分配服务来动态分配提前创建好的group name。
- 优点:不需要创建consumer group,简单方便。
- 缺点:由于是程序自己管理分区,故 kafka tools 等工具上看不到消费情况,消息堆积情况等等。另外如果新增分区,要么重启程序,要么程序中定时拉取,kafka需要预先就估算创建好分区数量,有一定难度。
Assign模式代码实现
assign模式由来
- subscribe:为consumer自动分配partition,有内部算法保证topic-partition以最优的方式均匀分配给同group下的不同consumer
// Subscribe to the given list of topics to get dynamically assigned partitions.
void subscribe(Collection<String> topics, ConsumerRebalanceListener listener)
- assign:为consumer手动、显示的指定需要消费的topic-partitions,不受group.id限制,相当于指定的group无效(this method does not use the consumer's group management)
// Manually assign a list of partitions to this consumer.
void assign(Collection<TopicPartition> partitions)

go中代码实现
package main import (
"context"
"sync"
"time" "github.com/Shopify/sarama"
) type ConsumerHandler func(partition int32, partitionConsumer sarama.PartitionConsumer, message *sarama.ConsumerMessage) func NewConsumer(addrs []string, config *sarama.Config) (sarama.Consumer, error) {
if config == nil {
config = sarama.NewConfig()
// Aliyun kafka version 2.2.0
config.Version = sarama.V2_0_0_0
}
return sarama.NewConsumer(addrs, config)
} // Consume start consume, will block until exit, call in `goroutine`
// note: `handle` called in `goroutine`
func Consume(ctx context.Context, consumer sarama.Consumer, topic string, handle ConsumerHandler) error {
defer consumer.Close() // 获取所有分区
partitions, err := consumer.Partitions(topic)
if err != nil {
return err
} // 消费所有分区
waitGroup := sync.WaitGroup{}
for k, part := range partitions {
p, err := consumer.ConsumePartition(topic, part, sarama.OffsetNewest)
if err != nil {
return err
} waitGroup.Add(1)
go func(partition int32, partitionConsumer sarama.PartitionConsumer) {
defer waitGroup.Done()
defer partitionConsumer.AsyncClose() for {
select {
case <-ctx.Done():
return
case m := <-partitionConsumer.Messages():
handle(partition, partitionConsumer, m)
default:
time.Sleep(time.Millisecond)
}
}
}(int32(k), p)
}
waitGroup.Wait()
return nil
}
main.go中使用:
func main() {
// create and start consumer
consumer, err := NewConsumer(kafkaAddr, nil)
if err != nil {
panic(err)
}
for {
log.Println("consumer is running...")
// will block
err := Consume(context.Background(), consumer, topic, func(partition int32, partitionConsumer sarama.PartitionConsumer, message *sarama.ConsumerMessage) {
log.Println("consumer new mq, paritition=", partition, ",topic:", message.Topic, ",offset:", message.Offset)
})
if err != nil {
log.Println(err)
} else {
log.Println("consume exit")
}
time.Sleep(time.Second * 3)
}
}
producer代码:
func startProducer(addrs []string, topic string) {
config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForAll
config.Producer.Partitioner = sarama.NewRandomPartitioner
config.Producer.Return.Successes = true
producer, err := sarama.NewSyncProducer(addrs, config)
if err != nil {
panic(err)
}
for i := 0; i < 1000; i++ {
p, offset, err := producer.SendMessage(&sarama.ProducerMessage{
Key: sarama.StringEncoder(strconv.Itoa(i)),
Value: sarama.StringEncoder("hello" + strconv.Itoa(i)),
Topic: topic,
})
if err != nil {
log.Println(err)
} else {
log.Println("produce success, partition:", p, ",offset:", offset)
}
time.Sleep(time.Second)
}
log.Println("exit producer.")
}
效果如下:


加餐:epoll和连接池的应用以及其局限
1)单体性能

- 首先客户端A和B都和Server1建立TCP长连接,建立时,Server1在内存中插入一条 `User - TcpConn` 的关系,断开时,移除一个对应的关系。
- 当B 给 A发消息时,服务端直接使用本地维护的路由表(连接池)来查找对方的soket句柄,然后Send()到对方的Tcp连接即可。
map[int64]tcp.Conn
2)水平扩展和信息孤岛

- 分布式路由表。在某个地方统一存放用户登录的节点,推送的时候倒查即可。
- 服务广播。给所有服务器广播消息,那么在该服务器上的用户自然也能收到。
总结
利用Kafka的Assign模式实现超大群组(10万+)消息推送的更多相关文章
- spring websocket 和socketjs实现单聊群聊,广播的消息推送详解
spring websocket 和socketjs实现单聊群聊,广播的消息推送详解 WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随 ...
- Knative 实战:基于 Kafka 实现消息推送
作者 | 元毅 阿里云智能事业群高级开发工程师 导读:当前在 Knative 中已经提供了对 Kafka 事件源的支持,那么如何基于 Kafka 实现消息推送呢?本文作者将以阿里云 Kafka 产品为 ...
- MPush开源消息推送系统:简洁、安全、支持集群
引言由于之前自己团队需要一个消息推送系统来替换JPUSH,一直找了很久基本没有真正可用的开源系统所有就直接造了个轮子,造轮子的时候就奔着开源做打算的,只是后来创业项目失败一直没时间整理这一套代码,最近 ...
- dwr消息推送和tomcat集群
网友的提问: 项目中用到了dwr消息推送.而服务端是通过一个http请求后 触发dwr中的推送方法.而单个tomcat中.服务器发送的http请求和用户都在一个tomcat服务器中.这样就能精准推送到 ...
- Java Socket聊天室编程(一)之利用socket实现聊天之消息推送
这篇文章主要介绍了Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 网上已经有很多利用socket实现聊天的例子了 ...
- JBoss 系列十九:使用JGroups构建块RspFilter对群组通信返回消息进行过滤
内容概述 本部分说明JGroups构建块接口RspFilter,具体提供一个简单示例来说明如何使用JGroups构建块RspFilter对群组通信返回消息进行过滤. 示例描述 我们知道构建块基于通道之 ...
- (七)RabbitMQ消息队列-通过fanout模式将消息推送到多个Queue中
原文:(七)RabbitMQ消息队列-通过fanout模式将消息推送到多个Queue中 前面第六章我们使用的是direct直连模式来进行消息投递和分发.本章将介绍如何使用fanout模式将消息推送到多 ...
- SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)
SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=>提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/si ...
- APNS IOS 消息推送沙盒模式和发布模式
在做.NET向IOS设备的App进行消息推送时候,采用的是PushSharp开源类库进行消息的推送,而在开发过程中,采用的是测试版本的app,使用的是测试的p12证书采用的是ApnsConfigura ...
随机推荐
- NC15979 小q的数列
NC15979 小q的数列 题目 题目描述 小q最近迷上了各种好玩的数列,这天,他发现了一个有趣的数列,其递推公式如下: \[f[i] = \left\{ \begin{array}{l} 0 ,&a ...
- 基于YCbCr色彩模型的简易肤色识别器
一.实验方法 实验共选取了12张图像,利用画笔工具在每幅图像上选取5个点,并分别记录RGB值.取点方式如下图所示: 总共70个点,R,G,B的值分别如下表所示: RGB色彩模型和YCbC ...
- thymeleaf实现前后端数据交换
1.前端传数据后端接收: 用户在登录界面输入用户名和密码传给后端controller,由后端判断是否正确! 在html界面中要传递的数据name命名,通过表单的提交按钮会传递给响应的controlle ...
- 千位分隔符在web开发中的作用
有千位分隔符会被认为是数字,否则在移动端会被直接识别成手机号 在开发实战中主流实现方式是添加meta标签 <meta name="format-detection" cont ...
- Git Rebase操作
概括 rebase翻译过来为"变基",可以理解为改变基础,它可以用于分支合并和修改提交记录. 合并分支的区别 我们知道merge操作也可以用于分支合并,但是其和rebase操作有着 ...
- 0基础就可以上手的Spark脚本开发-for Java
前言 最近由于工作需要,要分析大几百G的Nginx日志数据.之前也有过类似的需求,但那个时候数据量不多.一次只有几百兆,或者几个G.因为数据都在Hive里面,当时的做法是:把数据从Hive导到MySQ ...
- 7 什么是dubbo
什么是dubbo 快速入门dubbo 了解什么是dubbo之前,我们得先了解什么是分布式系统? <分布式系统原理与范型>定义: 分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像 ...
- [NOIP2015 提高组] 运输计划题解
题目链接:P2680 [NOIP2015 提高组] 运输计划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 看了好长时间题解才终于懂的,有关lca和二分答案的题解解释的不详细,一时 ...
- SQL语句实战学习
参考:https://zhuanlan.zhihu.com/p/38354000再次感谢作者的整理!! 1.数据已提前准备好了,已知有如下4张表:学生表:student 成绩表:score(学号,课程 ...
- python开发环境配置(Windows)
简介 由于在搭建pyhon开发环境时会出现各种各样的问题,因此将这些问题记录下来 1.下载python 从官网下载对应系统的python版本(最新稳定版即可):官网地址为:python下载地址, 建议 ...