- gochat is an instant messaging system based on go. It supports private message messages and room broadcast messages. It communicates with each other through RPC and supports horizontal expansion.
- Support websocket and TCP access, and support websocket and TCP message interworking in the latest version.
- Based on etcd service discovery among different layers, it will be much more convenient to expand and deploy.
- Using redis as the carrier of message storage and delivery is very lightweight, and it can be replaced by heavier Kafka and rabbitmq in actual scenarios.
- Because of the clear structure of chago, it can run quickly on various platforms.
- This project provides docker with one click to build all environment dependencies, which is very convenient to install. (if it's an experience, we strongly recommend using docker to build)
- At present, the version of golang has been upgraded to 1.18. If docker is not used, choose to compile and install by yourself. Please ensure whether your own version of go meets the requirements
- The vendor is also packaged in the warehouse. In addition, the size of the whole vendor project is about 66m. It can be used after git clone. Due to irresistible network factors, it may take a long time
- Some package dependent versions have been upgraded. It is not recommended to try to compile this project on a lower version of golang, and try to upgrade to 1.18+
- Optimization: dynamically update the service IP address according to the kV change in watch etcd to ensure that other layers can perceive after adding / removing each layer
The latest version supports websocket and TCP message interworking,(the test TCP port uses 70017002. If you want to use TCP, the firewall also needs to release the two ports.)
TCP message delivery and receiving test code in the pkg/stickpackage directory of this project: stickpackage_test.go Test in file_Tcpclient method
among stickpackage.go The file is mainly used for TCP unpacking and unpacking. You can trace where the pack and unpack methods are called.
The main reason is that TCP is based on the streaming protocol of layer 4 rather than the application layer protocol, so there is this process.
If it is Android, IOS client to link, then the corresponding is to use a familiar language to implement the TCP unpacking and unpacking process. The code in the example is demo implemented by golang.
go test -v -count=1 *.go -test.run Test_TcpClient
For test TCP message delivery:
Just change the @ todo part of this method to the correct content when you tested it.
AuthToken is the authentication token for TCP link. This token is the user ID. you can see the JSON return in the API return after login on the web, or you can directly find the token of a user in redis.
When the server receives the authToken, it will add the corresponding user's TCP link session to the session bidirectional list of the corresponding room.
After adding TCP support, if there are both users linking through websocket and users linking through TCP in a room, the general process of message delivery is as follows:
1. First, the user logs in, carries the token and room number to connect to the websocket and TCP server, and establishes a long link session in the link layer,
For example, user a is in room 1 and linked through websocket, and user B is also in room 1 through TCP.
2. Users send messages to the room. At present, they directly put the messages into the corresponding message queue through HTTP,
In fact, this place can also be sent through websocket and TCP, but the final messages are to be queued.
3. The message in the queue is consumed by the task layer, and the RPC is broadcast to the corresponding rooms of the websocket link layer and the TCP link layer,
After getting the message, the link layer delivers the message to the corresponding remote user (equivalent to traversing the user link session bidirectional list maintained in the room)
The message must be sent in the login state. As shown above, User A sends a message to User B.
Then experienced the following process:
1. User A invokes the api layer interface to log in to the system. After the login succeeds,
the user keeps a long link with the connect layer authentication,
and the rpc call logic layer records the serverId that user A logs in at the connect layer.
The default joins the room number 1.
2. User B calls the api layer interface to log in to the system.
After the login succeeds, the user keeps a long link with the connect layer authentication,
and the rpc call logic layer records the serverId of the user B login at the connect layer.
The default joins the room number 1.
3. User A calls the api layer interface to send a message,
and the api layer rpc call logic layer sends a message method.
The logic layer pushes the message to the queue and waits for the task layer to consume.
4, After the task layer subscribes to the message sent by the logic layer to the queue,
according to the message content (userId, roomId, serverId),
the user B can be positioned to maintain a long link on the serverId of the connect layer,
and the rpc call connect layer method is further
5, After the connect layer is rpc call by the task layer,
the message will be delivered to the relevant room,
and then further delivered to the user B in the room to complete a complete message session communication.
6, if it is a private message,
then the task layer will locate the serverId corresponding to the connect layer according to the userId,
directly rpc call the connect layer of the serverId, and complete the private message delivery.
Learning other im systems, in order to reduce the lock competition, will be divided in the connect layer bucket:
It will roughly look like the following structure:
Connect layer:
Β Β Β Β Bucket: (bucket, reduce lock competition)
Β Β Β Β Β Β Β Β Room: (room)
Β Β Β Β Β Β Β Β Β Β Β Β Channel: (user session)
β gochat git:(master) β tree -L 1
.
βββ api # api interface layer, providing rest api service, main rpc call logic layer service, horizontal expansion
βββarchitecture # architecture resource picture folder
βββ bin # golang compiled binary, do not submit to the git repository
βββ config # configuration file
βββ connect # link layer, this layer is used for handlers to live a large number of user long connections, real-time message push, in addition, the main rpc call logic layer service, can be horizontally extended
βββ db # database link initialization, internal gochat.sqlite3 for the convenience of the use of the sqlite database, the actual scene can be replaced with other relational database
βββ docker # for quickly building a docker environment
βββ go.mod # go package management mod file
βββ go.sum # go package management sum file
βββ logic # Logic layer, this layer mainly receives the rpc request of the connect layer and the api layer. If it is a message, it will be pushed to the queue, and finally consumed by the task layer, which can be horizontally expanded.
βββ main.go # gochat program only entry file
βββ proto # golang rpc proto file
βββ readme.md # Chinese documentation
βββ readme.en.md # English documentation
βββ reload.sh # Compile gochat and execute supervisorctl restart to restart related processes
βββ run.sh # Quickly build a docker container and start the demo
βββ site # site layer, this layer is a pure static page, will http request api layer, can be extended horizontally
βββ task # task layer, the data in the consumption queue of this layer, and the rpc call connect layer performs message transmission, which can be extended horizontally
βββ tools # tools function
βββ vendor # vendor package
Language: golang
Database: sqlite3
can be replaced by mysql or other database according to the actual business scenario. In this project,
for the convenience of demonstration, use sqlite instead of large relational database,
only store simple user information
Database ORM: gorm
Service discovery: etcd
Rpc communication: rpcx
Queue: redis
convenient to use redis, can be replaced with kafka or rabbitmq according to the actual situation
Cache: redis
store user session, and related counters, chat room information, etc.
Message id:
The snowflakeId algorithm,
which can be split into microservices separately,
making it part of the underlying service.
The id numbering device qps theory is up to 409.6w/s.
No company on the Internet can achieve such high concurrency unless it suffers from DDOS attacks.
In this demo, in order to be lightweight and convenient to demonstrate,
the database uses sqlite3, based on gorm,
so this can be replaced.
If you need to replace other relational databases, just modify the relevant db driver.
Related table structure:
cd db && sqlite3 gochat.sqlite3
.tables
create table user(
`id` INTEGER PRIMARY KEY autoincrement , -- 'userId'
`user_name` varchar(20) not null UNIQUE default '', -- 'userName'
`password` char(40) not null default '', -- 'passWord'
`create_time` timestamp NOT NULL DEFAULT current_timestamp -- 'createTime'
);
Before starting each layer,
Please make sure that the 7000, 7070, 8080 ports are not occupied. (the test TCP port uses 70017002. If you want to use TCP, the firewall also needs to release the two ports.)
make sure that the etcd and redis services and the above database tables have been started,
and then start the layers in the following order.
If you want to expand the connect layer,
make sure that the serverId in the connect layer configuration is different!
0,Compile
go build -o gochat.bin -tags=etcd main.go
1,Start the logic layer
./gochat.bin -module logic
2,Start the connect layer
./gochat.bin -module connect_tcp
or
./gochat.bin -module connect_websocket
3,Start the task layer
./gochat.bin -module task
4,Start the api layer
./gochat.bin -module api
5,Start a site and start a chat room
./gochat.bin -module site
If you feel that the above steps are too cumbersome,
you can use the following docker image to build all the dependencies and quickly start a chat room.
You can use the image I pushed to the docker hub
there have been several test users created in the default image.
username password
demo 111111
test 111111
admin 111111
1,docker pull lockgit/gochat:1.18 (version 1.18 is currently used)
2,git clone [email protected]:LockGit/gochat.git
3,cd gochat && sh run.sh dev (This step requires a certain time to compile each module and wait patiently. Some systems may not have sh. if an error is reported during execution, change sh run.sh dev to ./ run.sh dev for execution)
4,visit http://127.0.0.1:8080 to open the chat room
If you want to build an image yourself,
you only need to build the Dockerfile under the docker file.
Docker build -f docker/Dockerfile . -t lockgit/gochat
then execute:
1,git clone [email protected]:LockGit/gochat.git
2,cd gochat && sh run.sh dev (This step requires a certain time to compile each module and wait patiently. Some systems may not have sh. if an error is reported during execution, change sh run.sh dev to ./ run.sh dev for execution)
3,visit http://127.0.0.1:8080 to open the chat room
If you want to deploy on personal vps,
remember to change the address of socketUrl and apiUrl in site/js/common.js to your ip address of vps.
And make sure there are no firewall restrictions on the relevant ports on the vps.
Log in with the above user name and password, or register one by yourself.
if the provide url can't visit one dayοΌplease use the docker above to visit it.
You can log in to different browsers with different accounts.
If it is Chrome, you can use several browsers in incognito mode to log in with different accounts.
Then, experience the chat between different accounts and the effect of message delivery.
(Note: TCP channel is not enabled in this demo)
If you want to deploy a similar private IM chat service to the public network experience, you can also register an account on vultr and purchase a VPS host to deploy the IM service experience: https://www.vultr.com/?ref=8981750-8H
gochat implements a simple chat room function. Due to limited energy,
you can use your own business logic to customize some requirements and optimize some code in gochat.
Please contact the relevant issue for any questions in use,
and follow up and optimize the relevant code according to the actual situation.
jetbrains
JetBrains has an open source sponsorship program that allows you to apply for the JetBrains family bucket license for free through the open source project
Jetbranins officials will ask for the proposal to add their brand logo to the warehouse when giving the license,
But all this is the principle of users' willingness
Your support is also a kind of affirmation, if you find it helpful,
you can also scan the WeChat QR code below to support the author to continue to optimize and improve gochat
gochat is licensed under the MIT License.