- comet服务器,维持客户端长链接,netty
- web服务器,客户端选择comet服务器,netty
- admin服务器,消息发送,netty
- zookeeper服务发现curator
- redis存储jedis
- nginx路由web和admin服务器
- http调用unirest
- supervisor进程监控
- maven exec运行进程
- 自定义二进制协议
- 消息加密
|----------------------------|
| nginx |
|____________________________|
|----------o-----------| |------------| |------------|
| socket port | | | | |
| | | | | |
| Comet | | Web | | Admin |
| | | | | |
| rpc[http] port | | http port | | http port |
|__________o___________| |______o_____| |______o_____|
/|\ |
|-------------------------------------|
|------------------------------------------------------|
| zookeeper cluster |
|------------------------------------------------------|
|--------| |--------| |--------| |---------| |--------|
| | | | | | | | | |
| meta | | user | | route | | message | | topic |
| redis | | redis | | redis | | redis | | redis |
| | | | | | | | | |
|________| |________| |________| |_________| |________|
- 外网IP端口, 监听客户端长链接请求
- 内网IP端口,提供内网Http RPC服务(发送消息)
- 7w长链接 < 0.6G内存[优化后]
/------io--------\ /---worker---\
------acceptor----/--------io---------\_____main processor----/----worker----\______
------acceptor----\--------io---------/ /|\ \----worker----/ |
\-------io--------/ | \---worker---/ |
| |
| |
|-------------------------------|
- 内网IP端口
/------io---------
------acceptor----/--------io---------
------acceptor----\--------io---------
\-------io---------
- comet进程各20台
- web/admin进程各4个
- zookeeper实例1个
- nginx实例1个
- dns映射到10台机器的外网IP
- deviceId
- clientId
- 私有消息
- 主题消息
command = auth|get_topic_list|unsubscribe|subscribe|get_message_list|heartbeat
response = ok|error|topic_list|message_list|message
auth = msg_len{short} + msg_type_auth{byte} + client_id{string} + token{string}
exchange_key = msg_len{short} + msg_type_exchange_key{byte} + secret_key{bytes}
get_topic_list = msg_len{short} + msg_type_get_topic_list{byte}
get_message_list = msg_len{short} + msg_type_get_message_list{byte}
unsubscribe = msg_len{short} + msg_type_unsubscribe{byte} + topics_size{byte} + topics{string[len]}
subscribe = msg_len{short} + msg_type_subscribe{byte} + topics_size{byte} + topics{string[len]}
heatbeat = msg_len{short} + msg_type_hearbeat{byte}
ok = response_len{short} + response_type_ok{byte}
error = response_len{short} + response_type_error{byte} + error_code{byte} + reason{string}
auth_success = response_len{short} + response_type_auth_success{byte} + encrypt_key{bytes}
topic_list = response_len{short} + response_type_topic_list{byte} + topics_size{byte} + topics{string[len]}
message_list = response_len{short} + response_type_message_list{byte} + messages_size{byte} + messages{message_struct[len]}
message = response_len{short} + response_type_message{byte} + body{message_struct}
message_struct = type{byte} + id{string} + job_id{string} + timestamp{long} + encrypted_content{bytes}
string = len[short] + byte{len}
bytes = len[short] + byte[len]
- 所有链接的用户 Set[Channel]
- 已认证的用户 Map[ClientId, ClientInfo] ClientInfo{appId, topics, messages, channel}
- [主题消息]缓存 Map[MessageId, MessageInfo] MessageInfo{type, id, content, timestamp}
- 应用列表 Map[AppKey, AppInfo], Map[AppId, AppInfo] AppInfo{id, key, secret, name}
- 命令队列 BlockingQueue[ProtocolCommand]
prefix{1} + serverId{2} + sequence{5} + timestamp{8}
- 设备device_id采用taobao deviceId,这个由客户端生成
- 用户client_id前缀c
- 私有消息message_id前缀p
- 主题消息message_id前缀m
- token直接uuid
- 应用列表apps用hash存储{appkey=>appinfo{json}}
- 设备到clientId的映射 [device_id, app_id] => client_id
- clientId到设备的映射 client_id => [device_id, app_id]{json}
- 路由映射 client_id => server_id
- 消息体 message_id => messageinfo{json} 过期1天
- 主题消息体 zset{message_id => timestamp}
- 用户的消息列表 client_id => messageid{join(',')} 过期1天
- 用户订阅的主题 client_id => topic_names{join(',')}
- 主题订阅用户列表 [app_id,topic_name,server_id] => zset{client_id=>timestamp}
- meta redis
- message redis 30G
- topic redis 80G
- user redis 50G
- route redis 10G
- 不需要安全机制的可以直接访问web节点获取token
- 需要安全机制保障的由第三方应用程序提供
- 第三方会分配appkey appsecret
- client通过第三方app代理来获取token
- 第三方需要拿appkey和appsecret以及device_id到admin节点拿token
- token有效期7天,客户端需要缓存起来
client => business app => admin server
|| ||
\||/ \||/
\/ \/
comet server ======> redis server{token=>client_id}
- 应用程序扩容,直接增加节点即可
- 存储扩容,这个得离线进行
永久保持沉默
- 维持user_name和client_id的关系 user_name=>client_id[] client_id => user_name
- 定向发送消息 提供client_id,msg_type,content定向发送
- 发送主题消息 先存消息得到msg_id,再提供msg_id,topic_name,app_key广播消息
- git clone git@192.168.6.70:qianwenpin/hipush.git
- 安装maven
- 安装supervisor
- 安装redis-server,用默认端口6379启动
- 安装zookeeper,用默认端口2181启动
- 修改supervisor/dev.conf中的192.168.1.106 改成你自己的ip地址
- mkdir /tmp/hipush
- mkdir /data/logs/hipush
- 执行mvn compile
- 执行supervisord -c supervisor/dev.conf
- 执行supervisorctl -c supervisor/dev.conf 打开 http://ip:8081 hipush/hipush 访问管理后台