2026-02-03 23:45:27 +08:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"ChatRoom/internal/rabbitmq"
|
2026-02-04 13:06:11 +08:00
|
|
|
|
"ChatRoom/internal/redis"
|
2026-02-03 23:45:27 +08:00
|
|
|
|
"ChatRoom/internal/ws"
|
|
|
|
|
|
"log"
|
|
|
|
|
|
"net/http"
|
|
|
|
|
|
"os"
|
|
|
|
|
|
"path/filepath"
|
2026-02-04 14:52:59 +08:00
|
|
|
|
"time"
|
2026-02-03 23:45:27 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
|
// 1. 初始化 RabbitMQ
|
|
|
|
|
|
rabbitmqURL := os.Getenv("RABBITMQ_URL")
|
|
|
|
|
|
if rabbitmqURL == "" {
|
2026-02-04 14:52:59 +08:00
|
|
|
|
// 默认使用本地 Docker 启动的 RabbitMQ 配置 (admin/1218Zhengyaqi)
|
|
|
|
|
|
rabbitmqURL = "amqp://admin:1218Zhengyaqi@localhost:5672/"
|
2026-02-04 13:06:11 +08:00
|
|
|
|
}
|
2026-02-04 14:52:59 +08:00
|
|
|
|
|
|
|
|
|
|
var rmq *rabbitmq.Client
|
|
|
|
|
|
var err error
|
|
|
|
|
|
maxRetries := 30
|
|
|
|
|
|
for i := 0; i < maxRetries; i++ {
|
|
|
|
|
|
rmq, err = rabbitmq.NewClient(rabbitmqURL)
|
|
|
|
|
|
if err == nil {
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
// 如果是 403 认证错误,重试也没用,直接报错退出
|
|
|
|
|
|
if err.Error() == "Exception (403) Reason: \"username or password not allowed\"" {
|
|
|
|
|
|
log.Fatalf("RabbitMQ 认证失败,请检查账号密码: %v", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
log.Printf("RabbitMQ 连接失败 (尝试 %d/%d): %v, 2秒后重试...", i+1, maxRetries, err)
|
|
|
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 23:45:27 +08:00
|
|
|
|
if err != nil {
|
2026-02-04 14:52:59 +08:00
|
|
|
|
log.Fatalf("RabbitMQ 连接最终失败: %v", err)
|
2026-02-03 23:45:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
defer rmq.Close()
|
|
|
|
|
|
|
2026-02-04 13:06:11 +08:00
|
|
|
|
// 1.5 初始化 Redis
|
|
|
|
|
|
redisAddr := os.Getenv("REDIS_ADDR")
|
|
|
|
|
|
if redisAddr == "" {
|
|
|
|
|
|
redisAddr = "localhost:6379"
|
|
|
|
|
|
}
|
|
|
|
|
|
redisClient, err := redis.NewClient(redisAddr, "", 0)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
log.Fatalf("Redis 连接失败: %v", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
defer redisClient.Close()
|
|
|
|
|
|
|
2026-02-03 23:45:27 +08:00
|
|
|
|
// 2. WebSocket 路由
|
|
|
|
|
|
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
|
2026-02-04 13:06:11 +08:00
|
|
|
|
ws.NewConnection(w, r, rmq, redisClient) // 传入 RabbitMQ 和 Redis 客户端
|
2026-02-03 23:45:27 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 静态文件服务(用于测试前端)
|
|
|
|
|
|
webDir := "./web"
|
|
|
|
|
|
if _, err := os.Stat(webDir); os.IsNotExist(err) {
|
|
|
|
|
|
// 从 cmd/server 目录运行时,web 在项目根目录
|
|
|
|
|
|
webDir = filepath.Join("..", "..", "web")
|
|
|
|
|
|
}
|
|
|
|
|
|
http.Handle("/", http.FileServer(http.Dir(webDir)))
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 启动服务
|
|
|
|
|
|
port := os.Getenv("PORT")
|
|
|
|
|
|
if port == "" {
|
|
|
|
|
|
port = "8080"
|
|
|
|
|
|
}
|
|
|
|
|
|
log.Printf("服务启动: http://localhost:%s", port)
|
|
|
|
|
|
log.Fatal(http.ListenAndServe(":"+port, nil))
|
|
|
|
|
|
}
|