系统介绍
mpush,是一款开源的实时消息推送系统,采用java语言开发,服务端采用模块化设计,具有协议简洁,传输安全,接口流畅,实时高效,扩展性强,可配置化,部署方便,监控完善等特点。同时也是少有的可商用的开源push推送系统。
特性和优势
- 源码全部开放,包括server、android、ios 、websocket等
- 代码质量高,全部模块化设计,真正的商用级产品,考虑到推送中遇到的大部分场景
- 安全性高,基于RSA精简的加密握手协议,简单,高效,安全
- 支持断线重连,及弱网下的快速重连,无网络下自动休眠节省电量和资源
- 协议简洁,接口流畅,支持数据压缩,更加节省流量
- 支持集群部署,支持负载均衡,基于成熟的zookeeper实现
- 用户路由使用redis集群,支持单写,双写,集群分组;性能好,可用性高
- 支持http代理,一根TCP链接接管应用大部分请求,让http请求更加及时
- 高度可配置化,基本上通过修改配置可满足大部分场景
- 扩展性强,高度模块化,基于SPI模式的可拔插设计,以满足特殊需求
- 监控完善,日志详细,可快速排查线上问题及服务调优
部署环境,这里将各个服务,分开部署,模拟分布式部署环境,各个服务器上可以根据情况进行集群方式部署。
主机IP端口Redis192.168.0.1186379Zookeeper192.168.0.1192181Mpush192.168.0.1203000Alloc192.168.0.1219999Android192.168.0.103
服务器版本为Centos7,最小化安装。
note:
1)最小化安装,默认网卡没有开机自动启动,可以编辑网卡文件(默认为ifcfg-eth0),将ONBOOT设置为yes
[root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE=Ethernet
BOOTPROTO=dhcp
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=eno16777736
UUID=a4ad8a0c-ff3a-4a49-87fe-639f0053873f
DEVICE=eno16777736
ONBOOT=yes
2)安装系统基本依赖包,用于编译安装软件
[root@localhost ~]# yum install net-tools vim wget make gcc g++ gc++ -y
3)关闭防火墙和SELinux,防止系统干扰导致部署不成功
[root@localhost ~]# setenforce 0
[root@localhost ~]# iptables -F
[root@localhost ~]# iptables -X
一、编译安装Redis
官网下载Redis包,这里下载的是3.2.3版本
1、编译安装Redis
[root@localhost ~]# mkdir /app
[root@localhost ~]# cd /app
[root@localhost ~]# wget http://download.redis.io/releases/redis-3.2.3.tar.gz
解压
[root@localhost ~]# tar xf redis-3.2.3.tar.gz
[root@localhost ~]# cd redis-3.2.3
编译Redis
[root@localhost redis-3.2.3]# make
安装Redis
[root@localhost redis-3.2.3]# make install
cd src && make install
make[1]: Entering directory `/app/redis-3.2.3/src'
Hint: It's a good idea to run 'make test' ;)
INSTALL install
INSTALL install
INSTALL install
INSTALL install
INSTALL install
make[1]: Leaving directory `/app/redis-3.2.3/src'
2、提供配置文件和基础数据目录(我这里将Redis执行文件复制出来了)
[root@localhost redis-3.2.3]# mkdir -pv /app/redis/{bin,conf,log,db}
mkdir: created directory ‘/app/redis’
mkdir: created directory ‘/app/redis/bin’
mkdir: created directory ‘/app/redis/conf’
mkdir: created directory ‘/app/redis/log’
mkdir: created directory ‘/app/redis/db’
[root@localhost redis-3.2.3]# cd src
[root@localhost src]# mv redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server /app/redis/bin/
[root@localhost src]# cd /app/redis
提供启动配置文件
[root@localhost redis]# vim conf/redis.conf
daemonize yes
protected-mode no
pidfile /var/run/redis.pid
port 6379
timeout 0
tcp-keepalive 0
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dir /app/redis/db
dbfilename dump-6379.rdb
loglevel notice
logfile /app/redis/log/redis.log
slave-serve-stale-data yes
slave-read-only yes
repl-disable-tcp-nodelay no
slave-priority 100
appendonly no
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
启动Redis服务
[root@localhost redis]# /app/redis/bin/redis-server /app/redis/conf/redis.conf
查看是否启动Redis服务,并监听指定端口
[root@localhost redis]# netstat -tplan | grep redis
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 6309/redis-server *
tcp6 0 0 :::6379 :::* LISTEN 6309/redis-server *
[root@localhost redis]# ps aux | grep redis
root 6309 0.1 0.7 136916 7572 ? Ssl 12:03 0:00 /app/redis/bin/redis-server *:6379
root 6335 0.0 0.0 112644 980 pts/0 S+ 12:08 0:00 grep --color=auto redis
使用Redis客户端测试
[root@localhost redis]# /app/redis/bin/redis-cli
127.0.0.1:6379> set mpush mpush0.0.3
OK
127.0.0.1:6379> get mpush
"mpush0.0.3"
127.0.0.1:6379>
查看Redis日志
[root@localhost redis]# tailf /app/redis/log/redis.log
二、安装Zookeeper
[root@localhost app]# ll
-rw-------. 1 root root 181352138 Sep 6 22:54 jdk-8u101-linux-x64.tar.gz
-rw-------. 1 root root 22724574 Sep 6 23:02 zookeeper-3.4.9.tar.gz
1、安装JDK并设置环境变量
[root@localhost app]# tar xf jdk-8u101-linux-x64.tar.gz
[root@localhost app]# ln -s jdk1.8.0_101 jdk
设置JAVA环境变量
[root@localhost app]# vim /etc/profile.d/java.sh
JAVA_HOME=/app/jdk
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME PATH CLASSPATH
[root@localhost app]# chmod +x /etc/profile.d/java.sh
[root@localhost app]# source /etc/profile.d/java.sh
[root@localhost app]# java -version
java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)
2、安装Zookeeper
[root@localhost app]# tar xf zookeeper-3.4.9.tar.gz
[root@localhost app]# ln -s zookeeper-3.4.9 zookeeper
[root@localhost app]# cd zookeeper
[root@localhost zookeeper]# mkdir data
提供配置文件
[root@localhost zookeeper]# cp conf/zoo_sample.cfg conf/zoo.cfg
[root@localhost zookeeper]# vim conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/app/zookeeper/data
clientPort=2181
启动Zookeeper服务
[root@localhost zookeeper]# bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /app/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
查看端口监听
[root@localhost zookeeper]# netstat -tplan | grep 2181
tcp6 0 0 :::2181 :::* LISTEN 3180/java
使用Zookeeper的客户端测试
[root@localhost zookeeper]# bin/zkCli.sh
Connecting to localhost:2181
......................................................
......................................................
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0]
[zk: localhost:2181(CONNECTED) 2] create mpush
[zk: localhost:2181(CONNECTED) 4] ls /
[zookeeper]
三、安装MPush
使用群文件提供的mpush-release-0.0.3.tar.gz,或者下载https://github.com/mpusher/mpush代码,自己打包,都可以
[root@localhost app]# ll
total 186716
-rw-------. 1 root root 181352138 Sep 6 22:54 jdk-8u101-linux-x64.tar.gz
-rw-------. 1 root root 9840899 Sep 7 02:28 mpush-release-0.0.3.tar.gz
1、安装JDK并设置环境变量
[root@localhost app]# tar xf jdk-8u101-linux-x64.tar.gz
[root@localhost app]# ln -s jdk1.8.0_101 jdk
设置JAVA环境变量
[root@localhost app]# vim /etc/profile.d/java.sh
JAVA_HOME=/app/jdk
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME PATH CLASSPATH
[root@localhost app]# chmod +x /etc/profile.d/java.sh
[root@localhost app]# source /etc/profile.d/java.sh
[root@localhost app]# java -version
java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)
2、安装Mpush
[root@localhost app]# tar xf mpush-release-0.0.3.tar.gz
[root@localhost app]# ln -s mpush-0.0.3 mpush
编辑Mpush配置文件(注意,只需要修改mpush.conf配置文件即可,不需要修改reference.conf),修改默认提供的Redis、Zookeeper服务器地址和端口信息。注意,加上mp.http.proxy-enabled=true
[root@localhost mpush]# vim conf/mpush.conf
mp.log.level=warn
mp.min-heartbeat=3m
mp.net.connect-server-port=3000
mp.security.private-key="MIIBNgIBADANBgkqhkiG9w0BAQEFAASCASAwggEcAgEAAoGBAKCE8JYKhsbydMPbiO7BJVq1pbuJWJHFxOR7L8Hv3ZVkSG4eNC8DdwAmDHYu/wadfw0ihKFm2gKDcLHp5yz5UQ8PZ8FyDYvgkrvGV0ak4nc40QDJWws621dm01e/INlGKOIStAAsxOityCLv0zm5Vf3+My/YaBvZcB5mGUsPbx8fAgEAAoGAAy0+WanRqwRHXUzt89OsupPXuNNqBlCEqgTqGAt4Nimq6Ur9u2R1KXKXUotxjp71Ubw6JbuUWvJg+5Rmd9RjT0HOUEQF3rvzEepKtaraPhV5ejEIrB+nJWNfGye4yzLdfEXJBGUQzrG+wNe13izfRNXI4dN/6Q5npzqaqv0E1CkCAQACAQACAQACAQACAQA="
mp.security.public-key="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCghPCWCobG8nTD24juwSVataW7iViRxcTkey/B792VZEhuHjQvA3cAJgx2Lv8GnX8NIoShZtoCg3Cx6ecs+VEPD2fBcg2L4JK7xldGpOJ3ONEAyVsLOttXZtNXvyDZRijiErQALMTorcgi79M5uVX9/jMv2Ggb2XAeZhlLD28fHwIDAQAB"
mp.zk.server-address="192.168.0.119:2181"
mp.zk.namespace=mpush
mp.http.proxy-enabled=true
mp.redis={
#redis 集群配置,group 是个二维数组,第一层表示有多少组集群,每个组下面可以有多台机器
cluster-group:[["192.168.0.118:6379"]]//格式是ip:port:password,密码可以没有ip:port
}
[root@localhost mpush]# chmod +x bin/*.sh
[root@localhost mpush]# bin/mp.sh start
MPush JMX enabled by default
Using config: /app/mpush/bin/../conf/mpush.conf
Starting mpush ... STARTED
[root@localhost mpush]# bin/mp.sh start
MPush JMX enabled by default
Using config: /app/mpush/bin/../conf/mpush.conf
Starting mpush ... STARTED
查看启动情况和端口监听情况
[root@localhost mpush]#netstat -tplan | grep java
tcp6 0 0 :::47188 :::* LISTEN 3358/java
tcp6 0 0 :::3000 :::* LISTEN 3358/java
tcp6 0 0 :::3001 :::* LISTEN 3358/java
tcp6 0 0 :::3002 :::* LISTEN 3358/java
tcp6 0 0 192.168.0.120:45801 192.168.0.119:2181 ESTABLISHED 3358/java
可以看到端口已经处于监听状态
[root@localhost mpush]# tailf -n 30 logs/mpush.log
2016-09-21 13:35:13.427 - [main] INFO - console - launch mpush server...
2016-09-21 13:35:13.439 - [main] WARN - com.mpush.tools.Utils - getExtranetAddress is null
2016-09-21 13:35:13.488 - [main] INFO - console - begin start bootstrap chain...
2016-09-21 13:35:13.489 - [main] INFO - console - start next bootstrap job [ZKBoot]
2016-09-21 13:35:13.759 - [main] INFO - console - init zk client, config=ZKConfig{hosts='192.168.0.119:2181', digest='mpush', namespace='mpush', maxRetries=3, baseSleepTimeMs=3000, maxSleepMs=5000, sessionTimeout=5000, connectionTimeout=5000, localCachePath='/'}
2016-09-21 13:35:13.818 - [main] INFO - console - init zk client waiting for connected...
2016-09-21 13:35:13.891 - [main] INFO - console - start next bootstrap job [RedisBoot]
2016-09-21 13:35:13.894 - [main] INFO - console - begin init redis cluster
2016-09-21 13:35:13.990 - [main] WARN - c.m.zk.listener.ZKRedisNodeWatcher - refresh zk redis node cache, data=[{"redisNodeList":[{"host":"192.168.0.118","port":6379}]}]
2016-09-21 13:35:14.003 - [main] INFO - console - init redis cluster success...
2016-09-21 13:35:14.051 - [main] WARN - com.mpush.tools.Utils - getExtranetAddress is null
2016-09-21 13:35:14.066 - [main] INFO - console - start next bootstrap job [ServerBoot]
2016-09-21 13:35:14.087 - [main] INFO - console - init zk client success...
2016-09-21 13:35:14.267 - [mp-boss-p-2-t-1] INFO - console - server start success on:3000
2016-09-21 13:35:14.267 - [mp-boss-p-2-t-1] INFO - console - start ConnectionServer success listen:3000
2016-09-21 13:35:14.288 - [mp-boss-p-2-t-1] INFO - console - register server node={"ip":"192.168.0.120","port":3000,"extranetIp":"192.168.0.120"} to zk name=/cs/hosts/machine
2016-09-21 13:35:14.289 - [mp-boss-p-2-t-1] INFO - console - start next bootstrap job [ServerBoot]
2016-09-21 13:35:14.307 - [epollEventLoopGroup-2-1] INFO - console - server start success on:3001
2016-09-21 13:35:14.307 - [epollEventLoopGroup-2-1] INFO - console - start GatewayServer success listen:3001
2016-09-21 13:35:14.312 - [epollEventLoopGroup-2-1] INFO - console - register server node={"ip":"192.168.0.120","port":3001} to zk name=/gs/hosts/machine
2016-09-21 13:35:14.313 - [epollEventLoopGroup-2-1] INFO - console - start next bootstrap job [ServerBoot]
2016-09-21 13:35:14.318 - [mp-worker-p-3-t-1] INFO - console - server start success on:3002
2016-09-21 13:35:14.318 - [mp-worker-p-3-t-1] INFO - console - start AdminServer success listen:3002
2016-09-21 13:35:14.318 - [mp-worker-p-3-t-1] INFO - console - start next bootstrap job [HttpProxyBoot]
2016-09-21 13:35:14.318 - [mp-worker-p-3-t-1] INFO - console - start next bootstrap job [MonitorBoot]
2016-09-21 13:35:14.325 - [mp-worker-p-3-t-1] INFO - console - start next bootstrap job [LastBoot]
2016-09-21 13:35:14.326 - [mp-worker-p-3-t-1] INFO - console - end start bootstrap chain...
2016-09-21 13:35:14.326 - [mp-worker-p-3-t-1] INFO - console - ===================================================================
2016-09-21 13:35:14.326 - [mp-worker-p-3-t-1] INFO - console - ====================MPUSH SERVER START SUCCESS=====================
2016-09-21 13:35:14.326 - [mp-worker-p-3-t-1] INFO - console - ===================================================================
[root@localhost mpush]# cat logs/mpush.log | grep error
[root@localhost mpush]#
可以看到日志中服务器已经启动,且日志中没有错误信息
四、安装Alloc服务(此服务建议部署到tomcat或者其他环境中,在此仅提供测试使用)
使用群文件提供的mpush-alloc-1.0-jar-with-dependencies.jar,或者下载https://github.com/mpusher/alloc代码,自己打包,都可以
[root@localhost app]# ll
total 188064
-rw-------. 1 root root 181352138 Sep 6 22:54 jdk-8u101-linux-x64.tar.gz
-rw-------. 1 root root 11221246 Sep 21 05:21 mpush-alloc-1.0-jar-with-dependencies.jar
1、安装JDK并设置环境变量
[root@localhost app]# tar xf jdk-8u101-linux-x64.tar.gz
[root@localhost app]# ln -s jdk1.8.0_101 jdk
设置JAVA环境变量
[root@localhost app]# vim /etc/profile.d/java.sh
JAVA_HOME=/app/jdk
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME PATH CLASSPATH
[root@localhost app]# chmod +x /etc/profile.d/java.sh
[root@localhost app]# source /etc/profile.d/java.sh
[root@localhost app]# java -version
java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)
2、提供alloc配置文件
[root@localhost app]# vim alloc.conf
mp.log.level=debug
mp.zk.namespace=mpush
mp.zk.server-address="192.168.0.119:2181"
启动alloc
[root@localhost app]# java -jar -Dmp.conf=alloc.conf mpush-alloc-1.0-jar-with-dependencies.jar > alloc.log 2>&1 < /dev/null &
查看日志和启动情况
[root@localhost app]# netstat -tplan | grep java
tcp6 0 0 :::9999 :::* LISTEN 3187/java
tcp6 0 0 192.168.0.121:57930 192.168.0.120:3001 ESTABLISHED 3187/java
tcp6 0 0 192.168.0.121:45079 192.168.0.119:2181 ESTABLISHED 3187/java
可以看到9999端口已经处于监听状态,且已经与我们的Zookeeper(192.168.0.119)、MPush(192.168.0.120)建立了通信
[root@localhost app]# tailf alloc.log
省略部分日志
2016-09-21 14:01:22.493 - [nioEventLoopGroup-2-1] INFO - c.m.c.g.GatewayClientChannelHandler - client connect channel=[id: 0x070321da, L:/192.168.0.121:57930 - R:/192.168.0.120:3001]
2016-09-21 14:01:22.530 - [main] INFO - console - ===================================================================
2016-09-21 14:01:22.531 - [main] INFO - console - ====================ALLOC SERVER START SUCCESS=====================
2016-09-21 14:01:22.531 - [main] INFO - console - ===================================================================
可以看到ALLOC已经启动成功
浏览器测试
可以看到,Alloc已经正常工作
五、完整测试
1、Android测试
note:注意,Android和Alloc、Mpush必须在一个网中且相互可以访问(Alloc、Mpush在公网除外)
1)填写Alloc服务器地址,注意以http://开头,且加端口号
2)填写发送的消息
3)点击Start Push
4)点击Send Push
正常情况,客户端会受到由服务器端推送过来的消息
2、模拟IM
客户端1使用Android手机,客户端2使用浏览器模拟,客户端2给客户端1发送消息。
客户端1
1)填写Alloc服务器地址
2)输入用户ID:user-0
3)点击Start Push
客户端2,使用Chrome插件POSTMAN模拟
六、常见问题
1、报错redis.clients.jedis.exceptions.JedisDataException: DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface.
Redis protected-mode 是3.2 之后加入的新特性,禁用即可
2、没收收到PUSH信息
1)查看服务器日志看是否有报错
2)手机浏览器和PC浏览器输入alloc地址(http://alloc-IP:9999,alloc-IP替换成Alloc服务器IP),查看是否有内容输出
3)关闭防火墙等,防止系统安全导致访问失败
閱讀更多 儒雅程序員 的文章