Bảng giá

Tổng quan dự án

Tệp nguồn liên quan

Trang này được tạo dựa trên các tệp nguồn sau:

gochat là một hệ thống nhắn tin tức thời (IM - Instant Messaging) được triển khai hoàn toàn bằng ngôn ngữ Go, thiết kế với kiến trúc nhẹ và có khả năng mở rộng theo chiều ngang. Dự án hỗ trợ cả giao thức WebSocket và TCP để thiết lập kết nối dài, cho phép các client khác nhau giao tiếp với nhau thông qua cơ chế RPC và service discovery dựa trên etcd (readme.md:19-26).

Hệ thống được thiết kế theo mô hình microservice với các layer tách biệt: API layer xử lý REST API requests, Connect layer quản lý các kết nối dài từ người dùng, Logic layer xử lý logic nghiệp vụ, Task layer tiêu thụ message queue và thực hiện push notification. Mỗi layer có thể triển khai độc lập và mở rộng theo chiều ngang, sử dụng Redis làm message queue và cache, etcd cho service discovery (readme.md:64-69).

Điểm nổi bật của gochat là khả năng hỗ trợ cả WebSocket và TCP đồng thời, với cơ chế message互通 cho phép người dùng kết nối qua các giao thức khác nhau vẫn có thể giao tiếp trong cùng một phòng chat. Dự án cũng cung cấp Docker để xây dựng môi trường một cách nhanh chóng, phù hợp cho việc demo và testing.

Kiến trúc hệ thống

Tổng quan các module chính

gochat được tổ chức thành 6 module chính, mỗi module đảm nhận một trách nhiệm cụ thể trong hệ thống IM. Điểm nhập của ứng dụng nằm tại file main.go, sử dụng flag -module để xác định module nào sẽ được khởi chạy (main.go:20-48).

正在加载图表渲染器...

Giải thích kiến trúc:

  • Client Layer: Hỗ trợ hai loại client - Web Browser kết nối qua WebSocket và TCP Client cho mobile/desktop applications
  • Gateway Layer: Site module phục vụ static pages, API module cung cấp REST API endpoints cho authentication và message sending
  • Core Services: Connect module quản lý long-lived connections, Logic module xử lý business logic, Task module tiêu thụ messages từ queue và push đến recipients
  • Infrastructure: etcd cho service discovery, Redis làm message queue và cache, SQLite/MySQL cho persistent storage

Chi tiết các module

ModuleVai tròKhả năng mở rộngGiao tiếp
apiREST API service, xử lý HTTP requestsHorizontalRPC đến Logic
connect_websocketQuản lý WebSocket connections, real-time pushHorizontalRPC đến Logic
connect_tcpQuản lý TCP connections, xử lý sticky packagesHorizontalRPC đến Logic
logicBusiness logic, message routingHorizontalRPC từ API/Connect
taskMessage queue consumer, push coordinationHorizontalRPC đến Connect
siteStatic web pages servingHorizontalHTTP đến API

Cấu trúc thư mục của dự án phản ánh rõ ràng sự phân chia trách nhiệm này (readme.md:125-148):

gochat/
├── api/          # REST API layer
├── connect/      # Connection management layer
├── logic/        # Business logic layer
├── task/         # Task/message processing layer
├── site/         # Static web pages
├── config/       # Configuration files
├── db/           # Database initialization
├── proto/        # RPC protocol definitions
├── pkg/          # Shared utilities
└── main.go       # Application entry point

Cơ chế khởi động module

Mỗi module được khởi động thông qua command line flag -module. Khi khởi động, module sẽ đăng ký với etcd để các module khác có thể discover và giao tiếp (main.go:20-48):

go
1// Ví dụ khởi động module
2go run main.go -module logic
3go run main.go -module connect_websocket
4go run main.go -module connect_tcp
5go run main.go -module task
6go run main.go -module api
7go run main.go -module site

Luồng xử lý tin nhắn

Kiến trúc xử lý message

Luồng xử lý tin nhắn trong gochat tuân theo mô hình producer-consumer, với Logic layer đóng vai trò producer đẩy messages vào Redis queue, và Task layer đóng vai trò consumer tiêu thụ và phân phối messages đến recipients.

正在加载图表渲染器...

Giải thích sequence diagram:

  1. Request Phase: Người gửi gọi API để gửi tin nhắn, API layer forward request đến Logic layer qua RPC
  2. Queue Phase: Logic layer xử lý business logic và đẩy message vào Redis queue, trả về response ngay lập tức
  3. Consume Phase: Task layer liên tục poll messages từ Redis queue
  4. Push Phase: Task layer xác định recipient's server và gọi RPC đến Connect layer tương ứng
  5. Delivery Phase: Connect layer tìm channel của recipient và push message qua WebSocket hoặc TCP

Xử lý tin nhắn tại Task Layer

Task layer đóng vai trò quan trọng trong việc tiêu thụ messages từ Redis queue và điều phối việc push đến các Connect servers. Module này xử lý 4 loại operations khác nhau (task/push.go:35-65):

go
1// Các loại operation được xử lý
2switch m.Op {
3case config.OpSingleSend:      // Tin nhắn riêng tư
4case config.OpRoomSend:        // Broadcast phòng chat
5case config.OpRoomCountSend:   // Cập nhật số lượng thành viên
6case config.OpRoomInfoSend:    // Cập nhật thông tin phòng
7}

Cơ chế xử lý tin nhắn riêng (Single Send):

Tin nhắn riêng được xử lý thông qua channel buffer để tăng throughput. Task layer sử dụng random distribution để chọn channel từ pool, sau đó goroutine worker sẽ xử lý việc push đến Connect layer (task/push.go:35-65):

go
1// Push tin nhắn riêng vào channel buffer
2pushChannel[rand.Int()%config.Conf.Task.TaskBase.PushChan] <- &PushParams{
3    ServerId: m.ServerId,
4    UserId:   m.UserId,
5    Msg:      m.Msg,
6}

Cơ chế broadcast phòng chat:

Tin nhắn broadcast được gửi đến tất cả Connect servers, mỗi server sẽ chịu trách nhiệm push đến các users đang kết nối với server đó (task/push.go:35-65):

go
1// Broadcast đến tất cả Connect servers
2rpcList := RClient.GetAllConnectTypeRpcClient()
3for _, rpc := range rpcList {
4    rpc.Call(context.Background(), "PushRoomMsg", pushRoomMsgReq, reply)
5}

RPC Communication giữa Task và Connect

Task layer sử dụng RPC client pool để giao tiếp với các Connect servers. Cơ chế service discovery cho phép Task layer dynamically cập nhật danh sách Connect servers khi có thay đổi (task/rpc.go:110-189).

Watch Service Changes:

Task layer theo dõi thay đổi từ etcd và cập nhật RPC client pool tương ứng:

go
1func (task *Task) watchServicesChange(d client.ServiceDiscovery) {
2    for kvChan := range d.WatchService() {
3        // Xử lý thay đổi service
4        // Cập nhật RClient.ServerInsMap
5    }
6}

Push Single Message:

Khi push tin nhắn riêng, Task layer xác định Connect server dựa trên serverId và gọi RPC method PushSingleMsg (task/rpc.go:110-189):

go
1func (task *Task) pushSingleToConnect(serverId string, userId int, msg []byte) {
2    pushMsgReq := &proto.PushMsgRequest{
3        UserId: userId,
4        Msg: proto.Msg{
5            Ver:       config.MsgVersion,
6            Operation: config.OpSingleSend,
7            SeqId:     tools.GetSnowflakeId(),
8            Body:      msg,
9        },
10    }
11    connectRpc, _ := RClient.GetRpcClientByServerId(serverId)
12    connectRpc.Call(context.Background(), "PushSingleMsg", pushMsgReq, reply)
13}

Xử lý RPC tại Connect Layer

Connect layer expose các RPC methods để nhận messages từ Task layer. Hai methods chính là PushSingleMsg cho tin nhắn riêng và PushRoomMsg cho broadcast (connect/rpc.go:109-148).

PushSingleMsg Implementation:

Method này tìm channel của user trong bucket và push message trực tiếp:

go
1func (rpc *RpcConnectPush) PushSingleMsg(ctx context.Context, pushMsgReq *proto.PushMsgRequest, successReply *proto.SuccessReply) error {
2    bucket := DefaultServer.Bucket(pushMsgReq.UserId)
3    if channel := bucket.Channel(pushMsgReq.UserId); channel != nil {
4        channel.Push(&pushMsgReq.Msg)
5    }
6    return nil
7}

PushRoomMsg Implementation:

Method này broadcast message đến tất cả buckets, mỗi bucket sẽ broadcast đến các rooms mà nó quản lý:

go
1func (rpc *RpcConnectPush) PushRoomMsg(ctx context.Context, pushRoomMsgReq *proto.PushRoomMsgRequest, successReply *proto.SuccessReply) error {
2    for _, bucket := range DefaultServer.Buckets {
3        bucket.BroadcastRoom(pushRoomMsgReq)
4    }
5    return nil
6}

Cấu trúc dữ liệu trong Connect Layer

Connect layer sử dụng cấu trúc Bucket-Room-Channel để giảm lock contention và tăng throughput. Mỗi Bucket quản lý một subset của users, và trong mỗi Bucket có các Rooms, mỗi Room chứa danh sách Channels của users (readme.md:94-100):

Connect Server
├── Bucket 1
│   ├── Room 1
│   │   ├── Channel (User A)
│   │   └── Channel (User B)
│   └── Room 2
│       └── Channel (User C)
├── Bucket 2
│   └── Room 1
│       └── Channel (User D)
└── Bucket N

Cơ chế này cho phép concurrent access vào các buckets khác nhau mà không gây lock contention, cải thiện significantly performance khi hệ thống có nhiều users.

Công nghệ và Dependencies

Technology Stack

gochat được xây dựng trên nền tảng Go 1.18, tận dụng các thư viện open source đã được verify trong production. Dưới đây là bảng tổng hợp các công nghệ chính (go.mod:1-22):

CategoryTechnologyVersionPurpose
LanguageGolang1.18Core language
Web FrameworkGin1.7.7HTTP server & routing
WebSocketgorilla/websocket1.5.0WebSocket protocol
RPCrpcx1.7.4Inter-service communication
Service Discoveryetcd-Dynamic service registry
Message QueueRedis6.15.9Message buffering & delivery
CacheRedis6.15.9Session & counter storage
Database ORMGORM1.9.16Database abstraction
DatabaseSQLite3-Default database (demo)
ID GeneratorSnowflake0.3.0Distributed ID generation
ConfigurationViper1.11.0Configuration management
LoggingLogrus1.8.1Structured logging

Core Dependencies Analysis

RPC Framework - rpcx:

gochat sử dụng rpcx làm RPC framework, một high-performance RPC library cho Go. rpcx hỗ trợ multiple service discovery mechanisms bao gồm etcd, Consul, và ZooKeeper (go.mod:1-22):

go
1require (
2    github.com/rpcxio/libkv v0.5.1-0.20210420120011-1fceaedca8a5
3    github.com/rpcxio/rpcx-etcd v0.1.0
4    github.com/smallnest/rpcx v1.7.4
5)

WebSocket Support:

Thư viện gorilla/websocket được sử dụng cho WebSocket implementation, cung cấp complete và tested implementation của WebSocket protocol (go.mod:1-22):

go
1require (
2    github.com/gorilla/websocket v1.5.0
3)

Technology Decisions

Tại sao chọn Redis làm Message Queue:

Theo documentation, Redis được chọn làm message queue để giữ cho hệ thống lightweight và dễ demo. Trong production environment, có thể thay thế bằng Kafka hoặc RabbitMQ để có better throughput và durability (readme.md:150-173):

队列:redis 
方便演示使用redis,可以根据实际情况替换为kafka或者rabbitmq

Tại sao chọn SQLite3 cho Demo:

SQLite3 được sử dụng để minimize dependencies và simplify setup process. GORM abstraction layer cho phép dễ dàng migrate sang MySQL hoặc PostgreSQL trong production (readme.md:150-173):

数据库:sqlite3 
可以根据实际业务场景替换成mysql或者其他数据库,
在本项目中为方便演示,使用sqlite替代大型关系型数据库,仅存储了简单用户信息

Snowflake ID Generator:

Hệ thống sử dụng Snowflake algorithm để generate unique message IDs. Theo documentation, ID generator này có theoretical throughput lên đến 4.096M IDs/second (readme.md:150-173):

消息id:
snowflakeId算法,此部分可以单独拆分成微服务,使其成为基础服务的一部分。
该id发号器qps理论最高409.6w/s

Triển khai và Docker

Docker Support

gochat cung cấp Docker support để simplify deployment process. Dockerfile được base trên golang:1.18 image và setup working directory tại /go/src/gochat (docker/Dockerfile:1-29).

Docker Image Structure:

dockerfile
1FROM golang:1.18
2MAINTAINER Lock <lockexit@gmail.com>
3WORKDIR /go/src/gochat
4# ... build and run commands

Docker image bao gồm tất cả dependencies cần thiết và có thể chạy tất cả modules trong single container hoặc separate containers tùy theo deployment strategy.

Build Automation với Makefile

Makefile cung cấp convenient commands để build Docker images với custom tags (Makefile:1-4):

makefile
1.PHONY:build
2build: # make build TAG=1.18;make build TAG=latest
3	cd ./docker && docker build -t lockgit/gochat:${TAG} .

Usage Examples:

bash
1# Build với specific version tag
2make build TAG=1.18
3
4# Build với latest tag
5make build TAG=latest

Quick Start với Docker

Dự án cung cấp script run.sh để quickly spin up demo environment với Docker. Đây là recommended approach cho việc testing và evaluation (readme.md:19-26):

本项目贴心的提供了docker一键构建所有环境依赖,安装起来十分便捷。
(如果是体验,强烈建议使用docker构建)

Tính năng chính

Multi-Protocol Support

gochat hỗ trợ đồng thời WebSocket và TCP protocols, cho phép clients chọn protocol phù hợp với platform của họ. Điểm đặc biệt là hai protocols này có thể interoperate - một user kết nối qua WebSocket có thể chat với user khác kết nối qua TCP trong cùng một room (readme.md:19-26).

TCP Sticky Package Handling:

TCP là stream-based protocol nên cần mechanism để handle message boundaries. gochat implement sticky package handling trong pkg/stickpackage directory (pkg/stickpackage/stickpackage.go:42-54):

go
1type StickPackage struct {
2    Version string
3    Length  int16
4    Msg     string
5}
6
7func (p *StickPackage) GetPackageLength() int16 {
8    p.Length = 4 + int16(len(p.Msg))
9    return p.Length
10}

Horizontal Scalability

Tất cả modules đều được thiết kế để scale horizontally. Key enabler cho khả năng này là:

  1. Stateless Design: API, Logic, Site modules hoàn toàn stateless
  2. Service Discovery: etcd-based service discovery cho phép dynamic registration và discovery
  3. Distributed State: User sessions được distribute across Connect servers với consistent hashing

Real-time Message Delivery

Hệ thống đảm bảo real-time message delivery thông qua:

  1. Long-lived Connections: WebSocket và TCP connections maintain persistent connections
  2. Push Architecture: Messages được push đến recipients thay vì poll
  3. Low-latency RPC: rpcx framework cung cấp high-performance inter-service communication

Room-based Broadcasting

Hệ thống hỗ trợ room-based chat với efficient broadcasting mechanism. Khi message được gửi đến room, Task layer sẽ broadcast đến tất cả Connect servers, mỗi server sẽ push đến local users trong room đó (task/rpc.go:110-189).

Lộ trình đọc báo cáo

正在加载图表渲染器...

Recommended Reading Order:

  1. Tổng quan dự án (trang hiện tại): Hiểu tổng quan về hệ thống, các modules chính và technology stack
  2. Kiến trúc hệ thống: Đi sâu vào chi tiết từng module, responsibilities và interactions
  3. Luồng dữ liệu: Hiểu message flow từ sender đến receiver, bao gồm cả error handling
  4. API Design: Chi tiết về REST APIs và RPC interfaces
  5. Data Model: Database schema và data storage strategies
  6. Deployment: Hướng dẫn deploy và configuration

Chỉ số định lượng

MetricValueNote
Số modules chính6api, connect_websocket, connect_tcp, logic, task, site
Protocols hỗ trợ2WebSocket, TCP
RPC methods4+PushSingleMsg, PushRoomMsg, PushRoomCount, etc.
Message operations4Single send, Room broadcast, Room count, Room info
Go version1.18Minimum required version
Direct dependencies15+Core libraries trong go.mod
Database support2+SQLite (default), MySQL (via GORM)
Queue support3+Redis (default), Kafka, RabbitMQ (pluggable)
ID throughput4.096M/sTheoretical max với Snowflake

Kết luận

gochat là một well-architected IM system demonstration với clean separation of concerns và horizontal scalability. Dự án showcase best practices trong việc xây dựng real-time messaging systems bằng Go, bao gồm:

  • Microservice Architecture: Clear separation giữa API, Logic, Connect, và Task layers
  • Multi-protocol Support: Đồng thời hỗ trợ WebSocket và TCP với message interop
  • Scalable Design: Tất cả components có thể scale independently
  • Production-ready Patterns: Service discovery, message queuing, distributed ID generation

Dự án phù hợp cho việc học tập về distributed systems design và có thể serve as starting point cho production IM systems với proper enhancements như adding authentication, persistence, và monitoring.