3 changed files with 272 additions and 0 deletions
@ -0,0 +1,116 @@ |
|||||
|
package webstocetmsg |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"sync" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/golang-module/carbon" |
||||
|
) |
||||
|
|
||||
|
var GatewayClients, GatewayUser, GatewayGroup sync.Map |
||||
|
|
||||
|
/** |
||||
|
* @description: 客户端心跳检测,超时即断开连接(主要是为了降低服务端承载压力) |
||||
|
* @param {string} clientID |
||||
|
* @return {*} |
||||
|
*/ |
||||
|
|
||||
|
func clientHeartbeatCheck(clientID string) { |
||||
|
|
||||
|
for { |
||||
|
|
||||
|
time.Sleep(5 * time.Second) |
||||
|
|
||||
|
clientInterface, exists := GatewayClients.Load(clientID) |
||||
|
|
||||
|
if !exists { |
||||
|
|
||||
|
break |
||||
|
} |
||||
|
|
||||
|
client, _ := clientInterface.(*WebSocketClientBase) |
||||
|
|
||||
|
if (carbon.Now().Timestamp() - client.LastHeartbeat) > int64(HeartbeatTime) { |
||||
|
|
||||
|
fmt.Println("Client", clientID, "heartbeat timeout") |
||||
|
|
||||
|
client.Conn.Close() |
||||
|
GatewayClients.Delete(clientID) |
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description: 客户端断线时自动踢出Uid绑定列表 |
||||
|
* @param {string} clientID |
||||
|
* @param {string} uid |
||||
|
* @return {*} |
||||
|
*/ |
||||
|
func clientUnBindUid(clientID string, uid string) { |
||||
|
|
||||
|
value, ok := GatewayUser.Load(uid) |
||||
|
|
||||
|
if ok { |
||||
|
|
||||
|
users := value.(*WebSocketUserBase) |
||||
|
|
||||
|
for k, v := range users.ClientID { |
||||
|
|
||||
|
if v == clientID { |
||||
|
|
||||
|
users.ClientID = append(users.ClientID[:k], users.ClientID[k+1:]...) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if len(users.ClientID) == 0 { |
||||
|
|
||||
|
GatewayUser.Delete(uid) |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description: 客户端断线时自动踢出已加入的群组 |
||||
|
* @param {string} clientID |
||||
|
* @return {*} |
||||
|
*/ |
||||
|
func clientLeaveGroup(clientID string) { |
||||
|
// 使用 Load 方法获取值
|
||||
|
value, ok := GatewayClients.Load(clientID) |
||||
|
if !ok { |
||||
|
// 如果没有找到对应的值,处理相应的逻辑
|
||||
|
return |
||||
|
} |
||||
|
|
||||
|
client := value.(*WebSocketClientBase) |
||||
|
|
||||
|
// 遍历 JoinGroup
|
||||
|
for _, v := range client.JoinGroup { |
||||
|
// 使用 Load 方法获取值
|
||||
|
groupValue, groupOK := GatewayGroup.Load(v) |
||||
|
if !groupOK { |
||||
|
// 如果没有找到对应的值,处理相应的逻辑
|
||||
|
continue |
||||
|
} |
||||
|
|
||||
|
group := groupValue.(*WebSocketGroupBase) |
||||
|
|
||||
|
// 在群组中找到对应的 clientID,并删除
|
||||
|
for j, id := range group.ClientID { |
||||
|
if id == clientID { |
||||
|
copy(group.ClientID[j:], group.ClientID[j+1:]) |
||||
|
group.ClientID = group.ClientID[:len(group.ClientID)-1] |
||||
|
|
||||
|
// 如果群组中没有成员了,删除群组
|
||||
|
if len(group.ClientID) == 0 { |
||||
|
GatewayGroup.Delete(v) |
||||
|
} |
||||
|
|
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
[gateway] |
||||
|
# gateway服务运行占用端口 (默认占用端口:20818) |
||||
|
gatewayServicePort = 8282 |
||||
|
|
||||
|
# gRPC服务运行占用端口(默认占用端口:20819) |
||||
|
gRPCServicePort = 8182 |
||||
|
|
||||
|
# 消息发送缓冲区大小,如果这个值设置得太小,可能会导致服务端在发送大型消息时遇到问题 (默认大小:1024byte) |
||||
|
writeBufferSize = 1024 |
||||
|
|
||||
|
# websocket消息内容格式(默认:text,可选,text = 文本,binary = 二进制) |
||||
|
messageFormat = text |
||||
|
|
||||
|
# 心跳超时时间,超时未发送ping包服务端自动断线(默认时长:180秒) |
||||
|
heartbeatTimeout = 360 |
||||
|
|
||||
|
[server] |
||||
|
|
||||
|
# 限制服务端的来源(默认为空即不限制服务端来源,多个ip使用逗号分割即可) |
||||
|
ip = [] |
||||
|
|
||||
|
[cluster] |
||||
|
|
||||
|
# 集群名称 |
||||
|
clusterName = "gateway" |
||||
@ -0,0 +1,131 @@ |
|||||
|
package webstocketconfig |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"net" |
||||
|
"os" |
||||
|
"strconv" |
||||
|
|
||||
|
"github.com/gorilla/websocket" |
||||
|
"gopkg.in/ini.v1" |
||||
|
) |
||||
|
|
||||
|
var GatewayConfig = make(map[string]interface{}) |
||||
|
|
||||
|
/** |
||||
|
* @description: 初始化进程 |
||||
|
* @return {*} |
||||
|
*/ |
||||
|
func init() { |
||||
|
|
||||
|
/** |
||||
|
* 初始化时定义服务的配置项 |
||||
|
*/ |
||||
|
|
||||
|
GatewayConfig["GatewayServicePort"] = 20818 |
||||
|
GatewayConfig["WriteBufferSize"] = 1024 |
||||
|
GatewayConfig["HeartbeatTimeout"] = 180 |
||||
|
GatewayConfig["GRPCServicePort"] = 20819 |
||||
|
GatewayConfig["ClientIP"] = []string{} |
||||
|
GatewayConfig["MessageFormat"] = websocket.TextMessage |
||||
|
|
||||
|
configPath := "./webstocketconfig/config.ini" |
||||
|
|
||||
|
checkPath := func(path string) bool { |
||||
|
|
||||
|
_, err := os.Stat(path) |
||||
|
|
||||
|
return err == nil || os.IsExist(err) |
||||
|
} |
||||
|
|
||||
|
if !checkPath(configPath) { |
||||
|
|
||||
|
return |
||||
|
} |
||||
|
|
||||
|
cnf, err := ini.Load(configPath) |
||||
|
|
||||
|
if err != nil { |
||||
|
|
||||
|
return |
||||
|
} |
||||
|
|
||||
|
// 设置gRPC服务端运行端口
|
||||
|
if cnf.Section("gateway").Key("gRPCServicePort").String() != "" { |
||||
|
|
||||
|
gRPCServicePort, err := strconv.Atoi(cnf.Section("gateway").Key("gRPCServicePort").String()) |
||||
|
|
||||
|
if err == nil { |
||||
|
|
||||
|
GatewayConfig["GRPCServicePort"] = gRPCServicePort |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 设置ws服务端运行端口
|
||||
|
if cnf.Section("gateway").Key("gatewayServicePort").String() != "" { |
||||
|
|
||||
|
gatewayServicePort, err := strconv.Atoi(cnf.Section("gateway").Key("gatewayServicePort").String()) |
||||
|
|
||||
|
if err == nil { |
||||
|
|
||||
|
GatewayConfig["GatewayServicePort"] = gatewayServicePort |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 消息发送缓冲区大小
|
||||
|
if cnf.Section("gateway").Key("writeBufferSize").String() != "" { |
||||
|
|
||||
|
writeBufferSize, err := strconv.Atoi(cnf.Section("gateway").Key("writeBufferSize").String()) |
||||
|
|
||||
|
if err == nil { |
||||
|
|
||||
|
GatewayConfig["WriteBufferSize"] = writeBufferSize |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 设置websocket消息体格式
|
||||
|
if cnf.Section("gateway").Key("messageFormat").String() != "" { |
||||
|
|
||||
|
if cnf.Section("gateway").Key("messageFormat").String() == "binary" { |
||||
|
|
||||
|
GatewayConfig["MessageFormat"] = websocket.BinaryMessage |
||||
|
|
||||
|
} else { |
||||
|
|
||||
|
GatewayConfig["MessageFormat"] = websocket.TextMessage |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 心跳超时时间
|
||||
|
if cnf.Section("gateway").Key("heartbeatTimeout").String() != "" { |
||||
|
|
||||
|
heartbeatTimeout, err := strconv.Atoi(cnf.Section("gateway").Key("heartbeatTimeout").String()) |
||||
|
|
||||
|
if err == nil { |
||||
|
|
||||
|
GatewayConfig["HeartbeatTimeout"] = heartbeatTimeout |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if cnf.Section("server").Key("ip").String() != "" { |
||||
|
|
||||
|
var ips []string |
||||
|
|
||||
|
if err := json.Unmarshal([]byte(cnf.Section("server").Key("ip").String()), &ips); err != nil { |
||||
|
|
||||
|
return |
||||
|
} |
||||
|
|
||||
|
var validIPs []string |
||||
|
|
||||
|
for _, ip := range ips { |
||||
|
|
||||
|
if net.ParseIP(ip) != nil { |
||||
|
|
||||
|
validIPs = append(validIPs, ip) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
GatewayConfig["ServerIP"] = validIPs |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue