github.com/glide-im/glide@v1.6.0/internal/im_server/gateway.go (about) 1 package im_server 2 3 import ( 4 "github.com/glide-im/glide/pkg/conn" 5 "github.com/glide-im/glide/pkg/gate" 6 "github.com/glide-im/glide/pkg/logger" 7 "github.com/glide-im/glide/pkg/messages" 8 "github.com/rcrowley/go-metrics" 9 "time" 10 ) 11 12 type GatewayMetrics struct { 13 ServerId string 14 Addr string 15 Port int 16 StartAt time.Time 17 RunningHours float64 18 Message *MessageMetrics 19 Conn *ConnectionMetrics 20 } 21 22 var _ gate.DefaultGateway = (*GatewayServer)(nil) 23 24 type GatewayServer struct { 25 decorator *gate.Impl 26 27 server conn.Server 28 h gate.MessageHandler 29 30 gateID string 31 addr string 32 port int 33 34 metrics *GatewayMetrics 35 } 36 37 func (c *GatewayServer) GetClient(id gate.ID) gate.Client { 38 return c.decorator.GetClient(id) 39 } 40 41 func (c *GatewayServer) GetAll() map[gate.ID]gate.Info { 42 return c.decorator.GetAll() 43 } 44 45 func (c *GatewayServer) AddClient(cs gate.Client) { 46 c.decorator.AddClient(cs) 47 } 48 49 func NewServer(id string, addr string, port int, secretKey string) (*GatewayServer, error) { 50 srv := GatewayServer{} 51 srv.decorator, _ = gate.NewServer( 52 &gate.Options{ 53 ID: id, 54 MaxMessageConcurrency: 30_0000, 55 SecretKey: secretKey, 56 }, 57 ) 58 srv.metrics = &GatewayMetrics{ 59 ServerId: id, 60 Addr: addr, 61 Port: port, 62 Message: NewMessageMetrics(), 63 Conn: NewConnectionMetrics(), 64 } 65 srv.addr = addr 66 srv.port = port 67 srv.gateID = id 68 69 sample := metrics.NewExpDecaySample(1024, 0.015) 70 histogram := metrics.NewHistogram(sample) 71 _ = metrics.Register("s", histogram) 72 histogram.Update(1) 73 74 options := &conn.WsServerOptions{ 75 ReadTimeout: time.Minute * 3, 76 WriteTimeout: time.Minute * 3, 77 } 78 srv.server = conn.NewWsServer(options) 79 return &srv, nil 80 } 81 82 func (c *GatewayServer) Run() error { 83 84 c.metrics.StartAt = time.Now() 85 86 c.server.SetConnHandler(func(conn conn.Connection) { 87 c.HandleConnection(conn) 88 c.metrics.Conn.Connected() 89 }) 90 return c.server.Run(c.addr, c.port) 91 } 92 93 func (c *GatewayServer) SetMessageHandler(h gate.MessageHandler) { 94 handler := func(id *gate.Info, msg *messages.GlideMessage) { 95 c.metrics.Message.In() 96 h(id, msg) 97 } 98 c.h = handler 99 c.decorator.SetMessageHandler(handler) 100 } 101 102 // HandleConnection 当一个用户连接建立后, 由该方法创建 UserClient 实例 UserClient 并管理该连接, 返回该由连接创建客户端的标识 id 103 // 返回的标识 id 是一个临时 id, 后续连接认证后会改变 104 func (c *GatewayServer) HandleConnection(conn conn.Connection) gate.ID { 105 106 // 获取一个临时 uid 标识这个连接 107 id, err := gate.GenTempID(c.gateID) 108 if err != nil { 109 logger.E("[gateway] gen temp id error: %v", err) 110 return "" 111 } 112 ret := gate.NewClientWithConfig(conn, c, c.h, &gate.ClientConfig{ 113 HeartbeatLostLimit: 3, 114 ClientHeartbeatDuration: time.Second * 30, 115 ServerHeartbeatDuration: time.Second * 30, 116 CloseImmediately: false, 117 }) 118 ret.SetID(id) 119 c.decorator.AddClient(ret) 120 121 // 开始处理连接的消息 122 ret.Run() 123 124 hello := messages.ServerHello{ 125 TempID: id.UID(), 126 HeartbeatInterval: 30, 127 } 128 129 m := messages.NewMessage(0, messages.ActionHello, hello) 130 _ = ret.EnqueueMessage(m) 131 132 return id 133 } 134 135 func (c *GatewayServer) EnqueueMessage(id gate.ID, msg *messages.GlideMessage) error { 136 err := c.decorator.EnqueueMessage(id, msg) 137 if err != nil { 138 c.metrics.Message.Out() 139 } else { 140 c.metrics.Message.OutFailed() 141 } 142 return err 143 } 144 145 func (c *GatewayServer) SetClientID(oldID, newID gate.ID) error { 146 err := c.decorator.SetClientID(oldID, newID) 147 if err == nil { 148 c.metrics.Conn.Login() 149 } 150 return err 151 } 152 153 func (c *GatewayServer) ExitClient(id gate.ID) error { 154 id.SetGateway(c.gateID) 155 156 client := c.decorator.GetClient(id) 157 if client != nil { 158 c.metrics.Conn.Exit(client.GetInfo()) 159 } 160 161 err := c.decorator.ExitClient(id) 162 return err 163 } 164 165 func (c *GatewayServer) GetState() GatewayMetrics { 166 span := time.Now().Unix() - c.metrics.StartAt.Unix() 167 c.metrics.RunningHours = float64(span) / 60.0 / 60.0 168 return *c.metrics 169 } 170 171 func (c *GatewayServer) UpdateClient(id gate.ID, info *gate.ClientSecrets) error { 172 return c.decorator.UpdateClient(id, info) 173 }