|
@@ -2,164 +2,14 @@ package main
|
|
|
|
|
|
import (
|
|
|
"encoding/json"
|
|
|
- "errors"
|
|
|
"flag"
|
|
|
- "io"
|
|
|
"math/rand"
|
|
|
"mfw/util"
|
|
|
- "sync"
|
|
|
- "time"
|
|
|
)
|
|
|
|
|
|
//
|
|
|
-type ClientItem struct {
|
|
|
- conn io.ReadWriteCloser
|
|
|
- timestamp int64
|
|
|
- name string //
|
|
|
- canhandlerevent []int //
|
|
|
- id string
|
|
|
-}
|
|
|
-
|
|
|
-//
|
|
|
-var lock sync.Mutex
|
|
|
var gcinterval int64
|
|
|
|
|
|
-//所有的请求
|
|
|
-var allclient map[string]*ClientItem = make(map[string]*ClientItem)
|
|
|
-
|
|
|
-//服务与提供者对应表
|
|
|
-var allservice map[int][]string = make(map[int][]string)
|
|
|
-
|
|
|
-//心跳检测规则重新定义::
|
|
|
-//每次读写都会刷新心跳时间,
|
|
|
-//长时间未发生读写时发送心跳查询,
|
|
|
-//3倍检测时间后仍未响应的,自动剔除队列
|
|
|
-func gc() {
|
|
|
- now := time.Now().Unix()
|
|
|
- now_bs := util.Int2Byte(int32(now))
|
|
|
- for k, v := range allclient {
|
|
|
- if now-v.timestamp > gcinterval*3 {
|
|
|
- v.conn.Close()
|
|
|
- removeClient(k)
|
|
|
- continue
|
|
|
- } else if now-v.timestamp > gcinterval {
|
|
|
- util.Log.Debug.Println("发送心跳请求包到", v.name)
|
|
|
- _, err := v.conn.Write(util.Enpacket("", k, "", util.EVENT_REQUEST_HEARTBEAT,
|
|
|
- util.SENDTO_TYPE_P2P, now_bs))
|
|
|
- if err != nil { //发心跳包出错
|
|
|
- v.conn.Close()
|
|
|
- removeClient(k)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- time.AfterFunc(time.Duration(gcinterval)*time.Second, gc)
|
|
|
-}
|
|
|
-
|
|
|
-//删除服务节点
|
|
|
-func removeClient(myid string) {
|
|
|
- lock.Lock()
|
|
|
- defer lock.Unlock()
|
|
|
- defer util.Catch()
|
|
|
- if v, ok := allclient[myid]; ok {
|
|
|
- v.conn.Close()
|
|
|
- }
|
|
|
- delete(allclient, myid)
|
|
|
- for k, v := range allservice {
|
|
|
- for j, smid := range v {
|
|
|
- if smid == myid {
|
|
|
- allservice[k] = append(v[:j], v[j+1:]...)
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- util.Log.Debug.Println("删除节点", myid, "全部服务", allservice)
|
|
|
-}
|
|
|
-
|
|
|
-//通过名称查找客户端
|
|
|
-func findClientByName(name string) (*ClientItem, error) {
|
|
|
- for _, c := range allclient {
|
|
|
- if c.name == name {
|
|
|
- return c, nil
|
|
|
- }
|
|
|
- }
|
|
|
- return nil, errors.New("cant't find the client")
|
|
|
-}
|
|
|
-
|
|
|
-//发布服务
|
|
|
-func publishservice(myid string, s []int) {
|
|
|
- if myid == "00000000" { //无效请求验证
|
|
|
- return
|
|
|
- }
|
|
|
- lock.Lock()
|
|
|
- defer lock.Unlock()
|
|
|
- defer util.Catch()
|
|
|
- if allclient[myid] != nil {
|
|
|
- allclient[myid].canhandlerevent = s
|
|
|
- //删除该ID以前发布的服务
|
|
|
- for k, v := range allservice {
|
|
|
- for j, smid := range v {
|
|
|
- if smid == myid {
|
|
|
- allservice[k] = append(v[:j], v[j+1:]...)
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- //追加新发布的服务
|
|
|
- for _, v := range s {
|
|
|
- if v == util.EVENT_RETURN { //回调的不再作为服务注册
|
|
|
- continue
|
|
|
- }
|
|
|
- allservice[v] = append(allservice[v], myid)
|
|
|
- }
|
|
|
- }
|
|
|
- util.Log.Debug.Println("全部服务", allservice)
|
|
|
-}
|
|
|
-
|
|
|
-//更新心跳
|
|
|
-func updateheartbeat(from string) {
|
|
|
- lock.Lock()
|
|
|
- defer lock.Unlock()
|
|
|
- defer util.Catch()
|
|
|
- if v, ok := allclient[from]; ok {
|
|
|
- v.timestamp = time.Now().Unix()
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-//加入网络
|
|
|
-func join(msg *util.Packet) {
|
|
|
- data := map[string]interface{}{}
|
|
|
- err := json.Unmarshal(msg.Raw, &data)
|
|
|
- if err != nil { //解析join指令失败
|
|
|
- msg.Conn.Close()
|
|
|
- return
|
|
|
- }
|
|
|
- //
|
|
|
- uuid := data["myid"].(string)
|
|
|
- if allclient[uuid] != nil {
|
|
|
- util.Log.Debug.Println(uuid, "已经存在")
|
|
|
- msg.Conn.Close()
|
|
|
- return
|
|
|
- }
|
|
|
- //
|
|
|
- clientname := data["name"].(string)
|
|
|
- handers_o_arr := data["handler"].([]interface{})
|
|
|
- handers := []int{}
|
|
|
- for _, v := range handers_o_arr {
|
|
|
- handers = append(handers, int(v.(float64)))
|
|
|
- }
|
|
|
- //
|
|
|
- allclient[uuid] = &ClientItem{conn: msg.Conn,
|
|
|
- timestamp: time.Now().Unix(),
|
|
|
- name: clientname,
|
|
|
- id: uuid,
|
|
|
- }
|
|
|
- //
|
|
|
- publishservice(uuid, handers)
|
|
|
- util.Log.Debug.Println(allservice)
|
|
|
-}
|
|
|
-
|
|
|
//处理客户端发过来的消息
|
|
|
func processmsg(msg *util.Packet) {
|
|
|
defer util.Catch()
|
|
@@ -171,7 +21,7 @@ func processmsg(msg *util.Packet) {
|
|
|
//TODO 只写需要特殊处理的时间,其他都走default
|
|
|
case util.EVENT_REQUEST_JOIN:
|
|
|
//TODO 加入指令,直接返回
|
|
|
- join(msg)
|
|
|
+ joinNetwork(msg)
|
|
|
case util.EVENT_RETURN_HEARTBEAT: //心跳回应包处理
|
|
|
case util.EVENT_PUBLISH_MYSERVICES: //客户端发布了自己的服务,支持二次发布服务,用于暂停、更新服务能力
|
|
|
services := []int{}
|
|
@@ -198,13 +48,6 @@ func processmsg(msg *util.Packet) {
|
|
|
updateheartbeat(msg.To)
|
|
|
}
|
|
|
}
|
|
|
- } else if sttype == util.SENDTO_TYPE_P2P_BYNAME { //通过名称点对点发消息
|
|
|
- if v2, err2 := findClientByName(msg.To); err2 == nil {
|
|
|
- _, err := v2.conn.Write(msg.Bytes())
|
|
|
- if err == nil {
|
|
|
- updateheartbeat(v2.id)
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
if v, ok := allservice[event]; ok {
|
|
|
switch sttype {
|
|
@@ -214,9 +57,7 @@ func processmsg(msg *util.Packet) {
|
|
|
break
|
|
|
}
|
|
|
service_machine_id := v[rand.Intn(len(v))]
|
|
|
- lock.Lock()
|
|
|
client, ok := allclient[service_machine_id]
|
|
|
- lock.Unlock()
|
|
|
if ok {
|
|
|
_, err := client.conn.Write(msg.Bytes())
|
|
|
if err == nil {
|
|
@@ -226,7 +67,6 @@ func processmsg(msg *util.Packet) {
|
|
|
removeClient(service_machine_id)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
case util.SENDTO_TYPE_ALL_RECIVER:
|
|
|
if v, ok := allservice[event]; ok {
|
|
@@ -255,12 +95,14 @@ func main() {
|
|
|
interval := flag.Int64("gc", 10, "GC间隔时间")
|
|
|
usetls := flag.Bool("usetls", false, "是否使用tls")
|
|
|
tlsca := flag.String("ca", "", "ca文件")
|
|
|
+ log2std := flag.Bool("log2std", false, "日志是否输出到控制台")
|
|
|
+ logsizelimit := flag.Int64("loglimit", 50, "日志文件大(mByte)小限制,超过限制会自动切分日志文件")
|
|
|
tlscert := flag.String("cert", "", "cert文件")
|
|
|
tlskey := flag.String("key", "", "key文件")
|
|
|
flag.Parse()
|
|
|
gcinterval = *interval
|
|
|
//初始化日志
|
|
|
- util.Log = util.NewLogger("./logs", util.LOG_LEVEL_INFO, true, "msgserver", 1024*1024*50)
|
|
|
+ util.Log = util.NewLogger("./logs", util.LOG_LEVEL_INFO, *log2std, "msgserver", *logsizelimit*1024*1024)
|
|
|
//心跳检测
|
|
|
go gc()
|
|
|
//启动服务
|