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  }