{"id":13523362,"url":"https://github.com/LockGit/gochat","last_synced_at":"2025-04-01T00:31:48.166Z","repository":{"id":37405657,"uuid":"218706050","full_name":"LockGit/gochat","owner":"LockGit","description":"goim server write by golang !🚀","archived":false,"fork":false,"pushed_at":"2024-03-24T16:21:41.000Z","size":22815,"stargazers_count":2745,"open_issues_count":30,"forks_count":465,"subscribers_count":37,"default_branch":"master","last_synced_at":"2024-10-16T09:03:13.865Z","etag":null,"topics":["awesome-go","chat","gochat","goim","im","online-chat","websocket"],"latest_commit_sha":null,"homepage":"http://45.77.108.245:8080","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LockGit.png","metadata":{"files":{"readme":"readme.en.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-10-31T07:13:30.000Z","updated_at":"2024-10-16T05:17:34.000Z","dependencies_parsed_at":"2023-01-20T22:47:24.492Z","dependency_job_id":"76543ed4-6deb-4c2b-9618-a2d8c472d16d","html_url":"https://github.com/LockGit/gochat","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LockGit%2Fgochat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LockGit%2Fgochat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LockGit%2Fgochat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LockGit%2Fgochat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LockGit","download_url":"https://codeload.github.com/LockGit/gochat/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222688173,"owners_count":17023297,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["awesome-go","chat","gochat","goim","im","online-chat","websocket"],"created_at":"2024-08-01T06:00:59.366Z","updated_at":"2025-04-01T00:31:48.154Z","avatar_url":"https://github.com/LockGit.png","language":"Go","readme":"# 🚀 gochat\n[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/LockGit/gochat/issues)\n\u003cimg src=\"https://img.shields.io/badge/gochat-im-green\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/documentation-yes-brightgreen.svg\"\u003e\n\u003cimg src=\"https://img.shields.io/github/license/LockGit/gochat\"\u003e\n\u003cimg src=\"https://img.shields.io/github/contributors/LockGit/gochat\"\u003e\n\u003cimg src=\"https://img.shields.io/github/last-commit/LockGit/gochat\"\u003e\n\u003cimg src=\"https://img.shields.io/github/issues/LockGit/gochat\"\u003e \n\u003cimg src=\"https://img.shields.io/github/forks/LockGit/gochat\"\u003e \n\u003cimg src=\"https://img.shields.io/github/stars/LockGit/gochat\"\u003e\n\u003cimg src=\"https://img.shields.io/docker/pulls/lockgit/gochat\"\u003e\n\u003cimg src=\"https://img.shields.io/github/repo-size/LockGit/gochat\"\u003e\n\u003cimg src=\"https://img.shields.io/github/followers/LockGit\"\u003e\n\n### [中文版本(Chinese version)](readme.md)\n\n### Subscribe\n```\nShare architecture design, research and development, network security, hacker culture, and Internet knowledge\n```\n![](./architecture/wx.jpg)\n\n### gochat is a lightweight im server implemented using pure go\n* 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.\n* Support websocket and TCP access, and support websocket and TCP message interworking in the latest version.\n* Based on etcd service discovery among different layers, it will be much more convenient to expand and deploy.\n* 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.\n* Because of the clear structure of chago, it can run quickly on various platforms.\n* 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)\n\n### Renew\n* August 6, 2022\n  * Although UI is not very important in this system, it does look awkward. Typescript + react is used to paste a slightly normal front-end UI interface. UI project address: https://github.com/LockGit/gochat-ui\n* May 8, 2022\n  * At present, the version of golang has been upgraded to 1.18. If you do not use docker, choose to compile and install it yourself. Please ensure that your go version meets the requirements\n  * The vendor is also packaged in the warehouse. In addition, the entire project size of the vendor is about 66m, which can be used after git clone. Due to irresistible network factors, it may take a long time\n  * Some package dependent versions have been upgraded. It is not recommended to try to compile this project on a lower version of golang. Try to upgrade to 1.18+\n  * Optimization: dynamically update the service IP address according to the corresponding kV change in the watch etcd to ensure that other layers can perceive the added / removed layers\n\n### About Websocket \u0026\u0026 Tcp Support\n```\nThe 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.)\nTCP message delivery and receiving test code in the pkg/stickpackage directory of this project: stickpackage_test.go Test in file_Tcpclient method\namong stickpackage.go The file is mainly used for TCP unpacking and unpacking. You can trace where the pack and unpack methods are called.\nThe 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.\nIf 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.\ngo test -v -count=1 *.go -test.run Test_TcpClient\n\nFor test TCP message delivery:\nJust change the @ todo part of this method to the correct content when you tested it.\nAuthToken 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.\nWhen the server receives the authToken, it will add the corresponding user's TCP link session to the session bidirectional list of the corresponding room.\n\nAfter 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:\n1. 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,\nFor example, user a is in room 1 and linked through websocket, and user B is also in room 1 through TCP.\n\n2. Users send messages to the room. At present, they directly put the messages into the corresponding message queue through HTTP,\nIn fact, this place can also be sent through websocket and TCP, but the final messages are to be queued.\n\n3. 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,\nAfter 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)\n```\n![](./architecture/gochat_tcp.gif)\n\n### Architecture design\n ![](./architecture/gochat.png)\n\n### Service discovery\n![](./architecture/gochat_discovery.png)\n\n\n### Message delivery\n![](./architecture/single_send.png)\n```\nThe message must be sent in the login state. As shown above, User A sends a message to User B. \nThen experienced the following process:\n1. User A invokes the api layer interface to log in to the system. After the login succeeds, \nthe user keeps a long link with the connect layer authentication, \nand the rpc call logic layer records the serverId that user A logs in at the connect layer. \nThe default joins the room number 1.\n\n2. User B calls the api layer interface to log in to the system. \nAfter the login succeeds, the user keeps a long link with the connect layer authentication, \nand the rpc call logic layer records the serverId of the user B login at the connect layer. \nThe default joins the room number 1.\n\n3. User A calls the api layer interface to send a message, \nand the api layer rpc call logic layer sends a message method. \nThe logic layer pushes the message to the queue and waits for the task layer to consume.\n\n4, After the task layer subscribes to the message sent by the logic layer to the queue, \naccording to the message content (userId, roomId, serverId), \nthe user B can be positioned to maintain a long link on the serverId of the connect layer, \nand the rpc call connect layer method is further\n\n5, After the connect layer is rpc call by the task layer, \nthe message will be delivered to the relevant room, \nand then further delivered to the user B in the room to complete a complete message session communication.\n\n6, if it is a private message, \nthen the task layer will locate the serverId corresponding to the connect layer according to the userId, \ndirectly rpc call the connect layer of the serverId, and complete the private message delivery.\n\nLearning other im systems, in order to reduce the lock competition, will be divided in the connect layer bucket:\nIt will roughly look like the following structure:\nConnect layer:\n     Bucket: (bucket, reduce lock competition)\n         Room: (room)\n             Channel: (user session)\n```\n### timing\n![](./architecture/timing.png)\n\n### Chat room preview\nUse typescript + react to paste a slightly normal front-end UI. UI project address: https://github.com/LockGit/gochat-ui\n![](./architecture/gochat-new.png)\n\n### Internal structure of user long connect session\n![](./architecture/session.png)\n\n### Dividing buckets to reduce lock competition\n![](./architecture/lock_competition.png)\n\n### Making hash distribution more uniform based on cityhash\n![](./architecture/hash.png)\n\n### Preview of the internal structure of a single server in the connect layer\n![](./architecture/gochat_room.png)\n\n### Simple pressure measurement\n![](./architecture/pressure_test.png)\n\n### Directory Structure\n```\n➜ gochat git:(master) ✗ tree -L 1\n.\n├── api             # api interface layer, providing rest api service, main rpc call logic layer service, horizontal expansion\n├──architecture     # architecture resource picture folder\n├── bin             # golang compiled binary, do not submit to the git repository\n├── config          # configuration file\n├── 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\n├── 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\n├── docker          # for quickly building a docker environment\n├── go.mod          # go package management mod file\n├── go.sum          # go package management sum file\n├── 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.\n├── main.go         # gochat program only entry file\n├── proto           # golang rpc proto file\n├── readme.md       # Chinese documentation\n├── readme.en.md    # English documentation\n├── reload.sh       # Compile gochat and execute supervisorctl restart to restart related processes\n├── run.sh          # Quickly build a docker container and start the demo\n├── site            # site layer, this layer is a pure static page, will http request api layer, can be extended horizontally\n├── 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\n├── tools           # tools function\n└── vendor          # vendor package\n```\n\n### Related components\n```\nLanguage: golang\n\nDatabase: sqlite3\ncan be replaced by mysql or other database according to the actual business scenario. In this project, \nfor the convenience of demonstration, use sqlite instead of large relational database, \nonly store simple user information\n\nDatabase ORM: gorm\n\nService discovery: etcd\n\nRpc communication: rpcx\n\nQueue: redis \nconvenient to use redis, can be replaced with kafka or rabbitmq according to the actual situation\n\nCache: redis \nstore user session, and related counters, chat room information, etc.\n\nMessage id: \nThe snowflakeId algorithm, \nwhich can be split into microservices separately, \nmaking it part of the underlying service. \nThe id numbering device qps theory is up to 409.6w/s. \nNo company on the Internet can achieve such high concurrency unless it suffers from DDOS attacks.\n```\n\n### Database and table structure\n```\nIn this demo, in order to be lightweight and convenient to demonstrate, \nthe database uses sqlite3, based on gorm, \nso this can be replaced. \nIf you need to replace other relational databases, just modify the relevant db driver.\n\nRelated table structure:\ncd db \u0026\u0026 sqlite3 gochat.sqlite3\n.tables\n```\n```sqlite\ncreate table user(\n  `id` INTEGER PRIMARY KEY autoincrement , -- 'userId'\n  `user_name` varchar(20) not null UNIQUE default '', -- 'userName'\n  `password` char(40) not null default '', -- 'passWord'\n  `create_time` timestamp NOT NULL DEFAULT current_timestamp -- 'createTime'\n);\n```\n\n### Installation\n```\nBefore starting each layer, \nPlease 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.)\nmake sure that the etcd and redis services and the above database tables have been started, \nand then start the layers in the following order. \n\nIf you want to expand the connect layer, \nmake sure that the serverId in the connect layer configuration is different!\n\n0,Compile\ngo build -o gochat.bin -tags=etcd main.go\n\n1,Start the logic layer\n./gochat.bin -module logic\n\n2,Start the connect layer\n./gochat.bin -module connect_tcp\nor  \n./gochat.bin -module connect_websocket\n\n3,Start the task layer\n./gochat.bin -module task\n\n4,Start the api layer\n./gochat.bin -module api \n\n5,Start a site and start a chat room\n./gochat.bin -module site\n```\n\n### Start with a docker\n\n#### Use existing image\n```\nIf you feel that the above steps are too cumbersome, \nyou can use the following docker image to build all the dependencies and quickly start a chat room.\n\nYou can use the image I pushed to the docker hub \nthere have been several test users created in the default image.\nusername  password\ndemo        111111\ntest        111111\nadmin       111111\n1,docker pull lockgit/gochat:1.18 (version 1.18 is currently used)\n2,git clone git@github.com:LockGit/gochat.git\n3,cd gochat \u0026\u0026 sh run.sh dev 127.0.0.1 (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 127.0.0.1 for execution)\n4,visit http://127.0.0.1:8080/login; enter username/password to access the chat room\n5,visit http://127.0.0.1:8080 to open the chat room\n```\n\n\n#### Building a new image\nFor other platforms, such as arm or m1 chips\n```\nIf you want to build an image yourself, \nyou only need to build the Dockerfile under the docker file.\nDocker build -f docker/Dockerfile . -t lockgit/gochat\nthen execute:\n1,git clone git@github.com:LockGit/gochat.git\n2,cd gochat \u0026\u0026 sh run.sh dev 127.0.0.1 (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 127.0.0.1 for execution)\n3,visit http://127.0.0.1:8080/login; enter username/password to access the chat room\n4,visit http://127.0.0.1:8080 to open the chat room\n\nIf you want to deploy on personal vps, you can execute: sh run.sh dev vps_ip\nAnd make sure there are no firewall restrictions on the relevant ports on the vps.\n```\n\n### Here is an online chat demo site:\n\u003ca href=\"http://45.77.108.245:8080\" target=\"_blank\"\u003ehttp://45.77.108.245:8080\u003c/a\u003e\n```\nLog in with the above user name and password, or register one by yourself.\nif the provide url can't visit one day，please use the docker above to visit it.\nYou can log in to different browsers with different accounts. \nIf it is Chrome, you can use several browsers in incognito mode to log in with different accounts.\nThen, experience the chat between different accounts and the effect of message delivery.\n(Note: TCP channel is not enabled in this demo)\n```\nIf you want to deploy a similar private IM chat service to the public network experience, \nyou can also register an account on vultr and purchase a VPS host to deploy the IM service experience:\n\u003ca href=\"https://www.vultr.com/?ref=8981750-8H\" target=\"_blank\"\u003ehttps://www.vultr.com/?ref=8981750-8H\u003c/a\u003e\n\n### Follow-up\n```\ngochat implements a simple chat room function. Due to limited energy, \nyou can use your own business logic to customize some requirements and optimize some code in gochat.\nPlease contact the relevant issue for any questions in use, \nand follow up and optimize the relevant code according to the actual situation.\n```\n\n### Backer and Sponsor\n\u003ejetbrains\n\n\u003ca href=\"https://www.jetbrains.com/?from=LockGit/gochat\" target=\"_blank\"\u003e\n\u003cimg src=\"https://github.com/LockGit/gochat/blob/master/architecture/jetbrains-gold-reseller.svg\" width=\"100px\" height=\"100px\"\u003e\n\u003c/a\u003e\n\n```\nJetBrains has an open source sponsorship program that allows you to apply for the JetBrains family bucket license for free through the open source project\nJetbranins officials will ask for the proposal to add their brand logo to the warehouse when giving the license,\nBut all this is the principle of users' willingness\n```\n\n### Support gochat\n```\nYour support is also a kind of affirmation, if you find it helpful, \nyou can also scan the WeChat QR code below to support the author to continue to optimize and improve gochat\n```\n![](./architecture/support.png)\n\n### License\ngochat is licensed under the MIT License. \n\n### Star History\n[![Star History Chart](https://api.star-history.com/svg?repos=LockGit/gochat\u0026type=Date)](https://star-history.com/#LockGit/gochat\u0026Date)","funding_links":[],"categories":["开源工具","Go"],"sub_categories":["Docker工具"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLockGit%2Fgochat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FLockGit%2Fgochat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLockGit%2Fgochat/lists"}