系統介紹
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)關閉防火牆等,防止系統安全導致訪問失敗
閱讀更多 儒雅程序員 的文章