| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- package bootstraps
-
- import (
- "context"
- "fmt"
- "log"
- "net/http"
- "os"
- "os/signal"
- "syscall"
- "time"
-
- "git.x2erp.com/qdy/go-base/config"
- "git.x2erp.com/qdy/go-base/logger"
- )
-
- // Bootstrapper 服务启动器
- type Bootstrapper struct {
- serviceName string
- serviceVersion string
- Cfg config.IConfig
- HttpServer *http.Server
- Router *http.ServeMux
- quit chan os.Signal
- }
-
- // New 创建启动器
- func New(name, version string) *Bootstrapper {
- b := &Bootstrapper{
- serviceName: name,
- serviceVersion: version,
- quit: make(chan os.Signal, 1),
- Router: http.NewServeMux(), // 直接创建路由器
- }
-
- return b
- }
-
- // Init 初始化配置和日志
- func (b *Bootstrapper) Init() *Bootstrapper {
- // 1. 初始化启动日志
- if err := logger.InitBootLog(b.serviceName); err != nil {
- log.Fatal("无法初始化启动日志: ", err)
- }
-
- // 2. 加载配置
- log.Println("正在加载配置...")
- cfg, err := config.GetConfig()
- if err != nil {
- log.Fatalf("加载配置失败: %v", err)
- }
- cfg.SetServiceName(b.serviceName)
- cfg.SetServiceVersion(b.serviceVersion)
- b.Cfg = cfg
-
- // 3. 初始化运行时日志
- logger.InitRuntimeLogger(b.serviceName, b.serviceVersion, b.Cfg.GetLog())
- log.Println("配置和日志初始化完成")
-
- return b
- }
-
- // StartService 启动HTTP服务
- func (b *Bootstrapper) StartService() *Bootstrapper {
- serviceCfg := b.Cfg.GetService()
-
- // 创建HTTP服务器
- b.HttpServer = &http.Server{
- Addr: fmt.Sprintf(":%d", serviceCfg.Port),
- Handler: b.Router, // 直接使用Router
- ReadTimeout: 15 * time.Second,
- WriteTimeout: 15 * time.Second,
- IdleTimeout: 60 * time.Second,
- }
-
- log.Printf("正在启动服务: %s v%s", b.serviceName, b.serviceVersion)
- log.Printf("模式: 独立运行 (net/http)")
- log.Printf("服务端口: :%d", serviceCfg.Port)
-
- return b
- }
-
- // Run 运行服务
- func (b *Bootstrapper) Run() {
- log.Printf("服务 %s 开始运行...", b.serviceName)
-
- // 设置信号监听 - 在这里设置,而不是在New中
- signal.Notify(b.quit, syscall.SIGINT, syscall.SIGTERM)
-
- // 启动HTTP服务器
- go func() {
- log.Printf("服务器启动在 %s", b.HttpServer.Addr)
- if err := b.HttpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
- log.Fatalf("服务运行失败: %v", err)
- }
- }()
-
- // 等待中断信号
- b.waitForShutdown()
- }
-
- // RunTLS 运行HTTPS服务
- func (b *Bootstrapper) RunTLS(certFile, keyFile string) {
- log.Printf("服务 %s 开始运行(HTTPS)...", b.serviceName)
-
- // 设置信号监听
- signal.Notify(b.quit, syscall.SIGINT, syscall.SIGTERM)
-
- // 启动HTTPS服务器
- go func() {
- log.Printf("HTTPS服务器启动在 %s", b.HttpServer.Addr)
- if err := b.HttpServer.ListenAndServeTLS(certFile, keyFile); err != nil && err != http.ErrServerClosed {
- log.Fatalf("服务运行失败: %v", err)
- }
- }()
-
- // 等待中断信号
- b.waitForShutdown()
- }
-
- // waitForShutdown 等待关闭信号
- func (b *Bootstrapper) waitForShutdown() {
- log.Println("按 Ctrl+C 停止服务")
-
- // 等待信号
- <-b.quit
- log.Println("接收到终止信号,正在优雅关闭服务...")
-
- // 创建关闭上下文,给30秒完成当前请求
- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
- defer cancel()
-
- // 停止接收新请求,完成当前请求
- if err := b.HttpServer.Shutdown(ctx); err != nil {
- log.Printf("服务关闭失败: %v", err)
- } else {
- log.Println("HTTP服务器已关闭")
- }
-
- // 停止日志写入
- logger.StopESWriter()
- log.Println("服务优雅关闭完成")
-
- // 等待一小段时间确保日志写入完成
- time.Sleep(100 * time.Millisecond)
- os.Exit(0)
- }
-
- // GetConfig 获取配置
- func (b *Bootstrapper) GetConfig() config.IConfig {
- return b.Cfg
- }
-
- // GetRouter 获取路由器
- func (b *Bootstrapper) GetRouter() *http.ServeMux {
- return b.Router
- }
-
- // 兼容性方法
-
- // GetWebService 获取Web服务(兼容性方法)
- func (b *Bootstrapper) GetWebService() interface{} {
- return b.Router
- }
-
- // Handle 注册路由处理器(兼容性方法)
- func (b *Bootstrapper) Handle(pattern string, handler http.Handler) {
- b.Router.Handle(pattern, handler)
- }
|