项目中增加Redis,更稳定高效(项目中加redis)
921
2022-10-23
CookIM - 一个基于akka的分布式websocket聊天程序
CookIM - is a distributed websocket chat applications based on akka
Support private message and group messageSupport chat servers cluster communicationNow we support send text message, file message and voice message. Thanks for ft115637850 's PR for voice message.
中文文档English document
GitHub projectOSChina project
Category
DemoDemo on PCDemo on MobileDemo link Start multiple nodes CookIM in docker composeStart docker composeAdd nodes in docker composeDebug in docker containerStop docker compose How to runPrerequisitesClone source codeConfiguration and assemblyStart CookIM serverOpen browser and access web port 8080Start another CookIM serverOpen browser and access web port 8081 ArchitectureArchitecture pictureakka stream websocket graphMongoDB tables specificationWebsocket message type ChangeLog0.1.0-SNAPSHOT0.2.0-SNAPSHOT0.2.4-SNAPSHOT
Category
###Demo
Demo on PC
Demo on Mobile
Demo link
https://im.cookeem.com
Start multiple nodes CookIM in docker compose
Start docker compose
Change into CookIM directory, run command below, start multiple nodes CookIM servers in docker compose mode. This way will start 3 container: mongo, cookim1 and cookim2
$ git clone https://github.com/cookeem/CookIM.git$ cd CookIM$ sudo docker-compose up -dCreating mongoCreating cookim1Creating cookim2
After run docker compose, use different browser to access the URLs below to connect to cookim1 and cookim2
http://localhost:8080 http://localhost:8081
Category
Add nodes in docker compose
You can add config in docker-compose.yml (in CookIM directory) to add CookIM server nodes, this example show how to add cookim3 in docker compose:
cookim3: image: cookeem/cookim container_name: cookim3 hostname: cookim3 environment: HOST_NAME: cookim3 WEB_PORT: 8080 AKKA_PORT: 2551 SEED_NODES: cookim1:2551 MONGO_URI: mongodb://mongo:27017/local ports: - "8082:8080" depends_on: - mongo - cookim1
Category
Debug in docker container
View container cookim1 logs output
$ sudo docker logs -f cookim1
Exec into container cookim1 to debug
$ sudo docker exec -ti cookim1 bash
Category
Stop docker compose
$ sudo docker-compose stop$ sudo docker-compose rm
Category
How to run
Prerequisites
JDK 8+Scala 2.11+SBT 0.13.15MongoDB 2.6 - 3.4
Category
Clone source code
git clone https://github.com/cookeem/CookIM.gitcd CookIM
Category
Configuration and assembly
The configuration file locate at conf/application.conf, please make sure your mongodb uri configuration.
mongodb { dbname = "cookim" uri = "mongodb://mongo:27017/local"}
Assembly CookIM project to a fatjar, target jar locate at target/scala-2.11/CookIM-assembly-0.2.0-SNAPSHOT.jar
sbt clean assembly
Category
Start CookIM server
CookIM use MongoDB to store chat messages and users data, make sure you startup MongoDB before you startup CookIM.
There are two ways to start CookIM server: sbt and java
a. sbt debug way:
$ cd #CookIM directory#$ sbt "run-main com.cookeem.chat.CookIM -h localhost -w 8080 -a 2551 -s localhost:2551"
b. pack and compile fat jar:
$ sbt assembly
c. java production way:
$ java -classpath "target/scala-2.11/CookIM-assembly-0.2.4-SNAPSHOT.jar" com.cookeem.chat.CookIM -h localhost -w 8080 -a 2551 -s localhost:2551
Command above has start a web server listen port 8080 and akka system listen port 2551
Parameters:
-a -h [-m ] [-n] -s -w -a,--akka-port akka cluster node port -h,--host-name current web service external host name -m,--mongo-uri mongodb connection uri, example: mongodb://localhost:27017/local -n,--nat is nat network or in docker -s,--seed-nodes akka cluster seed nodes, seperate with comma, example: localhost:2551,localhost:2552 -w,--web-port web service port
Category
Open browser and access web port 8080
http://localhost:8080
Category
Start another CookIM server
Open another terminal, start another CookIM server to test message communication between servers:
a. sbt debug way:
$ sbt "run-main com.cookeem.chat.CookIM -h localhost -w 8081 -a 2552 -s localhost:2551"
b. java production way:
$ java -classpath "target/scala-2.11/CookIM-assembly-0.2.0-SNAPSHOT.jar" com.cookeem.chat.CookIM -h localhost -w 8081 -a 2552 -s localhost:2551
Command above has start a web server listen port 8081 and akka system listen port 2552
Category
Open browser and access web port 8081
http://localhost:8081
Category
Architecture
Architecture picture
**CookIM server make from 3 parts: **
akka http: provide web service, browser connect distributed chat servers by websocket
akka stream: akka http receive websocket message (websocket message include TextMessage and BinaryMessage), then send message to chatService by akka stream way, websocket message include JWT(Javascript web token), if JWT verify failure, chatService stream will return reject message; if JWT verify success, chatService stream will send message to ChatSessionActor
akka cluster:akka stream send websocket message to akka cluster ChatSessionActor, ChatSessionActor use DistributedPubSub to subscribe and publish message in akka cluster. When user online session, it will subscribe the session; when user send message in session, it will publish message in akka cluster, the actors who subscribe the session will receive the publish message
Category
akka stream websocket graph
When akka http receive messsage from websocket, it will send message to chatService flow, here we use akka stream graph:
Websocket message body include JWT, flowFromWS use to receive websocket message and decode JWT;
When JWT verify failure, it will broadcast to filterFailure to filter to fail message; When JWT verify success, it will broadcast to filterSuccess to filter to success message;
When akka stream created, builder.materializedValue will send message to connectedWs, connectedWs convert message receive to UserOnline message, then send to chatSinkActor finally send to ChatSessionActor;
chatActorSink send message to chatSessionActor, when akka stream closed if will send UserOffline message to down stream;
chatSource receive message back from ChatSessionActor, then send message back to flowAcceptBack;
flowAcceptBack will let the websocket connection keepAlive;
flowReject and flowAcceptBack messages finally send to flowBackWs, flowBackWs convert messages to websocket format then send back to users;
Category
MongoDB tables specification
users: users table
*login (login email)nickname (nickname)password (password SHA1)gender (gender: unknow:0, boy:1, girl:2)avatar (avatar abs path, example: /upload/avatar/201610/26/xxxx.JPG)lastLogin (last login timestamp)loginCount (login counts)sessionsStatus (user joined sessions status) [{sessionid: session id, newCount: unread message count in this session}]friends (user's friends list: [friends uid])dateline (register timestamp)
sessions: sessions table
*createuid (creator uid)*ouid (receiver uid, when session type is private available)sessionIcon (session icon, when session type is group available)sessionType (session type: 0:private, 1:group)publicType (public type: 0:not public, 1:public)sessionName (session name)dateline (created timestamp)usersStatus (users who joined this session status) [{uid: uid, online: (true, false)}]lastMsgid (last message id)lastUpdate (last update timestamp)
messages: messages tables
*uid (send user uid)*sessionid (relative session id)msgType (message type)content (message content)fileInfo (file information) { filePath fileName fileType fileSize fileThumb }*dateline (created timestamp)
onlines: online users table
*uid (online user id)dateline (last update timestamp)
notifications: receive notifications table
noticeType (notification type: "joinFriend", "removeFriend", "inviteSession")senduid (send user id)*recvuid (receive user id)sessionid (relative session id)isRead (notification is read: 0:not read, 1:already read)dateline (created timestamp)
Category
Websocket message type
There are two websocket channel: ws-push and ws-chat
ws-push send sessions new message to users, when user not online the session, they still can receive which sessions has new messages
/ws-push channel
up message, use to subscribe push message:{ userToken: "xxx" }down message:acceptMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "accept", content: "xxx", dateline: "xxx" }rejectMsg: { uid: "", nickname: "", avatar: "", sessionid: "", sessionName: "", sessionIcon: "", msgType: "reject", content: "xxx", dateline: "xxx" }keepAlive: { uid: "", nickname: "", avatar: "", sessionid: "", sessionName: "", sessionIcon: "", msgType: "keepalive", content: "", dateline: "xxx" }textMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "text", content: "xxx", dateline: "xxx" }fileMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "file", fileName: "xxx", fileType: "xxx", fileid: "xxx", thumbid: "xxx", dateline: "xxx" }onlineMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "online", content: "xxx", dateline: "xxx" }offlineMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "offline", content: "xxx", dateline: "xxx" }joinSessionMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "join", content: "xxx", dateline: "xxx" }leaveSessionMsg:{ uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "leave", content: "xxx", dateline: "xxx" }noticeMsg: { uid: "", nickname: "", avatar: "", sessionid: "", sessionName: "xxx", sessionIcon: "xxx", msgType: "system", content: "xxx", dateline: "xxx" }message push to browser:pushMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "xxx", content: "xxx", fileName: "xxx", fileType: "xxx", fileid: "xxx", thumbid: "xxx", dateline: "xxx" }
Category
ws-chat is session chat channel, user send and receive session messages in this channel
/ws-chat channelup message: onlineMsg: { userToken: "xxx", sessionToken: "xxx", msgType:"online", content:"" }textMsg: { userToken: "xxx", sessionToken: "xxx", msgType:"text", content:"xxx" }fileMsg: { userToken: "xxx", sessionToken: "xxx", msgType:"file", fileName:"xxx", fileSize: 999, fileType: "xxx" }<#BinaryInfo#>binary_file_array_bufferdown message: rejectMsg: { uid: "", nickname: "", avatar: "", sessionid: "", sessionName: "", sessionIcon: "", msgType: "reject", content: "xxx", dateline: "xxx" }keepAlive: { uid: "", nickname: "", avatar: "", sessionid: "", sessionName: "", sessionIcon: "", msgType: "keepalive", content: "", dateline: "xxx" }textMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "text", content: "xxx", dateline: "xxx" }fileMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "file", fileName: "xxx", fileType: "xxx", fileid: "xxx", thumbid: "xxx", dateline: "xxx" }onlineMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "online", content: "xxx", dateline: "xxx" }offlineMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "offline", content: "xxx", dateline: "xxx" }joinSessionMsg:{ uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "join", content: "xxx", dateline: "xxx" }leaveSessionMsg:{ uid: "xxx", nickname: "xxx", avatar: "xxx", sessionid: "xxx", sessionName: "xxx", sessionIcon: "xxx", msgType: "leave", content: "xxx", dateline: "xxx" }noticeMsg: { uid: "", nickname: "", avatar: "", sessionid: "", sessionName: "xxx", sessionIcon: "xxx", msgType: "system", content: "xxx", dateline: "xxx" }message push to browser:chatMsg: { uid: "xxx", nickname: "xxx", avatar: "xxx", msgType: "xxx", content: "xxx", fileName: "xxx", fileType: "xxx", fileid: "xxx", thumbid: "xxx", dateline: "xxx" }
Category
ChangeLog
0.1.0-SNAPSHOT
Category
0.2.0-SNAPSHOT
CookIM now support MongoDB 3.4.4Upgrade akka version to 2.5.2Update docker-compose startup CookIM cluster readme
Category
0.2.4-SNAPSHOT
Now support send voice message, required WebRTC support browser, now Chrome Firefox and the new Safari11 available.Configurate mongodb connection params by command line.Update docker startup mode.
Category
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~