github.com/15mga/kiwi@v0.0.2-0.20240324021231-b95d5c3ac751/core/node_net.go (about)

     1  package core
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/15mga/kiwi"
     6  	"github.com/15mga/kiwi/ds"
     7  	"github.com/15mga/kiwi/network"
     8  	"github.com/15mga/kiwi/util"
     9  	"github.com/15mga/kiwi/worker"
    10  	"math/rand"
    11  	"net"
    12  )
    13  
    14  type (
    15  	NodeOption func(opt *nodeOption)
    16  	nodeOption struct {
    17  		ip       string
    18  		port     int
    19  		connType NodeConnType
    20  		selector NodeDialerSelector
    21  	}
    22  	NodeConnType uint8
    23  )
    24  
    25  type NodeDialerSelector func(set *ds.Set2Item[kiwi.TSvc, int64, kiwi.INodeDialer]) (int64, *util.Err)
    26  
    27  const (
    28  	Tcp NodeConnType = iota
    29  	Udp
    30  )
    31  
    32  func NodeType(t NodeConnType) NodeOption {
    33  	return func(opt *nodeOption) {
    34  		opt.connType = t
    35  	}
    36  }
    37  
    38  func NodeIp(ip string) NodeOption {
    39  	return func(opt *nodeOption) {
    40  		opt.ip = ip
    41  	}
    42  }
    43  
    44  func NodePort(port int) NodeOption {
    45  	return func(opt *nodeOption) {
    46  		opt.port = port
    47  	}
    48  }
    49  
    50  func NodeSelector(selector NodeDialerSelector) NodeOption {
    51  	return func(opt *nodeOption) {
    52  		opt.selector = selector
    53  	}
    54  }
    55  
    56  func InitNodeNet(opts ...NodeOption) {
    57  	kiwi.SetNode(NewNodeNet(opts...))
    58  }
    59  
    60  func NewNodeNet(opts ...NodeOption) kiwi.INode {
    61  	opt := &nodeOption{
    62  		connType: Tcp,
    63  		selector: func(set *ds.Set2Item[kiwi.TSvc, int64, kiwi.INodeDialer]) (int64, *util.Err) {
    64  			i := rand.Intn(set.Count())
    65  			dialer, _ := set.GetWithIdx(i)
    66  			return dialer.NodeId(), nil
    67  		},
    68  	}
    69  	for _, o := range opts {
    70  		o(opt)
    71  	}
    72  	n := &nodeNet{
    73  		option:   opt,
    74  		nodeBase: newNodeBase(),
    75  		svcToDialer: ds.NewKSet2[kiwi.TSvc, int64, kiwi.INodeDialer](8, func(dialer kiwi.INodeDialer) int64 {
    76  			return dialer.NodeId()
    77  		}),
    78  		idToDialer: ds.NewKSet[int64, kiwi.INodeDialer](16, func(dialer kiwi.INodeDialer) int64 {
    79  			return dialer.NodeId()
    80  		}),
    81  		codeToWatchers: make(map[kiwi.TCode]map[int64]struct{}),
    82  	}
    83  	ip, err := util.CheckLocalIp(opt.ip)
    84  	if err != nil {
    85  		kiwi.Fatal(err)
    86  	}
    87  	opt.ip = ip
    88  	n.worker = worker.NewJobWorker(n.processor)
    89  	addr := fmt.Sprintf("%s:%d", n.option.ip, n.option.port)
    90  	switch opt.connType {
    91  	case Tcp:
    92  		n.listener = network.NewTcpListener(addr, n.onAddTcpConn)
    93  	case Udp:
    94  		n.listener = network.NewUdpListener(addr, n.onAddUdpConn)
    95  	}
    96  
    97  	err = n.listener.Start()
    98  	if err != nil {
    99  		panic(err.Error())
   100  	}
   101  
   102  	n.worker.Start()
   103  	return n
   104  }
   105  
   106  type nodeNet struct {
   107  	nodeBase
   108  	option         *nodeOption
   109  	worker         *worker.JobWorker
   110  	svcToDialer    *ds.KSet2[kiwi.TSvc, int64, kiwi.INodeDialer]
   111  	idToDialer     *ds.KSet[int64, kiwi.INodeDialer]
   112  	listener       kiwi.IListener
   113  	codeToWatchers map[kiwi.TCode]map[int64]struct{} //本机方法的远程监听者
   114  	watcherToCodes map[int64][]kiwi.TCode            //远程机监听的方法
   115  }
   116  
   117  func (n *nodeNet) Init() *util.Err {
   118  	return nil
   119  }
   120  
   121  func (n *nodeNet) Ip() string {
   122  	return n.option.ip
   123  }
   124  
   125  func (n *nodeNet) Port() int {
   126  	return n.listener.Port()
   127  }
   128  
   129  func (n *nodeNet) Connect(ip string, port int, svc kiwi.TSvc, nodeId int64, ver string, head util.M) {
   130  	n.worker.Push(nodeConnect, ip, port, svc, nodeId, ver, head)
   131  }
   132  
   133  func (n *nodeNet) Disconnect(svc kiwi.TSvc, nodeId int64) {
   134  	n.worker.Push(nodeDisconnect, svc, nodeId)
   135  }
   136  
   137  func (n *nodeNet) onConnected(dialer *nodeDialer) {
   138  	n.worker.Push(nodeConnected, dialer)
   139  }
   140  
   141  func (n *nodeNet) onDisconnected(dialer *nodeDialer, err *util.Err) {
   142  	n.worker.Push(nodeDisconnected, dialer, err)
   143  }
   144  
   145  func (n *nodeNet) pushSelf(pus kiwi.ISndPush) {
   146  	pkt := NewRcvPusPkt()
   147  	msg := pus.Msg()
   148  	if msg != nil {
   149  		pkt.InitWithMsg(HdPush, pus.Tid(), pus.Head(), pus.Json(), pus.Msg())
   150  	} else {
   151  		err := pkt.InitWithBytes(HdPush, pus.Tid(), pus.Head(), pus.Json(), pus.Payload())
   152  		if err != nil {
   153  			kiwi.Error(err)
   154  			return
   155  		}
   156  	}
   157  	kiwi.Router().OnPush(pkt)
   158  }
   159  
   160  func (n *nodeNet) Push(pus kiwi.ISndPush) {
   161  	if kiwi.GetNodeMeta().HasService(pus.Svc()) {
   162  		n.pushSelf(pus)
   163  		return
   164  	}
   165  	n.worker.Push(nodePush, pus)
   166  }
   167  
   168  func (n *nodeNet) PushNode(nodeId int64, pus kiwi.ISndPush) {
   169  	if nodeId == kiwi.GetNodeMeta().NodeId {
   170  		n.pushSelf(pus)
   171  		return
   172  	}
   173  	n.worker.Push(nodePushNode, nodeId, pus)
   174  }
   175  
   176  func (n *nodeNet) requestSelf(req kiwi.ISndRequest) {
   177  	pkt := NewRcvReqPkt()
   178  	msg := req.Msg()
   179  	if msg != nil {
   180  		pkt.InitWithMsg(HdRequest, req.Tid(), req.Head(), req.Json(), req.Msg())
   181  	} else {
   182  		err := pkt.InitWithBytes(HdRequest, req.Tid(), req.Head(), req.Json(), req.Payload())
   183  		if err != nil {
   184  			kiwi.Error(err)
   185  			return
   186  		}
   187  	}
   188  	kiwi.Router().OnRequest(pkt)
   189  }
   190  
   191  func (n *nodeNet) Request(req kiwi.ISndRequest) {
   192  	if kiwi.GetNodeMeta().HasService(req.Svc()) {
   193  		n.requestSelf(req)
   194  		return
   195  	}
   196  	n.worker.Push(nodeRequest, req)
   197  }
   198  
   199  func (n *nodeNet) RequestNode(nodeId int64, req kiwi.ISndRequest) {
   200  	if nodeId == kiwi.GetNodeMeta().NodeId {
   201  		n.requestSelf(req)
   202  		return
   203  	}
   204  	n.worker.Push(nodeRequestNode, req)
   205  }
   206  
   207  func (n *nodeNet) Notify(ntf kiwi.ISndNotice) {
   208  	n.worker.Push(nodeSendNotify, ntf)
   209  }
   210  
   211  func (n *nodeNet) ReceiveWatchNotice(nodeId int64, codes []kiwi.TCode) {
   212  	n.worker.Push(nodeWatchNotify, nodeId, codes)
   213  }
   214  
   215  func (n *nodeNet) SendToNode(nodeId int64, bytes []byte, fnErr util.FnErr) {
   216  	n.worker.Push(nodeSendNode, nodeId, bytes, fnErr)
   217  }
   218  
   219  func (n *nodeNet) onAddTcpConn(conn net.Conn) {
   220  	addr := conn.RemoteAddr().String()
   221  	agent := network.NewTcpAgent(addr, n.receive,
   222  		kiwi.AgentErr(func(err *util.Err) {
   223  			err.AddParam("addr", addr)
   224  			kiwi.Error(err)
   225  		}),
   226  		kiwi.AgentMode(kiwi.AgentR),
   227  		kiwi.AgentDeadline(30),
   228  	)
   229  	agent.Start(util.Ctx(), conn)
   230  }
   231  
   232  func (n *nodeNet) onAddUdpConn(conn net.Conn) {
   233  	addr := conn.RemoteAddr().String()
   234  	agent := network.NewUdpAgent(addr, n.receive,
   235  		kiwi.AgentErr(func(err *util.Err) {
   236  			err.AddParam("addr", addr)
   237  			kiwi.Error(err)
   238  		}),
   239  		kiwi.AgentMode(kiwi.AgentR),
   240  		kiwi.AgentDeadline(30),
   241  	)
   242  	agent.Start(util.Ctx(), conn)
   243  }
   244  
   245  func (n *nodeNet) createDialer(name, addr string) kiwi.IDialer {
   246  	switch n.option.connType {
   247  	case Tcp:
   248  		return network.NewTcpDialer(name, addr, n.receive, kiwi.AgentMode(kiwi.AgentW))
   249  	case Udp:
   250  		return network.NewUdpDialer(name, addr, n.receive, kiwi.AgentMode(kiwi.AgentW))
   251  	default:
   252  		kiwi.Fatal2(util.EcParamsErr, util.M{
   253  			"conn type": n.option.connType,
   254  		})
   255  		return nil
   256  	}
   257  }
   258  
   259  func (n *nodeNet) processor(job *worker.Job) {
   260  	switch job.Name {
   261  	case nodeConnect:
   262  		ip, port, svc, nodeId, ver, head := util.SplitSlc6[string, int, kiwi.TSvc, int64, string, util.M](job.Data)
   263  		if n.idToDialer.Has(nodeId) {
   264  			kiwi.Info("exist service", util.M{
   265  				"node id": nodeId,
   266  			})
   267  			return
   268  		}
   269  		kiwi.Info("connect service", util.M{
   270  			"ip":      ip,
   271  			"port":    port,
   272  			"svc":     svc,
   273  			"node id": nodeId,
   274  			"ver":     ver,
   275  			"head":    head,
   276  		})
   277  		dialer := n.createDialer(fmt.Sprintf("%s_%d", svc, nodeId), fmt.Sprintf("%s:%d", ip, port))
   278  		newNodeDialer(dialer, svc, nodeId, ver, head, n.onConnected, n.onDisconnected).connect()
   279  	case nodeConnected:
   280  		dialer := util.SplitSlc1[*nodeDialer](job.Data)
   281  		set, _ := n.svcToDialer.GetOrNew(dialer.svc, func() *ds.Set2Item[kiwi.TSvc, int64, kiwi.INodeDialer] {
   282  			return ds.NewSet2Item[kiwi.TSvc, int64, kiwi.INodeDialer](dialer.svc, 2, func(dialer kiwi.INodeDialer) int64 {
   283  				return dialer.NodeId()
   284  			})
   285  		})
   286  		old := set.Set(dialer)
   287  		if old != nil {
   288  			kiwi.Error2(util.EcExist, util.M{
   289  				"node id": dialer.nodeId,
   290  			})
   291  		}
   292  		_ = n.idToDialer.Set(dialer)
   293  		kiwi.Info("service connected", util.M{
   294  			"svc":     dialer.svc,
   295  			"ver":     dialer.ver,
   296  			"node id": dialer.nodeId,
   297  			"head":    dialer.head,
   298  		})
   299  		//发送消息监听
   300  		codes, ok := kiwi.Router().GetWatchCodes(dialer.Svc())
   301  		if ok {
   302  			bytes := kiwi.Packer().PackWatchNotify(kiwi.GetNodeMeta().NodeId, codes)
   303  			dialer.Send(bytes, kiwi.Error)
   304  		}
   305  		var head util.M
   306  		dialer.head.CopyTo(head)
   307  		kiwi.DispatchEvent(kiwi.Evt_Svc_Connected, &kiwi.EvtSvcConnected{
   308  			Svc:  dialer.svc,
   309  			Id:   dialer.nodeId,
   310  			Head: head,
   311  		})
   312  	case nodeDisconnected:
   313  		dialer, err := util.SplitSlc2[*nodeDialer, *util.Err](job.Data)
   314  		set, ok := n.svcToDialer.Get(dialer.svc)
   315  		if !ok {
   316  			return
   317  		}
   318  		nodeId := dialer.nodeId
   319  		_, ok = set.Del(nodeId)
   320  		if !ok {
   321  			return
   322  		}
   323  		_, _ = n.idToDialer.Del(nodeId)
   324  		codes, ok := n.watcherToCodes[nodeId]
   325  		if ok {
   326  			for _, code := range codes {
   327  				m, ok := n.codeToWatchers[code]
   328  				if ok {
   329  					delete(m, nodeId)
   330  				}
   331  			}
   332  		}
   333  		kiwi.Info("dialer disconnected", util.M{
   334  			"error":   err,
   335  			"svc":     dialer.svc,
   336  			"node id": dialer.nodeId,
   337  			"head":    dialer.head,
   338  		})
   339  		kiwi.DispatchEvent(kiwi.Evt_Svc_Disonnected, &kiwi.EvtSvcDisconnected{
   340  			Svc: dialer.svc,
   341  			Id:  dialer.nodeId,
   342  		})
   343  	case nodeDisconnect:
   344  		svc, nodeId := util.SplitSlc2[kiwi.TSvc, int64](job.Data)
   345  		set, ok := n.svcToDialer.Get(svc)
   346  		if !ok {
   347  			return
   348  		}
   349  		dialer, ok := set.Get(nodeId)
   350  		if !ok {
   351  			return
   352  		}
   353  		kiwi.Info("disconnect service", util.M{
   354  			"service": dialer.Svc(),
   355  			"node id": dialer.NodeId(),
   356  			"head":    dialer.Head(),
   357  		})
   358  		dialer.Dialer().Agent().Dispose()
   359  	case nodeSendNotify:
   360  		ntf := job.Data[0].(kiwi.ISndNotice)
   361  		tid := ntf.Tid()
   362  		bytes, err := kiwi.Packer().PackNotify(tid, ntf)
   363  		if err != nil {
   364  			kiwi.TE(tid, err)
   365  			return
   366  		}
   367  		m, ok := n.codeToWatchers[ntf.Code()]
   368  		if !ok {
   369  			return
   370  		}
   371  		for nodeId := range m {
   372  			dialer, ok := n.idToDialer.Get(nodeId)
   373  			if !ok {
   374  				delete(m, nodeId)
   375  				break
   376  			}
   377  			dialer.Send(util.CopyBytes(bytes), nil)
   378  		}
   379  	case nodeWatchNotify:
   380  		nodeId, codes := util.SplitSlc2[int64, []kiwi.TCode](job.Data)
   381  		_, ok := n.idToDialer.Get(nodeId)
   382  		if !ok {
   383  			kiwi.Error2(util.EcNotExist, util.M{
   384  				"node id": nodeId,
   385  			})
   386  			return
   387  		}
   388  		n.watcherToCodes[nodeId] = codes
   389  		for _, code := range codes {
   390  			m, ok := n.codeToWatchers[code]
   391  			if ok {
   392  				m[nodeId] = struct{}{}
   393  			} else {
   394  				n.codeToWatchers[code] = map[int64]struct{}{
   395  					nodeId: {},
   396  				}
   397  			}
   398  		}
   399  	case nodePush:
   400  		pus := job.Data[0].(kiwi.ISndPush)
   401  		tid := pus.Tid()
   402  		bytes, err := kiwi.Packer().PackPush(tid, pus)
   403  		if err != nil {
   404  			kiwi.TE(tid, err)
   405  			return
   406  		}
   407  		n.sendToSvc(pus.Svc(), bytes, func(err *util.Err) {
   408  			kiwi.TE(tid, err)
   409  		})
   410  	case nodePushNode:
   411  		nodeId, pus := util.SplitSlc2[int64, kiwi.ISndPush](job.Data)
   412  		tid := pus.Tid()
   413  		bytes, err := kiwi.Packer().PackPush(tid, pus)
   414  		if err != nil {
   415  			kiwi.TE(tid, err)
   416  			return
   417  		}
   418  		n.sendToNode(nodeId, bytes, func(err *util.Err) {
   419  			kiwi.TE(tid, err)
   420  		})
   421  	case nodeRequest:
   422  		req := job.Data[0].(kiwi.ISndRequest)
   423  		tid := req.Tid()
   424  		bytes, err := kiwi.Packer().PackRequest(tid, req)
   425  		if err != nil {
   426  			kiwi.TE(tid, err)
   427  			return
   428  		}
   429  		n.sendToSvc(req.Svc(), bytes, func(err *util.Err) {
   430  			kiwi.TE(tid, err)
   431  		})
   432  	case nodeRequestNode:
   433  		nodeId, req := util.SplitSlc2[int64, kiwi.ISndRequest](job.Data)
   434  		tid := req.Tid()
   435  		bytes, err := kiwi.Packer().PackRequest(tid, req)
   436  		if err != nil {
   437  			kiwi.TE(tid, err)
   438  			return
   439  		}
   440  		n.sendToNode(nodeId, bytes, func(err *util.Err) {
   441  			kiwi.TE(tid, err)
   442  		})
   443  	case nodeSendNode:
   444  		n.sendToNode(util.SplitSlc3[int64, []byte, util.FnErr](job.Data))
   445  	}
   446  }
   447  
   448  func (n *nodeNet) sendToSvc(svc kiwi.TSvc, bytes []byte, fnErr util.FnErr) {
   449  	set, ok := n.svcToDialer.Get(svc)
   450  	if !ok {
   451  		fnErr(util.NewErr(util.EcNotExist, util.M{
   452  			"svc": svc,
   453  		}))
   454  		return
   455  	}
   456  	switch set.Count() {
   457  	case 0:
   458  		fnErr(util.NewErr(util.EcNotExist, util.M{
   459  			"svc": svc,
   460  		}))
   461  	case 1:
   462  		dialer, _ := set.GetWithIdx(0)
   463  		dialer.Send(bytes, fnErr)
   464  	default:
   465  		nodeId, err := n.option.selector(set)
   466  		if err != nil {
   467  			fnErr(err)
   468  			return
   469  		}
   470  		dialer, ok := n.idToDialer.Get(nodeId)
   471  		if !ok {
   472  			fnErr(util.NewErr(util.EcNotExist, util.M{
   473  				"id": nodeId,
   474  			}))
   475  			return
   476  		}
   477  		dialer.Send(bytes, fnErr)
   478  	}
   479  }
   480  
   481  func (n *nodeNet) sendToNode(nodeId int64, bytes []byte, fnErr util.FnErr) {
   482  	dialer, ok := n.idToDialer.Get(nodeId)
   483  	if !ok {
   484  		fnErr(util.NewErr(util.EcNotExist, util.M{
   485  			"id": nodeId,
   486  		}))
   487  		return
   488  	}
   489  	dialer.Send(bytes, fnErr)
   490  }
   491  
   492  const (
   493  	nodeConnect      = "svc_connect"
   494  	nodeConnected    = "svc_connected"
   495  	nodeDisconnect   = "svc_disconnect"
   496  	nodeDisconnected = "svc_disconnected"
   497  	nodeSendNotify   = "send_notify"
   498  	nodeWatchNotify  = "listen_notify"
   499  	nodePush         = "push"
   500  	nodePushNode     = "push_node"
   501  	nodeRequest      = "request"
   502  	nodeRequestNode  = "request_node"
   503  	nodeSendNode     = "send_node"
   504  )