mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-14 07:34:43 +08:00
Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
166facc959 | ||
|
|
5bb747201b | ||
|
|
1014bc54e4 | ||
|
|
9c26c742fe | ||
|
|
d1935b1bbc | ||
|
|
90d54bf3e2 | ||
|
|
78cc33c84e | ||
|
|
9cf21bf418 | ||
|
|
c6d0bd9a19 | ||
|
|
61bf95e457 | ||
|
|
8b2a551ee5 | ||
|
|
927c2ffa37 | ||
|
|
b23b30aac5 | ||
|
|
03f8ba0316 | ||
|
|
277480a7f0 | ||
|
|
647a654a36 | ||
|
|
de483a88f1 | ||
|
|
bbbb511b5f | ||
|
|
0489ee3ef4 | ||
|
|
692dacda0c | ||
|
|
7f86b1007d | ||
|
|
ba5e30ae2e | ||
|
|
0b1a1d2283 | ||
|
|
7780947a96 | ||
|
|
d31b1ac657 | ||
|
|
27723bf684 | ||
|
|
3f45b19bab | ||
|
|
94b4572c2f | ||
|
|
1d970de0f9 | ||
|
|
81625635ba | ||
|
|
c6ade7d3e1 | ||
|
|
bba5eb2929 | ||
|
|
59efc05d24 | ||
|
|
4c169cf0bb | ||
|
|
e36693eeff | ||
|
|
a26210f17f | ||
|
|
0cf935ffa4 | ||
|
|
161a67c8a1 | ||
|
|
96d02c8f71 | ||
|
|
3a56282a0b | ||
|
|
eebbef52c9 | ||
|
|
2ddc54f5ac | ||
|
|
75ef7302de | ||
|
|
ecea9d1706 | ||
|
|
4898116698 | ||
|
|
bcbee6dd11 | ||
|
|
43122190a3 | ||
|
|
39b862e3d9 | ||
|
|
8c9b796fce | ||
|
|
c0971a46a7 | ||
|
|
ba019ac466 | ||
|
|
c803b9b9ad | ||
|
|
3f52ea8331 | ||
|
|
2d1bee4dea | ||
|
|
fa8cbfb40e | ||
|
|
388b946401 | ||
|
|
582a0faa6f | ||
|
|
fa6039e2cb | ||
|
|
25a672ca53 | ||
|
|
75f881be28 | ||
|
|
ef8182eec7 | ||
|
|
4ad8204fde | ||
|
|
8f15546fb1 | ||
|
|
0f3a965d73 | ||
|
|
dfb6959843 | ||
|
|
dd4aaf9c57 | ||
|
|
6ef98a2104 | ||
|
|
1890b300ee | ||
|
|
6fea2226e1 | ||
|
|
ec1c2b4517 | ||
|
|
4b84d9a1d5 | ||
|
|
85a8ec58e5 | ||
|
|
962016d476 | ||
|
|
a61979e985 | ||
|
|
6de25d1c6d | ||
|
|
b392617d6e | ||
|
|
92fdb7860c | ||
|
|
f78d0d58be | ||
|
|
5675681ab1 | ||
|
|
ddeaaf7d77 | ||
|
|
1174b47475 | ||
|
|
18fff3b567 | ||
|
|
7ab6c88f9c | ||
|
|
6b64de06a2 | ||
|
|
95b153f8cf |
@@ -2,11 +2,14 @@ package cluster
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
var configDir = "./config/"
|
var configDir = "./config/"
|
||||||
@@ -20,17 +23,25 @@ const (
|
|||||||
Discard NodeStatus = 1 //丢弃
|
Discard NodeStatus = 1 //丢弃
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type DiscoveryService struct {
|
||||||
|
MasterNodeId string //要筛选的主结点Id,如果不配置或者配置成0,表示针对所有的主结点
|
||||||
|
NetworkName string //如果是etcd,指定要筛选的网络名中的服务,不配置,表示所有的网络
|
||||||
|
ServiceList []string //只发现的服务列表
|
||||||
|
}
|
||||||
|
|
||||||
type NodeInfo struct {
|
type NodeInfo struct {
|
||||||
NodeId int
|
NodeId string
|
||||||
NodeName string
|
|
||||||
Private bool
|
Private bool
|
||||||
ListenAddr string
|
ListenAddr string
|
||||||
MaxRpcParamLen uint32 //最大Rpc参数长度
|
MaxRpcParamLen uint32 //最大Rpc参数长度
|
||||||
|
CompressBytesLen int //超过字节进行压缩的长度
|
||||||
ServiceList []string //所有的有序服务列表
|
ServiceList []string //所有的有序服务列表
|
||||||
PublicServiceList []string //对外公开的服务列表
|
PublicServiceList []string //对外公开的服务列表
|
||||||
DiscoveryService []string //筛选发现的服务,如果不配置,不进行筛选
|
DiscoveryService []DiscoveryService //筛选发现的服务,如果不配置,不进行筛选
|
||||||
NeighborService []string
|
|
||||||
status NodeStatus
|
status NodeStatus
|
||||||
|
Retire bool
|
||||||
|
|
||||||
|
NetworkName string
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeRpcInfo struct {
|
type NodeRpcInfo struct {
|
||||||
@@ -42,22 +53,25 @@ var cluster Cluster
|
|||||||
|
|
||||||
type Cluster struct {
|
type Cluster struct {
|
||||||
localNodeInfo NodeInfo //本结点配置信息
|
localNodeInfo NodeInfo //本结点配置信息
|
||||||
masterDiscoveryNodeList []NodeInfo //配置发现Master结点
|
|
||||||
|
discoveryInfo DiscoveryInfo //服务发现配置
|
||||||
|
rpcMode RpcMode
|
||||||
globalCfg interface{} //全局配置
|
globalCfg interface{} //全局配置
|
||||||
|
|
||||||
localServiceCfg map[string]interface{} //map[serviceName]配置数据*
|
localServiceCfg map[string]interface{} //map[serviceName]配置数据*
|
||||||
serviceDiscovery IServiceDiscovery //服务发现接口
|
serviceDiscovery IServiceDiscovery //服务发现接口
|
||||||
|
|
||||||
|
|
||||||
locker sync.RWMutex //结点与服务关系保护锁
|
locker sync.RWMutex //结点与服务关系保护锁
|
||||||
mapRpc map[int]NodeRpcInfo //nodeId
|
mapRpc map[string]*NodeRpcInfo //nodeId
|
||||||
mapIdNode map[int]NodeInfo //map[NodeId]NodeInfo
|
mapServiceNode map[string]map[string]struct{} //map[serviceName]map[NodeId]
|
||||||
mapServiceNode map[string]map[int]struct{} //map[serviceName]map[NodeId]
|
mapTemplateServiceNode map[string]map[string]struct{} //map[templateServiceName]map[serviceName]nodeId
|
||||||
|
|
||||||
|
callSet rpc.CallSet
|
||||||
|
rpcNats rpc.RpcNats
|
||||||
|
rpcServer rpc.IServer
|
||||||
|
|
||||||
rpcServer rpc.Server
|
|
||||||
rpcEventLocker sync.RWMutex //Rpc事件监听保护锁
|
rpcEventLocker sync.RWMutex //Rpc事件监听保护锁
|
||||||
mapServiceListenRpcEvent map[string]struct{} //ServiceName
|
mapServiceListenRpcEvent map[string]struct{} //ServiceName
|
||||||
mapServiceListenDiscoveryEvent map[string]struct{} //ServiceName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCluster() *Cluster {
|
func GetCluster() *Cluster {
|
||||||
@@ -72,78 +86,72 @@ func SetServiceDiscovery(serviceDiscovery IServiceDiscovery) {
|
|||||||
cluster.serviceDiscovery = serviceDiscovery
|
cluster.serviceDiscovery = serviceDiscovery
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) Start() {
|
func (cls *Cluster) Start() error{
|
||||||
cls.rpcServer.Start(cls.localNodeInfo.ListenAddr, cls.localNodeInfo.MaxRpcParamLen)
|
return cls.rpcServer.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) Stop() {
|
func (cls *Cluster) Stop() {
|
||||||
cls.serviceDiscovery.OnNodeStop()
|
cls.rpcServer.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) DiscardNode(nodeId int) {
|
func (cls *Cluster) DiscardNode(nodeId string) {
|
||||||
cls.locker.Lock()
|
cls.locker.Lock()
|
||||||
nodeInfo, ok := cls.mapIdNode[nodeId]
|
nodeInfo, ok := cls.mapRpc[nodeId]
|
||||||
|
bDel := (ok == true) && nodeInfo.nodeInfo.status == Discard
|
||||||
cls.locker.Unlock()
|
cls.locker.Unlock()
|
||||||
|
|
||||||
if ok == true && nodeInfo.status == Discard {
|
if bDel {
|
||||||
cls.DelNode(nodeId, true)
|
cls.DelNode(nodeId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) DelNode(nodeId int, immediately bool) {
|
func (cls *Cluster) DelNode(nodeId string) {
|
||||||
//MasterDiscover结点与本地结点不删除
|
//MasterDiscover结点与本地结点不删除
|
||||||
if cls.GetMasterDiscoveryNodeInfo(nodeId) != nil || nodeId == cls.localNodeInfo.NodeId {
|
if cls.IsOriginMasterDiscoveryNode(nodeId) || nodeId == cls.localNodeInfo.NodeId {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cls.locker.Lock()
|
cls.locker.Lock()
|
||||||
defer cls.locker.Unlock()
|
defer cls.locker.Unlock()
|
||||||
|
|
||||||
nodeInfo, ok := cls.mapIdNode[nodeId]
|
rpc, ok := cls.mapRpc[nodeId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc, ok := cls.mapRpc[nodeId]
|
cls.TriggerDiscoveryEvent(false,nodeId,rpc.nodeInfo.ServiceList)
|
||||||
for {
|
for _, serviceName := range rpc.nodeInfo.ServiceList {
|
||||||
//立即删除
|
|
||||||
if immediately || ok == false {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
//正在连接中不主动断开,只断开没有连接中的
|
|
||||||
if rpc.client.IsConnected() {
|
|
||||||
nodeInfo.status = Discard
|
|
||||||
log.SRelease("Discard node ", nodeInfo.NodeId, " ", nodeInfo.ListenAddr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, serviceName := range nodeInfo.ServiceList {
|
|
||||||
cls.delServiceNode(serviceName, nodeId)
|
cls.delServiceNode(serviceName, nodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(cls.mapIdNode, nodeId)
|
|
||||||
delete(cls.mapRpc, nodeId)
|
delete(cls.mapRpc, nodeId)
|
||||||
if ok == true {
|
if ok == true {
|
||||||
rpc.client.Close(false)
|
rpc.client.Close(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SRelease("remove node ", nodeInfo.NodeId, " ", nodeInfo.ListenAddr)
|
log.Info("remove node ",log.String("NodeId", rpc.nodeInfo.NodeId),log.String("ListenAddr", rpc.nodeInfo.ListenAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) serviceDiscoveryDelNode(nodeId int, immediately bool) {
|
func (cls *Cluster) serviceDiscoveryDelNode(nodeId string) {
|
||||||
if nodeId == 0 {
|
cls.DelNode(nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) delServiceNode(serviceName string, nodeId string) {
|
||||||
|
if nodeId == cls.localNodeInfo.NodeId {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cls.DelNode(nodeId, immediately)
|
//处理模板服务
|
||||||
}
|
splitServiceName := strings.Split(serviceName,":")
|
||||||
|
if len(splitServiceName) == 2 {
|
||||||
|
serviceName = splitServiceName[0]
|
||||||
|
templateServiceName := splitServiceName[1]
|
||||||
|
|
||||||
func (cls *Cluster) delServiceNode(serviceName string, nodeId int) {
|
mapService := cls.mapTemplateServiceNode[templateServiceName]
|
||||||
if nodeId == cls.localNodeInfo.NodeId {
|
delete(mapService,serviceName)
|
||||||
return
|
|
||||||
|
if len(cls.mapTemplateServiceNode[templateServiceName]) == 0 {
|
||||||
|
delete(cls.mapTemplateServiceNode,templateServiceName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mapNode := cls.mapServiceNode[serviceName]
|
mapNode := cls.mapServiceNode[serviceName]
|
||||||
@@ -163,66 +171,91 @@ func (cls *Cluster) serviceDiscoverySetNodeInfo(nodeInfo *NodeInfo) {
|
|||||||
defer cls.locker.Unlock()
|
defer cls.locker.Unlock()
|
||||||
|
|
||||||
//先清一次的NodeId对应的所有服务清理
|
//先清一次的NodeId对应的所有服务清理
|
||||||
lastNodeInfo, ok := cls.mapIdNode[nodeInfo.NodeId]
|
lastNodeInfo, ok := cls.mapRpc[nodeInfo.NodeId]
|
||||||
if ok == true {
|
if ok == true {
|
||||||
for _, serviceName := range lastNodeInfo.ServiceList {
|
for _, serviceName := range lastNodeInfo.nodeInfo.ServiceList {
|
||||||
cls.delServiceNode(serviceName, nodeInfo.NodeId)
|
cls.delServiceNode(serviceName, nodeInfo.NodeId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cluster.TriggerDiscoveryEvent(true,nodeInfo.NodeId,nodeInfo.PublicServiceList)
|
||||||
//再重新组装
|
//再重新组装
|
||||||
mapDuplicate := map[string]interface{}{} //预防重复数据
|
mapDuplicate := map[string]interface{}{} //预防重复数据
|
||||||
for _, serviceName := range nodeInfo.PublicServiceList {
|
for _, serviceName := range nodeInfo.PublicServiceList {
|
||||||
if _, ok := mapDuplicate[serviceName]; ok == true {
|
if _, ok := mapDuplicate[serviceName]; ok == true {
|
||||||
//存在重复
|
//存在重复
|
||||||
log.SError("Bad duplicate Service Cfg.")
|
log.Error("Bad duplicate Service Cfg.")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mapDuplicate[serviceName] = nil
|
mapDuplicate[serviceName] = nil
|
||||||
if _, ok := cls.mapServiceNode[serviceName]; ok == false {
|
|
||||||
cls.mapServiceNode[serviceName] = make(map[int]struct{}, 1)
|
//如果是模板服务,则记录模板关系
|
||||||
|
splitServiceName := strings.Split(serviceName,":")
|
||||||
|
if len(splitServiceName) == 2 {
|
||||||
|
serviceName = splitServiceName[0]
|
||||||
|
templateServiceName := splitServiceName[1]
|
||||||
|
//记录模板
|
||||||
|
if _, ok = cls.mapTemplateServiceNode[templateServiceName]; ok == false {
|
||||||
|
cls.mapTemplateServiceNode[templateServiceName]=map[string]struct{}{}
|
||||||
|
}
|
||||||
|
cls.mapTemplateServiceNode[templateServiceName][serviceName] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok = cls.mapServiceNode[serviceName]; ok == false {
|
||||||
|
cls.mapServiceNode[serviceName] = make(map[string]struct{}, 1)
|
||||||
}
|
}
|
||||||
cls.mapServiceNode[serviceName][nodeInfo.NodeId] = struct{}{}
|
cls.mapServiceNode[serviceName][nodeInfo.NodeId] = struct{}{}
|
||||||
}
|
}
|
||||||
cls.mapIdNode[nodeInfo.NodeId] = *nodeInfo
|
|
||||||
|
|
||||||
log.SRelease("Discovery nodeId: ", nodeInfo.NodeId, " services:", nodeInfo.PublicServiceList)
|
if lastNodeInfo != nil {
|
||||||
|
log.Info("Discovery nodeId",log.String("NodeId", nodeInfo.NodeId),log.Any("services:", nodeInfo.PublicServiceList),log.Bool("Retire",nodeInfo.Retire))
|
||||||
//已经存在连接,则不需要进行设置
|
lastNodeInfo.nodeInfo = *nodeInfo
|
||||||
if _, rpcInfoOK := cls.mapRpc[nodeInfo.NodeId]; rpcInfoOK == true {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//不存在时,则建立连接
|
||||||
rpcInfo := NodeRpcInfo{}
|
rpcInfo := NodeRpcInfo{}
|
||||||
rpcInfo.nodeInfo = *nodeInfo
|
rpcInfo.nodeInfo = *nodeInfo
|
||||||
rpcInfo.client =rpc.NewRClient(nodeInfo.NodeId, nodeInfo.ListenAddr, nodeInfo.MaxRpcParamLen,cls.triggerRpcEvent)
|
|
||||||
cls.mapRpc[nodeInfo.NodeId] = rpcInfo
|
if cls.IsNatsMode() {
|
||||||
|
rpcInfo.client = cls.rpcNats.NewNatsClient(nodeInfo.NodeId, cls.GetLocalNodeInfo().NodeId,&cls.callSet,cls.NotifyAllService)
|
||||||
|
}else{
|
||||||
|
rpcInfo.client =rpc.NewRClient(nodeInfo.NodeId, nodeInfo.ListenAddr, nodeInfo.MaxRpcParamLen,cls.localNodeInfo.CompressBytesLen,&cls.callSet,cls.NotifyAllService)
|
||||||
|
}
|
||||||
|
cls.mapRpc[nodeInfo.NodeId] = &rpcInfo
|
||||||
|
if cls.IsNatsMode() == true || cls.discoveryInfo.discoveryType!=OriginType {
|
||||||
|
log.Info("Discovery nodeId and new rpc client",log.String("NodeId", nodeInfo.NodeId),log.Any("services:", nodeInfo.PublicServiceList),log.Bool("Retire",nodeInfo.Retire))
|
||||||
|
}else{
|
||||||
|
log.Info("Discovery nodeId and new rpc client",log.String("NodeId", nodeInfo.NodeId),log.Any("services:", nodeInfo.PublicServiceList),log.Bool("Retire",nodeInfo.Retire),log.String("nodeListenAddr",nodeInfo.ListenAddr))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) buildLocalRpc() {
|
|
||||||
rpcInfo := NodeRpcInfo{}
|
|
||||||
rpcInfo.nodeInfo = cls.localNodeInfo
|
|
||||||
rpcInfo.client = rpc.NewLClient(rpcInfo.nodeInfo.NodeId)
|
|
||||||
|
|
||||||
cls.mapRpc[cls.localNodeInfo.NodeId] = rpcInfo
|
func (cls *Cluster) Init(localNodeId string, setupServiceFun SetupServiceFun) error {
|
||||||
}
|
|
||||||
|
|
||||||
func (cls *Cluster) Init(localNodeId int, setupServiceFun SetupServiceFun) error {
|
|
||||||
//1.初始化配置
|
//1.初始化配置
|
||||||
err := cls.InitCfg(localNodeId)
|
err := cls.InitCfg(localNodeId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cls.rpcServer.Init(cls)
|
cls.callSet.Init()
|
||||||
cls.buildLocalRpc()
|
if cls.IsNatsMode() {
|
||||||
|
cls.rpcNats.Init(cls.rpcMode.Nats.NatsUrl,cls.rpcMode.Nats.NoRandomize,cls.GetLocalNodeInfo().NodeId,cls.localNodeInfo.CompressBytesLen,cls,cluster.NotifyAllService)
|
||||||
|
cls.rpcServer = &cls.rpcNats
|
||||||
|
}else{
|
||||||
|
s := &rpc.Server{}
|
||||||
|
s.Init(cls.localNodeInfo.ListenAddr,cls.localNodeInfo.MaxRpcParamLen,cls.localNodeInfo.CompressBytesLen,cls)
|
||||||
|
cls.rpcServer = s
|
||||||
|
}
|
||||||
|
|
||||||
//2.安装服务发现结点
|
//2.安装服务发现结点
|
||||||
cls.SetupServiceDiscovery(localNodeId, setupServiceFun)
|
err = cls.setupDiscovery(localNodeId, setupServiceFun)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("setupDiscovery fail",log.ErrorAttr("err",err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
service.RegRpcEventFun = cls.RegRpcEvent
|
service.RegRpcEventFun = cls.RegRpcEvent
|
||||||
service.UnRegRpcEventFun = cls.UnRegRpcEvent
|
service.UnRegRpcEventFun = cls.UnRegRpcEvent
|
||||||
service.RegDiscoveryServiceEventFun = cls.RegDiscoveryEvent
|
|
||||||
service.UnRegDiscoveryServiceEventFun = cls.UnReDiscoveryEvent
|
|
||||||
|
|
||||||
err = cls.serviceDiscovery.InitDiscovery(localNodeId, cls.serviceDiscoveryDelNode, cls.serviceDiscoverySetNodeInfo)
|
err = cls.serviceDiscovery.InitDiscovery(localNodeId, cls.serviceDiscoveryDelNode, cls.serviceDiscoverySetNodeInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -232,74 +265,6 @@ func (cls *Cluster) Init(localNodeId int, setupServiceFun SetupServiceFun) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) checkDynamicDiscovery(localNodeId int) (bool, bool) {
|
|
||||||
var localMaster bool //本结点是否为Master结点
|
|
||||||
var hasMaster bool //是否配置Master服务
|
|
||||||
|
|
||||||
//遍历所有结点
|
|
||||||
for _, nodeInfo := range cls.masterDiscoveryNodeList {
|
|
||||||
if nodeInfo.NodeId == localNodeId {
|
|
||||||
localMaster = true
|
|
||||||
}
|
|
||||||
hasMaster = true
|
|
||||||
}
|
|
||||||
|
|
||||||
//返回查询结果
|
|
||||||
return localMaster, hasMaster
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cls *Cluster) AddDynamicDiscoveryService(serviceName string, bPublicService bool) {
|
|
||||||
addServiceList := append([]string{},serviceName)
|
|
||||||
cls.localNodeInfo.ServiceList = append(addServiceList,cls.localNodeInfo.ServiceList...)
|
|
||||||
if bPublicService {
|
|
||||||
cls.localNodeInfo.PublicServiceList = append(cls.localNodeInfo.PublicServiceList, serviceName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := cls.mapServiceNode[serviceName]; ok == false {
|
|
||||||
cls.mapServiceNode[serviceName] = map[int]struct{}{}
|
|
||||||
}
|
|
||||||
cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cls *Cluster) GetDiscoveryNodeList() []NodeInfo {
|
|
||||||
return cls.masterDiscoveryNodeList
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cls *Cluster) GetMasterDiscoveryNodeInfo(nodeId int) *NodeInfo {
|
|
||||||
for i := 0; i < len(cls.masterDiscoveryNodeList); i++ {
|
|
||||||
if cls.masterDiscoveryNodeList[i].NodeId == nodeId {
|
|
||||||
return &cls.masterDiscoveryNodeList[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cls *Cluster) IsMasterDiscoveryNode() bool {
|
|
||||||
return cls.GetMasterDiscoveryNodeInfo(cls.GetLocalNodeInfo().NodeId) != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cls *Cluster) SetupServiceDiscovery(localNodeId int, setupServiceFun SetupServiceFun) {
|
|
||||||
if cls.serviceDiscovery != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//1.如果没有配置DiscoveryNode配置,则使用默认配置文件发现服务
|
|
||||||
localMaster, hasMaster := cls.checkDynamicDiscovery(localNodeId)
|
|
||||||
if hasMaster == false {
|
|
||||||
cls.serviceDiscovery = &ConfigDiscovery{}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setupServiceFun(&masterService, &clientService)
|
|
||||||
|
|
||||||
//2.如果为动态服务发现安装本地发现服务
|
|
||||||
cls.serviceDiscovery = getDynamicDiscovery()
|
|
||||||
cls.AddDynamicDiscoveryService(DynamicDiscoveryClientName, true)
|
|
||||||
if localMaster == true {
|
|
||||||
cls.AddDynamicDiscoveryService(DynamicDiscoveryMasterName, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cls *Cluster) FindRpcHandler(serviceName string) rpc.IRpcHandler {
|
func (cls *Cluster) FindRpcHandler(serviceName string) rpc.IRpcHandler {
|
||||||
pService := service.GetService(serviceName)
|
pService := service.GetService(serviceName)
|
||||||
if pService == nil {
|
if pService == nil {
|
||||||
@@ -309,93 +274,90 @@ func (cls *Cluster) FindRpcHandler(serviceName string) rpc.IRpcHandler {
|
|||||||
return pService.GetRpcHandler()
|
return pService.GetRpcHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) getRpcClient(nodeId int) *rpc.Client {
|
func (cls *Cluster) getRpcClient(nodeId string) (*rpc.Client,bool) {
|
||||||
c, ok := cls.mapRpc[nodeId]
|
c, ok := cls.mapRpc[nodeId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return nil
|
return nil,false
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.client
|
return c.client,c.nodeInfo.Retire
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) GetRpcClient(nodeId int) *rpc.Client {
|
func (cls *Cluster) GetRpcClient(nodeId string) (*rpc.Client,bool) {
|
||||||
cls.locker.RLock()
|
cls.locker.RLock()
|
||||||
defer cls.locker.RUnlock()
|
defer cls.locker.RUnlock()
|
||||||
return cls.getRpcClient(nodeId)
|
return cls.getRpcClient(nodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRpcClient(nodeId int, serviceMethod string, clientList []*rpc.Client) (error, int) {
|
func GetNodeIdByTemplateService(templateServiceName string, rpcClientList []*rpc.Client, filterRetire bool) (error, []*rpc.Client) {
|
||||||
if nodeId > 0 {
|
return GetCluster().GetNodeIdByTemplateService(templateServiceName, rpcClientList, filterRetire)
|
||||||
pClient := GetCluster().GetRpcClient(nodeId)
|
}
|
||||||
|
|
||||||
|
func GetRpcClient(nodeId string, serviceMethod string,filterRetire bool, clientList []*rpc.Client) (error, []*rpc.Client) {
|
||||||
|
if nodeId != rpc.NodeIdNull {
|
||||||
|
pClient,retire := GetCluster().GetRpcClient(nodeId)
|
||||||
if pClient == nil {
|
if pClient == nil {
|
||||||
return fmt.Errorf("cannot find nodeid %d!", nodeId), 0
|
return fmt.Errorf("cannot find nodeid %d!", nodeId), nil
|
||||||
}
|
}
|
||||||
clientList[0] = pClient
|
|
||||||
return nil, 1
|
//如果需要筛选掉退休结点
|
||||||
|
if filterRetire == true && retire == true {
|
||||||
|
return fmt.Errorf("cannot find nodeid %d!", nodeId), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
clientList = append(clientList,pClient)
|
||||||
|
return nil, clientList
|
||||||
}
|
}
|
||||||
|
|
||||||
findIndex := strings.Index(serviceMethod, ".")
|
findIndex := strings.Index(serviceMethod, ".")
|
||||||
if findIndex == -1 {
|
if findIndex == -1 {
|
||||||
return fmt.Errorf("servicemethod param %s is error!", serviceMethod), 0
|
return fmt.Errorf("servicemethod param %s is error!", serviceMethod), nil
|
||||||
}
|
}
|
||||||
serviceName := serviceMethod[:findIndex]
|
serviceName := serviceMethod[:findIndex]
|
||||||
|
|
||||||
//1.找到对应的rpcNodeid
|
//1.找到对应的rpcNodeid
|
||||||
return GetCluster().GetNodeIdByService(serviceName, clientList, true)
|
return GetCluster().GetNodeIdByService(serviceName, clientList, filterRetire)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRpcServer() *rpc.Server {
|
func GetRpcServer() rpc.IServer {
|
||||||
return &cluster.rpcServer
|
return cluster.rpcServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) IsNodeConnected(nodeId int) bool {
|
func (cls *Cluster) IsNodeConnected(nodeId string) bool {
|
||||||
pClient := cls.GetRpcClient(nodeId)
|
pClient,_ := cls.GetRpcClient(nodeId)
|
||||||
return pClient != nil && pClient.IsConnected()
|
return pClient != nil && pClient.IsConnected()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) triggerRpcEvent(bConnect bool, clientId uint32, nodeId int) {
|
func (cls *Cluster) IsNodeRetire(nodeId string) bool {
|
||||||
cls.locker.Lock()
|
cls.locker.RLock()
|
||||||
nodeInfo, ok := cls.mapRpc[nodeId]
|
defer cls.locker.RUnlock()
|
||||||
if ok == false || nodeInfo.client == nil || nodeInfo.client.GetClientId() != clientId {
|
|
||||||
cls.locker.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cls.locker.Unlock()
|
|
||||||
|
|
||||||
|
_,retire :=cls.getRpcClient(nodeId)
|
||||||
|
return retire
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) NotifyAllService(event event.IEvent){
|
||||||
cls.rpcEventLocker.Lock()
|
cls.rpcEventLocker.Lock()
|
||||||
defer cls.rpcEventLocker.Unlock()
|
defer cls.rpcEventLocker.Unlock()
|
||||||
|
|
||||||
for serviceName, _ := range cls.mapServiceListenRpcEvent {
|
for serviceName, _ := range cls.mapServiceListenRpcEvent {
|
||||||
ser := service.GetService(serviceName)
|
ser := service.GetService(serviceName)
|
||||||
if ser == nil {
|
if ser == nil {
|
||||||
log.SError("cannot find service name ", serviceName)
|
log.Error("cannot find service name "+serviceName)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var eventData service.RpcConnEvent
|
ser.(service.IModule).NotifyEvent(event)
|
||||||
eventData.IsConnect = bConnect
|
|
||||||
eventData.NodeId = nodeId
|
|
||||||
ser.(service.IModule).NotifyEvent(&eventData)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) TriggerDiscoveryEvent(bDiscovery bool, nodeId int, serviceName []string) {
|
func (cls *Cluster) TriggerDiscoveryEvent(bDiscovery bool, nodeId string, serviceName []string) {
|
||||||
cls.rpcEventLocker.Lock()
|
var eventData service.DiscoveryServiceEvent
|
||||||
defer cls.rpcEventLocker.Unlock()
|
eventData.IsDiscovery = bDiscovery
|
||||||
|
eventData.NodeId = nodeId
|
||||||
for sName, _ := range cls.mapServiceListenDiscoveryEvent {
|
eventData.ServiceName = serviceName
|
||||||
ser := service.GetService(sName)
|
|
||||||
if ser == nil {
|
|
||||||
log.SError("cannot find service name ", serviceName)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var eventData service.DiscoveryServiceEvent
|
|
||||||
eventData.IsDiscovery = bDiscovery
|
|
||||||
eventData.NodeId = nodeId
|
|
||||||
eventData.ServiceName = serviceName
|
|
||||||
ser.(service.IModule).NotifyEvent(&eventData)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
cls.NotifyAllService(&eventData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) GetLocalNodeInfo() *NodeInfo {
|
func (cls *Cluster) GetLocalNodeInfo() *NodeInfo {
|
||||||
@@ -418,26 +380,7 @@ func (cls *Cluster) UnRegRpcEvent(serviceName string) {
|
|||||||
cls.rpcEventLocker.Unlock()
|
cls.rpcEventLocker.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HasService(nodeId string, serviceName string) bool {
|
||||||
func (cls *Cluster) RegDiscoveryEvent(serviceName string) {
|
|
||||||
cls.rpcEventLocker.Lock()
|
|
||||||
if cls.mapServiceListenDiscoveryEvent == nil {
|
|
||||||
cls.mapServiceListenDiscoveryEvent = map[string]struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
cls.mapServiceListenDiscoveryEvent[serviceName] = struct{}{}
|
|
||||||
cls.rpcEventLocker.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cls *Cluster) UnReDiscoveryEvent(serviceName string) {
|
|
||||||
cls.rpcEventLocker.Lock()
|
|
||||||
delete(cls.mapServiceListenDiscoveryEvent, serviceName)
|
|
||||||
cls.rpcEventLocker.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func HasService(nodeId int, serviceName string) bool {
|
|
||||||
cluster.locker.RLock()
|
cluster.locker.RLock()
|
||||||
defer cluster.locker.RUnlock()
|
defer cluster.locker.RUnlock()
|
||||||
|
|
||||||
@@ -450,7 +393,7 @@ func HasService(nodeId int, serviceName string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetNodeByServiceName(serviceName string) map[int]struct{} {
|
func GetNodeByServiceName(serviceName string) map[string]struct{} {
|
||||||
cluster.locker.RLock()
|
cluster.locker.RLock()
|
||||||
defer cluster.locker.RUnlock()
|
defer cluster.locker.RUnlock()
|
||||||
|
|
||||||
@@ -459,7 +402,7 @@ func GetNodeByServiceName(serviceName string) map[int]struct{} {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mapNodeId := map[int]struct{}{}
|
mapNodeId := map[string]struct{}{}
|
||||||
for nodeId,_ := range mapNode {
|
for nodeId,_ := range mapNode {
|
||||||
mapNodeId[nodeId] = struct{}{}
|
mapNodeId[nodeId] = struct{}{}
|
||||||
}
|
}
|
||||||
@@ -467,15 +410,81 @@ func GetNodeByServiceName(serviceName string) map[int]struct{} {
|
|||||||
return mapNodeId
|
return mapNodeId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNodeByTemplateServiceName 通过模板服务名获取服务名,返回 map[serviceName真实服务名]NodeId
|
||||||
|
func GetNodeByTemplateServiceName(templateServiceName string) map[string]string {
|
||||||
|
cluster.locker.RLock()
|
||||||
|
defer cluster.locker.RUnlock()
|
||||||
|
|
||||||
|
mapServiceName := cluster.mapTemplateServiceNode[templateServiceName]
|
||||||
|
mapNodeId := make(map[string]string,9)
|
||||||
|
for serviceName := range mapServiceName {
|
||||||
|
mapNode, ok := cluster.mapServiceNode[serviceName]
|
||||||
|
if ok == false {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for nodeId,_ := range mapNode {
|
||||||
|
mapNodeId[serviceName] = nodeId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapNodeId
|
||||||
|
}
|
||||||
|
|
||||||
func (cls *Cluster) GetGlobalCfg() interface{} {
|
func (cls *Cluster) GetGlobalCfg() interface{} {
|
||||||
return cls.globalCfg
|
return cls.globalCfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (cls *Cluster) GetNodeInfo(nodeId int) (NodeInfo,bool) {
|
func (cls *Cluster) ParseGlobalCfg(cfg interface{}) error{
|
||||||
|
if cls.globalCfg == nil {
|
||||||
|
return errors.New("no service configuration found")
|
||||||
|
}
|
||||||
|
|
||||||
|
rv := reflect.ValueOf(cls.globalCfg)
|
||||||
|
if rv.Kind() == reflect.Ptr && rv.IsNil() {
|
||||||
|
return errors.New("no service configuration found")
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes,err := json.Marshal(cls.globalCfg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Unmarshal(bytes,cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) GetNodeInfo(nodeId string) (NodeInfo,bool) {
|
||||||
cls.locker.RLock()
|
cls.locker.RLock()
|
||||||
defer cls.locker.RUnlock()
|
defer cls.locker.RUnlock()
|
||||||
|
|
||||||
nodeInfo,ok:= cls.mapIdNode[nodeId]
|
nodeInfo,ok:= cls.mapRpc[nodeId]
|
||||||
return nodeInfo,ok
|
if ok == false || nodeInfo == nil {
|
||||||
|
return NodeInfo{},false
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeInfo.nodeInfo,true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dc *Cluster) CanDiscoveryService(fromMasterNodeId string,serviceName string) bool{
|
||||||
|
canDiscovery := true
|
||||||
|
|
||||||
|
for i:=0;i<len(dc.GetLocalNodeInfo().DiscoveryService);i++{
|
||||||
|
masterNodeId := dc.GetLocalNodeInfo().DiscoveryService[i].MasterNodeId
|
||||||
|
//无效的配置,则跳过
|
||||||
|
if masterNodeId == rpc.NodeIdNull && len(dc.GetLocalNodeInfo().DiscoveryService[i].ServiceList)==0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
canDiscovery = false
|
||||||
|
if masterNodeId == fromMasterNodeId || masterNodeId == rpc.NodeIdNull {
|
||||||
|
for _,discoveryService := range dc.GetLocalNodeInfo().DiscoveryService[i].ServiceList {
|
||||||
|
if discoveryService == serviceName {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return canDiscovery
|
||||||
|
}
|
||||||
@@ -1,19 +1,21 @@
|
|||||||
package cluster
|
package cluster
|
||||||
|
|
||||||
|
import "github.com/duanhf2012/origin/v2/rpc"
|
||||||
|
|
||||||
type ConfigDiscovery struct {
|
type ConfigDiscovery struct {
|
||||||
funDelService FunDelNode
|
funDelNode FunDelNode
|
||||||
funSetService FunSetNodeInfo
|
funSetNode FunSetNode
|
||||||
localNodeId int
|
localNodeId string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (discovery *ConfigDiscovery) InitDiscovery(localNodeId int,funDelNode FunDelNode,funSetNodeInfo FunSetNodeInfo) error{
|
func (discovery *ConfigDiscovery) InitDiscovery(localNodeId string,funDelNode FunDelNode,funSetNode FunSetNode) error{
|
||||||
discovery.localNodeId = localNodeId
|
discovery.localNodeId = localNodeId
|
||||||
discovery.funDelService = funDelNode
|
discovery.funDelNode = funDelNode
|
||||||
discovery.funSetService = funSetNodeInfo
|
discovery.funSetNode = funSetNode
|
||||||
|
|
||||||
//解析本地其他服务配置
|
//解析本地其他服务配置
|
||||||
_,nodeInfoList,err := GetCluster().readLocalClusterConfig(0)
|
_,nodeInfoList,_,err := GetCluster().readLocalClusterConfig(rpc.NodeIdNull)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -23,12 +25,10 @@ func (discovery *ConfigDiscovery) InitDiscovery(localNodeId int,funDelNode FunDe
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
discovery.funSetService(&nodeInfo)
|
discovery.funSetNode(&nodeInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (discovery *ConfigDiscovery) OnNodeStop(){
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
71
cluster/discovery.go
Normal file
71
cluster/discovery.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package cluster
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (cls *Cluster) setupDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error{
|
||||||
|
if cls.discoveryInfo.getDiscoveryType() == OriginType { //origin类型服务发现
|
||||||
|
return cls.setupOriginDiscovery(localNodeId,setupServiceFun)
|
||||||
|
}else if cls.discoveryInfo.getDiscoveryType() == EtcdType{//etcd类型服务发现
|
||||||
|
return cls.setupEtcdDiscovery(localNodeId,setupServiceFun)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cls.setupConfigDiscovery(localNodeId,setupServiceFun)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) setupOriginDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error{
|
||||||
|
if cls.serviceDiscovery != nil {
|
||||||
|
return errors.New("service discovery has been setup")
|
||||||
|
}
|
||||||
|
|
||||||
|
//1.如果没有配置DiscoveryNode配置,则使用默认配置文件发现服务
|
||||||
|
localMaster, hasMaster := cls.checkOriginDiscovery(localNodeId)
|
||||||
|
if hasMaster == false {
|
||||||
|
return errors.New("no master node config")
|
||||||
|
}
|
||||||
|
|
||||||
|
cls.serviceDiscovery = getOriginDiscovery()
|
||||||
|
//2.如果为动态服务发现安装本地发现服务
|
||||||
|
if localMaster == true {
|
||||||
|
setupServiceFun(&masterService)
|
||||||
|
cls.AddDiscoveryService(OriginDiscoveryMasterName, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
setupServiceFun(&clientService)
|
||||||
|
cls.AddDiscoveryService(OriginDiscoveryClientName, true)
|
||||||
|
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) setupEtcdDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error{
|
||||||
|
if cls.serviceDiscovery != nil {
|
||||||
|
return errors.New("service discovery has been setup")
|
||||||
|
}
|
||||||
|
|
||||||
|
//setup etcd service
|
||||||
|
cls.serviceDiscovery = getEtcdDiscovery()
|
||||||
|
setupServiceFun(cls.serviceDiscovery.(service.IService))
|
||||||
|
|
||||||
|
cls.AddDiscoveryService(cls.serviceDiscovery.(service.IService).GetName(),false)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) setupConfigDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error{
|
||||||
|
if cls.serviceDiscovery != nil {
|
||||||
|
return errors.New("service discovery has been setup")
|
||||||
|
}
|
||||||
|
|
||||||
|
cls.serviceDiscovery = &ConfigDiscovery{}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) GetOriginDiscovery() *OriginDiscovery {
|
||||||
|
return cls.discoveryInfo.Origin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) GetEtcdDiscovery() *EtcdDiscovery {
|
||||||
|
return cls.discoveryInfo.Etcd
|
||||||
|
}
|
||||||
@@ -1,422 +0,0 @@
|
|||||||
package cluster
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"github.com/duanhf2012/origin/log"
|
|
||||||
"github.com/duanhf2012/origin/rpc"
|
|
||||||
"github.com/duanhf2012/origin/service"
|
|
||||||
)
|
|
||||||
|
|
||||||
const DynamicDiscoveryMasterName = "DiscoveryMaster"
|
|
||||||
const DynamicDiscoveryClientName = "DiscoveryClient"
|
|
||||||
const RegServiceDiscover = DynamicDiscoveryMasterName + ".RPC_RegServiceDiscover"
|
|
||||||
const SubServiceDiscover = DynamicDiscoveryClientName + ".RPC_SubServiceDiscover"
|
|
||||||
const AddSubServiceDiscover = DynamicDiscoveryMasterName + ".RPC_AddSubServiceDiscover"
|
|
||||||
|
|
||||||
type DynamicDiscoveryMaster struct {
|
|
||||||
service.Service
|
|
||||||
|
|
||||||
mapNodeInfo map[int32]struct{}
|
|
||||||
nodeInfo []*rpc.NodeInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
type DynamicDiscoveryClient struct {
|
|
||||||
service.Service
|
|
||||||
|
|
||||||
funDelService FunDelNode
|
|
||||||
funSetService FunSetNodeInfo
|
|
||||||
localNodeId int
|
|
||||||
|
|
||||||
mapDiscovery map[int32]map[int32]struct{} //map[masterNodeId]map[nodeId]struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var masterService DynamicDiscoveryMaster
|
|
||||||
var clientService DynamicDiscoveryClient
|
|
||||||
|
|
||||||
func getDynamicDiscovery() IServiceDiscovery {
|
|
||||||
return &clientService
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
masterService.SetName(DynamicDiscoveryMasterName)
|
|
||||||
clientService.SetName(DynamicDiscoveryClientName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ds *DynamicDiscoveryMaster) isRegNode(nodeId int32) bool {
|
|
||||||
_, ok := ds.mapNodeInfo[nodeId]
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ds *DynamicDiscoveryMaster) addNodeInfo(nodeInfo *rpc.NodeInfo) {
|
|
||||||
if len(nodeInfo.PublicServiceList) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, ok := ds.mapNodeInfo[nodeInfo.NodeId]
|
|
||||||
if ok == true {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ds.mapNodeInfo[nodeInfo.NodeId] = struct{}{}
|
|
||||||
ds.nodeInfo = append(ds.nodeInfo, nodeInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ds *DynamicDiscoveryMaster) removeNodeInfo(nodeId int32) {
|
|
||||||
if _,ok:= ds.mapNodeInfo[nodeId];ok == false {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i:=0;i<len(ds.nodeInfo);i++ {
|
|
||||||
if ds.nodeInfo[i].NodeId == nodeId {
|
|
||||||
ds.nodeInfo = append(ds.nodeInfo[:i],ds.nodeInfo[i+1:]...)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(ds.mapNodeInfo,nodeId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ds *DynamicDiscoveryMaster) OnInit() error {
|
|
||||||
ds.mapNodeInfo = make(map[int32]struct{}, 20)
|
|
||||||
ds.RegRpcListener(ds)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ds *DynamicDiscoveryMaster) OnStart() {
|
|
||||||
var nodeInfo rpc.NodeInfo
|
|
||||||
localNodeInfo := cluster.GetLocalNodeInfo()
|
|
||||||
if localNodeInfo.Private == true {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeInfo.NodeId = int32(localNodeInfo.NodeId)
|
|
||||||
nodeInfo.NodeName = localNodeInfo.NodeName
|
|
||||||
nodeInfo.ListenAddr = localNodeInfo.ListenAddr
|
|
||||||
nodeInfo.PublicServiceList = localNodeInfo.PublicServiceList
|
|
||||||
nodeInfo.MaxRpcParamLen = localNodeInfo.MaxRpcParamLen
|
|
||||||
|
|
||||||
ds.addNodeInfo(&nodeInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ds *DynamicDiscoveryMaster) OnNodeConnected(nodeId int) {
|
|
||||||
//没注册过结点不通知
|
|
||||||
if ds.isRegNode(int32(nodeId)) == false {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//向它发布所有服务列表信息
|
|
||||||
var notifyDiscover rpc.SubscribeDiscoverNotify
|
|
||||||
notifyDiscover.IsFull = true
|
|
||||||
notifyDiscover.NodeInfo = ds.nodeInfo
|
|
||||||
notifyDiscover.MasterNodeId = int32(cluster.GetLocalNodeInfo().NodeId)
|
|
||||||
|
|
||||||
ds.GoNode(nodeId, SubServiceDiscover, ¬ifyDiscover)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ds *DynamicDiscoveryMaster) OnNodeDisconnect(nodeId int) {
|
|
||||||
if ds.isRegNode(int32(nodeId)) == false {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ds.removeNodeInfo(int32(nodeId))
|
|
||||||
|
|
||||||
var notifyDiscover rpc.SubscribeDiscoverNotify
|
|
||||||
notifyDiscover.MasterNodeId = int32(cluster.GetLocalNodeInfo().NodeId)
|
|
||||||
notifyDiscover.DelNodeId = int32(nodeId)
|
|
||||||
//删除结点
|
|
||||||
cluster.DelNode(nodeId, true)
|
|
||||||
|
|
||||||
//无注册过的结点不广播,避免非当前Master网络中的连接断开时通知到本网络
|
|
||||||
ds.CastGo(SubServiceDiscover, ¬ifyDiscover)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ds *DynamicDiscoveryMaster) RpcCastGo(serviceMethod string, args interface{}) {
|
|
||||||
for nodeId, _ := range ds.mapNodeInfo {
|
|
||||||
ds.GoNode(int(nodeId), serviceMethod, args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 收到注册过来的结点
|
|
||||||
func (ds *DynamicDiscoveryMaster) RPC_RegServiceDiscover(req *rpc.ServiceDiscoverReq, res *rpc.Empty) error {
|
|
||||||
if req.NodeInfo == nil {
|
|
||||||
err := errors.New("RPC_RegServiceDiscover req is error.")
|
|
||||||
log.SError(err.Error())
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
//广播给其他所有结点
|
|
||||||
var notifyDiscover rpc.SubscribeDiscoverNotify
|
|
||||||
notifyDiscover.MasterNodeId = int32(cluster.GetLocalNodeInfo().NodeId)
|
|
||||||
notifyDiscover.NodeInfo = append(notifyDiscover.NodeInfo, req.NodeInfo)
|
|
||||||
ds.RpcCastGo(SubServiceDiscover, ¬ifyDiscover)
|
|
||||||
|
|
||||||
//存入本地
|
|
||||||
ds.addNodeInfo(req.NodeInfo)
|
|
||||||
|
|
||||||
//初始化结点信息
|
|
||||||
var nodeInfo NodeInfo
|
|
||||||
nodeInfo.NodeId = int(req.NodeInfo.NodeId)
|
|
||||||
nodeInfo.NodeName = req.NodeInfo.NodeName
|
|
||||||
nodeInfo.Private = req.NodeInfo.Private
|
|
||||||
nodeInfo.ServiceList = req.NodeInfo.PublicServiceList
|
|
||||||
nodeInfo.PublicServiceList = req.NodeInfo.PublicServiceList
|
|
||||||
nodeInfo.ListenAddr = req.NodeInfo.ListenAddr
|
|
||||||
nodeInfo.MaxRpcParamLen = req.NodeInfo.MaxRpcParamLen
|
|
||||||
//主动删除已经存在的结点,确保先断开,再连接
|
|
||||||
cluster.serviceDiscoveryDelNode(nodeInfo.NodeId, true)
|
|
||||||
|
|
||||||
//加入到本地Cluster模块中,将连接该结点
|
|
||||||
cluster.serviceDiscoverySetNodeInfo(&nodeInfo)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) OnInit() error {
|
|
||||||
dc.RegRpcListener(dc)
|
|
||||||
dc.mapDiscovery = map[int32]map[int32]struct{}{}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) addMasterNode(masterNodeId int32, nodeId int32) {
|
|
||||||
_, ok := dc.mapDiscovery[masterNodeId]
|
|
||||||
if ok == false {
|
|
||||||
dc.mapDiscovery[masterNodeId] = map[int32]struct{}{}
|
|
||||||
}
|
|
||||||
dc.mapDiscovery[masterNodeId][nodeId] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) removeMasterNode(masterNodeId int32, nodeId int32) {
|
|
||||||
mapNodeId, ok := dc.mapDiscovery[masterNodeId]
|
|
||||||
if ok == false {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(mapNodeId, nodeId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) findNodeId(nodeId int32) bool {
|
|
||||||
for _, mapNodeId := range dc.mapDiscovery {
|
|
||||||
_, ok := mapNodeId[nodeId]
|
|
||||||
if ok == true {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) OnStart() {
|
|
||||||
//2.添加并连接发现主结点
|
|
||||||
dc.addDiscoveryMaster()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) addDiscoveryMaster() {
|
|
||||||
discoveryNodeList := cluster.GetDiscoveryNodeList()
|
|
||||||
for i := 0; i < len(discoveryNodeList); i++ {
|
|
||||||
if discoveryNodeList[i].NodeId == cluster.GetLocalNodeInfo().NodeId {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dc.funSetService(&discoveryNodeList[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) fullCompareDiffNode(masterNodeId int32, mapNodeInfo map[int32]*rpc.NodeInfo) []int32 {
|
|
||||||
if mapNodeInfo == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
diffNodeIdSlice := make([]int32, 0, len(mapNodeInfo))
|
|
||||||
mapNodeId := map[int32]struct{}{}
|
|
||||||
mapNodeId, ok := dc.mapDiscovery[masterNodeId]
|
|
||||||
if ok == false {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//本地任何Master都不存在的,放到diffNodeIdSlice
|
|
||||||
for nodeId, _ := range mapNodeId {
|
|
||||||
_, ok := mapNodeInfo[nodeId]
|
|
||||||
if ok == false {
|
|
||||||
diffNodeIdSlice = append(diffNodeIdSlice, nodeId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return diffNodeIdSlice
|
|
||||||
}
|
|
||||||
|
|
||||||
//订阅发现的服务通知
|
|
||||||
func (dc *DynamicDiscoveryClient) RPC_SubServiceDiscover(req *rpc.SubscribeDiscoverNotify) error {
|
|
||||||
//整理当前master结点需要筛选的NeighborService
|
|
||||||
masterDiscoveryNodeInfo := cluster.GetMasterDiscoveryNodeInfo(int(req.MasterNodeId))
|
|
||||||
mapMasterDiscoveryService := map[string]struct{}{}
|
|
||||||
if masterDiscoveryNodeInfo != nil {
|
|
||||||
for i := 0; i < len(masterDiscoveryNodeInfo.NeighborService); i++ {
|
|
||||||
mapMasterDiscoveryService[masterDiscoveryNodeInfo.NeighborService[i]] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mapNodeInfo := map[int32]*rpc.NodeInfo{}
|
|
||||||
for _, nodeInfo := range req.NodeInfo {
|
|
||||||
//不对本地结点或者不存在任何公开服务的结点
|
|
||||||
if int(nodeInfo.NodeId) == dc.localNodeId {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if cluster.IsMasterDiscoveryNode() == false && len(nodeInfo.PublicServiceList) == 1 &&
|
|
||||||
nodeInfo.PublicServiceList[0] == DynamicDiscoveryClientName {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//遍历所有的公开服务,并筛选之
|
|
||||||
for _, serviceName := range nodeInfo.PublicServiceList {
|
|
||||||
//只有存在配置时才做筛选
|
|
||||||
if len(mapMasterDiscoveryService) > 0 {
|
|
||||||
if _, ok := mapMasterDiscoveryService[serviceName]; ok == false {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nInfo := mapNodeInfo[nodeInfo.NodeId]
|
|
||||||
if nInfo == nil {
|
|
||||||
nInfo = &rpc.NodeInfo{}
|
|
||||||
nInfo.NodeId = nodeInfo.NodeId
|
|
||||||
nInfo.NodeName = nodeInfo.NodeName
|
|
||||||
nInfo.ListenAddr = nodeInfo.ListenAddr
|
|
||||||
nInfo.MaxRpcParamLen = nodeInfo.MaxRpcParamLen
|
|
||||||
mapNodeInfo[nodeInfo.NodeId] = nInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
nInfo.PublicServiceList = append(nInfo.PublicServiceList, serviceName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//如果为完整同步,则找出差异的结点
|
|
||||||
var willDelNodeId []int32
|
|
||||||
//如果不是邻居结点,则做筛选
|
|
||||||
if req.IsFull == true {
|
|
||||||
diffNode := dc.fullCompareDiffNode(req.MasterNodeId, mapNodeInfo)
|
|
||||||
if len(diffNode) > 0 {
|
|
||||||
willDelNodeId = append(willDelNodeId, diffNode...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//指定删除结点
|
|
||||||
if req.DelNodeId > 0 && req.DelNodeId != int32(dc.localNodeId) {
|
|
||||||
willDelNodeId = append(willDelNodeId, req.DelNodeId)
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除不必要的结点
|
|
||||||
for _, nodeId := range willDelNodeId {
|
|
||||||
nodeInfo,_ := cluster.GetNodeInfo(int(nodeId))
|
|
||||||
cluster.TriggerDiscoveryEvent(false,int(nodeId),nodeInfo.PublicServiceList)
|
|
||||||
dc.removeMasterNode(req.MasterNodeId, int32(nodeId))
|
|
||||||
if dc.findNodeId(nodeId) == false {
|
|
||||||
dc.funDelService(int(nodeId), false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//设置新结点
|
|
||||||
for _, nodeInfo := range mapNodeInfo {
|
|
||||||
dc.addMasterNode(req.MasterNodeId, nodeInfo.NodeId)
|
|
||||||
dc.setNodeInfo(nodeInfo)
|
|
||||||
|
|
||||||
if len(nodeInfo.PublicServiceList) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
cluster.TriggerDiscoveryEvent(true,int(nodeInfo.NodeId),nodeInfo.PublicServiceList)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) isDiscoverNode(nodeId int) bool {
|
|
||||||
for i := 0; i < len(cluster.masterDiscoveryNodeList); i++ {
|
|
||||||
if cluster.masterDiscoveryNodeList[i].NodeId == nodeId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) OnNodeConnected(nodeId int) {
|
|
||||||
nodeInfo := cluster.GetMasterDiscoveryNodeInfo(nodeId)
|
|
||||||
if nodeInfo == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var req rpc.ServiceDiscoverReq
|
|
||||||
req.NodeInfo = &rpc.NodeInfo{}
|
|
||||||
req.NodeInfo.NodeId = int32(cluster.localNodeInfo.NodeId)
|
|
||||||
req.NodeInfo.NodeName = cluster.localNodeInfo.NodeName
|
|
||||||
req.NodeInfo.ListenAddr = cluster.localNodeInfo.ListenAddr
|
|
||||||
req.NodeInfo.MaxRpcParamLen = cluster.localNodeInfo.MaxRpcParamLen
|
|
||||||
|
|
||||||
//MasterDiscoveryNode配置中没有配置NeighborService,则同步当前结点所有服务
|
|
||||||
if len(nodeInfo.NeighborService) == 0 {
|
|
||||||
req.NodeInfo.PublicServiceList = cluster.localNodeInfo.PublicServiceList
|
|
||||||
} else {
|
|
||||||
req.NodeInfo.PublicServiceList = append(req.NodeInfo.PublicServiceList, DynamicDiscoveryClientName)
|
|
||||||
}
|
|
||||||
|
|
||||||
//向Master服务同步本Node服务信息
|
|
||||||
err := dc.AsyncCallNode(nodeId, RegServiceDiscover, &req, func(res *rpc.Empty, err error) {
|
|
||||||
if err != nil {
|
|
||||||
log.SError("call ", RegServiceDiscover, " is fail :", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.SError("call ", RegServiceDiscover, " is fail :", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) setNodeInfo(nodeInfo *rpc.NodeInfo) {
|
|
||||||
if nodeInfo == nil || nodeInfo.Private == true || int(nodeInfo.NodeId) == dc.localNodeId {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//筛选关注的服务
|
|
||||||
localNodeInfo := cluster.GetLocalNodeInfo()
|
|
||||||
if len(localNodeInfo.DiscoveryService) > 0 {
|
|
||||||
var discoverServiceSlice = make([]string, 0, 24)
|
|
||||||
for _, pubService := range nodeInfo.PublicServiceList {
|
|
||||||
for _, discoverService := range localNodeInfo.DiscoveryService {
|
|
||||||
if pubService == discoverService {
|
|
||||||
discoverServiceSlice = append(discoverServiceSlice, pubService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodeInfo.PublicServiceList = discoverServiceSlice
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(nodeInfo.PublicServiceList) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var nInfo NodeInfo
|
|
||||||
nInfo.ServiceList = nodeInfo.PublicServiceList
|
|
||||||
nInfo.PublicServiceList = nodeInfo.PublicServiceList
|
|
||||||
nInfo.NodeId = int(nodeInfo.NodeId)
|
|
||||||
nInfo.NodeName = nodeInfo.NodeName
|
|
||||||
nInfo.ListenAddr = nodeInfo.ListenAddr
|
|
||||||
nInfo.MaxRpcParamLen = nodeInfo.MaxRpcParamLen
|
|
||||||
dc.funSetService(&nInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) OnNodeDisconnect(nodeId int) {
|
|
||||||
//将Discard结点清理
|
|
||||||
cluster.DiscardNode(nodeId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) InitDiscovery(localNodeId int, funDelNode FunDelNode, funSetNodeInfo FunSetNodeInfo) error {
|
|
||||||
dc.localNodeId = localNodeId
|
|
||||||
dc.funDelService = funDelNode
|
|
||||||
dc.funSetService = funSetNodeInfo
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) OnNodeStop() {
|
|
||||||
}
|
|
||||||
521
cluster/etcddiscovery.go
Normal file
521
cluster/etcddiscovery.go
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
package cluster
|
||||||
|
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
"github.com/duanhf2012/origin/v2/util/timer"
|
||||||
|
"go.etcd.io/etcd/api/v3/mvccpb"
|
||||||
|
"go.etcd.io/etcd/client/v3"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"path"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
const originDir = "/origin"
|
||||||
|
const testKey = originDir+"/_inner/_test_7501f3ed-b716-44c2-0090-fc1ed0166d7a"
|
||||||
|
|
||||||
|
type etcdClientInfo struct {
|
||||||
|
watchKeys []string
|
||||||
|
leaseID clientv3.LeaseID
|
||||||
|
keepAliveChan <-chan *clientv3.LeaseKeepAliveResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
type EtcdDiscoveryService struct {
|
||||||
|
service.Service
|
||||||
|
funDelNode FunDelNode
|
||||||
|
funSetNode FunSetNode
|
||||||
|
localNodeId string
|
||||||
|
|
||||||
|
byteLocalNodeInfo string
|
||||||
|
mapClient map[*clientv3.Client]*etcdClientInfo
|
||||||
|
isClose int32
|
||||||
|
bRetire bool
|
||||||
|
mapDiscoveryNodeId map[string]map[string]struct{} //map[networkName]map[nodeId]
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEtcdDiscovery() (IServiceDiscovery) {
|
||||||
|
etcdDiscovery := &EtcdDiscoveryService{}
|
||||||
|
return etcdDiscovery
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) InitDiscovery(localNodeId string,funDelNode FunDelNode,funSetNode FunSetNode) error {
|
||||||
|
ed.localNodeId = localNodeId
|
||||||
|
|
||||||
|
ed.funDelNode = funDelNode
|
||||||
|
ed.funSetNode = funSetNode
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const(
|
||||||
|
eeGets = 0
|
||||||
|
eePut = 1
|
||||||
|
eeDelete = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type etcdDiscoveryEvent struct {
|
||||||
|
typ int
|
||||||
|
watchKey string
|
||||||
|
Kvs []*mvccpb.KeyValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ee *etcdDiscoveryEvent) GetEventType() event.EventType{
|
||||||
|
return event.Sys_Event_EtcdDiscovery
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) OnInit() error {
|
||||||
|
ed.mapClient = make(map[*clientv3.Client]*etcdClientInfo,1)
|
||||||
|
ed.mapDiscoveryNodeId = make(map[string]map[string]struct{})
|
||||||
|
|
||||||
|
ed.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_EtcdDiscovery, ed.GetEventHandler(), ed.OnEtcdDiscovery)
|
||||||
|
|
||||||
|
err := ed.marshalNodeInfo()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
etcdDiscoveryCfg := cluster.GetEtcdDiscovery()
|
||||||
|
if etcdDiscoveryCfg == nil {
|
||||||
|
return errors.New("etcd discovery config is nil.")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i:=0;i<len(etcdDiscoveryCfg.EtcdList);i++{
|
||||||
|
client, cerr := clientv3.New(clientv3.Config{
|
||||||
|
Endpoints: etcdDiscoveryCfg.EtcdList[i].Endpoints,
|
||||||
|
DialTimeout: etcdDiscoveryCfg.DialTimeoutMillisecond,
|
||||||
|
Logger: zap.NewNop(),
|
||||||
|
})
|
||||||
|
|
||||||
|
if cerr != nil {
|
||||||
|
log.Error("etcd discovery init fail",log.ErrorAttr("err",cerr))
|
||||||
|
return cerr
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx,_:=context.WithTimeout(context.Background(),time.Second*3)
|
||||||
|
_,err = client.Leases(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("etcd discovery init fail",log.Any("endpoint",etcdDiscoveryCfg.EtcdList[i].Endpoints),log.ErrorAttr("err",err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ec := &etcdClientInfo{}
|
||||||
|
for _, networkName := range etcdDiscoveryCfg.EtcdList[i].NetworkName {
|
||||||
|
ec.watchKeys = append(ec.watchKeys,fmt.Sprintf("%s/%s",originDir,networkName))
|
||||||
|
}
|
||||||
|
|
||||||
|
ed.mapClient[client] = ec
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) getRegisterKey(watchkey string) string{
|
||||||
|
return watchkey+"/"+ed.localNodeId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client,etcdClient *etcdClientInfo) {
|
||||||
|
// 创建租约
|
||||||
|
var err error
|
||||||
|
var resp *clientv3.LeaseGrantResponse
|
||||||
|
resp, err = client.Grant(context.Background(), cluster.GetEtcdDiscovery().TTLSecond)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("etcd registerService fail",log.ErrorAttr("err",err))
|
||||||
|
ed.tryRegisterService(client,etcdClient)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
etcdClient.leaseID = resp.ID
|
||||||
|
for _,watchKey:= range etcdClient.watchKeys {
|
||||||
|
// 注册服务节点到 etcd
|
||||||
|
_, err = client.Put(context.Background(), ed.getRegisterKey(watchKey), ed.byteLocalNodeInfo, clientv3.WithLease(resp.ID))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("etcd Put fail",log.ErrorAttr("err",err))
|
||||||
|
ed.tryRegisterService(client,etcdClient)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
etcdClient.keepAliveChan,err = client.KeepAlive(context.Background(), etcdClient.leaseID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("etcd KeepAlive fail",log.ErrorAttr("err",err))
|
||||||
|
ed.tryRegisterService(client,etcdClient)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case _, ok := <-etcdClient.keepAliveChan:
|
||||||
|
//log.Debug("ok",log.Any("addr",client.Endpoints()))
|
||||||
|
if !ok {
|
||||||
|
log.Error("etcd keepAliveChan fail",log.Any("watchKeys",etcdClient.watchKeys))
|
||||||
|
ed.tryRegisterService(client,etcdClient)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) tryRegisterService(client *clientv3.Client,etcdClient *etcdClientInfo){
|
||||||
|
if ed.isStop() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ed.AfterFunc(time.Second*3, func(t *timer.Timer) {
|
||||||
|
ed.registerServiceByClient(client,etcdClient)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) tryWatch(client *clientv3.Client,etcdClient *etcdClientInfo) {
|
||||||
|
if ed.isStop() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ed.AfterFunc(time.Second*3, func(t *timer.Timer) {
|
||||||
|
ed.watchByClient(client,etcdClient)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) tryLaterRetire() {
|
||||||
|
ed.AfterFunc(time.Second, func(*timer.Timer) {
|
||||||
|
if ed.retire() != nil {
|
||||||
|
ed.tryLaterRetire()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) retire() error{
|
||||||
|
//从etcd中更新
|
||||||
|
for c,ec := range ed.mapClient {
|
||||||
|
for _, watchKey := range ec.watchKeys {
|
||||||
|
// 注册服务节点到 etcd
|
||||||
|
_, err := c.Put(context.Background(), ed.getRegisterKey(watchKey), ed.byteLocalNodeInfo, clientv3.WithLease(ec.leaseID))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("etcd Put fail", log.ErrorAttr("err", err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) OnRetire(){
|
||||||
|
ed.bRetire = true
|
||||||
|
ed.marshalNodeInfo()
|
||||||
|
|
||||||
|
if ed.retire()!= nil {
|
||||||
|
ed.tryLaterRetire()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) OnRelease(){
|
||||||
|
atomic.StoreInt32(&ed.isClose,1)
|
||||||
|
ed.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) isStop() bool{
|
||||||
|
return atomic.LoadInt32(&ed.isClose) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nd *EtcdDiscoveryService) OnStart() {
|
||||||
|
for c, ec := range nd.mapClient {
|
||||||
|
nd.tryRegisterService(c,ec)
|
||||||
|
nd.tryWatch(c,ec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) marshalNodeInfo() error{
|
||||||
|
nInfo := cluster.GetLocalNodeInfo()
|
||||||
|
var nodeInfo rpc.NodeInfo
|
||||||
|
nodeInfo.NodeId = nInfo.NodeId
|
||||||
|
nodeInfo.ListenAddr = nInfo.ListenAddr
|
||||||
|
nodeInfo.Retire = ed.bRetire
|
||||||
|
nodeInfo.PublicServiceList = nInfo.PublicServiceList
|
||||||
|
nodeInfo.MaxRpcParamLen = nInfo.MaxRpcParamLen
|
||||||
|
|
||||||
|
byteLocalNodeInfo,err := proto.Marshal(&nodeInfo)
|
||||||
|
if err ==nil{
|
||||||
|
ed.byteLocalNodeInfo = string(byteLocalNodeInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) setNodeInfo(networkName string,nodeInfo *rpc.NodeInfo) bool{
|
||||||
|
if nodeInfo == nil || nodeInfo.Private == true || nodeInfo.NodeId == ed.localNodeId {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//筛选关注的服务
|
||||||
|
var discoverServiceSlice = make([]string, 0, 24)
|
||||||
|
for _, pubService := range nodeInfo.PublicServiceList {
|
||||||
|
if cluster.CanDiscoveryService(networkName,pubService) == true {
|
||||||
|
discoverServiceSlice = append(discoverServiceSlice,pubService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(discoverServiceSlice) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var nInfo NodeInfo
|
||||||
|
nInfo.ServiceList = discoverServiceSlice
|
||||||
|
nInfo.PublicServiceList = discoverServiceSlice
|
||||||
|
nInfo.NodeId = nodeInfo.NodeId
|
||||||
|
nInfo.ListenAddr = nodeInfo.ListenAddr
|
||||||
|
nInfo.MaxRpcParamLen = nodeInfo.MaxRpcParamLen
|
||||||
|
nInfo.Retire = nodeInfo.Retire
|
||||||
|
nInfo.Private = nodeInfo.Private
|
||||||
|
|
||||||
|
ed.funSetNode(&nInfo)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) close(){
|
||||||
|
for c, ec := range ed.mapClient {
|
||||||
|
if _, err := c.Revoke(context.Background(), ec.leaseID); err != nil {
|
||||||
|
log.Error("etcd Revoke fail",log.ErrorAttr("err",err))
|
||||||
|
}
|
||||||
|
c.Watcher.Close()
|
||||||
|
err := c.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("etcd Close fail",log.ErrorAttr("err",err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) getServices(client *clientv3.Client,etcdClient *etcdClientInfo,watchKey string) bool {
|
||||||
|
// 根据前缀获取现有的key
|
||||||
|
resp, err := client.Get(context.Background(), watchKey, clientv3.WithPrefix())
|
||||||
|
if err != nil {
|
||||||
|
log.Error("etcd Get fail", log.ErrorAttr("err", err))
|
||||||
|
ed.tryWatch(client, etcdClient)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历获取得到的k和v
|
||||||
|
ed.notifyGets(watchKey,resp.Kvs)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) watchByClient(client *clientv3.Client,etcdClient *etcdClientInfo){
|
||||||
|
//先关闭所有的watcher
|
||||||
|
for _, watchKey := range etcdClient.watchKeys {
|
||||||
|
// 监视前缀,修改变更server
|
||||||
|
go ed.watcher(client,etcdClient, watchKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// watcher 监听Key的前缀
|
||||||
|
func (ed *EtcdDiscoveryService) watcher(client *clientv3.Client,etcdClient *etcdClientInfo,watchKey string) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
l := runtime.Stack(buf, false)
|
||||||
|
errString := fmt.Sprint(r)
|
||||||
|
log.Dump(string(buf[:l]),log.String("error",errString))
|
||||||
|
|
||||||
|
ed.tryWatch(client,etcdClient)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
rch := client.Watch(context.Background(), watchKey, clientv3.WithPrefix())
|
||||||
|
|
||||||
|
if ed.getServices(client,etcdClient,watchKey) == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for wresp := range rch {
|
||||||
|
for _, ev := range wresp.Events {
|
||||||
|
switch ev.Type {
|
||||||
|
case clientv3.EventTypePut: // 修改或者新增
|
||||||
|
ed.notifyPut(watchKey,ev.Kv)
|
||||||
|
case clientv3.EventTypeDelete: // 删除
|
||||||
|
ed.notifyDelete(watchKey,ev.Kv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ed.tryWatch(client,etcdClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) setNode(netWorkName string,byteNode []byte) string{
|
||||||
|
var nodeInfo rpc.NodeInfo
|
||||||
|
err := proto.Unmarshal(byteNode,&nodeInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unmarshal fail",log.String("netWorkName",netWorkName),log.ErrorAttr("err",err))
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
ed.setNodeInfo(netWorkName,&nodeInfo)
|
||||||
|
|
||||||
|
return nodeInfo.NodeId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) delNode(fullKey string) string{
|
||||||
|
nodeId := ed.getNodeId(fullKey)
|
||||||
|
if nodeId == ed.localNodeId {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
ed.funDelNode(nodeId)
|
||||||
|
return nodeId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) getNetworkNameByWatchKey(watchKey string) string{
|
||||||
|
return watchKey[strings.LastIndex(watchKey,"/")+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) getNetworkNameByFullKey(fullKey string) string{
|
||||||
|
return fullKey[len(originDir)+1:strings.LastIndex(fullKey,"/")]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) getNodeId(fullKey string) string{
|
||||||
|
return fullKey[strings.LastIndex(fullKey,"/")+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) OnEtcdDiscovery(ev event.IEvent){
|
||||||
|
disEvent := ev.(*etcdDiscoveryEvent)
|
||||||
|
switch disEvent.typ {
|
||||||
|
case eeGets:
|
||||||
|
ed.OnEventGets(disEvent.watchKey,disEvent.Kvs)
|
||||||
|
case eePut:
|
||||||
|
if len(disEvent.Kvs) == 1 {
|
||||||
|
ed.OnEventPut(disEvent.watchKey,disEvent.Kvs[0])
|
||||||
|
}
|
||||||
|
case eeDelete:
|
||||||
|
if len(disEvent.Kvs) == 1 {
|
||||||
|
ed.OnEventDelete(disEvent.watchKey,disEvent.Kvs[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) notifyGets(watchKey string,Kvs []*mvccpb.KeyValue) {
|
||||||
|
var ev etcdDiscoveryEvent
|
||||||
|
ev.typ = eeGets
|
||||||
|
ev.watchKey = watchKey
|
||||||
|
ev.Kvs = Kvs
|
||||||
|
ed.NotifyEvent(&ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) notifyPut(watchKey string,Kvs *mvccpb.KeyValue) {
|
||||||
|
var ev etcdDiscoveryEvent
|
||||||
|
ev.typ = eePut
|
||||||
|
ev.watchKey = watchKey
|
||||||
|
ev.Kvs = append(ev.Kvs,Kvs)
|
||||||
|
ed.NotifyEvent(&ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) notifyDelete(watchKey string,Kvs *mvccpb.KeyValue) {
|
||||||
|
var ev etcdDiscoveryEvent
|
||||||
|
ev.typ = eeDelete
|
||||||
|
ev.watchKey = watchKey
|
||||||
|
ev.Kvs = append(ev.Kvs,Kvs)
|
||||||
|
ed.NotifyEvent(&ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) OnEventGets(watchKey string,Kvs []*mvccpb.KeyValue) {
|
||||||
|
mapNode := make(map[string]struct{},32)
|
||||||
|
for _, kv := range Kvs {
|
||||||
|
nodeId := ed.setNode(ed.getNetworkNameByFullKey(string(kv.Key)), kv.Value)
|
||||||
|
mapNode[nodeId] = struct{}{}
|
||||||
|
ed.addNodeId(watchKey,nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 此段代码为遍历并删除过期节点的逻辑。
|
||||||
|
// 对于mapDiscoveryNodeId中与watchKey关联的所有节点ID,遍历该集合。
|
||||||
|
// 如果某个节点ID不在mapNode中且不是本地节点ID,则调用funDelNode函数删除该节点。
|
||||||
|
mapLastNodeId := ed.mapDiscoveryNodeId[watchKey] // 根据watchKey获取对应的节点ID集合
|
||||||
|
for nodeId := range mapLastNodeId { // 遍历所有节点ID
|
||||||
|
if _,ok := mapNode[nodeId];ok == false && nodeId != ed.localNodeId { // 检查节点是否不存在于mapNode且不是本地节点
|
||||||
|
ed.funDelNode(nodeId) // 调用函数删除该节点
|
||||||
|
delete(ed.mapDiscoveryNodeId[watchKey],nodeId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) OnEventPut(watchKey string,Kv *mvccpb.KeyValue) {
|
||||||
|
nodeId := ed.setNode(ed.getNetworkNameByFullKey(string(Kv.Key)), Kv.Value)
|
||||||
|
ed.addNodeId(watchKey,nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) OnEventDelete(watchKey string,Kv *mvccpb.KeyValue) {
|
||||||
|
nodeId := ed.delNode(string(Kv.Key))
|
||||||
|
delete(ed.mapDiscoveryNodeId[watchKey],nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) addNodeId(watchKey string,nodeId string) {
|
||||||
|
if _,ok := ed.mapDiscoveryNodeId[watchKey];ok == false {
|
||||||
|
ed.mapDiscoveryNodeId[watchKey] = make(map[string]struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
ed.mapDiscoveryNodeId[watchKey][nodeId] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) OnNodeDisconnect(nodeId string) {
|
||||||
|
//将Discard结点清理
|
||||||
|
cluster.DiscardNode(nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EtcdDiscoveryService) RPC_ServiceRecord(etcdServiceRecord *service.EtcdServiceRecordEvent,empty *service.Empty) error{
|
||||||
|
var client *clientv3.Client
|
||||||
|
|
||||||
|
//写入到etcd中
|
||||||
|
for c, info := range ed.mapClient{
|
||||||
|
for _,watchKey := range info.watchKeys {
|
||||||
|
if ed.getNetworkNameByWatchKey(watchKey) == etcdServiceRecord.NetworkName {
|
||||||
|
client = c
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if client == nil {
|
||||||
|
log.Error("etcd record fail,cannot find network name",log.String("networkName",etcdServiceRecord.NetworkName))
|
||||||
|
return errors.New("annot find network name")
|
||||||
|
}
|
||||||
|
|
||||||
|
var lg *clientv3.LeaseGrantResponse
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if etcdServiceRecord.TTLSecond > 0 {
|
||||||
|
ctx,_:=context.WithTimeout(context.Background(),time.Second*3)
|
||||||
|
lg, err = client.Grant(ctx, etcdServiceRecord.TTLSecond)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("etcd record fail,cannot grant lease",log.ErrorAttr("err",err))
|
||||||
|
return errors.New("cannot grant lease")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if lg != nil {
|
||||||
|
ctx,_:=context.WithTimeout(context.Background(),time.Second*3)
|
||||||
|
_, err = client.Put(ctx, path.Join(originDir,etcdServiceRecord.RecordKey),etcdServiceRecord.RecordInfo, clientv3.WithLease(lg.ID))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("etcd record fail,cannot put record",log.ErrorAttr("err",err))
|
||||||
|
}
|
||||||
|
return errors.New("cannot put record")
|
||||||
|
}
|
||||||
|
|
||||||
|
_,err = client.Put(context.Background(), path.Join(originDir,etcdServiceRecord.RecordKey),etcdServiceRecord.RecordInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("etcd record fail,cannot put record",log.ErrorAttr("err",err))
|
||||||
|
return errors.New("cannot put record")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
71
cluster/nodettl.go
Normal file
71
cluster/nodettl.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package cluster
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
"container/list"
|
||||||
|
)
|
||||||
|
|
||||||
|
type nodeTTL struct {
|
||||||
|
nodeId string
|
||||||
|
refreshTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type nodeSetTTL struct {
|
||||||
|
l *list.List
|
||||||
|
mapElement map[string]*list.Element
|
||||||
|
ttl time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *nodeSetTTL) init(ttl time.Duration) {
|
||||||
|
ns.ttl = ttl
|
||||||
|
ns.mapElement = make(map[string]*list.Element,32)
|
||||||
|
ns.l = list.New()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *nodeSetTTL) removeNode(nodeId string) {
|
||||||
|
ele,ok:=ns.mapElement[nodeId]
|
||||||
|
if ok == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ns.l.Remove(ele)
|
||||||
|
delete(ns.mapElement,nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *nodeSetTTL) addAndRefreshNode(nodeId string){
|
||||||
|
ele,ok:=ns.mapElement[nodeId]
|
||||||
|
if ok == false {
|
||||||
|
ele = ns.l.PushBack(nodeId)
|
||||||
|
ele.Value = &nodeTTL{nodeId,time.Now()}
|
||||||
|
ns.mapElement[nodeId] = ele
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ele.Value.(*nodeTTL).refreshTime = time.Now()
|
||||||
|
ns.l.MoveToBack(ele)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *nodeSetTTL) checkTTL(cb func(nodeIdList []string)){
|
||||||
|
nodeIdList := []string{}
|
||||||
|
for{
|
||||||
|
f := ns.l.Front()
|
||||||
|
if f == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
nt := f.Value.(*nodeTTL)
|
||||||
|
if time.Now().Sub(nt.refreshTime) > ns.ttl {
|
||||||
|
nodeIdList = append(nodeIdList,nt.nodeId)
|
||||||
|
}else{
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除结点
|
||||||
|
ns.l.Remove(f)
|
||||||
|
delete(ns.mapElement,nt.nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(nodeIdList) >0 {
|
||||||
|
cb(nodeIdList)
|
||||||
|
}
|
||||||
|
}
|
||||||
640
cluster/origindiscovery.go
Normal file
640
cluster/origindiscovery.go
Normal file
@@ -0,0 +1,640 @@
|
|||||||
|
package cluster
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
"github.com/duanhf2012/origin/v2/util/timer"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const OriginDiscoveryMasterName = "DiscoveryMaster"
|
||||||
|
const OriginDiscoveryClientName = "DiscoveryClient"
|
||||||
|
const RegServiceDiscover = OriginDiscoveryMasterName + ".RPC_RegServiceDiscover"
|
||||||
|
const SubServiceDiscover = OriginDiscoveryClientName + ".RPC_SubServiceDiscover"
|
||||||
|
const AddSubServiceDiscover = OriginDiscoveryMasterName + ".RPC_AddSubServiceDiscover"
|
||||||
|
const NodeRetireRpcMethod = OriginDiscoveryMasterName+".RPC_NodeRetire"
|
||||||
|
const RpcPingMethod = OriginDiscoveryMasterName+".RPC_Ping"
|
||||||
|
const UnRegServiceDiscover = OriginDiscoveryMasterName+".RPC_UnRegServiceDiscover"
|
||||||
|
|
||||||
|
type OriginDiscoveryMaster struct {
|
||||||
|
service.Service
|
||||||
|
|
||||||
|
mapNodeInfo map[string]struct{}
|
||||||
|
nodeInfo []*rpc.NodeInfo
|
||||||
|
|
||||||
|
nsTTL nodeSetTTL
|
||||||
|
}
|
||||||
|
|
||||||
|
type OriginDiscoveryClient struct {
|
||||||
|
service.Service
|
||||||
|
|
||||||
|
funDelNode FunDelNode
|
||||||
|
funSetNode FunSetNode
|
||||||
|
localNodeId string
|
||||||
|
|
||||||
|
mapDiscovery map[string]map[string][]string //map[masterNodeId]map[nodeId]struct{}
|
||||||
|
bRetire bool
|
||||||
|
isRegisterOk bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var masterService OriginDiscoveryMaster
|
||||||
|
var clientService OriginDiscoveryClient
|
||||||
|
|
||||||
|
func getOriginDiscovery() IServiceDiscovery {
|
||||||
|
return &clientService
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
masterService.SetName(OriginDiscoveryMasterName)
|
||||||
|
clientService.SetName(OriginDiscoveryClientName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) isRegNode(nodeId string) bool {
|
||||||
|
_, ok := ds.mapNodeInfo[nodeId]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) updateNodeInfo(nInfo *rpc.NodeInfo) {
|
||||||
|
if _,ok:= ds.mapNodeInfo[nInfo.NodeId];ok == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeInfo := proto.Clone(nInfo).(*rpc.NodeInfo)
|
||||||
|
for i:=0;i<len(ds.nodeInfo);i++ {
|
||||||
|
if ds.nodeInfo[i].NodeId == nodeInfo.NodeId {
|
||||||
|
ds.nodeInfo[i] = nodeInfo
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) addNodeInfo(nInfo *rpc.NodeInfo) {
|
||||||
|
if len(nInfo.PublicServiceList) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := ds.mapNodeInfo[nInfo.NodeId]
|
||||||
|
if ok == true {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ds.mapNodeInfo[nInfo.NodeId] = struct{}{}
|
||||||
|
|
||||||
|
nodeInfo := proto.Clone(nInfo).(*rpc.NodeInfo)
|
||||||
|
ds.nodeInfo = append(ds.nodeInfo, nodeInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) removeNodeInfo(nodeId string) {
|
||||||
|
if _,ok:= ds.mapNodeInfo[nodeId];ok == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i:=0;i<len(ds.nodeInfo);i++ {
|
||||||
|
if ds.nodeInfo[i].NodeId == nodeId {
|
||||||
|
ds.nodeInfo = append(ds.nodeInfo[:i],ds.nodeInfo[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ds.nsTTL.removeNode(nodeId)
|
||||||
|
delete(ds.mapNodeInfo,nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) OnInit() error {
|
||||||
|
ds.mapNodeInfo = make(map[string]struct{}, 20)
|
||||||
|
ds.RegNodeConnListener(ds)
|
||||||
|
ds.RegNatsConnListener(ds)
|
||||||
|
|
||||||
|
ds.nsTTL.init(time.Duration(cluster.GetOriginDiscovery().TTLSecond)*time.Second)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) checkTTL(){
|
||||||
|
if cluster.IsNatsMode() == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
interval := time.Duration(cluster.GetOriginDiscovery().TTLSecond)*time.Second
|
||||||
|
interval = interval /3 /2
|
||||||
|
if interval < time.Second {
|
||||||
|
interval = time.Second
|
||||||
|
}
|
||||||
|
|
||||||
|
ds.NewTicker(interval,func(t *timer.Ticker){
|
||||||
|
ds.nsTTL.checkTTL(func(nodeIdList []string) {
|
||||||
|
for _,nodeId := range nodeIdList {
|
||||||
|
log.Info("TTL expiry",log.String("nodeId",nodeId))
|
||||||
|
ds.OnNodeDisconnect(nodeId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) OnStart() {
|
||||||
|
var nodeInfo rpc.NodeInfo
|
||||||
|
localNodeInfo := cluster.GetLocalNodeInfo()
|
||||||
|
nodeInfo.NodeId = localNodeInfo.NodeId
|
||||||
|
nodeInfo.ListenAddr = localNodeInfo.ListenAddr
|
||||||
|
nodeInfo.PublicServiceList = localNodeInfo.PublicServiceList
|
||||||
|
nodeInfo.MaxRpcParamLen = localNodeInfo.MaxRpcParamLen
|
||||||
|
nodeInfo.Private = localNodeInfo.Private
|
||||||
|
nodeInfo.Retire = localNodeInfo.Retire
|
||||||
|
ds.addNodeInfo(&nodeInfo)
|
||||||
|
|
||||||
|
ds.checkTTL()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryMaster) OnNatsConnected(){
|
||||||
|
//向所有的节点同步服务发现信息
|
||||||
|
var notifyDiscover rpc.SubscribeDiscoverNotify
|
||||||
|
notifyDiscover.IsFull = true
|
||||||
|
notifyDiscover.NodeInfo = dc.nodeInfo
|
||||||
|
notifyDiscover.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
|
||||||
|
dc.RpcCastGo(SubServiceDiscover, ¬ifyDiscover)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryMaster) OnNatsDisconnect(){
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) OnNodeConnected(nodeId string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) OnNodeDisconnect(nodeId string) {
|
||||||
|
if ds.isRegNode(nodeId) == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ds.removeNodeInfo(nodeId)
|
||||||
|
|
||||||
|
//主动删除已经存在的结点,确保先断开,再连接
|
||||||
|
var notifyDiscover rpc.SubscribeDiscoverNotify
|
||||||
|
notifyDiscover.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
|
||||||
|
notifyDiscover.DelNodeId = nodeId
|
||||||
|
|
||||||
|
//删除结点
|
||||||
|
cluster.DelNode(nodeId)
|
||||||
|
|
||||||
|
//无注册过的结点不广播,避免非当前Master网络中的连接断开时通知到本网络
|
||||||
|
ds.CastGo(SubServiceDiscover, ¬ifyDiscover)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) RpcCastGo(serviceMethod string, args interface{}) {
|
||||||
|
for nodeId, _ := range ds.mapNodeInfo {
|
||||||
|
if nodeId == cluster.GetLocalNodeInfo().NodeId {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ds.GoNode(nodeId, serviceMethod, args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) RPC_Ping(req *rpc.Ping, res *rpc.Pong) error {
|
||||||
|
if ds.isRegNode(req.NodeId) == false{
|
||||||
|
res.Ok = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Ok = true
|
||||||
|
ds.nsTTL.addAndRefreshNode(req.NodeId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) RPC_NodeRetire(req *rpc.NodeRetireReq, res *rpc.Empty) error {
|
||||||
|
log.Info("node is retire",log.String("nodeId",req.NodeInfo.NodeId),log.Bool("retire",req.NodeInfo.Retire))
|
||||||
|
|
||||||
|
ds.updateNodeInfo(req.NodeInfo)
|
||||||
|
|
||||||
|
var notifyDiscover rpc.SubscribeDiscoverNotify
|
||||||
|
notifyDiscover.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
|
||||||
|
notifyDiscover.NodeInfo = append(notifyDiscover.NodeInfo, req.NodeInfo)
|
||||||
|
ds.RpcCastGo(SubServiceDiscover, ¬ifyDiscover)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收到注册过来的结点
|
||||||
|
func (ds *OriginDiscoveryMaster) RPC_RegServiceDiscover(req *rpc.RegServiceDiscoverReq, res *rpc.SubscribeDiscoverNotify) error {
|
||||||
|
if req.NodeInfo == nil {
|
||||||
|
err := errors.New("RPC_RegServiceDiscover req is error.")
|
||||||
|
log.Error(err.Error())
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.NodeInfo.NodeId != cluster.GetLocalNodeInfo().NodeId {
|
||||||
|
ds.nsTTL.addAndRefreshNode(req.NodeInfo.NodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
//广播给其他所有结点
|
||||||
|
var notifyDiscover rpc.SubscribeDiscoverNotify
|
||||||
|
notifyDiscover.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
|
||||||
|
notifyDiscover.NodeInfo = append(notifyDiscover.NodeInfo, req.NodeInfo)
|
||||||
|
ds.RpcCastGo(SubServiceDiscover, ¬ifyDiscover)
|
||||||
|
|
||||||
|
//存入本地
|
||||||
|
ds.addNodeInfo(req.NodeInfo)
|
||||||
|
|
||||||
|
//初始化结点信息
|
||||||
|
var nodeInfo NodeInfo
|
||||||
|
nodeInfo.NodeId = req.NodeInfo.NodeId
|
||||||
|
nodeInfo.Private = req.NodeInfo.Private
|
||||||
|
nodeInfo.ServiceList = req.NodeInfo.PublicServiceList
|
||||||
|
nodeInfo.PublicServiceList = req.NodeInfo.PublicServiceList
|
||||||
|
nodeInfo.ListenAddr = req.NodeInfo.ListenAddr
|
||||||
|
nodeInfo.MaxRpcParamLen = req.NodeInfo.MaxRpcParamLen
|
||||||
|
nodeInfo.Retire = req.NodeInfo.Retire
|
||||||
|
|
||||||
|
//主动删除已经存在的结点,确保先断开,再连接
|
||||||
|
cluster.serviceDiscoveryDelNode(nodeInfo.NodeId)
|
||||||
|
|
||||||
|
//加入到本地Cluster模块中,将连接该结点
|
||||||
|
cluster.serviceDiscoverySetNodeInfo(&nodeInfo)
|
||||||
|
|
||||||
|
|
||||||
|
res.IsFull = true
|
||||||
|
res.NodeInfo = ds.nodeInfo
|
||||||
|
res.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *OriginDiscoveryMaster) RPC_UnRegServiceDiscover(req *rpc.UnRegServiceDiscoverReq, res *rpc.Empty) error {
|
||||||
|
log.Debug("RPC_UnRegServiceDiscover",log.String("nodeId",req.NodeId))
|
||||||
|
ds.OnNodeDisconnect(req.NodeId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) OnInit() error {
|
||||||
|
dc.RegNodeConnListener(dc)
|
||||||
|
dc.RegNatsConnListener(dc)
|
||||||
|
|
||||||
|
dc.mapDiscovery = map[string]map[string][]string{}
|
||||||
|
//dc.mapMasterNetwork = map[string]string{}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) addMasterNode(masterNodeId string, nodeId string,serviceList []string) {
|
||||||
|
_, ok := dc.mapDiscovery[masterNodeId]
|
||||||
|
if ok == false {
|
||||||
|
dc.mapDiscovery[masterNodeId] = map[string][]string{}
|
||||||
|
}
|
||||||
|
dc.mapDiscovery[masterNodeId][nodeId] = serviceList
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) getNodePublicService(masterNodeId string,nodeId string) []string{
|
||||||
|
mapNodeId, ok := dc.mapDiscovery[masterNodeId]
|
||||||
|
if ok == false {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
publicService := mapNodeId[nodeId]
|
||||||
|
return publicService
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) removeMasterNode(masterNodeId string, nodeId string) {
|
||||||
|
mapNodeId, ok := dc.mapDiscovery[masterNodeId]
|
||||||
|
if ok == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(mapNodeId, nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) findNodeId(nodeId string) bool {
|
||||||
|
for _, mapNodeId := range dc.mapDiscovery {
|
||||||
|
_, ok := mapNodeId[nodeId]
|
||||||
|
if ok == true {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) ping(){
|
||||||
|
interval := time.Duration(cluster.GetOriginDiscovery().TTLSecond)*time.Second
|
||||||
|
interval = interval /3
|
||||||
|
if interval < time.Second {
|
||||||
|
interval = time.Second
|
||||||
|
}
|
||||||
|
|
||||||
|
dc.NewTicker(interval,func(t *timer.Ticker){
|
||||||
|
if cluster.IsNatsMode() == false || dc.isRegisterOk == false{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var ping rpc.Ping
|
||||||
|
ping.NodeId = cluster.GetLocalNodeInfo().NodeId
|
||||||
|
masterNodes := GetCluster().GetOriginDiscovery().MasterNodeList
|
||||||
|
for i:=0;i<len(masterNodes);i++ {
|
||||||
|
if masterNodes[i].NodeId == cluster.GetLocalNodeInfo().NodeId {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
masterNodeId := masterNodes[i].NodeId
|
||||||
|
dc.AsyncCallNodeWithTimeout(3*time.Second,masterNodeId,RpcPingMethod,&ping, func(empty *rpc.Pong,err error) {
|
||||||
|
if err == nil && empty.Ok == false{
|
||||||
|
//断开master重
|
||||||
|
dc.regServiceDiscover(masterNodeId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) OnStart() {
|
||||||
|
//2.添加并连接发现主结点
|
||||||
|
dc.addDiscoveryMaster()
|
||||||
|
dc.ping()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) addDiscoveryMaster() {
|
||||||
|
discoveryNodeList := cluster.GetOriginDiscovery()
|
||||||
|
|
||||||
|
for i := 0; i < len(discoveryNodeList.MasterNodeList); i++ {
|
||||||
|
if discoveryNodeList.MasterNodeList[i].NodeId == cluster.GetLocalNodeInfo().NodeId {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dc.funSetNode(&discoveryNodeList.MasterNodeList[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) fullCompareDiffNode(masterNodeId string, mapNodeInfo map[string]*rpc.NodeInfo) []string {
|
||||||
|
if mapNodeInfo == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
diffNodeIdSlice := make([]string, 0, len(mapNodeInfo))
|
||||||
|
mapNodeId := map[string][]string{}
|
||||||
|
mapNodeId, ok := dc.mapDiscovery[masterNodeId]
|
||||||
|
if ok == false {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//本地任何Master都不存在的,放到diffNodeIdSlice
|
||||||
|
for nodeId, _ := range mapNodeId {
|
||||||
|
_, ok := mapNodeInfo[nodeId]
|
||||||
|
if ok == false {
|
||||||
|
diffNodeIdSlice = append(diffNodeIdSlice, nodeId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return diffNodeIdSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
//订阅发现的服务通知
|
||||||
|
func (dc *OriginDiscoveryClient) RPC_SubServiceDiscover(req *rpc.SubscribeDiscoverNotify) error {
|
||||||
|
mapNodeInfo := map[string]*rpc.NodeInfo{}
|
||||||
|
for _, nodeInfo := range req.NodeInfo {
|
||||||
|
//不对本地结点或者不存在任何公开服务的结点
|
||||||
|
if nodeInfo.NodeId == dc.localNodeId {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if cluster.IsOriginMasterDiscoveryNode(cluster.GetLocalNodeInfo().NodeId) == false && len(nodeInfo.PublicServiceList) == 1 &&
|
||||||
|
nodeInfo.PublicServiceList[0] == OriginDiscoveryClientName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//遍历所有的公开服务,并筛选之
|
||||||
|
for _, serviceName := range nodeInfo.PublicServiceList {
|
||||||
|
nInfo := mapNodeInfo[nodeInfo.NodeId]
|
||||||
|
if nInfo == nil {
|
||||||
|
nInfo = &rpc.NodeInfo{}
|
||||||
|
nInfo.NodeId = nodeInfo.NodeId
|
||||||
|
nInfo.ListenAddr = nodeInfo.ListenAddr
|
||||||
|
nInfo.MaxRpcParamLen = nodeInfo.MaxRpcParamLen
|
||||||
|
nInfo.Retire = nodeInfo.Retire
|
||||||
|
nInfo.Private = nodeInfo.Private
|
||||||
|
|
||||||
|
mapNodeInfo[nodeInfo.NodeId] = nInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
nInfo.PublicServiceList = append(nInfo.PublicServiceList, serviceName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果为完整同步,则找出差异的结点
|
||||||
|
var willDelNodeId []string
|
||||||
|
if req.IsFull == true {
|
||||||
|
diffNode := dc.fullCompareDiffNode(req.MasterNodeId, mapNodeInfo)
|
||||||
|
if len(diffNode) > 0 {
|
||||||
|
willDelNodeId = append(willDelNodeId, diffNode...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//指定删除结点
|
||||||
|
if req.DelNodeId != rpc.NodeIdNull && req.DelNodeId != dc.localNodeId {
|
||||||
|
willDelNodeId = append(willDelNodeId, req.DelNodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除不必要的结点
|
||||||
|
for _, nodeId := range willDelNodeId {
|
||||||
|
dc.funDelNode(nodeId)
|
||||||
|
dc.removeMasterNode(req.MasterNodeId, nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置新结点
|
||||||
|
for _, nodeInfo := range mapNodeInfo {
|
||||||
|
dc.addMasterNode(req.MasterNodeId, nodeInfo.NodeId,nodeInfo.PublicServiceList)
|
||||||
|
bSet := dc.setNodeInfo(req.MasterNodeId,nodeInfo)
|
||||||
|
if bSet == false {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) OnNodeConnected(nodeId string) {
|
||||||
|
dc.regServiceDiscover(nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) OnRelease(){
|
||||||
|
log.Debug("OriginDiscoveryClient")
|
||||||
|
|
||||||
|
//取消注册
|
||||||
|
var nodeRetireReq rpc.UnRegServiceDiscoverReq
|
||||||
|
nodeRetireReq.NodeId = cluster.GetLocalNodeInfo().NodeId
|
||||||
|
|
||||||
|
masterNodeList := cluster.GetOriginDiscovery()
|
||||||
|
for i:=0;i<len(masterNodeList.MasterNodeList);i++{
|
||||||
|
if masterNodeList.MasterNodeList[i].NodeId == cluster.GetLocalNodeInfo().NodeId {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err := dc.CallNodeWithTimeout(3*time.Second,masterNodeList.MasterNodeList[i].NodeId,UnRegServiceDiscover,&nodeRetireReq,&rpc.Empty{})
|
||||||
|
if err!= nil {
|
||||||
|
log.Error("call "+UnRegServiceDiscover+" is fail",log.ErrorAttr("err",err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) OnRetire(){
|
||||||
|
dc.bRetire = true
|
||||||
|
|
||||||
|
masterNodeList := cluster.GetOriginDiscovery()
|
||||||
|
for i:=0;i<len(masterNodeList.MasterNodeList);i++{
|
||||||
|
var nodeRetireReq rpc.NodeRetireReq
|
||||||
|
|
||||||
|
nodeRetireReq.NodeInfo = &rpc.NodeInfo{}
|
||||||
|
nodeRetireReq.NodeInfo.NodeId = cluster.localNodeInfo.NodeId
|
||||||
|
nodeRetireReq.NodeInfo.ListenAddr = cluster.localNodeInfo.ListenAddr
|
||||||
|
nodeRetireReq.NodeInfo.MaxRpcParamLen = cluster.localNodeInfo.MaxRpcParamLen
|
||||||
|
nodeRetireReq.NodeInfo.PublicServiceList = cluster.localNodeInfo.PublicServiceList
|
||||||
|
nodeRetireReq.NodeInfo.Retire = dc.bRetire
|
||||||
|
nodeRetireReq.NodeInfo.Private = cluster.localNodeInfo.Private
|
||||||
|
|
||||||
|
err := dc.GoNode(masterNodeList.MasterNodeList[i].NodeId,NodeRetireRpcMethod,&nodeRetireReq)
|
||||||
|
if err!= nil {
|
||||||
|
log.Error("call "+NodeRetireRpcMethod+" is fail",log.ErrorAttr("err",err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) tryRegServiceDiscover(nodeId string){
|
||||||
|
dc.AfterFunc(time.Second*3, func(timer *timer.Timer) {
|
||||||
|
dc.regServiceDiscover(nodeId)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) regServiceDiscover(nodeId string){
|
||||||
|
if nodeId == cluster.GetLocalNodeInfo().NodeId {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
nodeInfo := cluster.getOriginMasterDiscoveryNodeInfo(nodeId)
|
||||||
|
if nodeInfo == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req rpc.RegServiceDiscoverReq
|
||||||
|
req.NodeInfo = &rpc.NodeInfo{}
|
||||||
|
req.NodeInfo.NodeId = cluster.localNodeInfo.NodeId
|
||||||
|
req.NodeInfo.ListenAddr = cluster.localNodeInfo.ListenAddr
|
||||||
|
req.NodeInfo.MaxRpcParamLen = cluster.localNodeInfo.MaxRpcParamLen
|
||||||
|
req.NodeInfo.PublicServiceList = cluster.localNodeInfo.PublicServiceList
|
||||||
|
req.NodeInfo.Retire = dc.bRetire
|
||||||
|
req.NodeInfo.Private = cluster.localNodeInfo.Private
|
||||||
|
log.Debug("regServiceDiscover",log.String("nodeId",nodeId))
|
||||||
|
//向Master服务同步本Node服务信息
|
||||||
|
_,err := dc.AsyncCallNodeWithTimeout(3*time.Second,nodeId, RegServiceDiscover, &req, func(res *rpc.SubscribeDiscoverNotify, err error) {
|
||||||
|
if err != nil {
|
||||||
|
log.Error("call "+RegServiceDiscover+" is fail :"+ err.Error())
|
||||||
|
dc.tryRegServiceDiscover(nodeId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dc.isRegisterOk = true
|
||||||
|
dc.RPC_SubServiceDiscover(res)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("call "+ RegServiceDiscover+" is fail :"+ err.Error())
|
||||||
|
dc.tryRegServiceDiscover(nodeId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) setNodeInfo(masterNodeId string,nodeInfo *rpc.NodeInfo) bool{
|
||||||
|
if nodeInfo == nil || nodeInfo.Private == true || nodeInfo.NodeId == dc.localNodeId {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//筛选关注的服务
|
||||||
|
var discoverServiceSlice = make([]string, 0, 24)
|
||||||
|
for _, pubService := range nodeInfo.PublicServiceList {
|
||||||
|
if cluster.CanDiscoveryService(masterNodeId,pubService) == true {
|
||||||
|
discoverServiceSlice = append(discoverServiceSlice,pubService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(discoverServiceSlice) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var nInfo NodeInfo
|
||||||
|
nInfo.ServiceList = discoverServiceSlice
|
||||||
|
nInfo.PublicServiceList = discoverServiceSlice
|
||||||
|
nInfo.NodeId = nodeInfo.NodeId
|
||||||
|
nInfo.ListenAddr = nodeInfo.ListenAddr
|
||||||
|
nInfo.MaxRpcParamLen = nodeInfo.MaxRpcParamLen
|
||||||
|
nInfo.Retire = nodeInfo.Retire
|
||||||
|
nInfo.Private = nodeInfo.Private
|
||||||
|
|
||||||
|
dc.funSetNode(&nInfo)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) OnNodeDisconnect(nodeId string) {
|
||||||
|
//将Discard结点清理
|
||||||
|
cluster.DiscardNode(nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) InitDiscovery(localNodeId string, funDelNode FunDelNode, funSetNode FunSetNode) error {
|
||||||
|
dc.localNodeId = localNodeId
|
||||||
|
dc.funDelNode = funDelNode
|
||||||
|
dc.funSetNode = funSetNode
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) checkOriginDiscovery(localNodeId string) (bool, bool) {
|
||||||
|
var localMaster bool //本结点是否为Master结点
|
||||||
|
var hasMaster bool //是否配置Master服务
|
||||||
|
|
||||||
|
//遍历所有结点
|
||||||
|
for _, nodeInfo := range cls.discoveryInfo.Origin.MasterNodeList {
|
||||||
|
if nodeInfo.NodeId == localNodeId {
|
||||||
|
localMaster = true
|
||||||
|
}
|
||||||
|
hasMaster = true
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回查询结果
|
||||||
|
return localMaster, hasMaster
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) AddDiscoveryService(serviceName string, bPublicService bool) {
|
||||||
|
addServiceList := append([]string{},serviceName)
|
||||||
|
cls.localNodeInfo.ServiceList = append(addServiceList,cls.localNodeInfo.ServiceList...)
|
||||||
|
if bPublicService {
|
||||||
|
cls.localNodeInfo.PublicServiceList = append(cls.localNodeInfo.PublicServiceList, serviceName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := cls.mapServiceNode[serviceName]; ok == false {
|
||||||
|
cls.mapServiceNode[serviceName] = map[string]struct{}{}
|
||||||
|
}
|
||||||
|
cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (cls *Cluster) IsOriginMasterDiscoveryNode(nodeId string) bool {
|
||||||
|
return cls.getOriginMasterDiscoveryNodeInfo(nodeId) != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) getOriginMasterDiscoveryNodeInfo(nodeId string) *NodeInfo {
|
||||||
|
if cls.discoveryInfo.Origin == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(cls.discoveryInfo.Origin.MasterNodeList); i++ {
|
||||||
|
if cls.discoveryInfo.Origin.MasterNodeList[i].NodeId == nodeId {
|
||||||
|
return &cls.discoveryInfo.Origin.MasterNodeList[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) OnNatsConnected(){
|
||||||
|
masterNodes := GetCluster().GetOriginDiscovery().MasterNodeList
|
||||||
|
for i:=0;i<len(masterNodes);i++ {
|
||||||
|
dc.regServiceDiscover(masterNodes[i].NodeId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *OriginDiscoveryClient) OnNatsDisconnect(){
|
||||||
|
}
|
||||||
@@ -2,21 +2,159 @@ package cluster
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
|
||||||
|
type EtcdList struct {
|
||||||
|
NetworkName []string
|
||||||
|
Endpoints []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type EtcdDiscovery struct {
|
||||||
|
DialTimeoutMillisecond time.Duration
|
||||||
|
TTLSecond int64
|
||||||
|
|
||||||
|
EtcdList []EtcdList
|
||||||
|
}
|
||||||
|
|
||||||
|
type OriginDiscovery struct {
|
||||||
|
TTLSecond int64
|
||||||
|
MasterNodeList []NodeInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiscoveryType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
InvalidType = 0
|
||||||
|
OriginType = 1
|
||||||
|
EtcdType = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
const MinTTL = 3
|
||||||
|
|
||||||
|
type DiscoveryInfo struct {
|
||||||
|
discoveryType DiscoveryType
|
||||||
|
Etcd *EtcdDiscovery //etcd
|
||||||
|
Origin *OriginDiscovery //orign
|
||||||
|
}
|
||||||
|
|
||||||
|
type NatsConfig struct {
|
||||||
|
NatsUrl string
|
||||||
|
NoRandomize bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type RpcMode struct {
|
||||||
|
Typ string `json:"Type"`
|
||||||
|
Nats NatsConfig
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
type NodeInfoList struct {
|
type NodeInfoList struct {
|
||||||
MasterDiscoveryNode []NodeInfo //用于服务发现Node
|
RpcMode RpcMode
|
||||||
|
Discovery DiscoveryInfo
|
||||||
NodeList []NodeInfo
|
NodeList []NodeInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *DiscoveryInfo) getDiscoveryType() DiscoveryType{
|
||||||
|
return d.discoveryType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DiscoveryInfo) setDiscovery(discoveryInfo *DiscoveryInfo) error{
|
||||||
|
var err error
|
||||||
|
err = d.setOrigin(discoveryInfo.Origin)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.setEtcd(discoveryInfo.Etcd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DiscoveryInfo) setEtcd(etcd *EtcdDiscovery) error{
|
||||||
|
if etcd == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.discoveryType != InvalidType {
|
||||||
|
return fmt.Errorf("Repeat configuration of Discovery")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Endpoints不允许重复
|
||||||
|
mapAddr:=make (map[string]struct{})
|
||||||
|
for _, n := range etcd.EtcdList {
|
||||||
|
for _,endPoint := range n.Endpoints {
|
||||||
|
if _,ok:=mapAddr[endPoint];ok == true {
|
||||||
|
return fmt.Errorf("etcd discovery config Etcd.EtcdList.Endpoints %+v is repeat",endPoint)
|
||||||
|
}
|
||||||
|
mapAddr[endPoint] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
//networkName不允许重复
|
||||||
|
mapNetworkName := make(map[string]struct{})
|
||||||
|
for _,netName := range n.NetworkName{
|
||||||
|
if _,ok := mapNetworkName[netName];ok == true {
|
||||||
|
return fmt.Errorf("etcd discovery config Etcd.EtcdList.NetworkName %+v is repeat",n.NetworkName)
|
||||||
|
}
|
||||||
|
|
||||||
|
mapNetworkName[netName] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if etcd.TTLSecond < MinTTL {
|
||||||
|
etcd.TTLSecond = MinTTL
|
||||||
|
}
|
||||||
|
etcd.DialTimeoutMillisecond = etcd.DialTimeoutMillisecond * time.Millisecond
|
||||||
|
|
||||||
|
d.Etcd = etcd
|
||||||
|
d.discoveryType = EtcdType
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DiscoveryInfo) setOrigin(originDiscovery *OriginDiscovery) error{
|
||||||
|
if originDiscovery== nil || len(originDiscovery.MasterNodeList)==0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.discoveryType != InvalidType {
|
||||||
|
return fmt.Errorf("Repeat configuration of Discovery")
|
||||||
|
}
|
||||||
|
|
||||||
|
mapListenAddr := make(map[string]struct{})
|
||||||
|
mapNodeId := make(map[string]struct{})
|
||||||
|
for _, n := range originDiscovery.MasterNodeList {
|
||||||
|
if _, ok := mapListenAddr[n.ListenAddr]; ok == true {
|
||||||
|
return fmt.Errorf("discovery config Origin.ListenAddr %s is repeat", n.ListenAddr)
|
||||||
|
}
|
||||||
|
mapListenAddr[n.ListenAddr] = struct{}{}
|
||||||
|
|
||||||
|
if _, ok := mapNodeId[n.NodeId]; ok == true {
|
||||||
|
return fmt.Errorf("discovery config Origin.NodeId %s is repeat", n.NodeId)
|
||||||
|
}
|
||||||
|
mapNodeId[n.NodeId] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Origin = originDiscovery
|
||||||
|
if d.Origin.TTLSecond < MinTTL {
|
||||||
|
d.Origin.TTLSecond = MinTTL
|
||||||
|
}
|
||||||
|
d.discoveryType = OriginType
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (cls *Cluster) ReadClusterConfig(filepath string) (*NodeInfoList, error) {
|
func (cls *Cluster) ReadClusterConfig(filepath string) (*NodeInfoList, error) {
|
||||||
c := &NodeInfoList{}
|
c := &NodeInfoList{}
|
||||||
d, err := os.ReadFile(filepath)
|
d, err := os.ReadFile(filepath)
|
||||||
@@ -31,7 +169,7 @@ func (cls *Cluster) ReadClusterConfig(filepath string) (*NodeInfoList, error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) readServiceConfig(filepath string) (interface{}, map[string]interface{}, map[int]map[string]interface{}, error) {
|
func (cls *Cluster) readServiceConfig(filepath string) (interface{}, map[string]interface{}, map[string]map[string]interface{}, error) {
|
||||||
c := map[string]interface{}{}
|
c := map[string]interface{}{}
|
||||||
//读取配置
|
//读取配置
|
||||||
d, err := os.ReadFile(filepath)
|
d, err := os.ReadFile(filepath)
|
||||||
@@ -50,7 +188,7 @@ func (cls *Cluster) readServiceConfig(filepath string) (interface{}, map[string]
|
|||||||
serviceConfig = serviceCfg.(map[string]interface{})
|
serviceConfig = serviceCfg.(map[string]interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
mapNodeService := map[int]map[string]interface{}{}
|
mapNodeService := map[string]map[string]interface{}{}
|
||||||
nodeServiceCfg, ok := c["NodeService"]
|
nodeServiceCfg, ok := c["NodeService"]
|
||||||
if ok == true {
|
if ok == true {
|
||||||
nodeServiceList := nodeServiceCfg.([]interface{})
|
nodeServiceList := nodeServiceCfg.([]interface{})
|
||||||
@@ -58,42 +196,81 @@ func (cls *Cluster) readServiceConfig(filepath string) (interface{}, map[string]
|
|||||||
serviceCfg := v.(map[string]interface{})
|
serviceCfg := v.(map[string]interface{})
|
||||||
nodeId, ok := serviceCfg["NodeId"]
|
nodeId, ok := serviceCfg["NodeId"]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
log.SFatal("NodeService list not find nodeId field")
|
log.Fatal("NodeService list not find nodeId field")
|
||||||
}
|
}
|
||||||
mapNodeService[int(nodeId.(float64))] = serviceCfg
|
mapNodeService[nodeId.(string)] = serviceCfg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return GlobalCfg, serviceConfig, mapNodeService, nil
|
return GlobalCfg, serviceConfig, mapNodeService, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) readLocalClusterConfig(nodeId int) ([]NodeInfo, []NodeInfo, error) {
|
func (cls *Cluster) SetRpcMode(cfgRpcMode *RpcMode,rpcMode *RpcMode) error {
|
||||||
|
//忽略掉没有设置的配置
|
||||||
|
if cfgRpcMode.Typ == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//不允许重复的配置Rpc模式
|
||||||
|
|
||||||
|
if cfgRpcMode.Typ != "" && rpcMode.Typ != ""{
|
||||||
|
return errors.New("repeat config RpcMode")
|
||||||
|
}
|
||||||
|
|
||||||
|
//检查Typ是否合法
|
||||||
|
if cfgRpcMode.Typ!="Nats" && cfgRpcMode.Typ!="Default" {
|
||||||
|
return fmt.Errorf("RpcMode %s is not support", rpcMode.Typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfgRpcMode.Typ == "Nats" && len(cfgRpcMode.Nats.NatsUrl)==0 {
|
||||||
|
return fmt.Errorf("nats rpc mode config NatsUrl is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
*rpcMode = *cfgRpcMode
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) readLocalClusterConfig(nodeId string) (DiscoveryInfo, []NodeInfo,RpcMode, error) {
|
||||||
var nodeInfoList []NodeInfo
|
var nodeInfoList []NodeInfo
|
||||||
var masterDiscoverNodeList []NodeInfo
|
var discoveryInfo DiscoveryInfo
|
||||||
|
var rpcMode RpcMode
|
||||||
|
|
||||||
clusterCfgPath := strings.TrimRight(configDir, "/") + "/cluster"
|
clusterCfgPath := strings.TrimRight(configDir, "/") + "/cluster"
|
||||||
fileInfoList, err := os.ReadDir(clusterCfgPath)
|
fileInfoList, err := os.ReadDir(clusterCfgPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("Read dir %s is fail :%+v", clusterCfgPath, err)
|
return discoveryInfo, nil,rpcMode, fmt.Errorf("Read dir %s is fail :%+v", clusterCfgPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件
|
//读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件
|
||||||
for _, f := range fileInfoList {
|
for _, f := range fileInfoList {
|
||||||
if f.IsDir() == false {
|
if f.IsDir() == false {
|
||||||
filePath := strings.TrimRight(strings.TrimRight(clusterCfgPath, "/"), "\\") + "/" + f.Name()
|
filePath := strings.TrimRight(strings.TrimRight(clusterCfgPath, "/"), "\\") + "/" + f.Name()
|
||||||
localNodeInfoList, err := cls.ReadClusterConfig(filePath)
|
fileNodeInfoList, rerr := cls.ReadClusterConfig(filePath)
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("read file path %s is error:%+v", filePath, err)
|
if rerr != nil {
|
||||||
|
return discoveryInfo, nil,rpcMode, fmt.Errorf("read file path %s is error:%+v", filePath, rerr)
|
||||||
}
|
}
|
||||||
masterDiscoverNodeList = append(masterDiscoverNodeList, localNodeInfoList.MasterDiscoveryNode...)
|
|
||||||
for _, nodeInfo := range localNodeInfoList.NodeList {
|
err = cls.SetRpcMode(&fileNodeInfoList.RpcMode,&rpcMode)
|
||||||
if nodeInfo.NodeId == nodeId || nodeId == 0 {
|
if err != nil {
|
||||||
|
return discoveryInfo, nil,rpcMode, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = discoveryInfo.setDiscovery(&fileNodeInfoList.Discovery)
|
||||||
|
if err != nil {
|
||||||
|
return discoveryInfo,nil,rpcMode,err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, nodeInfo := range fileNodeInfoList.NodeList {
|
||||||
|
if nodeInfo.NodeId == nodeId || nodeId == rpc.NodeIdNull {
|
||||||
nodeInfoList = append(nodeInfoList, nodeInfo)
|
nodeInfoList = append(nodeInfoList, nodeInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if nodeId != 0 && (len(nodeInfoList) != 1) {
|
if nodeId != rpc.NodeIdNull && (len(nodeInfoList) != 1) {
|
||||||
return nil, nil, fmt.Errorf("%d configurations were found for the configuration with node ID %d!", len(nodeInfoList), nodeId)
|
return discoveryInfo, nil,rpcMode, fmt.Errorf("nodeid %s configuration error in NodeList", nodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, _ := range nodeInfoList {
|
for i, _ := range nodeInfoList {
|
||||||
@@ -107,10 +284,10 @@ func (cls *Cluster) readLocalClusterConfig(nodeId int) ([]NodeInfo, []NodeInfo,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return masterDiscoverNodeList, nodeInfoList, nil
|
return discoveryInfo, nodeInfoList, rpcMode,nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) readLocalService(localNodeId int) error {
|
func (cls *Cluster) readLocalService(localNodeId string) error {
|
||||||
clusterCfgPath := strings.TrimRight(configDir, "/") + "/cluster"
|
clusterCfgPath := strings.TrimRight(configDir, "/") + "/cluster"
|
||||||
fileInfoList, err := os.ReadDir(clusterCfgPath)
|
fileInfoList, err := os.ReadDir(clusterCfgPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -148,6 +325,10 @@ func (cls *Cluster) readLocalService(localNodeId int) error {
|
|||||||
//保存公共配置
|
//保存公共配置
|
||||||
for _, s := range cls.localNodeInfo.ServiceList {
|
for _, s := range cls.localNodeInfo.ServiceList {
|
||||||
for {
|
for {
|
||||||
|
splitServiceName := strings.Split(s,":")
|
||||||
|
if len(splitServiceName) == 2 {
|
||||||
|
s = splitServiceName[0]
|
||||||
|
}
|
||||||
//取公共服务配置
|
//取公共服务配置
|
||||||
pubCfg, ok := serviceConfig[s]
|
pubCfg, ok := serviceConfig[s]
|
||||||
if ok == true {
|
if ok == true {
|
||||||
@@ -178,6 +359,11 @@ func (cls *Cluster) readLocalService(localNodeId int) error {
|
|||||||
|
|
||||||
//组合所有的配置
|
//组合所有的配置
|
||||||
for _, s := range cls.localNodeInfo.ServiceList {
|
for _, s := range cls.localNodeInfo.ServiceList {
|
||||||
|
splitServiceName := strings.Split(s,":")
|
||||||
|
if len(splitServiceName) == 2 {
|
||||||
|
s = splitServiceName[0]
|
||||||
|
}
|
||||||
|
|
||||||
//先从NodeService中找
|
//先从NodeService中找
|
||||||
var serviceCfg interface{}
|
var serviceCfg interface{}
|
||||||
var ok bool
|
var ok bool
|
||||||
@@ -199,46 +385,55 @@ func (cls *Cluster) readLocalService(localNodeId int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) parseLocalCfg() {
|
func (cls *Cluster) parseLocalCfg() {
|
||||||
cls.mapIdNode[cls.localNodeInfo.NodeId] = cls.localNodeInfo
|
rpcInfo := NodeRpcInfo{}
|
||||||
|
rpcInfo.nodeInfo = cls.localNodeInfo
|
||||||
|
rpcInfo.client = rpc.NewLClient(rpcInfo.nodeInfo.NodeId,&cls.callSet)
|
||||||
|
|
||||||
for _, sName := range cls.localNodeInfo.ServiceList {
|
cls.mapRpc[cls.localNodeInfo.NodeId] = &rpcInfo
|
||||||
if _, ok := cls.mapServiceNode[sName]; ok == false {
|
|
||||||
cls.mapServiceNode[sName] = make(map[int]struct{})
|
|
||||||
}
|
|
||||||
|
|
||||||
cls.mapServiceNode[sName][cls.localNodeInfo.NodeId] = struct{}{}
|
for _, serviceName := range cls.localNodeInfo.ServiceList {
|
||||||
}
|
splitServiceName := strings.Split(serviceName,":")
|
||||||
}
|
if len(splitServiceName) == 2 {
|
||||||
|
serviceName = splitServiceName[0]
|
||||||
func (cls *Cluster) checkDiscoveryNodeList(discoverMasterNode []NodeInfo) bool {
|
templateServiceName := splitServiceName[1]
|
||||||
for i := 0; i < len(discoverMasterNode)-1; i++ {
|
//记录模板
|
||||||
for j := i + 1; j < len(discoverMasterNode); j++ {
|
if _, ok := cls.mapTemplateServiceNode[templateServiceName]; ok == false {
|
||||||
if discoverMasterNode[i].NodeId == discoverMasterNode[j].NodeId ||
|
cls.mapTemplateServiceNode[templateServiceName]=map[string]struct{}{}
|
||||||
discoverMasterNode[i].ListenAddr == discoverMasterNode[j].ListenAddr {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
cls.mapTemplateServiceNode[templateServiceName][serviceName] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
|
if _, ok := cls.mapServiceNode[serviceName]; ok == false {
|
||||||
|
cls.mapServiceNode[serviceName] = make(map[string]struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId] = struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) InitCfg(localNodeId int) error {
|
func (cls *Cluster) IsNatsMode() bool {
|
||||||
|
return cls.rpcMode.Typ == "Nats"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) GetNatsUrl() string {
|
||||||
|
return cls.rpcMode.Nats.NatsUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) InitCfg(localNodeId string) error {
|
||||||
cls.localServiceCfg = map[string]interface{}{}
|
cls.localServiceCfg = map[string]interface{}{}
|
||||||
cls.mapRpc = map[int]NodeRpcInfo{}
|
cls.mapRpc = map[string]*NodeRpcInfo{}
|
||||||
cls.mapIdNode = map[int]NodeInfo{}
|
cls.mapServiceNode = map[string]map[string]struct{}{}
|
||||||
cls.mapServiceNode = map[string]map[int]struct{}{}
|
cls.mapTemplateServiceNode = map[string]map[string]struct{}{}
|
||||||
|
|
||||||
//加载本地结点的NodeList配置
|
//加载本地结点的NodeList配置
|
||||||
discoveryNode, nodeInfoList, err := cls.readLocalClusterConfig(localNodeId)
|
discoveryInfo, nodeInfoList,rpcMode, err := cls.readLocalClusterConfig(localNodeId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cls.localNodeInfo = nodeInfoList[0]
|
cls.localNodeInfo = nodeInfoList[0]
|
||||||
if cls.checkDiscoveryNodeList(discoveryNode) == false {
|
cls.discoveryInfo = discoveryInfo
|
||||||
return fmt.Errorf("DiscoveryNode config is error!")
|
cls.rpcMode = rpcMode
|
||||||
}
|
|
||||||
cls.masterDiscoveryNodeList = discoveryNode
|
|
||||||
|
|
||||||
//读取本地服务配置
|
//读取本地服务配置
|
||||||
err = cls.readLocalService(localNodeId)
|
err = cls.readLocalService(localNodeId)
|
||||||
@@ -263,26 +458,54 @@ func (cls *Cluster) IsConfigService(serviceName string) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) GetNodeIdByService(serviceName string, rpcClientList []*rpc.Client, bAll bool) (error, int) {
|
func (cls *Cluster) GetNodeIdByTemplateService(templateServiceName string, rpcClientList []*rpc.Client, filterRetire bool) (error, []*rpc.Client) {
|
||||||
|
cls.locker.RLock()
|
||||||
|
defer cls.locker.RUnlock()
|
||||||
|
|
||||||
|
mapServiceName := cls.mapTemplateServiceNode[templateServiceName]
|
||||||
|
for serviceName := range mapServiceName {
|
||||||
|
mapNodeId, ok := cls.mapServiceNode[serviceName]
|
||||||
|
if ok == true {
|
||||||
|
for nodeId, _ := range mapNodeId {
|
||||||
|
pClient,retire := GetCluster().getRpcClient(nodeId)
|
||||||
|
if pClient == nil || pClient.IsConnected() == false {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果需要筛选掉退休的,对retire状态的结点略过
|
||||||
|
if filterRetire == true && retire == true {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcClientList = append(rpcClientList,pClient)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, rpcClientList
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cls *Cluster) GetNodeIdByService(serviceName string, rpcClientList []*rpc.Client, filterRetire bool) (error, []*rpc.Client) {
|
||||||
cls.locker.RLock()
|
cls.locker.RLock()
|
||||||
defer cls.locker.RUnlock()
|
defer cls.locker.RUnlock()
|
||||||
mapNodeId, ok := cls.mapServiceNode[serviceName]
|
mapNodeId, ok := cls.mapServiceNode[serviceName]
|
||||||
count := 0
|
|
||||||
if ok == true {
|
if ok == true {
|
||||||
for nodeId, _ := range mapNodeId {
|
for nodeId, _ := range mapNodeId {
|
||||||
pClient := GetCluster().getRpcClient(nodeId)
|
pClient,retire := GetCluster().getRpcClient(nodeId)
|
||||||
if pClient == nil || (bAll == false && pClient.IsConnected() == false) {
|
if pClient == nil || pClient.IsConnected() == false {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rpcClientList[count] = pClient
|
|
||||||
count++
|
//如果需要筛选掉退休的,对retire状态的结点略过
|
||||||
if count >= cap(rpcClientList) {
|
if filterRetire == true && retire == true {
|
||||||
break
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpcClientList = append(rpcClientList,pClient)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, count
|
return nil, rpcClientList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) GetServiceCfg(serviceName string) interface{} {
|
func (cls *Cluster) GetServiceCfg(serviceName string) interface{} {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cluster
|
package cluster
|
||||||
|
|
||||||
|
|
||||||
type OperType int
|
type OperType int
|
||||||
|
|
||||||
type FunDelNode func (nodeId int,immediately bool)
|
type FunDelNode func (nodeId string)
|
||||||
type FunSetNodeInfo func(nodeInfo *NodeInfo)
|
type FunSetNode func(nodeInfo *NodeInfo)
|
||||||
|
|
||||||
type IServiceDiscovery interface {
|
type IServiceDiscovery interface {
|
||||||
InitDiscovery(localNodeId int,funDelNode FunDelNode,funSetNodeInfo FunSetNodeInfo) error
|
InitDiscovery(localNodeId string,funDelNode FunDelNode,funSetNodeInfo FunSetNode) error
|
||||||
OnNodeStop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultMaxTaskChannelNum = 1000000
|
const defaultMaxTaskChannelNum = 1000000
|
||||||
@@ -12,8 +13,8 @@ const defaultMaxTaskChannelNum = 1000000
|
|||||||
type IConcurrent interface {
|
type IConcurrent interface {
|
||||||
OpenConcurrentByNumCPU(cpuMul float32)
|
OpenConcurrentByNumCPU(cpuMul float32)
|
||||||
OpenConcurrent(minGoroutineNum int32, maxGoroutineNum int32, maxTaskChannelNum int)
|
OpenConcurrent(minGoroutineNum int32, maxGoroutineNum int32, maxTaskChannelNum int)
|
||||||
AsyncDoByQueue(queueId int64, fn func(), cb func(err error))
|
AsyncDoByQueue(queueId int64, fn func() bool, cb func(err error))
|
||||||
AsyncDo(f func(), cb func(err error))
|
AsyncDo(f func() bool, cb func(err error))
|
||||||
}
|
}
|
||||||
|
|
||||||
type Concurrent struct {
|
type Concurrent struct {
|
||||||
@@ -21,6 +22,7 @@ type Concurrent struct {
|
|||||||
|
|
||||||
tasks chan task
|
tasks chan task
|
||||||
cbChannel chan func(error)
|
cbChannel chan func(error)
|
||||||
|
open int32
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -33,6 +35,10 @@ func (c *Concurrent) OpenConcurrentByNumCPU(cpuNumMul float32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Concurrent) OpenConcurrent(minGoroutineNum int32, maxGoroutineNum int32, maxTaskChannelNum int) {
|
func (c *Concurrent) OpenConcurrent(minGoroutineNum int32, maxGoroutineNum int32, maxTaskChannelNum int) {
|
||||||
|
if atomic.AddInt32(&c.open,1) > 1 {
|
||||||
|
panic("repeated calls to OpenConcurrent are not allowed!")
|
||||||
|
}
|
||||||
|
|
||||||
c.tasks = make(chan task, maxTaskChannelNum)
|
c.tasks = make(chan task, maxTaskChannelNum)
|
||||||
c.cbChannel = make(chan func(error), maxTaskChannelNum)
|
c.cbChannel = make(chan func(error), maxTaskChannelNum)
|
||||||
|
|
||||||
@@ -40,27 +46,17 @@ func (c *Concurrent) OpenConcurrent(minGoroutineNum int32, maxGoroutineNum int32
|
|||||||
c.dispatch.open(minGoroutineNum, maxGoroutineNum, c.tasks, c.cbChannel)
|
c.dispatch.open(minGoroutineNum, maxGoroutineNum, c.tasks, c.cbChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Concurrent) AsyncDo(f func(), cb func(err error)) {
|
func (c *Concurrent) AsyncDo(f func() bool, cb func(err error)) {
|
||||||
c.AsyncDoByQueue(0, f, cb)
|
c.AsyncDoByQueue(0, f, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Concurrent) AsyncDoByQueue(queueId int64, fn func(), cb func(err error)) {
|
func (c *Concurrent) AsyncDoByQueue(queueId int64, fn func() bool, cb func(err error)) {
|
||||||
if cap(c.tasks) == 0 {
|
if cap(c.tasks) == 0 {
|
||||||
panic("not open concurrent")
|
panic("not open concurrent")
|
||||||
}
|
}
|
||||||
|
|
||||||
if fn == nil && cb == nil {
|
if fn == nil && cb == nil {
|
||||||
log.SStack("fn and cb is nil")
|
log.Stack("fn and cb is nil")
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.tasks) > cap(c.tasks) {
|
|
||||||
log.SError("tasks channel is full")
|
|
||||||
if cb != nil {
|
|
||||||
c.pushAsyncDoCallbackEvent(func(err error) {
|
|
||||||
cb(errors.New("tasks channel is full"))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +71,14 @@ func (c *Concurrent) AsyncDoByQueue(queueId int64, fn func(), cb func(err error)
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case c.tasks <- task{queueId, fn, cb}:
|
case c.tasks <- task{queueId, fn, cb}:
|
||||||
|
default:
|
||||||
|
log.Error("tasks channel is full")
|
||||||
|
if cb != nil {
|
||||||
|
c.pushAsyncDoCallbackEvent(func(err error) {
|
||||||
|
cb(errors.New("tasks channel is full"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,11 +87,11 @@ func (c *Concurrent) Close() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SRelease("wait close concurrent")
|
log.Info("wait close concurrent")
|
||||||
|
|
||||||
c.dispatch.close()
|
c.dispatch.close()
|
||||||
|
|
||||||
log.SRelease("concurrent has successfully exited")
|
log.Info("concurrent has successfully exited")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Concurrent) GetCallBackChannel() chan func(error) {
|
func (c *Concurrent) GetCallBackChannel() chan func(error) {
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/util/queue"
|
"github.com/duanhf2012/origin/v2/util/queue"
|
||||||
|
"context"
|
||||||
)
|
)
|
||||||
|
|
||||||
var idleTimeout = 2 * time.Second
|
var idleTimeout = int64(2 * time.Second)
|
||||||
const maxTaskQueueSessionId = 10000
|
const maxTaskQueueSessionId = 10000
|
||||||
|
|
||||||
type dispatch struct {
|
type dispatch struct {
|
||||||
@@ -30,6 +31,9 @@ type dispatch struct {
|
|||||||
|
|
||||||
waitWorker sync.WaitGroup
|
waitWorker sync.WaitGroup
|
||||||
waitDispatch sync.WaitGroup
|
waitDispatch sync.WaitGroup
|
||||||
|
|
||||||
|
cancelContext context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dispatch) open(minGoroutineNum int32, maxGoroutineNum int32, tasks chan task, cbChannel chan func(error)) {
|
func (d *dispatch) open(minGoroutineNum int32, maxGoroutineNum int32, tasks chan task, cbChannel chan func(error)) {
|
||||||
@@ -40,14 +44,14 @@ func (d *dispatch) open(minGoroutineNum int32, maxGoroutineNum int32, tasks chan
|
|||||||
d.workerQueue = make(chan task)
|
d.workerQueue = make(chan task)
|
||||||
d.cbChannel = cbChannel
|
d.cbChannel = cbChannel
|
||||||
d.queueIdChannel = make(chan int64, cap(tasks))
|
d.queueIdChannel = make(chan int64, cap(tasks))
|
||||||
|
d.cancelContext,d.cancel = context.WithCancel(context.Background())
|
||||||
d.waitDispatch.Add(1)
|
d.waitDispatch.Add(1)
|
||||||
go d.run()
|
go d.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dispatch) run() {
|
func (d *dispatch) run() {
|
||||||
defer d.waitDispatch.Done()
|
defer d.waitDispatch.Done()
|
||||||
timeout := time.NewTimer(idleTimeout)
|
timeout := time.NewTimer(time.Duration(atomic.LoadInt64(&idleTimeout)))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@@ -64,10 +68,12 @@ func (d *dispatch) run() {
|
|||||||
d.processqueueEvent(queueId)
|
d.processqueueEvent(queueId)
|
||||||
case <-timeout.C:
|
case <-timeout.C:
|
||||||
d.processTimer()
|
d.processTimer()
|
||||||
if atomic.LoadInt32(&d.minConcurrentNum) == -1 && len(d.tasks) == 0 {
|
case <- d.cancelContext.Done():
|
||||||
idleTimeout = time.Millisecond * 10
|
atomic.StoreInt64(&idleTimeout,int64(time.Millisecond * 5))
|
||||||
|
timeout.Reset(time.Duration(atomic.LoadInt64(&idleTimeout)))
|
||||||
|
for i:=int32(0);i<d.workerNum;i++{
|
||||||
|
d.processIdle()
|
||||||
}
|
}
|
||||||
timeout.Reset(idleTimeout)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +86,7 @@ func (d *dispatch) run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *dispatch) processTimer() {
|
func (d *dispatch) processTimer() {
|
||||||
if d.idle == true && d.workerNum > d.minConcurrentNum {
|
if d.idle == true && d.workerNum > atomic.LoadInt32(&d.minConcurrentNum) {
|
||||||
d.processIdle()
|
d.processIdle()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,6 +172,8 @@ func (c *dispatch) pushAsyncDoCallbackEvent(cb func(err error)) {
|
|||||||
|
|
||||||
func (d *dispatch) close() {
|
func (d *dispatch) close() {
|
||||||
atomic.StoreInt32(&d.minConcurrentNum, -1)
|
atomic.StoreInt32(&d.minConcurrentNum, -1)
|
||||||
|
d.cancel()
|
||||||
|
|
||||||
|
|
||||||
breakFor:
|
breakFor:
|
||||||
for {
|
for {
|
||||||
@@ -187,8 +195,7 @@ func (d *dispatch) DoCallback(cb func(err error)) {
|
|||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
l := runtime.Stack(buf, false)
|
l := runtime.Stack(buf, false)
|
||||||
errString := fmt.Sprint(r)
|
errString := fmt.Sprint(r)
|
||||||
|
log.Dump(string(buf[:l]),log.String("error",errString))
|
||||||
log.SError("core dump info[", errString, "]\n", string(buf[:l]))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type task struct {
|
type task struct {
|
||||||
queueId int64
|
queueId int64
|
||||||
fn func()
|
fn func() bool
|
||||||
cb func(err error)
|
cb func(err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ func (w *worker) run(waitGroup *sync.WaitGroup, t task) {
|
|||||||
case tw := <-w.workerQueue:
|
case tw := <-w.workerQueue:
|
||||||
if tw.isExistTask() {
|
if tw.isExistTask() {
|
||||||
//exit goroutine
|
//exit goroutine
|
||||||
log.SRelease("worker goroutine exit")
|
log.Info("worker goroutine exit")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.exec(&tw)
|
w.exec(&tw)
|
||||||
@@ -59,18 +59,18 @@ func (w *worker) exec(t *task) {
|
|||||||
t.cb = func(err error) {
|
t.cb = func(err error) {
|
||||||
cb(errors.New(errString))
|
cb(errors.New(errString))
|
||||||
}
|
}
|
||||||
|
log.Dump(string(buf[:l]),log.String("error",errString))
|
||||||
w.endCallFun(t)
|
w.endCallFun(true,t)
|
||||||
log.SError("core dump info[", errString, "]\n", string(buf[:l]))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
t.fn()
|
w.endCallFun(t.fn(),t)
|
||||||
w.endCallFun(t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) endCallFun(t *task) {
|
func (w *worker) endCallFun(isDocallBack bool,t *task) {
|
||||||
w.pushAsyncDoCallbackEvent(t.cb)
|
if isDocallBack {
|
||||||
|
w.pushAsyncDoCallbackEvent(t.cb)
|
||||||
|
}
|
||||||
|
|
||||||
if t.queueId != 0 {
|
if t.queueId != 0 {
|
||||||
w.pushQueueTaskFinishEvent(t.queueId)
|
w.pushQueueTaskFinishEvent(t.queueId)
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ type CommandFunctionCB func(args interface{}) error
|
|||||||
var commandList []*command
|
var commandList []*command
|
||||||
var programName string
|
var programName string
|
||||||
const(
|
const(
|
||||||
boolType valueType = iota
|
boolType valueType = 0
|
||||||
stringType valueType = iota
|
stringType valueType = 1
|
||||||
|
intType valueType = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
type command struct{
|
type command struct{
|
||||||
@@ -20,6 +21,7 @@ type command struct{
|
|||||||
name string
|
name string
|
||||||
bValue bool
|
bValue bool
|
||||||
strValue string
|
strValue string
|
||||||
|
intValue int
|
||||||
usage string
|
usage string
|
||||||
fn CommandFunctionCB
|
fn CommandFunctionCB
|
||||||
}
|
}
|
||||||
@@ -29,6 +31,8 @@ func (cmd *command) execute() error{
|
|||||||
return cmd.fn(cmd.bValue)
|
return cmd.fn(cmd.bValue)
|
||||||
}else if cmd.valType == stringType {
|
}else if cmd.valType == stringType {
|
||||||
return cmd.fn(cmd.strValue)
|
return cmd.fn(cmd.strValue)
|
||||||
|
}else if cmd.valType == intType {
|
||||||
|
return cmd.fn(cmd.intValue)
|
||||||
}else{
|
}else{
|
||||||
return fmt.Errorf("Unknow command type.")
|
return fmt.Errorf("Unknow command type.")
|
||||||
}
|
}
|
||||||
@@ -72,6 +76,16 @@ func RegisterCommandBool(cmdName string, defaultValue bool, usage string,fn Comm
|
|||||||
commandList = append(commandList,&cmd)
|
commandList = append(commandList,&cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RegisterCommandInt(cmdName string, defaultValue int, usage string,fn CommandFunctionCB){
|
||||||
|
var cmd command
|
||||||
|
cmd.valType = intType
|
||||||
|
cmd.name = cmdName
|
||||||
|
cmd.fn = fn
|
||||||
|
cmd.usage = usage
|
||||||
|
flag.IntVar(&cmd.intValue, cmdName, defaultValue, usage)
|
||||||
|
commandList = append(commandList,&cmd)
|
||||||
|
}
|
||||||
|
|
||||||
func RegisterCommandString(cmdName string, defaultValue string, usage string,fn CommandFunctionCB){
|
func RegisterCommandString(cmdName string, defaultValue string, usage string,fn CommandFunctionCB){
|
||||||
var cmd command
|
var cmd command
|
||||||
cmd.valType = stringType
|
cmd.valType = stringType
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package event
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@@ -215,7 +215,7 @@ func (processor *EventProcessor) EventHandler(ev IEvent) {
|
|||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
l := runtime.Stack(buf, false)
|
l := runtime.Stack(buf, false)
|
||||||
errString := fmt.Sprint(r)
|
errString := fmt.Sprint(r)
|
||||||
log.SError("core dump info[",errString,"]\n",string(buf[:l]))
|
log.Dump(string(buf[:l]),log.String("error",errString))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -230,13 +230,12 @@ func (processor *EventProcessor) EventHandler(ev IEvent) {
|
|||||||
|
|
||||||
func (processor *EventProcessor) castEvent(event IEvent){
|
func (processor *EventProcessor) castEvent(event IEvent){
|
||||||
if processor.mapListenerEvent == nil {
|
if processor.mapListenerEvent == nil {
|
||||||
log.SError("mapListenerEvent not init!")
|
log.Error("mapListenerEvent not init!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
eventProcessor,ok := processor.mapListenerEvent[event.GetEventType()]
|
eventProcessor,ok := processor.mapListenerEvent[event.GetEventType()]
|
||||||
if ok == false || processor == nil{
|
if ok == false || processor == nil{
|
||||||
log.SDebug("event type ",event.GetEventType()," not listen.")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package event
|
package event
|
||||||
|
|
||||||
import "github.com/duanhf2012/origin/util/sync"
|
import "github.com/duanhf2012/origin/v2/util/sync"
|
||||||
|
|
||||||
// eventPool的内存池,缓存Event
|
// eventPool的内存池,缓存Event
|
||||||
const defaultMaxEventChannelNum = 2000000
|
const defaultMaxEventChannelNum = 2000000
|
||||||
|
|||||||
@@ -7,16 +7,18 @@ const (
|
|||||||
ServiceRpcRequestEvent EventType = -1
|
ServiceRpcRequestEvent EventType = -1
|
||||||
ServiceRpcResponseEvent EventType = -2
|
ServiceRpcResponseEvent EventType = -2
|
||||||
|
|
||||||
Sys_Event_Tcp EventType = -3
|
Sys_Event_Tcp EventType = -3
|
||||||
Sys_Event_Http_Event EventType = -4
|
Sys_Event_Http_Event EventType = -4
|
||||||
Sys_Event_WebSocket EventType = -5
|
Sys_Event_WebSocket EventType = -5
|
||||||
Sys_Event_Node_Event EventType = -6
|
Sys_Event_Node_Conn_Event EventType = -6
|
||||||
Sys_Event_DiscoverService EventType = -7
|
Sys_Event_Nats_Conn_Event EventType = -7
|
||||||
Sys_Event_DiscardGoroutine EventType = -8
|
Sys_Event_DiscoverService EventType = -8
|
||||||
Sys_Event_QueueTaskFinish EventType = -9
|
Sys_Event_DiscardGoroutine EventType = -9
|
||||||
|
Sys_Event_QueueTaskFinish EventType = -10
|
||||||
|
Sys_Event_Retire EventType = -11
|
||||||
|
Sys_Event_EtcdDiscovery EventType = -12
|
||||||
|
Sys_Event_Gin_Event EventType = -13
|
||||||
|
|
||||||
Sys_Event_User_Define EventType = 1
|
Sys_Event_User_Define EventType = 1
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
40
go.mod
40
go.mod
@@ -1,30 +1,54 @@
|
|||||||
module github.com/duanhf2012/origin
|
module github.com/duanhf2012/origin/v2
|
||||||
|
|
||||||
go 1.19
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-sql-driver/mysql v1.6.0
|
github.com/go-sql-driver/mysql v1.6.0
|
||||||
github.com/gogo/protobuf v1.3.2
|
|
||||||
github.com/gomodule/redigo v1.8.8
|
github.com/gomodule/redigo v1.8.8
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
|
github.com/nats-io/nats.go v1.34.1
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.18
|
||||||
|
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||||
|
go.etcd.io/etcd/api/v3 v3.5.13
|
||||||
|
go.etcd.io/etcd/client/v3 v3.5.13
|
||||||
go.mongodb.org/mongo-driver v1.9.1
|
go.mongodb.org/mongo-driver v1.9.1
|
||||||
|
go.uber.org/zap v1.27.0
|
||||||
|
google.golang.org/protobuf v1.33.0
|
||||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
|
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/coreos/go-semver v0.3.0 // indirect
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||||
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/go-stack/stack v1.8.0 // indirect
|
github.com/go-stack/stack v1.8.0 // indirect
|
||||||
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/golang/snappy v0.0.1 // indirect
|
github.com/golang/snappy v0.0.1 // indirect
|
||||||
github.com/klauspost/compress v1.13.6 // indirect
|
github.com/klauspost/compress v1.17.2 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/nats-io/nkeys v0.4.7 // indirect
|
||||||
|
github.com/nats-io/nuid v1.0.1 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/tklauser/go-sysconf v0.3.13 // indirect
|
||||||
|
github.com/tklauser/numcpus v0.7.0 // indirect
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
github.com/xdg-go/scram v1.0.2 // indirect
|
github.com/xdg-go/scram v1.0.2 // indirect
|
||||||
github.com/xdg-go/stringprep v1.0.2 // indirect
|
github.com/xdg-go/stringprep v1.0.2 // indirect
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||||
golang.org/x/crypto v0.1.0 // indirect
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect
|
go.etcd.io/etcd/client/pkg/v3 v3.5.13 // indirect
|
||||||
golang.org/x/text v0.4.0 // indirect
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
golang.org/x/crypto v0.18.0 // indirect
|
||||||
|
golang.org/x/net v0.17.0 // indirect
|
||||||
|
golang.org/x/sync v0.3.0 // indirect
|
||||||
|
golang.org/x/sys v0.16.0 // indirect
|
||||||
|
golang.org/x/text v0.14.0 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||||
|
google.golang.org/grpc v1.59.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
81
go.sum
81
go.sum
@@ -1,48 +1,77 @@
|
|||||||
|
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||||
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/gomodule/redigo v1.8.8 h1:f6cXq6RRfiyrOJEV7p3JhLDlmawGBVBBP1MggY8Mo4E=
|
github.com/gomodule/redigo v1.8.8 h1:f6cXq6RRfiyrOJEV7p3JhLDlmawGBVBBP1MggY8Mo4E=
|
||||||
github.com/gomodule/redigo v1.8.8/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
|
github.com/gomodule/redigo v1.8.8/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
|
||||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
|
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
||||||
|
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||||
|
github.com/nats-io/nats.go v1.34.1 h1:syWey5xaNHZgicYBemv0nohUPPmaLteiBEUT6Q5+F/4=
|
||||||
|
github.com/nats-io/nats.go v1.34.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
|
||||||
|
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
|
||||||
|
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
||||||
|
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||||
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||||
|
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
|
||||||
|
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
|
||||||
|
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
|
github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
|
||||||
@@ -53,14 +82,28 @@ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM
|
|||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
|
go.etcd.io/etcd/api/v3 v3.5.13 h1:8WXU2/NBge6AUF1K1gOexB6e07NgsN1hXK0rSTtgSp4=
|
||||||
|
go.etcd.io/etcd/api/v3 v3.5.13/go.mod h1:gBqlqkcMMZMVTMm4NDZloEVJzxQOQIls8splbqBDa0c=
|
||||||
|
go.etcd.io/etcd/client/pkg/v3 v3.5.13 h1:RVZSAnWWWiI5IrYAXjQorajncORbS0zI48LQlE2kQWg=
|
||||||
|
go.etcd.io/etcd/client/pkg/v3 v3.5.13/go.mod h1:XxHT4u1qU12E2+po+UVPrEeL94Um6zL58ppuJWXSAB8=
|
||||||
|
go.etcd.io/etcd/client/v3 v3.5.13 h1:o0fHTNJLeO0MyVbc7I3fsCf6nrOqn5d+diSarKnB2js=
|
||||||
|
go.etcd.io/etcd/client/v3 v3.5.13/go.mod h1:cqiAeY8b5DEEcpxvgWKsbLIWNM/8Wy2xJSDMtioMcoI=
|
||||||
go.mongodb.org/mongo-driver v1.9.1 h1:m078y9v7sBItkt1aaoe2YlvWEXcD263e1a4E1fBrJ1c=
|
go.mongodb.org/mongo-driver v1.9.1 h1:m078y9v7sBItkt1aaoe2YlvWEXcD263e1a4E1fBrJ1c=
|
||||||
go.mongodb.org/mongo-driver v1.9.1/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
|
go.mongodb.org/mongo-driver v1.9.1/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
|
||||||
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
|
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||||
|
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
@@ -68,20 +111,26 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||||
|
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
|
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||||
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@@ -90,8 +139,17 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY=
|
||||||
|
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
|
||||||
|
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||||
|
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||||
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@@ -99,5 +157,6 @@ gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3
|
|||||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -2,27 +2,20 @@ package log // import "go.uber.org/zap/buffer"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const _size = 9216
|
const _size = 9216
|
||||||
|
|
||||||
type Buffer struct {
|
type Buffer struct {
|
||||||
bs []byte
|
bs []byte
|
||||||
mu sync.Mutex // ensures atomic writes; protects the following fields
|
//mu sync.Mutex // ensures atomic writes; protects the following fields
|
||||||
}
|
}
|
||||||
|
|
||||||
func (buff *Buffer) Init(){
|
func (buff *Buffer) Init(){
|
||||||
buff.bs = make([]byte,_size)
|
buff.bs = make([]byte,_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (buff *Buffer) Locker() {
|
|
||||||
buff.mu.Lock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (buff *Buffer) UnLocker() {
|
|
||||||
buff.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendByte writes a single byte to the Buffer.
|
// AppendByte writes a single byte to the Buffer.
|
||||||
func (b *Buffer) AppendByte(v byte) {
|
func (b *Buffer) AppendByte(v byte) {
|
||||||
|
|||||||
147
log/handler.go
Normal file
147
log/handler.go
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"log/slog"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"runtime/debug"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IOriginHandler interface {
|
||||||
|
slog.Handler
|
||||||
|
Lock()
|
||||||
|
UnLock()
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseHandler struct {
|
||||||
|
addSource bool
|
||||||
|
w io.Writer
|
||||||
|
locker sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type OriginTextHandler struct {
|
||||||
|
BaseHandler
|
||||||
|
*slog.TextHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
type OriginJsonHandler struct {
|
||||||
|
BaseHandler
|
||||||
|
*slog.JSONHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStrLevel(level slog.Level) string{
|
||||||
|
switch level {
|
||||||
|
case LevelTrace:
|
||||||
|
return "Trace"
|
||||||
|
case LevelDebug:
|
||||||
|
return "Debug"
|
||||||
|
case LevelInfo:
|
||||||
|
return "Info"
|
||||||
|
case LevelWarning:
|
||||||
|
return "Warning"
|
||||||
|
case LevelError:
|
||||||
|
return "Error"
|
||||||
|
case LevelStack:
|
||||||
|
return "Stack"
|
||||||
|
case LevelDump:
|
||||||
|
return "Dump"
|
||||||
|
case LevelFatal:
|
||||||
|
return "Fatal"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultReplaceAttr(groups []string, a slog.Attr) slog.Attr {
|
||||||
|
if a.Key == slog.LevelKey {
|
||||||
|
level := a.Value.Any().(slog.Level)
|
||||||
|
a.Value = slog.StringValue(getStrLevel(level))
|
||||||
|
}else if a.Key == slog.TimeKey && len(groups) == 0 {
|
||||||
|
a.Value = slog.StringValue(a.Value.Time().Format("2006/01/02 15:04:05"))
|
||||||
|
}else if a.Key == slog.SourceKey {
|
||||||
|
source := a.Value.Any().(*slog.Source)
|
||||||
|
source.File = filepath.Base(source.File)
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOriginTextHandler(level slog.Level,w io.Writer,addSource bool,replaceAttr func([]string,slog.Attr) slog.Attr) slog.Handler{
|
||||||
|
var textHandler OriginTextHandler
|
||||||
|
textHandler.addSource = addSource
|
||||||
|
textHandler.w = w
|
||||||
|
textHandler.TextHandler = slog.NewTextHandler(w,&slog.HandlerOptions{
|
||||||
|
AddSource: addSource,
|
||||||
|
Level: level,
|
||||||
|
ReplaceAttr: replaceAttr,
|
||||||
|
})
|
||||||
|
|
||||||
|
return &textHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (oh *OriginTextHandler) Handle(context context.Context, record slog.Record) error{
|
||||||
|
oh.Fill(context,&record)
|
||||||
|
oh.locker.Lock()
|
||||||
|
defer oh.locker.Unlock()
|
||||||
|
|
||||||
|
if record.Level == LevelStack || record.Level == LevelFatal{
|
||||||
|
err := oh.TextHandler.Handle(context, record)
|
||||||
|
oh.logStack(&record)
|
||||||
|
return err
|
||||||
|
}else if record.Level == LevelDump {
|
||||||
|
strDump := record.Message
|
||||||
|
record.Message = "dump info"
|
||||||
|
err := oh.TextHandler.Handle(context, record)
|
||||||
|
oh.w.Write([]byte(strDump))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return oh.TextHandler.Handle(context, record)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseHandler) logStack(record *slog.Record){
|
||||||
|
b.w.Write(debug.Stack())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseHandler) Lock(){
|
||||||
|
b.locker.Lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseHandler) UnLock(){
|
||||||
|
b.locker.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOriginJsonHandler(level slog.Level,w io.Writer,addSource bool,replaceAttr func([]string,slog.Attr) slog.Attr) slog.Handler{
|
||||||
|
var jsonHandler OriginJsonHandler
|
||||||
|
jsonHandler.addSource = addSource
|
||||||
|
jsonHandler.w = w
|
||||||
|
jsonHandler.JSONHandler = slog.NewJSONHandler(w,&slog.HandlerOptions{
|
||||||
|
AddSource: addSource,
|
||||||
|
Level: level,
|
||||||
|
ReplaceAttr: replaceAttr,
|
||||||
|
})
|
||||||
|
|
||||||
|
return &jsonHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (oh *OriginJsonHandler) Handle(context context.Context, record slog.Record) error{
|
||||||
|
oh.Fill(context,&record)
|
||||||
|
if record.Level == LevelStack || record.Level == LevelFatal || record.Level == LevelDump{
|
||||||
|
record.Add("stack",debug.Stack())
|
||||||
|
}
|
||||||
|
|
||||||
|
oh.locker.Lock()
|
||||||
|
defer oh.locker.Unlock()
|
||||||
|
return oh.JSONHandler.Handle(context, record)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseHandler) Fill(context context.Context, record *slog.Record) {
|
||||||
|
if b.addSource {
|
||||||
|
var pcs [1]uintptr
|
||||||
|
runtime.Callers(7, pcs[:])
|
||||||
|
record.PC = pcs[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
1007
log/log.go
1007
log/log.go
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ package network
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -47,7 +47,7 @@ func (slf *HttpServer) startListen() error {
|
|||||||
for _, caFile := range slf.caFileList {
|
for _, caFile := range slf.caFileList {
|
||||||
cer, err := tls.LoadX509KeyPair(caFile.CertFile, caFile.Keyfile)
|
cer, err := tls.LoadX509KeyPair(caFile.CertFile, caFile.Keyfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SFatal("Load CA [",caFile.CertFile,"]-[",caFile.Keyfile,"] file is fail:",err.Error())
|
log.Fatal("Load CA file is fail",log.String("error",err.Error()),log.String("certFile",caFile.CertFile),log.String("keyFile",caFile.Keyfile))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tlsCaList = append(tlsCaList, cer)
|
tlsCaList = append(tlsCaList, cer)
|
||||||
@@ -74,7 +74,7 @@ func (slf *HttpServer) startListen() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SFatal("Listen for address ",slf.listenAddr," failure:",err.Error())
|
log.Fatal("Listen failure",log.String("error",err.Error()),log.String("addr:",slf.listenAddr))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package processor
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/network"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/util/bytespool"
|
||||||
"reflect"
|
"reflect"
|
||||||
"github.com/duanhf2012/origin/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type MessageJsonInfo struct {
|
type MessageJsonInfo struct {
|
||||||
@@ -13,9 +13,9 @@ type MessageJsonInfo struct {
|
|||||||
msgHandler MessageJsonHandler
|
msgHandler MessageJsonHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessageJsonHandler func(clientId uint64,msg interface{})
|
type MessageJsonHandler func(clientId string,msg interface{})
|
||||||
type ConnectJsonHandler func(clientId uint64)
|
type ConnectJsonHandler func(clientId string)
|
||||||
type UnknownMessageJsonHandler func(clientId uint64,msg []byte)
|
type UnknownMessageJsonHandler func(clientId string,msg []byte)
|
||||||
|
|
||||||
type JsonProcessor struct {
|
type JsonProcessor struct {
|
||||||
mapMsg map[uint16]MessageJsonInfo
|
mapMsg map[uint16]MessageJsonInfo
|
||||||
@@ -24,7 +24,7 @@ type JsonProcessor struct {
|
|||||||
unknownMessageHandler UnknownMessageJsonHandler
|
unknownMessageHandler UnknownMessageJsonHandler
|
||||||
connectHandler ConnectJsonHandler
|
connectHandler ConnectJsonHandler
|
||||||
disconnectHandler ConnectJsonHandler
|
disconnectHandler ConnectJsonHandler
|
||||||
network.INetMempool
|
bytespool.IBytesMempool
|
||||||
}
|
}
|
||||||
|
|
||||||
type JsonPackInfo struct {
|
type JsonPackInfo struct {
|
||||||
@@ -35,7 +35,7 @@ type JsonPackInfo struct {
|
|||||||
|
|
||||||
func NewJsonProcessor() *JsonProcessor {
|
func NewJsonProcessor() *JsonProcessor {
|
||||||
processor := &JsonProcessor{mapMsg:map[uint16]MessageJsonInfo{}}
|
processor := &JsonProcessor{mapMsg:map[uint16]MessageJsonInfo{}}
|
||||||
processor.INetMempool = network.NewMemAreaPool()
|
processor.IBytesMempool = bytespool.NewMemAreaPool()
|
||||||
|
|
||||||
return processor
|
return processor
|
||||||
}
|
}
|
||||||
@@ -45,8 +45,10 @@ func (jsonProcessor *JsonProcessor) SetByteOrder(littleEndian bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// must goroutine safe
|
||||||
func (jsonProcessor *JsonProcessor ) MsgRoute(clientId uint64,msg interface{}) error{
|
func (jsonProcessor *JsonProcessor ) MsgRoute(clientId string,msg interface{},recyclerReaderBytes func(data []byte)) error{
|
||||||
pPackInfo := msg.(*JsonPackInfo)
|
pPackInfo := msg.(*JsonPackInfo)
|
||||||
|
defer recyclerReaderBytes(pPackInfo.rawMsg)
|
||||||
|
|
||||||
v,ok := jsonProcessor.mapMsg[pPackInfo.typ]
|
v,ok := jsonProcessor.mapMsg[pPackInfo.typ]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return fmt.Errorf("cannot find msgtype %d is register!",pPackInfo.typ)
|
return fmt.Errorf("cannot find msgtype %d is register!",pPackInfo.typ)
|
||||||
@@ -56,9 +58,8 @@ func (jsonProcessor *JsonProcessor ) MsgRoute(clientId uint64,msg interface{}) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jsonProcessor *JsonProcessor) Unmarshal(clientId uint64,data []byte) (interface{}, error) {
|
func (jsonProcessor *JsonProcessor) Unmarshal(clientId string,data []byte) (interface{}, error) {
|
||||||
typeStruct := struct {Type int `json:"typ"`}{}
|
typeStruct := struct {Type int `json:"typ"`}{}
|
||||||
defer jsonProcessor.ReleaseByteSlice(data)
|
|
||||||
err := json.Unmarshal(data, &typeStruct)
|
err := json.Unmarshal(data, &typeStruct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -76,10 +77,10 @@ func (jsonProcessor *JsonProcessor) Unmarshal(clientId uint64,data []byte) (inte
|
|||||||
return nil,err
|
return nil,err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &JsonPackInfo{typ:msgType,msg:msgData},nil
|
return &JsonPackInfo{typ:msgType,msg:msgData,rawMsg: data},nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jsonProcessor *JsonProcessor) Marshal(clientId uint64,msg interface{}) ([]byte, error) {
|
func (jsonProcessor *JsonProcessor) Marshal(clientId string,msg interface{}) ([]byte, error) {
|
||||||
rawMsg,err := json.Marshal(msg)
|
rawMsg,err := json.Marshal(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil,err
|
return nil,err
|
||||||
@@ -104,9 +105,10 @@ func (jsonProcessor *JsonProcessor) MakeRawMsg(msgType uint16,msg []byte) *JsonP
|
|||||||
return &JsonPackInfo{typ:msgType,rawMsg:msg}
|
return &JsonPackInfo{typ:msgType,rawMsg:msg}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jsonProcessor *JsonProcessor) UnknownMsgRoute(clientId uint64,msg interface{}){
|
func (jsonProcessor *JsonProcessor) UnknownMsgRoute(clientId string,msg interface{},recyclerReaderBytes func(data []byte)){
|
||||||
|
defer recyclerReaderBytes(msg.([]byte))
|
||||||
if jsonProcessor.unknownMessageHandler==nil {
|
if jsonProcessor.unknownMessageHandler==nil {
|
||||||
log.SDebug("Unknown message received from ",clientId)
|
log.Debug("Unknown message",log.String("clientId",clientId))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,13 +116,13 @@ func (jsonProcessor *JsonProcessor) UnknownMsgRoute(clientId uint64,msg interfac
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jsonProcessor *JsonProcessor) ConnectedRoute(clientId uint64){
|
func (jsonProcessor *JsonProcessor) ConnectedRoute(clientId string){
|
||||||
if jsonProcessor.connectHandler != nil {
|
if jsonProcessor.connectHandler != nil {
|
||||||
jsonProcessor.connectHandler(clientId)
|
jsonProcessor.connectHandler(clientId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jsonProcessor *JsonProcessor) DisConnectedRoute(clientId uint64){
|
func (jsonProcessor *JsonProcessor) DisConnectedRoute(clientId string){
|
||||||
if jsonProcessor.disconnectHandler != nil {
|
if jsonProcessor.disconnectHandler != nil {
|
||||||
jsonProcessor.disconnectHandler(clientId)
|
jsonProcessor.disconnectHandler(clientId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package processor
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/network"
|
"github.com/duanhf2012/origin/v2/util/bytespool"
|
||||||
"github.com/gogo/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,9 +13,9 @@ type MessageInfo struct {
|
|||||||
msgHandler MessageHandler
|
msgHandler MessageHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessageHandler func(clientId uint64, msg proto.Message)
|
type MessageHandler func(clientId string, msg proto.Message)
|
||||||
type ConnectHandler func(clientId uint64)
|
type ConnectHandler func(clientId string)
|
||||||
type UnknownMessageHandler func(clientId uint64, msg []byte)
|
type UnknownMessageHandler func(clientId string, msg []byte)
|
||||||
|
|
||||||
const MsgTypeSize = 2
|
const MsgTypeSize = 2
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ type PBProcessor struct {
|
|||||||
unknownMessageHandler UnknownMessageHandler
|
unknownMessageHandler UnknownMessageHandler
|
||||||
connectHandler ConnectHandler
|
connectHandler ConnectHandler
|
||||||
disconnectHandler ConnectHandler
|
disconnectHandler ConnectHandler
|
||||||
network.INetMempool
|
bytespool.IBytesMempool
|
||||||
}
|
}
|
||||||
|
|
||||||
type PBPackInfo struct {
|
type PBPackInfo struct {
|
||||||
@@ -37,7 +37,7 @@ type PBPackInfo struct {
|
|||||||
|
|
||||||
func NewPBProcessor() *PBProcessor {
|
func NewPBProcessor() *PBProcessor {
|
||||||
processor := &PBProcessor{mapMsg: map[uint16]MessageInfo{}}
|
processor := &PBProcessor{mapMsg: map[uint16]MessageInfo{}}
|
||||||
processor.INetMempool = network.NewMemAreaPool()
|
processor.IBytesMempool = bytespool.NewMemAreaPool()
|
||||||
return processor
|
return processor
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,8 +54,10 @@ func (slf *PBPackInfo) GetMsg() proto.Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// must goroutine safe
|
||||||
func (pbProcessor *PBProcessor) MsgRoute(clientId uint64, msg interface{}) error {
|
func (pbProcessor *PBProcessor) MsgRoute(clientId string, msg interface{},recyclerReaderBytes func(data []byte)) error {
|
||||||
pPackInfo := msg.(*PBPackInfo)
|
pPackInfo := msg.(*PBPackInfo)
|
||||||
|
defer recyclerReaderBytes(pPackInfo.rawMsg)
|
||||||
|
|
||||||
v, ok := pbProcessor.mapMsg[pPackInfo.typ]
|
v, ok := pbProcessor.mapMsg[pPackInfo.typ]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return fmt.Errorf("Cannot find msgtype %d is register!", pPackInfo.typ)
|
return fmt.Errorf("Cannot find msgtype %d is register!", pPackInfo.typ)
|
||||||
@@ -66,8 +68,12 @@ func (pbProcessor *PBProcessor) MsgRoute(clientId uint64, msg interface{}) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// must goroutine safe
|
||||||
func (pbProcessor *PBProcessor) Unmarshal(clientId uint64, data []byte) (interface{}, error) {
|
func (pbProcessor *PBProcessor) Unmarshal(clientId string, data []byte) (interface{}, error) {
|
||||||
defer pbProcessor.ReleaseByteSlice(data)
|
return pbProcessor.UnmarshalWithOutRelease(clientId, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unmarshal but not release data
|
||||||
|
func (pbProcessor *PBProcessor) UnmarshalWithOutRelease(clientId string, data []byte) (interface{}, error) {
|
||||||
var msgType uint16
|
var msgType uint16
|
||||||
if pbProcessor.LittleEndian == true {
|
if pbProcessor.LittleEndian == true {
|
||||||
msgType = binary.LittleEndian.Uint16(data[:2])
|
msgType = binary.LittleEndian.Uint16(data[:2])
|
||||||
@@ -86,11 +92,11 @@ func (pbProcessor *PBProcessor) Unmarshal(clientId uint64, data []byte) (interfa
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &PBPackInfo{typ: msgType, msg: protoMsg}, nil
|
return &PBPackInfo{typ: msgType, msg: protoMsg,rawMsg:data}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// must goroutine safe
|
||||||
func (pbProcessor *PBProcessor) Marshal(clientId uint64, msg interface{}) ([]byte, error) {
|
func (pbProcessor *PBProcessor) Marshal(clientId string, msg interface{}) ([]byte, error) {
|
||||||
pMsg := msg.(*PBPackInfo)
|
pMsg := msg.(*PBPackInfo)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@@ -128,16 +134,17 @@ func (pbProcessor *PBProcessor) MakeRawMsg(msgType uint16, msg []byte) *PBPackIn
|
|||||||
return &PBPackInfo{typ: msgType, rawMsg: msg}
|
return &PBPackInfo{typ: msgType, rawMsg: msg}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pbProcessor *PBProcessor) UnknownMsgRoute(clientId uint64, msg interface{}) {
|
func (pbProcessor *PBProcessor) UnknownMsgRoute(clientId string, msg interface{},recyclerReaderBytes func(data []byte)) {
|
||||||
pbProcessor.unknownMessageHandler(clientId, msg.([]byte))
|
pbProcessor.unknownMessageHandler(clientId, msg.([]byte))
|
||||||
|
recyclerReaderBytes(msg.([]byte))
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect event
|
// connect event
|
||||||
func (pbProcessor *PBProcessor) ConnectedRoute(clientId uint64) {
|
func (pbProcessor *PBProcessor) ConnectedRoute(clientId string) {
|
||||||
pbProcessor.connectHandler(clientId)
|
pbProcessor.connectHandler(clientId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pbProcessor *PBProcessor) DisConnectedRoute(clientId uint64) {
|
func (pbProcessor *PBProcessor) DisConnectedRoute(clientId string) {
|
||||||
pbProcessor.disconnectHandler(clientId)
|
pbProcessor.disconnectHandler(clientId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ type RawMessageInfo struct {
|
|||||||
msgHandler RawMessageHandler
|
msgHandler RawMessageHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
type RawMessageHandler func(clientId uint64,packType uint16,msg []byte)
|
type RawMessageHandler func(clientId string,packType uint16,msg []byte)
|
||||||
type RawConnectHandler func(clientId uint64)
|
type RawConnectHandler func(clientId string)
|
||||||
type UnknownRawMessageHandler func(clientId uint64,msg []byte)
|
type UnknownRawMessageHandler func(clientId string,msg []byte)
|
||||||
|
|
||||||
const RawMsgTypeSize = 2
|
const RawMsgTypeSize = 2
|
||||||
type PBRawProcessor struct {
|
type PBRawProcessor struct {
|
||||||
@@ -38,14 +38,16 @@ func (pbRawProcessor *PBRawProcessor) SetByteOrder(littleEndian bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// must goroutine safe
|
||||||
func (pbRawProcessor *PBRawProcessor ) MsgRoute(clientId uint64, msg interface{}) error{
|
func (pbRawProcessor *PBRawProcessor ) MsgRoute(clientId string, msg interface{},recyclerReaderBytes func(data []byte)) error{
|
||||||
pPackInfo := msg.(*PBRawPackInfo)
|
pPackInfo := msg.(*PBRawPackInfo)
|
||||||
pbRawProcessor.msgHandler(clientId,pPackInfo.typ,pPackInfo.rawMsg)
|
pbRawProcessor.msgHandler(clientId,pPackInfo.typ,pPackInfo.rawMsg)
|
||||||
|
recyclerReaderBytes(pPackInfo.rawMsg)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// must goroutine safe
|
||||||
func (pbRawProcessor *PBRawProcessor ) Unmarshal(clientId uint64,data []byte) (interface{}, error) {
|
func (pbRawProcessor *PBRawProcessor ) Unmarshal(clientId string,data []byte) (interface{}, error) {
|
||||||
var msgType uint16
|
var msgType uint16
|
||||||
if pbRawProcessor.LittleEndian == true {
|
if pbRawProcessor.LittleEndian == true {
|
||||||
msgType = binary.LittleEndian.Uint16(data[:2])
|
msgType = binary.LittleEndian.Uint16(data[:2])
|
||||||
@@ -57,7 +59,7 @@ func (pbRawProcessor *PBRawProcessor ) Unmarshal(clientId uint64,data []byte) (i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// must goroutine safe
|
||||||
func (pbRawProcessor *PBRawProcessor ) Marshal(clientId uint64,msg interface{}) ([]byte, error){
|
func (pbRawProcessor *PBRawProcessor ) Marshal(clientId string,msg interface{}) ([]byte, error){
|
||||||
pMsg := msg.(*PBRawPackInfo)
|
pMsg := msg.(*PBRawPackInfo)
|
||||||
|
|
||||||
buff := make([]byte, 2, len(pMsg.rawMsg)+RawMsgTypeSize)
|
buff := make([]byte, 2, len(pMsg.rawMsg)+RawMsgTypeSize)
|
||||||
@@ -80,7 +82,8 @@ func (pbRawProcessor *PBRawProcessor) MakeRawMsg(msgType uint16,msg []byte,pbRaw
|
|||||||
pbRawPackInfo.rawMsg = msg
|
pbRawPackInfo.rawMsg = msg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pbRawProcessor *PBRawProcessor) UnknownMsgRoute(clientId uint64,msg interface{}){
|
func (pbRawProcessor *PBRawProcessor) UnknownMsgRoute(clientId string,msg interface{},recyclerReaderBytes func(data []byte)){
|
||||||
|
defer recyclerReaderBytes(msg.([]byte))
|
||||||
if pbRawProcessor.unknownMessageHandler == nil {
|
if pbRawProcessor.unknownMessageHandler == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -88,11 +91,11 @@ func (pbRawProcessor *PBRawProcessor) UnknownMsgRoute(clientId uint64,msg interf
|
|||||||
}
|
}
|
||||||
|
|
||||||
// connect event
|
// connect event
|
||||||
func (pbRawProcessor *PBRawProcessor) ConnectedRoute(clientId uint64){
|
func (pbRawProcessor *PBRawProcessor) ConnectedRoute(clientId string){
|
||||||
pbRawProcessor.connectHandler(clientId)
|
pbRawProcessor.connectHandler(clientId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pbRawProcessor *PBRawProcessor) DisConnectedRoute(clientId uint64){
|
func (pbRawProcessor *PBRawProcessor) DisConnectedRoute(clientId string){
|
||||||
pbRawProcessor.disconnectHandler(clientId)
|
pbRawProcessor.disconnectHandler(clientId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,17 +3,17 @@ package processor
|
|||||||
|
|
||||||
type IProcessor interface {
|
type IProcessor interface {
|
||||||
// must goroutine safe
|
// must goroutine safe
|
||||||
MsgRoute(clientId uint64,msg interface{}) error
|
MsgRoute(clientId string,msg interface{},recyclerReaderBytes func(data []byte)) error
|
||||||
//must goroutine safe
|
//must goroutine safe
|
||||||
UnknownMsgRoute(clientId uint64,msg interface{})
|
UnknownMsgRoute(clientId string,msg interface{},recyclerReaderBytes func(data []byte))
|
||||||
// connect event
|
// connect event
|
||||||
ConnectedRoute(clientId uint64)
|
ConnectedRoute(clientId string)
|
||||||
DisConnectedRoute(clientId uint64)
|
DisConnectedRoute(clientId string)
|
||||||
|
|
||||||
// must goroutine safe
|
// must goroutine safe
|
||||||
Unmarshal(clientId uint64,data []byte) (interface{}, error)
|
Unmarshal(clientId string,data []byte) (interface{}, error)
|
||||||
// must goroutine safe
|
// must goroutine safe
|
||||||
Marshal(clientId uint64,msg interface{}) ([]byte, error)
|
Marshal(clientId string,msg interface{}) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type IRawProcessor interface {
|
type IRawProcessor interface {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -40,44 +40,48 @@ func (client *TCPClient) init() {
|
|||||||
|
|
||||||
if client.ConnNum <= 0 {
|
if client.ConnNum <= 0 {
|
||||||
client.ConnNum = 1
|
client.ConnNum = 1
|
||||||
log.SRelease("invalid ConnNum, reset to ", client.ConnNum)
|
log.Info("invalid ConnNum",log.Int("reset", client.ConnNum))
|
||||||
}
|
}
|
||||||
if client.ConnectInterval <= 0 {
|
if client.ConnectInterval <= 0 {
|
||||||
client.ConnectInterval = 3 * time.Second
|
client.ConnectInterval = 3 * time.Second
|
||||||
log.SRelease("invalid ConnectInterval, reset to ", client.ConnectInterval)
|
log.Info("invalid ConnectInterval",log.Duration("reset", client.ConnectInterval))
|
||||||
}
|
}
|
||||||
if client.PendingWriteNum <= 0 {
|
if client.PendingWriteNum <= 0 {
|
||||||
client.PendingWriteNum = 1000
|
client.PendingWriteNum = 1000
|
||||||
log.SRelease("invalid PendingWriteNum, reset to ", client.PendingWriteNum)
|
log.Info("invalid PendingWriteNum",log.Int("reset",client.PendingWriteNum))
|
||||||
}
|
}
|
||||||
if client.ReadDeadline == 0 {
|
if client.ReadDeadline == 0 {
|
||||||
client.ReadDeadline = 15*time.Second
|
client.ReadDeadline = 15*time.Second
|
||||||
log.SRelease("invalid ReadDeadline, reset to ", int64(client.ReadDeadline.Seconds()),"s")
|
log.Info("invalid ReadDeadline",log.Int64("reset", int64(client.ReadDeadline.Seconds())))
|
||||||
}
|
}
|
||||||
if client.WriteDeadline == 0 {
|
if client.WriteDeadline == 0 {
|
||||||
client.WriteDeadline = 15*time.Second
|
client.WriteDeadline = 15*time.Second
|
||||||
log.SRelease("invalid WriteDeadline, reset to ", int64(client.WriteDeadline.Seconds()),"s")
|
log.Info("invalid WriteDeadline",log.Int64("reset", int64(client.WriteDeadline.Seconds())))
|
||||||
}
|
}
|
||||||
if client.NewAgent == nil {
|
if client.NewAgent == nil {
|
||||||
log.SFatal("NewAgent must not be nil")
|
log.Fatal("NewAgent must not be nil")
|
||||||
}
|
}
|
||||||
if client.cons != nil {
|
if client.cons != nil {
|
||||||
log.SFatal("client is running")
|
log.Fatal("client is running")
|
||||||
}
|
|
||||||
if client.LenMsgLen == 0 {
|
|
||||||
client.LenMsgLen = Default_LenMsgLen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if client.MinMsgLen == 0 {
|
if client.MinMsgLen == 0 {
|
||||||
client.MinMsgLen = Default_MinMsgLen
|
client.MinMsgLen = Default_MinMsgLen
|
||||||
}
|
}
|
||||||
if client.MaxMsgLen == 0 {
|
if client.MaxMsgLen == 0 {
|
||||||
client.MaxMsgLen = Default_MaxMsgLen
|
client.MaxMsgLen = Default_MaxMsgLen
|
||||||
}
|
}
|
||||||
|
if client.LenMsgLen ==0 {
|
||||||
|
client.LenMsgLen = Default_LenMsgLen
|
||||||
|
}
|
||||||
|
maxMsgLen := client.MsgParser.getMaxMsgLen(client.LenMsgLen)
|
||||||
|
if client.MaxMsgLen > maxMsgLen {
|
||||||
|
client.MaxMsgLen = maxMsgLen
|
||||||
|
log.Info("invalid MaxMsgLen",log.Uint32("reset", maxMsgLen))
|
||||||
|
}
|
||||||
|
|
||||||
client.cons = make(ConnSet)
|
client.cons = make(ConnSet)
|
||||||
client.closeFlag = false
|
client.closeFlag = false
|
||||||
|
|
||||||
// msg parser
|
|
||||||
client.MsgParser.init()
|
client.MsgParser.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +102,7 @@ func (client *TCPClient) dial() net.Conn {
|
|||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SWarning("connect to ",client.Addr," error:", err.Error())
|
log.Warning("connect error ",log.String("error",err.Error()), log.String("Addr",client.Addr))
|
||||||
time.Sleep(client.ConnectInterval)
|
time.Sleep(client.ConnectInterval)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/log"
|
"errors"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
"errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConnSet map[net.Conn]struct{}
|
type ConnSet map[net.Conn]struct{}
|
||||||
@@ -14,7 +15,7 @@ type TCPConn struct {
|
|||||||
sync.Mutex
|
sync.Mutex
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
writeChan chan []byte
|
writeChan chan []byte
|
||||||
closeFlag bool
|
closeFlag int32
|
||||||
msgParser *MsgParser
|
msgParser *MsgParser
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ func newTCPConn(conn net.Conn, pendingWriteNum int, msgParser *MsgParser,writeDe
|
|||||||
|
|
||||||
conn.SetWriteDeadline(time.Now().Add(writeDeadline))
|
conn.SetWriteDeadline(time.Now().Add(writeDeadline))
|
||||||
_, err := conn.Write(b)
|
_, err := conn.Write(b)
|
||||||
tcpConn.msgParser.ReleaseByteSlice(b)
|
tcpConn.msgParser.ReleaseBytes(b)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
@@ -49,7 +50,7 @@ func newTCPConn(conn net.Conn, pendingWriteNum int, msgParser *MsgParser,writeDe
|
|||||||
conn.Close()
|
conn.Close()
|
||||||
tcpConn.Lock()
|
tcpConn.Lock()
|
||||||
freeChannel(tcpConn)
|
freeChannel(tcpConn)
|
||||||
tcpConn.closeFlag = true
|
atomic.StoreInt32(&tcpConn.closeFlag,1)
|
||||||
tcpConn.Unlock()
|
tcpConn.Unlock()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -60,9 +61,9 @@ func (tcpConn *TCPConn) doDestroy() {
|
|||||||
tcpConn.conn.(*net.TCPConn).SetLinger(0)
|
tcpConn.conn.(*net.TCPConn).SetLinger(0)
|
||||||
tcpConn.conn.Close()
|
tcpConn.conn.Close()
|
||||||
|
|
||||||
if !tcpConn.closeFlag {
|
if atomic.LoadInt32(&tcpConn.closeFlag)==0 {
|
||||||
close(tcpConn.writeChan)
|
close(tcpConn.writeChan)
|
||||||
tcpConn.closeFlag = true
|
atomic.StoreInt32(&tcpConn.closeFlag,1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,12 +77,12 @@ func (tcpConn *TCPConn) Destroy() {
|
|||||||
func (tcpConn *TCPConn) Close() {
|
func (tcpConn *TCPConn) Close() {
|
||||||
tcpConn.Lock()
|
tcpConn.Lock()
|
||||||
defer tcpConn.Unlock()
|
defer tcpConn.Unlock()
|
||||||
if tcpConn.closeFlag {
|
if atomic.LoadInt32(&tcpConn.closeFlag)==1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpConn.doWrite(nil)
|
tcpConn.doWrite(nil)
|
||||||
tcpConn.closeFlag = true
|
atomic.StoreInt32(&tcpConn.closeFlag,1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpConn *TCPConn) GetRemoteIp() string {
|
func (tcpConn *TCPConn) GetRemoteIp() string {
|
||||||
@@ -91,7 +92,7 @@ func (tcpConn *TCPConn) GetRemoteIp() string {
|
|||||||
func (tcpConn *TCPConn) doWrite(b []byte) error{
|
func (tcpConn *TCPConn) doWrite(b []byte) error{
|
||||||
if len(tcpConn.writeChan) == cap(tcpConn.writeChan) {
|
if len(tcpConn.writeChan) == cap(tcpConn.writeChan) {
|
||||||
tcpConn.ReleaseReadMsg(b)
|
tcpConn.ReleaseReadMsg(b)
|
||||||
log.SError("close conn: channel full")
|
log.Error("close conn: channel full")
|
||||||
tcpConn.doDestroy()
|
tcpConn.doDestroy()
|
||||||
return errors.New("close conn: channel full")
|
return errors.New("close conn: channel full")
|
||||||
}
|
}
|
||||||
@@ -104,7 +105,7 @@ func (tcpConn *TCPConn) doWrite(b []byte) error{
|
|||||||
func (tcpConn *TCPConn) Write(b []byte) error{
|
func (tcpConn *TCPConn) Write(b []byte) error{
|
||||||
tcpConn.Lock()
|
tcpConn.Lock()
|
||||||
defer tcpConn.Unlock()
|
defer tcpConn.Unlock()
|
||||||
if tcpConn.closeFlag || b == nil {
|
if atomic.LoadInt32(&tcpConn.closeFlag)==1 || b == nil {
|
||||||
tcpConn.ReleaseReadMsg(b)
|
tcpConn.ReleaseReadMsg(b)
|
||||||
return errors.New("conn is close")
|
return errors.New("conn is close")
|
||||||
}
|
}
|
||||||
@@ -128,19 +129,26 @@ func (tcpConn *TCPConn) ReadMsg() ([]byte, error) {
|
|||||||
return tcpConn.msgParser.Read(tcpConn)
|
return tcpConn.msgParser.Read(tcpConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tcpConn *TCPConn) GetRecyclerReaderBytes() func (data []byte) {
|
||||||
|
bytePool := tcpConn.msgParser.IBytesMempool
|
||||||
|
return func(data []byte) {
|
||||||
|
bytePool.ReleaseBytes(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (tcpConn *TCPConn) ReleaseReadMsg(byteBuff []byte){
|
func (tcpConn *TCPConn) ReleaseReadMsg(byteBuff []byte){
|
||||||
tcpConn.msgParser.ReleaseByteSlice(byteBuff)
|
tcpConn.msgParser.ReleaseBytes(byteBuff)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpConn *TCPConn) WriteMsg(args ...[]byte) error {
|
func (tcpConn *TCPConn) WriteMsg(args ...[]byte) error {
|
||||||
if tcpConn.closeFlag == true {
|
if atomic.LoadInt32(&tcpConn.closeFlag) == 1 {
|
||||||
return errors.New("conn is close")
|
return errors.New("conn is close")
|
||||||
}
|
}
|
||||||
return tcpConn.msgParser.Write(tcpConn, args...)
|
return tcpConn.msgParser.Write(tcpConn, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpConn *TCPConn) WriteRawMsg(args []byte) error {
|
func (tcpConn *TCPConn) WriteRawMsg(args []byte) error {
|
||||||
if tcpConn.closeFlag == true {
|
if atomic.LoadInt32(&tcpConn.closeFlag) == 1 {
|
||||||
return errors.New("conn is close")
|
return errors.New("conn is close")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +157,7 @@ func (tcpConn *TCPConn) WriteRawMsg(args []byte) error {
|
|||||||
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) IsConnected() bool {
|
func (tcpConn *TCPConn) IsConnected() bool {
|
||||||
return tcpConn.closeFlag == false
|
return atomic.LoadInt32(&tcpConn.closeFlag) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpConn *TCPConn) SetReadDeadline(d time.Duration) {
|
func (tcpConn *TCPConn) SetReadDeadline(d time.Duration) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package network
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/duanhf2012/origin/v2/util/bytespool"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
@@ -16,34 +17,26 @@ type MsgParser struct {
|
|||||||
MaxMsgLen uint32
|
MaxMsgLen uint32
|
||||||
LittleEndian bool
|
LittleEndian bool
|
||||||
|
|
||||||
INetMempool
|
bytespool.IBytesMempool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (p *MsgParser) init(){
|
func (p *MsgParser) getMaxMsgLen(lenMsgLen int) uint32 {
|
||||||
var max uint32
|
|
||||||
switch p.LenMsgLen {
|
switch p.LenMsgLen {
|
||||||
case 1:
|
case 1:
|
||||||
max = math.MaxUint8
|
return math.MaxUint8
|
||||||
case 2:
|
case 2:
|
||||||
max = math.MaxUint16
|
return math.MaxUint16
|
||||||
case 4:
|
case 4:
|
||||||
max = math.MaxUint32
|
return math.MaxUint32
|
||||||
default:
|
default:
|
||||||
panic("LenMsgLen value must be 1 or 2 or 4")
|
panic("LenMsgLen value must be 1 or 2 or 4")
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.MinMsgLen > max {
|
|
||||||
p.MinMsgLen = max
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.MaxMsgLen > max {
|
|
||||||
p.MaxMsgLen = max
|
|
||||||
}
|
|
||||||
|
|
||||||
p.INetMempool = NewMemAreaPool()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *MsgParser) init(){
|
||||||
|
p.IBytesMempool = bytespool.NewMemAreaPool()
|
||||||
|
}
|
||||||
|
|
||||||
// goroutine safe
|
// goroutine safe
|
||||||
func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) {
|
func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) {
|
||||||
@@ -82,9 +75,9 @@ func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// data
|
// data
|
||||||
msgData := p.MakeByteSlice(int(msgLen))
|
msgData := p.MakeBytes(int(msgLen))
|
||||||
if _, err := io.ReadFull(conn, msgData[:msgLen]); err != nil {
|
if _, err := io.ReadFull(conn, msgData[:msgLen]); err != nil {
|
||||||
p.ReleaseByteSlice(msgData)
|
p.ReleaseBytes(msgData)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +100,7 @@ func (p *MsgParser) Write(conn *TCPConn, args ...[]byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//msg := make([]byte, uint32(p.lenMsgLen)+msgLen)
|
//msg := make([]byte, uint32(p.lenMsgLen)+msgLen)
|
||||||
msg := p.MakeByteSlice(p.LenMsgLen+int(msgLen))
|
msg := p.MakeBytes(p.LenMsgLen+int(msgLen))
|
||||||
// write len
|
// write len
|
||||||
switch p.LenMsgLen {
|
switch p.LenMsgLen {
|
||||||
case 1:
|
case 1:
|
||||||
|
|||||||
@@ -1,20 +1,25 @@
|
|||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/util/bytespool"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
"fmt"
|
||||||
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const Default_ReadDeadline = time.Second*30 //30s
|
const(
|
||||||
const Default_WriteDeadline = time.Second*30 //30s
|
Default_ReadDeadline = time.Second*30 //默认读超时30s
|
||||||
const Default_MaxConnNum = 9000
|
Default_WriteDeadline = time.Second*30 //默认写超时30s
|
||||||
const Default_PendingWriteNum = 10000
|
Default_MaxConnNum = 1000000 //默认最大连接数
|
||||||
const Default_LittleEndian = false
|
Default_PendingWriteNum = 100000 //单连接写消息Channel容量
|
||||||
const Default_MinMsgLen = 2
|
Default_LittleEndian = false //默认大小端
|
||||||
const Default_MaxMsgLen = 65535
|
Default_MinMsgLen = 2 //最小消息长度2byte
|
||||||
const Default_LenMsgLen = 2
|
Default_LenMsgLen = 2 //包头字段长度占用2byte
|
||||||
|
Default_MaxMsgLen = 65535 //最大消息长度
|
||||||
|
)
|
||||||
|
|
||||||
type TCPServer struct {
|
type TCPServer struct {
|
||||||
Addr string
|
Addr string
|
||||||
@@ -29,72 +34,84 @@ type TCPServer struct {
|
|||||||
mutexConns sync.Mutex
|
mutexConns sync.Mutex
|
||||||
wgLn sync.WaitGroup
|
wgLn sync.WaitGroup
|
||||||
wgConns sync.WaitGroup
|
wgConns sync.WaitGroup
|
||||||
|
|
||||||
// msg parser
|
|
||||||
MsgParser
|
MsgParser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TCPServer) Start() {
|
func (server *TCPServer) Start() error{
|
||||||
server.init()
|
err := server.init()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
go server.run()
|
go server.run()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TCPServer) init() {
|
func (server *TCPServer) init() error{
|
||||||
ln, err := net.Listen("tcp", server.Addr)
|
ln, err := net.Listen("tcp", server.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SFatal("Listen tcp error:", err.Error())
|
return fmt.Errorf("Listen tcp fail,error:%s",err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.MaxConnNum <= 0 {
|
if server.MaxConnNum <= 0 {
|
||||||
server.MaxConnNum = Default_MaxConnNum
|
server.MaxConnNum = Default_MaxConnNum
|
||||||
log.SRelease("invalid MaxConnNum, reset to ", server.MaxConnNum)
|
log.Info("invalid MaxConnNum",log.Int("reset", server.MaxConnNum))
|
||||||
}
|
|
||||||
if server.PendingWriteNum <= 0 {
|
|
||||||
server.PendingWriteNum = Default_PendingWriteNum
|
|
||||||
log.SRelease("invalid PendingWriteNum, reset to ", server.PendingWriteNum)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.MinMsgLen <= 0 {
|
if server.PendingWriteNum <= 0 {
|
||||||
server.MinMsgLen = Default_MinMsgLen
|
server.PendingWriteNum = Default_PendingWriteNum
|
||||||
log.SRelease("invalid MinMsgLen, reset to ", server.MinMsgLen)
|
log.Info("invalid PendingWriteNum",log.Int("reset", server.PendingWriteNum))
|
||||||
|
}
|
||||||
|
|
||||||
|
if server.LenMsgLen <= 0 {
|
||||||
|
server.LenMsgLen = Default_LenMsgLen
|
||||||
|
log.Info("invalid LenMsgLen", log.Int("reset", server.LenMsgLen))
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.MaxMsgLen <= 0 {
|
if server.MaxMsgLen <= 0 {
|
||||||
server.MaxMsgLen = Default_MaxMsgLen
|
server.MaxMsgLen = Default_MaxMsgLen
|
||||||
log.SRelease("invalid MaxMsgLen, reset to ", server.MaxMsgLen)
|
log.Info("invalid MaxMsgLen", log.Uint32("reset to", server.MaxMsgLen))
|
||||||
|
}
|
||||||
|
|
||||||
|
maxMsgLen := server.MsgParser.getMaxMsgLen(server.LenMsgLen)
|
||||||
|
if server.MaxMsgLen > maxMsgLen {
|
||||||
|
server.MaxMsgLen = maxMsgLen
|
||||||
|
log.Info("invalid MaxMsgLen",log.Uint32("reset", maxMsgLen))
|
||||||
|
}
|
||||||
|
|
||||||
|
if server.MinMsgLen <= 0 {
|
||||||
|
server.MinMsgLen = Default_MinMsgLen
|
||||||
|
log.Info("invalid MinMsgLen",log.Uint32("reset", server.MinMsgLen))
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.WriteDeadline == 0 {
|
if server.WriteDeadline == 0 {
|
||||||
server.WriteDeadline = Default_WriteDeadline
|
server.WriteDeadline = Default_WriteDeadline
|
||||||
log.SRelease("invalid WriteDeadline, reset to ", server.WriteDeadline.Seconds(),"s")
|
log.Info("invalid WriteDeadline",log.Int64("reset",int64(server.WriteDeadline.Seconds())))
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.ReadDeadline == 0 {
|
if server.ReadDeadline == 0 {
|
||||||
server.ReadDeadline = Default_ReadDeadline
|
server.ReadDeadline = Default_ReadDeadline
|
||||||
log.SRelease("invalid ReadDeadline, reset to ", server.ReadDeadline.Seconds(),"s")
|
log.Info("invalid ReadDeadline",log.Int64("reset", int64(server.ReadDeadline.Seconds())))
|
||||||
}
|
|
||||||
|
|
||||||
if server.LenMsgLen == 0 {
|
|
||||||
server.LenMsgLen = Default_LenMsgLen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.NewAgent == nil {
|
if server.NewAgent == nil {
|
||||||
log.SFatal("NewAgent must not be nil")
|
return errors.New("NewAgent must not be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
server.ln = ln
|
server.ln = ln
|
||||||
server.conns = make(ConnSet)
|
server.conns = make(ConnSet)
|
||||||
server.INetMempool = NewMemAreaPool()
|
|
||||||
|
|
||||||
server.MsgParser.init()
|
server.MsgParser.init()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TCPServer) SetNetMempool(mempool INetMempool){
|
func (server *TCPServer) SetNetMempool(mempool bytespool.IBytesMempool){
|
||||||
server.INetMempool = mempool
|
server.IBytesMempool = mempool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TCPServer) GetNetMempool() INetMempool{
|
func (server *TCPServer) GetNetMempool() bytespool.IBytesMempool {
|
||||||
return server.INetMempool
|
return server.IBytesMempool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TCPServer) run() {
|
func (server *TCPServer) run() {
|
||||||
@@ -114,7 +131,7 @@ func (server *TCPServer) run() {
|
|||||||
if max := 1 * time.Second; tempDelay > max {
|
if max := 1 * time.Second; tempDelay > max {
|
||||||
tempDelay = max
|
tempDelay = max
|
||||||
}
|
}
|
||||||
log.SRelease("accept error:",err.Error(),"; retrying in ", tempDelay)
|
log.Info("accept fail",log.String("error",err.Error()),log.Duration("sleep time", tempDelay))
|
||||||
time.Sleep(tempDelay)
|
time.Sleep(tempDelay)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -128,7 +145,7 @@ func (server *TCPServer) run() {
|
|||||||
if len(server.conns) >= server.MaxConnNum {
|
if len(server.conns) >= server.MaxConnNum {
|
||||||
server.mutexConns.Unlock()
|
server.mutexConns.Unlock()
|
||||||
conn.Close()
|
conn.Close()
|
||||||
log.SWarning("too many connections")
|
log.Warning("too many connections")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -40,29 +40,29 @@ func (client *WSClient) init() {
|
|||||||
|
|
||||||
if client.ConnNum <= 0 {
|
if client.ConnNum <= 0 {
|
||||||
client.ConnNum = 1
|
client.ConnNum = 1
|
||||||
log.SRelease("invalid ConnNum, reset to ", client.ConnNum)
|
log.Info("invalid ConnNum",log.Int("reset", client.ConnNum))
|
||||||
}
|
}
|
||||||
if client.ConnectInterval <= 0 {
|
if client.ConnectInterval <= 0 {
|
||||||
client.ConnectInterval = 3 * time.Second
|
client.ConnectInterval = 3 * time.Second
|
||||||
log.SRelease("invalid ConnectInterval, reset to ", client.ConnectInterval)
|
log.Info("invalid ConnectInterval",log.Duration("reset", client.ConnectInterval))
|
||||||
}
|
}
|
||||||
if client.PendingWriteNum <= 0 {
|
if client.PendingWriteNum <= 0 {
|
||||||
client.PendingWriteNum = 100
|
client.PendingWriteNum = 100
|
||||||
log.SRelease("invalid PendingWriteNum, reset to ", client.PendingWriteNum)
|
log.Info("invalid PendingWriteNum",log.Int("reset", client.PendingWriteNum))
|
||||||
}
|
}
|
||||||
if client.MaxMsgLen <= 0 {
|
if client.MaxMsgLen <= 0 {
|
||||||
client.MaxMsgLen = 4096
|
client.MaxMsgLen = 4096
|
||||||
log.SRelease("invalid MaxMsgLen, reset to ", client.MaxMsgLen)
|
log.Info("invalid MaxMsgLen",log.Uint32("reset", client.MaxMsgLen))
|
||||||
}
|
}
|
||||||
if client.HandshakeTimeout <= 0 {
|
if client.HandshakeTimeout <= 0 {
|
||||||
client.HandshakeTimeout = 10 * time.Second
|
client.HandshakeTimeout = 10 * time.Second
|
||||||
log.SRelease("invalid HandshakeTimeout, reset to ", client.HandshakeTimeout)
|
log.Info("invalid HandshakeTimeout",log.Duration("reset", client.HandshakeTimeout))
|
||||||
}
|
}
|
||||||
if client.NewAgent == nil {
|
if client.NewAgent == nil {
|
||||||
log.SFatal("NewAgent must not be nil")
|
log.Fatal("NewAgent must not be nil")
|
||||||
}
|
}
|
||||||
if client.cons != nil {
|
if client.cons != nil {
|
||||||
log.SFatal("client is running")
|
log.Fatal("client is running")
|
||||||
}
|
}
|
||||||
|
|
||||||
if client.MessageType == 0 {
|
if client.MessageType == 0 {
|
||||||
@@ -83,7 +83,7 @@ func (client *WSClient) dial() *websocket.Conn {
|
|||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SRelease("connect to ", client.Addr," error: ", err.Error())
|
log.Info("connect fail", log.String("error",err.Error()),log.String("addr",client.Addr))
|
||||||
time.Sleep(client.ConnectInterval)
|
time.Sleep(client.ConnectInterval)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package network
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -75,7 +75,7 @@ func (wsConn *WSConn) Close() {
|
|||||||
|
|
||||||
func (wsConn *WSConn) doWrite(b []byte) {
|
func (wsConn *WSConn) doWrite(b []byte) {
|
||||||
if len(wsConn.writeChan) == cap(wsConn.writeChan) {
|
if len(wsConn.writeChan) == cap(wsConn.writeChan) {
|
||||||
log.SDebug("close conn: channel full")
|
log.Debug("close conn: channel full")
|
||||||
wsConn.doDestroy()
|
wsConn.doDestroy()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package network
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -47,7 +47,7 @@ func (handler *WSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
conn, err := handler.upgrader.Upgrade(w, r, nil)
|
conn, err := handler.upgrader.Upgrade(w, r, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("upgrade error: ", err.Error())
|
log.Error("upgrade fail",log.String("error",err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn.SetReadLimit(int64(handler.maxMsgLen))
|
conn.SetReadLimit(int64(handler.maxMsgLen))
|
||||||
@@ -67,7 +67,7 @@ func (handler *WSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
if len(handler.conns) >= handler.maxConnNum {
|
if len(handler.conns) >= handler.maxConnNum {
|
||||||
handler.mutexConns.Unlock()
|
handler.mutexConns.Unlock()
|
||||||
conn.Close()
|
conn.Close()
|
||||||
log.SWarning("too many connections")
|
log.Warning("too many connections")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handler.conns[conn] = struct{}{}
|
handler.conns[conn] = struct{}{}
|
||||||
@@ -95,27 +95,27 @@ func (server *WSServer) SetMessageType(messageType int) {
|
|||||||
func (server *WSServer) Start() {
|
func (server *WSServer) Start() {
|
||||||
ln, err := net.Listen("tcp", server.Addr)
|
ln, err := net.Listen("tcp", server.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SFatal("WSServer Listen fail:", err.Error())
|
log.Fatal("WSServer Listen fail",log.String("error", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.MaxConnNum <= 0 {
|
if server.MaxConnNum <= 0 {
|
||||||
server.MaxConnNum = 100
|
server.MaxConnNum = 100
|
||||||
log.SRelease("invalid MaxConnNum, reset to ", server.MaxConnNum)
|
log.Info("invalid MaxConnNum", log.Int("reset", server.MaxConnNum))
|
||||||
}
|
}
|
||||||
if server.PendingWriteNum <= 0 {
|
if server.PendingWriteNum <= 0 {
|
||||||
server.PendingWriteNum = 100
|
server.PendingWriteNum = 100
|
||||||
log.SRelease("invalid PendingWriteNum, reset to ", server.PendingWriteNum)
|
log.Info("invalid PendingWriteNum", log.Int("reset", server.PendingWriteNum))
|
||||||
}
|
}
|
||||||
if server.MaxMsgLen <= 0 {
|
if server.MaxMsgLen <= 0 {
|
||||||
server.MaxMsgLen = 4096
|
server.MaxMsgLen = 4096
|
||||||
log.SRelease("invalid MaxMsgLen, reset to ", server.MaxMsgLen)
|
log.Info("invalid MaxMsgLen", log.Uint32("reset", server.MaxMsgLen))
|
||||||
}
|
}
|
||||||
if server.HTTPTimeout <= 0 {
|
if server.HTTPTimeout <= 0 {
|
||||||
server.HTTPTimeout = 10 * time.Second
|
server.HTTPTimeout = 10 * time.Second
|
||||||
log.SRelease("invalid HTTPTimeout, reset to ", server.HTTPTimeout)
|
log.Info("invalid HTTPTimeout", log.Duration("reset", server.HTTPTimeout))
|
||||||
}
|
}
|
||||||
if server.NewAgent == nil {
|
if server.NewAgent == nil {
|
||||||
log.SFatal("NewAgent must not be nil")
|
log.Fatal("NewAgent must not be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.CertFile != "" || server.KeyFile != "" {
|
if server.CertFile != "" || server.KeyFile != "" {
|
||||||
@@ -126,7 +126,7 @@ func (server *WSServer) Start() {
|
|||||||
config.Certificates = make([]tls.Certificate, 1)
|
config.Certificates = make([]tls.Certificate, 1)
|
||||||
config.Certificates[0], err = tls.LoadX509KeyPair(server.CertFile, server.KeyFile)
|
config.Certificates[0], err = tls.LoadX509KeyPair(server.CertFile, server.KeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SFatal("LoadX509KeyPair fail:", err.Error())
|
log.Fatal("LoadX509KeyPair fail",log.String("error", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
ln = tls.NewListener(ln, config)
|
ln = tls.NewListener(ln, config)
|
||||||
|
|||||||
270
node/node.go
270
node/node.go
@@ -3,15 +3,14 @@ package node
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/cluster"
|
"github.com/duanhf2012/origin/v2/cluster"
|
||||||
"github.com/duanhf2012/origin/console"
|
"github.com/duanhf2012/origin/v2/console"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/profiler"
|
"github.com/duanhf2012/origin/v2/profiler"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/duanhf2012/origin/util/buildtime"
|
"github.com/duanhf2012/origin/v2/util/buildtime"
|
||||||
"github.com/duanhf2012/origin/util/timer"
|
"github.com/duanhf2012/origin/v2/util/timer"
|
||||||
"io"
|
"io"
|
||||||
slog "log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
"os"
|
"os"
|
||||||
@@ -20,16 +19,22 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
"github.com/duanhf2012/origin/v2/util/sysprocess"
|
||||||
)
|
)
|
||||||
|
|
||||||
var sig chan os.Signal
|
var sig chan os.Signal
|
||||||
var nodeId int
|
var nodeId string
|
||||||
var preSetupService []service.IService //预安装
|
var preSetupService []service.IService //预安装
|
||||||
|
var preSetupTemplateService []func()service.IService
|
||||||
var profilerInterval time.Duration
|
var profilerInterval time.Duration
|
||||||
var bValid bool
|
var bValid bool
|
||||||
var configDir = "./config/"
|
var configDir = "./config/"
|
||||||
var logLevel string = "debug"
|
|
||||||
var logPath string
|
const(
|
||||||
|
SingleStop syscall.Signal = 10
|
||||||
|
SignalRetire syscall.Signal = 12
|
||||||
|
)
|
||||||
|
|
||||||
type BuildOSType = int8
|
type BuildOSType = int8
|
||||||
|
|
||||||
const(
|
const(
|
||||||
@@ -39,20 +44,28 @@ const(
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
sig = make(chan os.Signal, 3)
|
sig = make(chan os.Signal, 4)
|
||||||
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM, syscall.Signal(10))
|
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM, SingleStop,SignalRetire)
|
||||||
|
|
||||||
console.RegisterCommandBool("help", false, "<-help> This help.", usage)
|
console.RegisterCommandBool("help", false, "<-help> This help.", usage)
|
||||||
console.RegisterCommandString("name", "", "<-name nodeName> Node's name.", setName)
|
console.RegisterCommandString("name", "", "<-name nodeName> Node's name.", setName)
|
||||||
console.RegisterCommandString("start", "", "<-start nodeid=nodeid> Run originserver.", startNode)
|
console.RegisterCommandString("start", "", "<-start nodeid=nodeid> Run originserver.", startNode)
|
||||||
console.RegisterCommandString("stop", "", "<-stop nodeid=nodeid> Stop originserver process.", stopNode)
|
console.RegisterCommandString("stop", "", "<-stop nodeid=nodeid> Stop originserver process.", stopNode)
|
||||||
|
console.RegisterCommandString("retire", "", "<-retire nodeid=nodeid> retire originserver process.", retireNode)
|
||||||
console.RegisterCommandString("config", "", "<-config path> Configuration file path.", setConfigPath)
|
console.RegisterCommandString("config", "", "<-config path> Configuration file path.", setConfigPath)
|
||||||
console.RegisterCommandString("console", "", "<-console true|false> Turn on or off screen log output.", openConsole)
|
console.RegisterCommandString("console", "", "<-console true|false> Turn on or off screen log output.", openConsole)
|
||||||
console.RegisterCommandString("loglevel", "debug", "<-loglevel debug|release|warning|error|fatal> Set loglevel.", setLevel)
|
console.RegisterCommandString("loglevel", "debug", "<-loglevel debug|release|warning|error|fatal> Set loglevel.", setLevel)
|
||||||
console.RegisterCommandString("logpath", "", "<-logpath path> Set log file path.", setLogPath)
|
console.RegisterCommandString("logpath", "", "<-logpath path> Set log file path.", setLogPath)
|
||||||
|
console.RegisterCommandInt("logsize", 0, "<-logsize size> Set log size(MB).", setLogSize)
|
||||||
|
console.RegisterCommandInt("logchannelcap", 0, "<-logchannelcap num> Set log channel cap.", setLogChannelCapNum)
|
||||||
console.RegisterCommandString("pprof", "", "<-pprof ip:port> Open performance analysis.", setPprof)
|
console.RegisterCommandString("pprof", "", "<-pprof ip:port> Open performance analysis.", setPprof)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func notifyAllServiceRetire(){
|
||||||
|
service.NotifyAllServiceRetire()
|
||||||
|
}
|
||||||
|
|
||||||
func usage(val interface{}) error {
|
func usage(val interface{}) error {
|
||||||
ret := val.(bool)
|
ret := val.(bool)
|
||||||
if ret == false {
|
if ret == false {
|
||||||
@@ -104,8 +117,8 @@ func setConfigPath(val interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRunProcessPid(nodeId int) (int, error) {
|
func getRunProcessPid(nodeId string) (int, error) {
|
||||||
f, err := os.OpenFile(fmt.Sprintf("%s_%d.pid", os.Args[0], nodeId), os.O_RDONLY, 0600)
|
f, err := os.OpenFile(fmt.Sprintf("%s_%s.pid", os.Args[0], nodeId), os.O_RDONLY, 0600)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -119,9 +132,9 @@ func getRunProcessPid(nodeId int) (int, error) {
|
|||||||
return strconv.Atoi(string(pidByte))
|
return strconv.Atoi(string(pidByte))
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeProcessPid(nodeId int) {
|
func writeProcessPid(nodeId string) {
|
||||||
//pid
|
//pid
|
||||||
f, err := os.OpenFile(fmt.Sprintf("%s_%d.pid", os.Args[0], nodeId), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600)
|
f, err := os.OpenFile(fmt.Sprintf("%s_%s.pid", os.Args[0], nodeId), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
@@ -135,16 +148,17 @@ func writeProcessPid(nodeId int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetNodeId() int {
|
func GetNodeId() string {
|
||||||
return nodeId
|
return nodeId
|
||||||
}
|
}
|
||||||
|
|
||||||
func initNode(id int) {
|
func initNode(id string) {
|
||||||
//1.初始化集群
|
//1.初始化集群
|
||||||
nodeId = id
|
nodeId = id
|
||||||
err := cluster.GetCluster().Init(GetNodeId(), Setup)
|
err := cluster.GetCluster().Init(GetNodeId(), Setup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SFatal("read system config is error ", err.Error())
|
log.Error("Init cluster fail",log.ErrorAttr("error",err))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = initLog()
|
err = initLog()
|
||||||
@@ -156,6 +170,31 @@ func initNode(id int) {
|
|||||||
serviceOrder := cluster.GetCluster().GetLocalNodeInfo().ServiceList
|
serviceOrder := cluster.GetCluster().GetLocalNodeInfo().ServiceList
|
||||||
for _,serviceName:= range serviceOrder{
|
for _,serviceName:= range serviceOrder{
|
||||||
bSetup := false
|
bSetup := false
|
||||||
|
|
||||||
|
//判断是否有配置模板服务
|
||||||
|
splitServiceName := strings.Split(serviceName,":")
|
||||||
|
if len(splitServiceName) == 2 {
|
||||||
|
serviceName = splitServiceName[0]
|
||||||
|
templateServiceName := splitServiceName[1]
|
||||||
|
for _,newSer := range preSetupTemplateService {
|
||||||
|
ser := newSer()
|
||||||
|
ser.OnSetup(ser)
|
||||||
|
if ser.GetName() == templateServiceName {
|
||||||
|
ser.SetName(serviceName)
|
||||||
|
ser.Init(ser,cluster.GetRpcClient,cluster.GetRpcServer,cluster.GetCluster().GetServiceCfg(ser.GetName()))
|
||||||
|
service.Setup(ser)
|
||||||
|
|
||||||
|
bSetup = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if bSetup == false{
|
||||||
|
log.Error("Template service not found",log.String("service name",serviceName),log.String("template service name",templateServiceName))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, s := range preSetupService {
|
for _, s := range preSetupService {
|
||||||
if s.GetName() != serviceName {
|
if s.GetName() != serviceName {
|
||||||
continue
|
continue
|
||||||
@@ -168,7 +207,7 @@ func initNode(id int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if bSetup == false {
|
if bSetup == false {
|
||||||
log.SFatal("Service name "+serviceName+" configuration error")
|
log.Fatal("Service name "+serviceName+" configuration error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,18 +216,18 @@ func initNode(id int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initLog() error {
|
func initLog() error {
|
||||||
if logPath == "" {
|
if log.LogPath == "" {
|
||||||
setLogPath("./log")
|
setLogPath("./log")
|
||||||
}
|
}
|
||||||
|
|
||||||
localnodeinfo := cluster.GetCluster().GetLocalNodeInfo()
|
localnodeinfo := cluster.GetCluster().GetLocalNodeInfo()
|
||||||
filepre := fmt.Sprintf("%s_%d_", localnodeinfo.NodeName, localnodeinfo.NodeId)
|
filepre := fmt.Sprintf("%s_", localnodeinfo.NodeId)
|
||||||
logger, err := log.New(logLevel, logPath, filepre, slog.LstdFlags|slog.Lshortfile, 10)
|
logger, err := log.NewTextLogger(log.LogLevel,log.LogPath,filepre,true,log.LogChannelCap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("cannot create log file!\n")
|
fmt.Printf("cannot create log file!\n")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Export(logger)
|
log.SetLogger(logger)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +239,37 @@ func Start() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func retireNode(args interface{}) error {
|
||||||
|
//1.解析参数
|
||||||
|
param := args.(string)
|
||||||
|
if param == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sParam := strings.Split(param, "=")
|
||||||
|
if len(sParam) != 2 {
|
||||||
|
return fmt.Errorf("invalid option %s", param)
|
||||||
|
}
|
||||||
|
if sParam[0] != "nodeid" {
|
||||||
|
return fmt.Errorf("invalid option %s", param)
|
||||||
|
}
|
||||||
|
nId := strings.TrimSpace(sParam[1])
|
||||||
|
if nId == "" {
|
||||||
|
return fmt.Errorf("invalid option %s", param)
|
||||||
|
}
|
||||||
|
|
||||||
|
processId, err := getRunProcessPid(nId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RetireProcess(processId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func stopNode(args interface{}) error {
|
func stopNode(args interface{}) error {
|
||||||
//1.解析参数
|
//1.解析参数
|
||||||
param := args.(string)
|
param := args.(string)
|
||||||
@@ -214,12 +284,12 @@ func stopNode(args interface{}) error {
|
|||||||
if sParam[0] != "nodeid" {
|
if sParam[0] != "nodeid" {
|
||||||
return fmt.Errorf("invalid option %s", param)
|
return fmt.Errorf("invalid option %s", param)
|
||||||
}
|
}
|
||||||
nodeId, err := strconv.Atoi(sParam[1])
|
nId := strings.TrimSpace(sParam[1])
|
||||||
if err != nil {
|
if nId == "" {
|
||||||
return fmt.Errorf("invalid option %s", param)
|
return fmt.Errorf("invalid option %s", param)
|
||||||
}
|
}
|
||||||
|
|
||||||
processId, err := getRunProcessPid(nodeId)
|
processId, err := getRunProcessPid(nId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -242,45 +312,77 @@ func startNode(args interface{}) error {
|
|||||||
if sParam[0] != "nodeid" {
|
if sParam[0] != "nodeid" {
|
||||||
return fmt.Errorf("invalid option %s", param)
|
return fmt.Errorf("invalid option %s", param)
|
||||||
}
|
}
|
||||||
nodeId, err := strconv.Atoi(sParam[1])
|
strNodeId := strings.TrimSpace(sParam[1])
|
||||||
if err != nil {
|
if strNodeId == "" {
|
||||||
return fmt.Errorf("invalid option %s", param)
|
return fmt.Errorf("invalid option %s", param)
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.StartTimer(10*time.Millisecond, 1000000)
|
for{
|
||||||
log.SRelease("Start running server.")
|
processId, pErr := getRunProcessPid(strNodeId)
|
||||||
//2.初始化node
|
if pErr != nil {
|
||||||
initNode(nodeId)
|
break
|
||||||
|
}
|
||||||
|
|
||||||
//3.运行service
|
name, cErr := sysprocess.GetProcessNameByPID(int32(processId))
|
||||||
|
myName, mErr := sysprocess.GetMyProcessName()
|
||||||
|
//当前进程名获取失败,不应该发生
|
||||||
|
if mErr != nil {
|
||||||
|
log.SInfo("get my process's name is error,", mErr.Error())
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//进程id存在,而且进程名也相同,被认为是当前进程重复运行
|
||||||
|
if cErr == nil && name == myName {
|
||||||
|
log.SInfo(fmt.Sprintf("repeat runs are not allowed,node is %s,processid is %d",strNodeId,processId))
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
//2.记录进程id号
|
||||||
|
log.Info("Start running server.")
|
||||||
|
writeProcessPid(strNodeId)
|
||||||
|
timer.StartTimer(10*time.Millisecond, 1000000)
|
||||||
|
|
||||||
|
//3.初始化node
|
||||||
|
initNode(strNodeId)
|
||||||
|
|
||||||
|
//4.运行service
|
||||||
service.Start()
|
service.Start()
|
||||||
|
|
||||||
//4.运行集群
|
//5.运行集群
|
||||||
cluster.GetCluster().Start()
|
cluster.GetCluster().Start()
|
||||||
|
|
||||||
//5.记录进程id号
|
|
||||||
writeProcessPid(nodeId)
|
|
||||||
|
|
||||||
//6.监听程序退出信号&性能报告
|
//6.监听程序退出信号&性能报告
|
||||||
bRun := true
|
bRun := true
|
||||||
var pProfilerTicker *time.Ticker = &time.Ticker{}
|
var pProfilerTicker *time.Ticker = &time.Ticker{}
|
||||||
if profilerInterval > 0 {
|
if profilerInterval > 0 {
|
||||||
pProfilerTicker = time.NewTicker(profilerInterval)
|
pProfilerTicker = time.NewTicker(profilerInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
for bRun {
|
for bRun {
|
||||||
select {
|
select {
|
||||||
case <-sig:
|
case s := <-sig:
|
||||||
log.SRelease("receipt stop signal.")
|
signal := s.(syscall.Signal)
|
||||||
bRun = false
|
if signal == SignalRetire {
|
||||||
|
log.Info("receipt retire signal.")
|
||||||
|
notifyAllServiceRetire()
|
||||||
|
}else {
|
||||||
|
bRun = false
|
||||||
|
log.Info("receipt stop signal.")
|
||||||
|
}
|
||||||
case <-pProfilerTicker.C:
|
case <-pProfilerTicker.C:
|
||||||
profiler.Report()
|
profiler.Report()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cluster.GetCluster().Stop()
|
|
||||||
|
|
||||||
//7.退出
|
//7.退出
|
||||||
service.StopAllService()
|
service.StopAllService()
|
||||||
|
cluster.GetCluster().Stop()
|
||||||
|
|
||||||
log.SRelease("Server is stop.")
|
log.Info("Server is stop.")
|
||||||
|
log.Close()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,24 +393,25 @@ func Setup(s ...service.IService) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetupTemplate(fs ...func()service.IService){
|
||||||
|
for _, f := range fs {
|
||||||
|
preSetupTemplateService = append(preSetupTemplateService, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func GetService(serviceName string) service.IService {
|
func GetService(serviceName string) service.IService {
|
||||||
return service.GetService(serviceName)
|
return service.GetService(serviceName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetConfigDir(configDir string) {
|
func SetConfigDir(cfgDir string) {
|
||||||
configDir = configDir
|
configDir = cfgDir
|
||||||
cluster.SetConfigDir(configDir)
|
cluster.SetConfigDir(cfgDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetConfigDir() string {
|
func GetConfigDir() string {
|
||||||
return configDir
|
return configDir
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetSysLog(strLevel string, pathname string, flag int) {
|
|
||||||
logs, _ := log.New(strLevel, pathname, "", flag, 10)
|
|
||||||
log.Export(logs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func OpenProfilerReport(interval time.Duration) {
|
func OpenProfilerReport(interval time.Duration) {
|
||||||
profilerInterval = interval
|
profilerInterval = interval
|
||||||
}
|
}
|
||||||
@@ -333,9 +436,24 @@ func setLevel(args interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
logLevel = strings.TrimSpace(args.(string))
|
strlogLevel := strings.TrimSpace(args.(string))
|
||||||
if logLevel != "debug" && logLevel != "release" && logLevel != "warning" && logLevel != "error" && logLevel != "fatal" {
|
switch strlogLevel {
|
||||||
return errors.New("unknown level: " + logLevel)
|
case "trace":
|
||||||
|
log.LogLevel = log.LevelTrace
|
||||||
|
case "debug":
|
||||||
|
log.LogLevel = log.LevelDebug
|
||||||
|
case "info":
|
||||||
|
log.LogLevel = log.LevelInfo
|
||||||
|
case "warning":
|
||||||
|
log.LogLevel = log.LevelWarning
|
||||||
|
case "error":
|
||||||
|
log.LogLevel = log.LevelError
|
||||||
|
case "stack":
|
||||||
|
log.LogLevel = log.LevelStack
|
||||||
|
case "fatal":
|
||||||
|
log.LogLevel = log.LevelFatal
|
||||||
|
default:
|
||||||
|
return errors.New("unknown level: " + strlogLevel)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -344,18 +462,48 @@ func setLogPath(args interface{}) error {
|
|||||||
if args == "" {
|
if args == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
logPath = strings.TrimSpace(args.(string))
|
|
||||||
dir, err := os.Stat(logPath) //这个文件夹不存在
|
log.LogPath = strings.TrimSpace(args.(string))
|
||||||
|
dir, err := os.Stat(log.LogPath) //这个文件夹不存在
|
||||||
if err == nil && dir.IsDir() == false {
|
if err == nil && dir.IsDir() == false {
|
||||||
return errors.New("Not found dir " + logPath)
|
return errors.New("Not found dir " + log.LogPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = os.Mkdir(logPath, os.ModePerm)
|
err = os.Mkdir(log.LogPath, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Cannot create dir " + logPath)
|
return errors.New("Cannot create dir " + log.LogPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setLogSize(args interface{}) error {
|
||||||
|
if args == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logSize,ok := args.(int)
|
||||||
|
if ok == false{
|
||||||
|
return errors.New("param logsize is error")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.LogSize = int64(logSize)*1024*1024
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setLogChannelCapNum(args interface{}) error {
|
||||||
|
if args == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logChannelCap,ok := args.(int)
|
||||||
|
if ok == false{
|
||||||
|
return errors.New("param logsize is error")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.LogChannelCap = logChannelCap
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func KillProcess(processId int){
|
func KillProcess(processId int){
|
||||||
err := syscall.Kill(processId,syscall.Signal(10))
|
err := syscall.Kill(processId,SingleStop)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("kill processid %d is fail:%+v.\n",processId,err)
|
fmt.Printf("kill processid %d is fail:%+v.\n",processId,err)
|
||||||
}else{
|
}else{
|
||||||
@@ -19,3 +19,12 @@ func KillProcess(processId int){
|
|||||||
func GetBuildOSType() BuildOSType{
|
func GetBuildOSType() BuildOSType{
|
||||||
return Linux
|
return Linux
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RetireProcess(processId int){
|
||||||
|
err := syscall.Kill(processId,SignalRetire)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("retire processid %d is fail:%+v.\n",processId,err)
|
||||||
|
}else{
|
||||||
|
fmt.Printf("retire processid %d is successful.\n",processId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func KillProcess(processId int){
|
func KillProcess(processId int){
|
||||||
err := syscall.Kill(processId,syscall.Signal(10))
|
err := syscall.Kill(processId,SingleStop)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("kill processid %d is fail:%+v.\n",processId,err)
|
fmt.Printf("kill processid %d is fail:%+v.\n",processId,err)
|
||||||
}else{
|
}else{
|
||||||
@@ -19,3 +19,12 @@ func KillProcess(processId int){
|
|||||||
func GetBuildOSType() BuildOSType{
|
func GetBuildOSType() BuildOSType{
|
||||||
return Mac
|
return Mac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RetireProcess(processId int){
|
||||||
|
err := syscall.Kill(processId,SignalRetire)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("retire processid %d is fail:%+v.\n",processId,err)
|
||||||
|
}else{
|
||||||
|
fmt.Printf("retire processid %d is successful.\n",processId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,10 +2,28 @@
|
|||||||
|
|
||||||
package node
|
package node
|
||||||
|
|
||||||
func KillProcess(processId int){
|
import (
|
||||||
|
"os"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func KillProcess(processId int){
|
||||||
|
procss,err := os.FindProcess(processId)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("kill processid %d is fail:%+v.\n",processId,err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = procss.Kill()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("kill processid %d is fail:%+v.\n",processId,err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetBuildOSType() BuildOSType{
|
func GetBuildOSType() BuildOSType{
|
||||||
return Windows
|
return Windows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RetireProcess(processId int){
|
||||||
|
fmt.Printf("This command does not support Windows")
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package profiler
|
|||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -167,7 +167,7 @@ func DefaultReportFunction(name string,callNum int,costTime time.Duration,record
|
|||||||
elem = elem.Next()
|
elem = elem.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SRelease(strReport)
|
log.SInfo("report",strReport)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Report() {
|
func Report() {
|
||||||
@@ -193,9 +193,11 @@ func Report() {
|
|||||||
|
|
||||||
record = prof.record
|
record = prof.record
|
||||||
prof.record = list.New()
|
prof.record = list.New()
|
||||||
|
callNum := prof.callNum
|
||||||
|
totalCostTime := prof.totalCostTime
|
||||||
prof.stackLocker.RUnlock()
|
prof.stackLocker.RUnlock()
|
||||||
|
|
||||||
DefaultReportFunction(name,prof.callNum,prof.totalCostTime,record)
|
DefaultReportFunction(name,callNum,totalCostTime,record)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
146
rpc/callset.go
Normal file
146
rpc/callset.go
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
package rpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CallSet struct {
|
||||||
|
pendingLock sync.RWMutex
|
||||||
|
startSeq uint64
|
||||||
|
pending map[uint64]*Call
|
||||||
|
callRpcTimeout time.Duration
|
||||||
|
maxCheckCallRpcCount int
|
||||||
|
|
||||||
|
callTimerHeap CallTimerHeap
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func (cs *CallSet) Init(){
|
||||||
|
cs.pendingLock.Lock()
|
||||||
|
cs.callTimerHeap.Init()
|
||||||
|
cs.pending = make(map[uint64]*Call,4096)
|
||||||
|
|
||||||
|
cs.maxCheckCallRpcCount = DefaultMaxCheckCallRpcCount
|
||||||
|
cs.callRpcTimeout = DefaultRpcTimeout
|
||||||
|
|
||||||
|
go cs.checkRpcCallTimeout()
|
||||||
|
cs.pendingLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc *CallSet) makeCallFail(call *Call) {
|
||||||
|
if call.callback != nil && call.callback.IsValid() {
|
||||||
|
call.rpcHandler.PushRpcResponse(call)
|
||||||
|
} else {
|
||||||
|
call.done <- call
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc *CallSet) checkRpcCallTimeout() {
|
||||||
|
for{
|
||||||
|
time.Sleep(DefaultCheckRpcCallTimeoutInterval)
|
||||||
|
for i := 0; i < bc.maxCheckCallRpcCount; i++ {
|
||||||
|
bc.pendingLock.Lock()
|
||||||
|
|
||||||
|
callSeq := bc.callTimerHeap.PopTimeout()
|
||||||
|
if callSeq == 0 {
|
||||||
|
bc.pendingLock.Unlock()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
pCall := bc.pending[callSeq]
|
||||||
|
if pCall == nil {
|
||||||
|
bc.pendingLock.Unlock()
|
||||||
|
log.Error("call seq is not find",log.Uint64("seq", callSeq))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(bc.pending,callSeq)
|
||||||
|
strTimeout := strconv.FormatInt(int64(pCall.TimeOut.Seconds()), 10)
|
||||||
|
pCall.Err = errors.New("RPC call takes more than " + strTimeout + " seconds,method is "+pCall.ServiceMethod)
|
||||||
|
log.Error("call timeout",log.String("error",pCall.Err.Error()))
|
||||||
|
bc.makeCallFail(pCall)
|
||||||
|
bc.pendingLock.Unlock()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc *CallSet) AddPending(call *Call) {
|
||||||
|
bc.pendingLock.Lock()
|
||||||
|
|
||||||
|
if call.Seq == 0 {
|
||||||
|
bc.pendingLock.Unlock()
|
||||||
|
log.Stack("call is error.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bc.pending[call.Seq] = call
|
||||||
|
bc.callTimerHeap.AddTimer(call.Seq,call.TimeOut)
|
||||||
|
|
||||||
|
bc.pendingLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc *CallSet) RemovePending(seq uint64) *Call {
|
||||||
|
if seq == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
bc.pendingLock.Lock()
|
||||||
|
call := bc.removePending(seq)
|
||||||
|
bc.pendingLock.Unlock()
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc *CallSet) removePending(seq uint64) *Call {
|
||||||
|
v, ok := bc.pending[seq]
|
||||||
|
if ok == false {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bc.callTimerHeap.Cancel(seq)
|
||||||
|
delete(bc.pending, seq)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc *CallSet) FindPending(seq uint64) (pCall *Call) {
|
||||||
|
if seq == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bc.pendingLock.Lock()
|
||||||
|
pCall = bc.pending[seq]
|
||||||
|
bc.pendingLock.Unlock()
|
||||||
|
|
||||||
|
return pCall
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc *CallSet) cleanPending(){
|
||||||
|
bc.pendingLock.Lock()
|
||||||
|
for {
|
||||||
|
callSeq := bc.callTimerHeap.PopFirst()
|
||||||
|
if callSeq == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
pCall := bc.pending[callSeq]
|
||||||
|
if pCall == nil {
|
||||||
|
log.Error("call Seq is not find",log.Uint64("seq",callSeq))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(bc.pending,callSeq)
|
||||||
|
pCall.Err = errors.New("nodeid is disconnect ")
|
||||||
|
bc.makeCallFail(pCall)
|
||||||
|
}
|
||||||
|
|
||||||
|
bc.pendingLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc *CallSet) generateSeq() uint64 {
|
||||||
|
return atomic.AddUint64(&bc.startSeq, 1)
|
||||||
|
}
|
||||||
375
rpc/client.go
375
rpc/client.go
@@ -1,49 +1,56 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/duanhf2012/origin/network"
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const(
|
||||||
|
DefaultRpcConnNum = 1
|
||||||
|
DefaultRpcLenMsgLen = 4
|
||||||
|
DefaultRpcMinMsgLen = 2
|
||||||
|
DefaultMaxCheckCallRpcCount = 1000
|
||||||
|
DefaultMaxPendingWriteNum = 1000000
|
||||||
|
|
||||||
|
DefaultConnectInterval = 2*time.Second
|
||||||
|
DefaultCheckRpcCallTimeoutInterval = 1*time.Second
|
||||||
|
DefaultRpcTimeout = 15*time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
const MaxCheckCallRpcCount = 1000
|
|
||||||
const MaxPendingWriteNum = 200000
|
|
||||||
const ConnectInterval = 2*time.Second
|
|
||||||
const RpcConnNum = 1
|
|
||||||
const RpcLenMsgLen = 4
|
|
||||||
const RpcMinMsgLen = 2
|
|
||||||
const CheckRpcCallTimeoutInterval = 5*time.Second
|
|
||||||
const DefaultRpcTimeout = 15*time.Second
|
|
||||||
var clientSeq uint32
|
var clientSeq uint32
|
||||||
|
|
||||||
|
type IWriter interface {
|
||||||
|
WriteMsg (nodeId string,args ...[]byte) error
|
||||||
|
IsConnected() bool
|
||||||
|
}
|
||||||
|
|
||||||
type IRealClient interface {
|
type IRealClient interface {
|
||||||
SetConn(conn *network.TCPConn)
|
SetConn(conn *network.TCPConn)
|
||||||
Close(waitDone bool)
|
Close(waitDone bool)
|
||||||
|
|
||||||
AsyncCall(rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) error
|
AsyncCall(NodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error)
|
||||||
Go(rpcHandler IRpcHandler, noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call
|
Go(NodeId string,timeout time.Duration,rpcHandler IRpcHandler, noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call
|
||||||
RawGo(rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call
|
RawGo(NodeId string,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call
|
||||||
IsConnected() bool
|
IsConnected() bool
|
||||||
|
|
||||||
Run()
|
Run()
|
||||||
OnClose()
|
OnClose()
|
||||||
|
|
||||||
|
Bind(server IServer)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
clientId uint32
|
|
||||||
nodeId int
|
|
||||||
pendingLock sync.RWMutex
|
|
||||||
startSeq uint64
|
|
||||||
pending map[uint64]*list.Element
|
|
||||||
pendingTimer *list.List
|
|
||||||
callRpcTimeout time.Duration
|
|
||||||
maxCheckCallRpcCount int
|
|
||||||
|
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
clientId uint32
|
||||||
|
targetNodeId string
|
||||||
|
compressBytesLen int
|
||||||
|
|
||||||
|
*CallSet
|
||||||
IRealClient
|
IRealClient
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,116 +60,218 @@ func (client *Client) NewClientAgent(conn *network.TCPConn) network.Agent {
|
|||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *Client) makeCallFail(call *Call) {
|
func (client *Client) GetTargetNodeId() string {
|
||||||
bc.removePending(call.Seq)
|
return client.targetNodeId
|
||||||
if call.callback != nil && call.callback.IsValid() {
|
|
||||||
call.rpcHandler.PushRpcResponse(call)
|
|
||||||
} else {
|
|
||||||
call.done <- call
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bc *Client) checkRpcCallTimeout() {
|
|
||||||
for{
|
|
||||||
time.Sleep(CheckRpcCallTimeoutInterval)
|
|
||||||
now := time.Now()
|
|
||||||
|
|
||||||
for i := 0; i < bc.maxCheckCallRpcCount; i++ {
|
|
||||||
bc.pendingLock.Lock()
|
|
||||||
if bc.pendingTimer == nil {
|
|
||||||
bc.pendingLock.Unlock()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
pElem := bc.pendingTimer.Front()
|
|
||||||
if pElem == nil {
|
|
||||||
bc.pendingLock.Unlock()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
pCall := pElem.Value.(*Call)
|
|
||||||
if now.Sub(pCall.callTime) > bc.callRpcTimeout {
|
|
||||||
strTimeout := strconv.FormatInt(int64(bc.callRpcTimeout/time.Second), 10)
|
|
||||||
pCall.Err = errors.New("RPC call takes more than " + strTimeout + " seconds")
|
|
||||||
bc.makeCallFail(pCall)
|
|
||||||
bc.pendingLock.Unlock()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
bc.pendingLock.Unlock()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *Client) InitPending() {
|
|
||||||
client.pendingLock.Lock()
|
|
||||||
if client.pending != nil {
|
|
||||||
for _, v := range client.pending {
|
|
||||||
v.Value.(*Call).Err = errors.New("node is disconnect")
|
|
||||||
v.Value.(*Call).done <- v.Value.(*Call)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.pending = make(map[uint64]*list.Element, 4096)
|
|
||||||
client.pendingTimer = list.New()
|
|
||||||
client.pendingLock.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func (bc *Client) AddPending(call *Call) {
|
|
||||||
bc.pendingLock.Lock()
|
|
||||||
call.callTime = time.Now()
|
|
||||||
elemTimer := bc.pendingTimer.PushBack(call)
|
|
||||||
bc.pending[call.Seq] = elemTimer //如果下面发送失败,将会一一直存在这里
|
|
||||||
bc.pendingLock.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bc *Client) RemovePending(seq uint64) *Call {
|
|
||||||
if seq == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
bc.pendingLock.Lock()
|
|
||||||
call := bc.removePending(seq)
|
|
||||||
bc.pendingLock.Unlock()
|
|
||||||
return call
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bc *Client) removePending(seq uint64) *Call {
|
|
||||||
v, ok := bc.pending[seq]
|
|
||||||
if ok == false {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
call := v.Value.(*Call)
|
|
||||||
bc.pendingTimer.Remove(v)
|
|
||||||
delete(bc.pending, seq)
|
|
||||||
return call
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bc *Client) FindPending(seq uint64) *Call {
|
|
||||||
if seq == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
bc.pendingLock.Lock()
|
|
||||||
v, ok := bc.pending[seq]
|
|
||||||
if ok == false {
|
|
||||||
bc.pendingLock.Unlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pCall := v.Value.(*Call)
|
|
||||||
bc.pendingLock.Unlock()
|
|
||||||
|
|
||||||
return pCall
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bc *Client) generateSeq() uint64 {
|
|
||||||
return atomic.AddUint64(&bc.startSeq, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *Client) GetNodeId() int {
|
|
||||||
return client.nodeId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) GetClientId() uint32 {
|
func (client *Client) GetClientId() uint32 {
|
||||||
return client.clientId
|
return client.clientId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (client *Client) processRpcResponse(responseData []byte) error{
|
||||||
|
bCompress := (responseData[0]>>7) > 0
|
||||||
|
processor := GetProcessor(responseData[0]&0x7f)
|
||||||
|
if processor == nil {
|
||||||
|
//rc.conn.ReleaseReadMsg(responseData)
|
||||||
|
err:= errors.New(fmt.Sprintf("cannot find process %d",responseData[0]&0x7f))
|
||||||
|
log.Error(err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//1.解析head
|
||||||
|
response := RpcResponse{}
|
||||||
|
response.RpcResponseData = processor.MakeRpcResponse(0, "", nil)
|
||||||
|
|
||||||
|
//解压缩
|
||||||
|
byteData := responseData[1:]
|
||||||
|
var compressBuff []byte
|
||||||
|
|
||||||
|
if bCompress == true {
|
||||||
|
var unCompressErr error
|
||||||
|
compressBuff,unCompressErr = compressor.UncompressBlock(byteData)
|
||||||
|
if unCompressErr!= nil {
|
||||||
|
//rc.conn.ReleaseReadMsg(responseData)
|
||||||
|
err := fmt.Errorf("uncompressBlock failed,err :%s",unCompressErr.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
byteData = compressBuff
|
||||||
|
}
|
||||||
|
|
||||||
|
err := processor.Unmarshal(byteData, response.RpcResponseData)
|
||||||
|
if cap(compressBuff) > 0 {
|
||||||
|
compressor.UnCompressBufferCollection(compressBuff)
|
||||||
|
}
|
||||||
|
|
||||||
|
//rc.conn.ReleaseReadMsg(bytes)
|
||||||
|
if err != nil {
|
||||||
|
processor.ReleaseRpcResponse(response.RpcResponseData)
|
||||||
|
log.Error("rpcClient Unmarshal head error",log.ErrorAttr("error",err))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
v := client.RemovePending(response.RpcResponseData.GetSeq())
|
||||||
|
if v == nil {
|
||||||
|
log.Error("rpcClient cannot find seq",log.Uint64("seq",response.RpcResponseData.GetSeq()))
|
||||||
|
} else {
|
||||||
|
v.Err = nil
|
||||||
|
if len(response.RpcResponseData.GetReply()) > 0 {
|
||||||
|
err = processor.Unmarshal(response.RpcResponseData.GetReply(), v.Reply)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("rpcClient Unmarshal body failed",log.ErrorAttr("error",err))
|
||||||
|
v.Err = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.RpcResponseData.GetErr() != nil {
|
||||||
|
v.Err = response.RpcResponseData.GetErr()
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.callback != nil && v.callback.IsValid() {
|
||||||
|
v.rpcHandler.PushRpcResponse(v)
|
||||||
|
} else {
|
||||||
|
v.done <- v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processor.ReleaseRpcResponse(response.RpcResponseData)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//func (rc *Client) Go(timeout time.Duration,rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
|
||||||
|
// _, processor := GetProcessorType(args)
|
||||||
|
// InParam, err := processor.Marshal(args)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Error("Marshal is fail",log.ErrorAttr("error",err))
|
||||||
|
// call := MakeCall()
|
||||||
|
// call.DoError(err)
|
||||||
|
// return call
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return rc.RawGo(timeout,rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply)
|
||||||
|
//}
|
||||||
|
|
||||||
|
func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call {
|
||||||
|
call := MakeCall()
|
||||||
|
call.ServiceMethod = serviceMethod
|
||||||
|
call.Reply = reply
|
||||||
|
call.Seq = rc.generateSeq()
|
||||||
|
call.TimeOut = timeout
|
||||||
|
|
||||||
|
request := MakeRpcRequest(processor, call.Seq, rpcMethodId, serviceMethod, noReply, rawArgs)
|
||||||
|
bytes, err := processor.Marshal(request.RpcRequestData)
|
||||||
|
ReleaseRpcRequest(request)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
call.Seq = 0
|
||||||
|
log.Error("marshal is fail",log.String("error",err.Error()))
|
||||||
|
call.DoError(err)
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
|
||||||
|
if w == nil || w.IsConnected()==false {
|
||||||
|
call.Seq = 0
|
||||||
|
sErr := errors.New(serviceMethod + " was called failed,rpc client is disconnect")
|
||||||
|
log.Error("conn is disconnect",log.String("error",sErr.Error()))
|
||||||
|
call.DoError(sErr)
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
|
||||||
|
var compressBuff[]byte
|
||||||
|
bCompress := uint8(0)
|
||||||
|
if rc.compressBytesLen > 0 && len(bytes) >= rc.compressBytesLen {
|
||||||
|
var cErr error
|
||||||
|
compressBuff,cErr = compressor.CompressBlock(bytes)
|
||||||
|
if cErr != nil {
|
||||||
|
call.Seq = 0
|
||||||
|
log.Error("compress fail",log.String("error",cErr.Error()))
|
||||||
|
call.DoError(cErr)
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
if len(compressBuff) < len(bytes) {
|
||||||
|
bytes = compressBuff
|
||||||
|
bCompress = 1<<7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if noReply == false {
|
||||||
|
rc.AddPending(call)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = w.WriteMsg(nodeId,[]byte{uint8(processor.GetProcessorType())|bCompress}, bytes)
|
||||||
|
if cap(compressBuff) >0 {
|
||||||
|
compressor.CompressBufferCollection(compressBuff)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
rc.RemovePending(call.Seq)
|
||||||
|
log.Error("WiteMsg is fail",log.ErrorAttr("error",err))
|
||||||
|
call.Seq = 0
|
||||||
|
call.DoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *Client) asyncCall(nodeId string,w IWriter,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) {
|
||||||
|
processorType, processor := GetProcessorType(args)
|
||||||
|
InParam, herr := processor.Marshal(args)
|
||||||
|
if herr != nil {
|
||||||
|
return emptyCancelRpc,herr
|
||||||
|
}
|
||||||
|
|
||||||
|
seq := rc.generateSeq()
|
||||||
|
request := MakeRpcRequest(processor, seq, 0, serviceMethod, false, InParam)
|
||||||
|
bytes, err := processor.Marshal(request.RpcRequestData)
|
||||||
|
ReleaseRpcRequest(request)
|
||||||
|
if err != nil {
|
||||||
|
return emptyCancelRpc,err
|
||||||
|
}
|
||||||
|
|
||||||
|
if w == nil || w.IsConnected()==false {
|
||||||
|
return emptyCancelRpc,errors.New("Rpc server is disconnect,call " + serviceMethod)
|
||||||
|
}
|
||||||
|
|
||||||
|
var compressBuff[]byte
|
||||||
|
bCompress := uint8(0)
|
||||||
|
if rc.compressBytesLen>0 &&len(bytes) >= rc.compressBytesLen {
|
||||||
|
var cErr error
|
||||||
|
compressBuff,cErr = compressor.CompressBlock(bytes)
|
||||||
|
if cErr != nil {
|
||||||
|
return emptyCancelRpc,cErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(compressBuff) < len(bytes) {
|
||||||
|
bytes = compressBuff
|
||||||
|
bCompress = 1<<7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call := MakeCall()
|
||||||
|
call.Reply = replyParam
|
||||||
|
call.callback = &callback
|
||||||
|
call.rpcHandler = rpcHandler
|
||||||
|
call.ServiceMethod = serviceMethod
|
||||||
|
call.Seq = seq
|
||||||
|
call.TimeOut = timeout
|
||||||
|
rc.AddPending(call)
|
||||||
|
|
||||||
|
err = w.WriteMsg(nodeId,[]byte{uint8(processorType)|bCompress}, bytes)
|
||||||
|
if cap(compressBuff) >0 {
|
||||||
|
compressor.CompressBufferCollection(compressBuff)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
rc.RemovePending(call.Seq)
|
||||||
|
ReleaseCall(call)
|
||||||
|
return emptyCancelRpc,err
|
||||||
|
}
|
||||||
|
|
||||||
|
if cancelable {
|
||||||
|
rpcCancel := RpcCancel{CallSeq:seq,Cli: rc}
|
||||||
|
return rpcCancel.CancelRpc,nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return emptyCancelRpc,nil
|
||||||
|
}
|
||||||
102
rpc/compressor.go
Normal file
102
rpc/compressor.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package rpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/util/bytespool"
|
||||||
|
"github.com/pierrec/lz4/v4"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var memPool bytespool.IBytesMempool = bytespool.NewMemAreaPool()
|
||||||
|
|
||||||
|
type ICompressor interface {
|
||||||
|
CompressBlock(src []byte) ([]byte, error) //dst如果有预申请使用dst内存,传入nil时内部申请
|
||||||
|
UncompressBlock(src []byte) ([]byte, error) //dst如果有预申请使用dst内存,传入nil时内部申请
|
||||||
|
|
||||||
|
CompressBufferCollection(buffer []byte) //压缩的Buffer内存回收
|
||||||
|
UnCompressBufferCollection(buffer []byte) //解压缩的Buffer内存回收
|
||||||
|
}
|
||||||
|
|
||||||
|
var compressor ICompressor
|
||||||
|
func init(){
|
||||||
|
SetCompressor(&Lz4Compressor{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetCompressor(cp ICompressor){
|
||||||
|
compressor = cp
|
||||||
|
}
|
||||||
|
|
||||||
|
type Lz4Compressor struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lc *Lz4Compressor) CompressBlock(src []byte) (dest []byte, err error) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
l := runtime.Stack(buf, false)
|
||||||
|
errString := fmt.Sprint(r)
|
||||||
|
err = errors.New("core dump info[" + errString + "]\n" + string(buf[:l]))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var c lz4.Compressor
|
||||||
|
var cnt int
|
||||||
|
dest = memPool.MakeBytes(lz4.CompressBlockBound(len(src))+1)
|
||||||
|
cnt, err = c.CompressBlock(src, dest[1:])
|
||||||
|
if err != nil {
|
||||||
|
memPool.ReleaseBytes(dest)
|
||||||
|
return nil,err
|
||||||
|
}
|
||||||
|
|
||||||
|
ratio := len(src) / cnt
|
||||||
|
if len(src) % cnt > 0 {
|
||||||
|
ratio += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ratio > 255 {
|
||||||
|
memPool.ReleaseBytes(dest)
|
||||||
|
return nil,fmt.Errorf("Impermissible errors")
|
||||||
|
}
|
||||||
|
|
||||||
|
dest[0] = uint8(ratio)
|
||||||
|
dest = dest[:cnt+1]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lc *Lz4Compressor) UncompressBlock(src []byte) (dest []byte, err error) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
l := runtime.Stack(buf, false)
|
||||||
|
errString := fmt.Sprint(r)
|
||||||
|
err = errors.New("core dump info[" + errString + "]\n" + string(buf[:l]))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
radio := uint8(src[0])
|
||||||
|
if radio == 0 {
|
||||||
|
return nil,fmt.Errorf("Impermissible errors")
|
||||||
|
}
|
||||||
|
|
||||||
|
dest = memPool.MakeBytes(len(src)*int(radio))
|
||||||
|
cnt, err := lz4.UncompressBlock(src[1:], dest)
|
||||||
|
if err != nil {
|
||||||
|
memPool.ReleaseBytes(dest)
|
||||||
|
return nil,err
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest[:cnt],nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lc *Lz4Compressor) compressBlockBound(n int) int{
|
||||||
|
return lz4.CompressBlockBound(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lc *Lz4Compressor) CompressBufferCollection(buffer []byte){
|
||||||
|
memPool.ReleaseBytes(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lc *Lz4Compressor) UnCompressBufferCollection(buffer []byte) {
|
||||||
|
memPool.ReleaseBytes(buffer)
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,29 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
package rpc;
|
|
||||||
option go_package = "./rpc";
|
|
||||||
|
|
||||||
message NodeInfo{
|
|
||||||
int32 NodeId = 1;
|
|
||||||
string NodeName = 2;
|
|
||||||
string ListenAddr = 3;
|
|
||||||
uint32 MaxRpcParamLen = 4;
|
|
||||||
bool Private = 5;
|
|
||||||
repeated string PublicServiceList = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Client->Master
|
|
||||||
message ServiceDiscoverReq{
|
|
||||||
NodeInfo nodeInfo = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Master->Client
|
|
||||||
message SubscribeDiscoverNotify{
|
|
||||||
int32 MasterNodeId = 1;
|
|
||||||
bool IsFull = 2;
|
|
||||||
int32 DelNodeId = 3;
|
|
||||||
repeated NodeInfo nodeInfo = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Master->Client
|
|
||||||
message Empty{
|
|
||||||
}
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
package rpc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/duanhf2012/origin/util/sync"
|
|
||||||
"github.com/gogo/protobuf/proto"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type GoGoPBProcessor struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
var rpcGoGoPbResponseDataPool =sync.NewPool(make(chan interface{},10240), func()interface{}{
|
|
||||||
return &GoGoPBRpcResponseData{}
|
|
||||||
})
|
|
||||||
|
|
||||||
var rpcGoGoPbRequestDataPool =sync.NewPool(make(chan interface{},10240), func()interface{}{
|
|
||||||
return &GoGoPBRpcRequestData{}
|
|
||||||
})
|
|
||||||
|
|
||||||
func (slf *GoGoPBRpcRequestData) MakeRequest(seq uint64,rpcMethodId uint32,serviceMethod string,noReply bool,inParam []byte) *GoGoPBRpcRequestData{
|
|
||||||
slf.Seq = seq
|
|
||||||
slf.RpcMethodId = rpcMethodId
|
|
||||||
slf.ServiceMethod = serviceMethod
|
|
||||||
slf.NoReply = noReply
|
|
||||||
slf.InParam = inParam
|
|
||||||
|
|
||||||
return slf
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func (slf *GoGoPBRpcResponseData) MakeRespone(seq uint64,err RpcError,reply []byte) *GoGoPBRpcResponseData{
|
|
||||||
slf.Seq = seq
|
|
||||||
slf.Error = err.Error()
|
|
||||||
slf.Reply = reply
|
|
||||||
|
|
||||||
return slf
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *GoGoPBProcessor) Marshal(v interface{}) ([]byte, error){
|
|
||||||
return proto.Marshal(v.(proto.Message))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *GoGoPBProcessor) Unmarshal(data []byte, msg interface{}) error{
|
|
||||||
protoMsg,ok := msg.(proto.Message)
|
|
||||||
if ok == false {
|
|
||||||
return fmt.Errorf("%+v is not of proto.Message type",msg)
|
|
||||||
}
|
|
||||||
return proto.Unmarshal(data, protoMsg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *GoGoPBProcessor) MakeRpcRequest(seq uint64,rpcMethodId uint32,serviceMethod string,noReply bool,inParam []byte) IRpcRequestData{
|
|
||||||
pGogoPbRpcRequestData := rpcGoGoPbRequestDataPool.Get().(*GoGoPBRpcRequestData)
|
|
||||||
pGogoPbRpcRequestData.MakeRequest(seq,rpcMethodId,serviceMethod,noReply,inParam)
|
|
||||||
return pGogoPbRpcRequestData
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *GoGoPBProcessor) MakeRpcResponse(seq uint64,err RpcError,reply []byte) IRpcResponseData {
|
|
||||||
pGoGoPBRpcResponseData := rpcGoGoPbResponseDataPool.Get().(*GoGoPBRpcResponseData)
|
|
||||||
pGoGoPBRpcResponseData.MakeRespone(seq,err,reply)
|
|
||||||
return pGoGoPBRpcResponseData
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *GoGoPBProcessor) ReleaseRpcRequest(rpcRequestData IRpcRequestData){
|
|
||||||
rpcGoGoPbRequestDataPool.Put(rpcRequestData)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *GoGoPBProcessor) ReleaseRpcResponse(rpcResponseData IRpcResponseData){
|
|
||||||
rpcGoGoPbResponseDataPool.Put(rpcResponseData)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *GoGoPBProcessor) IsParse(param interface{}) bool {
|
|
||||||
_,ok := param.(proto.Message)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *GoGoPBProcessor) GetProcessorType() RpcProcessorType{
|
|
||||||
return RpcProcessorGoGoPB
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *GoGoPBProcessor) Clone(src interface{}) (interface{},error){
|
|
||||||
srcMsg,ok := src.(proto.Message)
|
|
||||||
if ok == false {
|
|
||||||
return nil,fmt.Errorf("param is not of proto.message type")
|
|
||||||
}
|
|
||||||
|
|
||||||
return proto.Clone(srcMsg),nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *GoGoPBRpcRequestData) IsNoReply() bool{
|
|
||||||
return slf.GetNoReply()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *GoGoPBRpcResponseData) GetErr() *RpcError {
|
|
||||||
if slf.GetError() == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := RpcError(slf.GetError())
|
|
||||||
return &err
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,769 +0,0 @@
|
|||||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
|
||||||
// source: gogorpc.proto
|
|
||||||
|
|
||||||
package rpc
|
|
||||||
|
|
||||||
import (
|
|
||||||
fmt "fmt"
|
|
||||||
proto "github.com/gogo/protobuf/proto"
|
|
||||||
io "io"
|
|
||||||
math "math"
|
|
||||||
math_bits "math/bits"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ = proto.Marshal
|
|
||||||
var _ = fmt.Errorf
|
|
||||||
var _ = math.Inf
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the proto package it is being compiled against.
|
|
||||||
// A compilation error at this line likely means your copy of the
|
|
||||||
// proto package needs to be updated.
|
|
||||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
|
||||||
|
|
||||||
type GoGoPBRpcRequestData struct {
|
|
||||||
Seq uint64 `protobuf:"varint,1,opt,name=Seq,proto3" json:"Seq,omitempty"`
|
|
||||||
RpcMethodId uint32 `protobuf:"varint,2,opt,name=RpcMethodId,proto3" json:"RpcMethodId,omitempty"`
|
|
||||||
ServiceMethod string `protobuf:"bytes,3,opt,name=ServiceMethod,proto3" json:"ServiceMethod,omitempty"`
|
|
||||||
NoReply bool `protobuf:"varint,4,opt,name=NoReply,proto3" json:"NoReply,omitempty"`
|
|
||||||
InParam []byte `protobuf:"bytes,5,opt,name=InParam,proto3" json:"InParam,omitempty"`
|
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
XXX_sizecache int32 `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcRequestData) Reset() { *m = GoGoPBRpcRequestData{} }
|
|
||||||
func (m *GoGoPBRpcRequestData) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*GoGoPBRpcRequestData) ProtoMessage() {}
|
|
||||||
func (*GoGoPBRpcRequestData) Descriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_d0e25d3af112ec8f, []int{0}
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcRequestData) XXX_Unmarshal(b []byte) error {
|
|
||||||
return m.Unmarshal(b)
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcRequestData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
||||||
if deterministic {
|
|
||||||
return xxx_messageInfo_GoGoPBRpcRequestData.Marshal(b, m, deterministic)
|
|
||||||
} else {
|
|
||||||
b = b[:cap(b)]
|
|
||||||
n, err := m.MarshalToSizedBuffer(b)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return b[:n], nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcRequestData) XXX_Merge(src proto.Message) {
|
|
||||||
xxx_messageInfo_GoGoPBRpcRequestData.Merge(m, src)
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcRequestData) XXX_Size() int {
|
|
||||||
return m.Size()
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcRequestData) XXX_DiscardUnknown() {
|
|
||||||
xxx_messageInfo_GoGoPBRpcRequestData.DiscardUnknown(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
var xxx_messageInfo_GoGoPBRpcRequestData proto.InternalMessageInfo
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcRequestData) GetSeq() uint64 {
|
|
||||||
if m != nil {
|
|
||||||
return m.Seq
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcRequestData) GetRpcMethodId() uint32 {
|
|
||||||
if m != nil {
|
|
||||||
return m.RpcMethodId
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcRequestData) GetServiceMethod() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.ServiceMethod
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcRequestData) GetNoReply() bool {
|
|
||||||
if m != nil {
|
|
||||||
return m.NoReply
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcRequestData) GetInParam() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.InParam
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type GoGoPBRpcResponseData struct {
|
|
||||||
Seq uint64 `protobuf:"varint,1,opt,name=Seq,proto3" json:"Seq,omitempty"`
|
|
||||||
Error string `protobuf:"bytes,2,opt,name=Error,proto3" json:"Error,omitempty"`
|
|
||||||
Reply []byte `protobuf:"bytes,3,opt,name=Reply,proto3" json:"Reply,omitempty"`
|
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
XXX_sizecache int32 `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcResponseData) Reset() { *m = GoGoPBRpcResponseData{} }
|
|
||||||
func (m *GoGoPBRpcResponseData) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*GoGoPBRpcResponseData) ProtoMessage() {}
|
|
||||||
func (*GoGoPBRpcResponseData) Descriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_d0e25d3af112ec8f, []int{1}
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcResponseData) XXX_Unmarshal(b []byte) error {
|
|
||||||
return m.Unmarshal(b)
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcResponseData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
||||||
if deterministic {
|
|
||||||
return xxx_messageInfo_GoGoPBRpcResponseData.Marshal(b, m, deterministic)
|
|
||||||
} else {
|
|
||||||
b = b[:cap(b)]
|
|
||||||
n, err := m.MarshalToSizedBuffer(b)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return b[:n], nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcResponseData) XXX_Merge(src proto.Message) {
|
|
||||||
xxx_messageInfo_GoGoPBRpcResponseData.Merge(m, src)
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcResponseData) XXX_Size() int {
|
|
||||||
return m.Size()
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcResponseData) XXX_DiscardUnknown() {
|
|
||||||
xxx_messageInfo_GoGoPBRpcResponseData.DiscardUnknown(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
var xxx_messageInfo_GoGoPBRpcResponseData proto.InternalMessageInfo
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcResponseData) GetSeq() uint64 {
|
|
||||||
if m != nil {
|
|
||||||
return m.Seq
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcResponseData) GetError() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.Error
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcResponseData) GetReply() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.Reply
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterType((*GoGoPBRpcRequestData)(nil), "rpc.GoGoPBRpcRequestData")
|
|
||||||
proto.RegisterType((*GoGoPBRpcResponseData)(nil), "rpc.GoGoPBRpcResponseData")
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { proto.RegisterFile("gogorpc.proto", fileDescriptor_d0e25d3af112ec8f) }
|
|
||||||
|
|
||||||
var fileDescriptor_d0e25d3af112ec8f = []byte{
|
|
||||||
// 233 bytes of a gzipped FileDescriptorProto
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4d, 0xcf, 0x4f, 0xcf,
|
|
||||||
0x2f, 0x2a, 0x48, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2e, 0x2a, 0x48, 0x56, 0x5a,
|
|
||||||
0xc2, 0xc8, 0x25, 0xe2, 0x9e, 0xef, 0x9e, 0x1f, 0xe0, 0x14, 0x54, 0x90, 0x1c, 0x94, 0x5a, 0x58,
|
|
||||||
0x9a, 0x5a, 0x5c, 0xe2, 0x92, 0x58, 0x92, 0x28, 0x24, 0xc0, 0xc5, 0x1c, 0x9c, 0x5a, 0x28, 0xc1,
|
|
||||||
0xa8, 0xc0, 0xa8, 0xc1, 0x12, 0x04, 0x62, 0x0a, 0x29, 0x70, 0x71, 0x07, 0x15, 0x24, 0xfb, 0xa6,
|
|
||||||
0x96, 0x64, 0xe4, 0xa7, 0x78, 0xa6, 0x48, 0x30, 0x29, 0x30, 0x6a, 0xf0, 0x06, 0x21, 0x0b, 0x09,
|
|
||||||
0xa9, 0x70, 0xf1, 0x06, 0xa7, 0x16, 0x95, 0x65, 0x26, 0xa7, 0x42, 0x84, 0x24, 0x98, 0x15, 0x18,
|
|
||||||
0x35, 0x38, 0x83, 0x50, 0x05, 0x85, 0x24, 0xb8, 0xd8, 0xfd, 0xf2, 0x83, 0x52, 0x0b, 0x72, 0x2a,
|
|
||||||
0x25, 0x58, 0x14, 0x18, 0x35, 0x38, 0x82, 0x60, 0x5c, 0x90, 0x8c, 0x67, 0x5e, 0x40, 0x62, 0x51,
|
|
||||||
0x62, 0xae, 0x04, 0xab, 0x02, 0xa3, 0x06, 0x4f, 0x10, 0x8c, 0xab, 0x14, 0xca, 0x25, 0x8a, 0xe4,
|
|
||||||
0xca, 0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, 0x1c, 0xce, 0x14, 0xe1, 0x62, 0x75, 0x2d, 0x2a, 0xca,
|
|
||||||
0x2f, 0x02, 0x3b, 0x90, 0x33, 0x08, 0xc2, 0x01, 0x89, 0x42, 0xac, 0x64, 0x06, 0x1b, 0x0c, 0xe1,
|
|
||||||
0x38, 0x09, 0x9f, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x51,
|
|
||||||
0xac, 0x7a, 0xfa, 0x45, 0x05, 0xc9, 0x49, 0x6c, 0xe0, 0xe0, 0x31, 0x06, 0x04, 0x00, 0x00, 0xff,
|
|
||||||
0xff, 0x26, 0xcf, 0x31, 0x39, 0x2f, 0x01, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcRequestData) Marshal() (dAtA []byte, err error) {
|
|
||||||
size := m.Size()
|
|
||||||
dAtA = make([]byte, size)
|
|
||||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return dAtA[:n], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcRequestData) MarshalTo(dAtA []byte) (int, error) {
|
|
||||||
size := m.Size()
|
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcRequestData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|
||||||
i := len(dAtA)
|
|
||||||
_ = i
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
if m.XXX_unrecognized != nil {
|
|
||||||
i -= len(m.XXX_unrecognized)
|
|
||||||
copy(dAtA[i:], m.XXX_unrecognized)
|
|
||||||
}
|
|
||||||
if len(m.InParam) > 0 {
|
|
||||||
i -= len(m.InParam)
|
|
||||||
copy(dAtA[i:], m.InParam)
|
|
||||||
i = encodeVarintGogorpc(dAtA, i, uint64(len(m.InParam)))
|
|
||||||
i--
|
|
||||||
dAtA[i] = 0x2a
|
|
||||||
}
|
|
||||||
if m.NoReply {
|
|
||||||
i--
|
|
||||||
if m.NoReply {
|
|
||||||
dAtA[i] = 1
|
|
||||||
} else {
|
|
||||||
dAtA[i] = 0
|
|
||||||
}
|
|
||||||
i--
|
|
||||||
dAtA[i] = 0x20
|
|
||||||
}
|
|
||||||
if len(m.ServiceMethod) > 0 {
|
|
||||||
i -= len(m.ServiceMethod)
|
|
||||||
copy(dAtA[i:], m.ServiceMethod)
|
|
||||||
i = encodeVarintGogorpc(dAtA, i, uint64(len(m.ServiceMethod)))
|
|
||||||
i--
|
|
||||||
dAtA[i] = 0x1a
|
|
||||||
}
|
|
||||||
if m.RpcMethodId != 0 {
|
|
||||||
i = encodeVarintGogorpc(dAtA, i, uint64(m.RpcMethodId))
|
|
||||||
i--
|
|
||||||
dAtA[i] = 0x10
|
|
||||||
}
|
|
||||||
if m.Seq != 0 {
|
|
||||||
i = encodeVarintGogorpc(dAtA, i, uint64(m.Seq))
|
|
||||||
i--
|
|
||||||
dAtA[i] = 0x8
|
|
||||||
}
|
|
||||||
return len(dAtA) - i, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcResponseData) Marshal() (dAtA []byte, err error) {
|
|
||||||
size := m.Size()
|
|
||||||
dAtA = make([]byte, size)
|
|
||||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return dAtA[:n], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcResponseData) MarshalTo(dAtA []byte) (int, error) {
|
|
||||||
size := m.Size()
|
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcResponseData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|
||||||
i := len(dAtA)
|
|
||||||
_ = i
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
if m.XXX_unrecognized != nil {
|
|
||||||
i -= len(m.XXX_unrecognized)
|
|
||||||
copy(dAtA[i:], m.XXX_unrecognized)
|
|
||||||
}
|
|
||||||
if len(m.Reply) > 0 {
|
|
||||||
i -= len(m.Reply)
|
|
||||||
copy(dAtA[i:], m.Reply)
|
|
||||||
i = encodeVarintGogorpc(dAtA, i, uint64(len(m.Reply)))
|
|
||||||
i--
|
|
||||||
dAtA[i] = 0x1a
|
|
||||||
}
|
|
||||||
if len(m.Error) > 0 {
|
|
||||||
i -= len(m.Error)
|
|
||||||
copy(dAtA[i:], m.Error)
|
|
||||||
i = encodeVarintGogorpc(dAtA, i, uint64(len(m.Error)))
|
|
||||||
i--
|
|
||||||
dAtA[i] = 0x12
|
|
||||||
}
|
|
||||||
if m.Seq != 0 {
|
|
||||||
i = encodeVarintGogorpc(dAtA, i, uint64(m.Seq))
|
|
||||||
i--
|
|
||||||
dAtA[i] = 0x8
|
|
||||||
}
|
|
||||||
return len(dAtA) - i, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeVarintGogorpc(dAtA []byte, offset int, v uint64) int {
|
|
||||||
offset -= sovGogorpc(v)
|
|
||||||
base := offset
|
|
||||||
for v >= 1<<7 {
|
|
||||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
|
||||||
v >>= 7
|
|
||||||
offset++
|
|
||||||
}
|
|
||||||
dAtA[offset] = uint8(v)
|
|
||||||
return base
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcRequestData) Size() (n int) {
|
|
||||||
if m == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
if m.Seq != 0 {
|
|
||||||
n += 1 + sovGogorpc(uint64(m.Seq))
|
|
||||||
}
|
|
||||||
if m.RpcMethodId != 0 {
|
|
||||||
n += 1 + sovGogorpc(uint64(m.RpcMethodId))
|
|
||||||
}
|
|
||||||
l = len(m.ServiceMethod)
|
|
||||||
if l > 0 {
|
|
||||||
n += 1 + l + sovGogorpc(uint64(l))
|
|
||||||
}
|
|
||||||
if m.NoReply {
|
|
||||||
n += 2
|
|
||||||
}
|
|
||||||
l = len(m.InParam)
|
|
||||||
if l > 0 {
|
|
||||||
n += 1 + l + sovGogorpc(uint64(l))
|
|
||||||
}
|
|
||||||
if m.XXX_unrecognized != nil {
|
|
||||||
n += len(m.XXX_unrecognized)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GoGoPBRpcResponseData) Size() (n int) {
|
|
||||||
if m == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
if m.Seq != 0 {
|
|
||||||
n += 1 + sovGogorpc(uint64(m.Seq))
|
|
||||||
}
|
|
||||||
l = len(m.Error)
|
|
||||||
if l > 0 {
|
|
||||||
n += 1 + l + sovGogorpc(uint64(l))
|
|
||||||
}
|
|
||||||
l = len(m.Reply)
|
|
||||||
if l > 0 {
|
|
||||||
n += 1 + l + sovGogorpc(uint64(l))
|
|
||||||
}
|
|
||||||
if m.XXX_unrecognized != nil {
|
|
||||||
n += len(m.XXX_unrecognized)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func sovGogorpc(x uint64) (n int) {
|
|
||||||
return (math_bits.Len64(x|1) + 6) / 7
|
|
||||||
}
|
|
||||||
func sozGogorpc(x uint64) (n int) {
|
|
||||||
return sovGogorpc(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcRequestData) Unmarshal(dAtA []byte) error {
|
|
||||||
l := len(dAtA)
|
|
||||||
iNdEx := 0
|
|
||||||
for iNdEx < l {
|
|
||||||
preIndex := iNdEx
|
|
||||||
var wire uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
wire |= uint64(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fieldNum := int32(wire >> 3)
|
|
||||||
wireType := int(wire & 0x7)
|
|
||||||
if wireType == 4 {
|
|
||||||
return fmt.Errorf("proto: GoGoPBRpcRequestData: wiretype end group for non-group")
|
|
||||||
}
|
|
||||||
if fieldNum <= 0 {
|
|
||||||
return fmt.Errorf("proto: GoGoPBRpcRequestData: illegal tag %d (wire type %d)", fieldNum, wire)
|
|
||||||
}
|
|
||||||
switch fieldNum {
|
|
||||||
case 1:
|
|
||||||
if wireType != 0 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field Seq", wireType)
|
|
||||||
}
|
|
||||||
m.Seq = 0
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
m.Seq |= uint64(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
if wireType != 0 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field RpcMethodId", wireType)
|
|
||||||
}
|
|
||||||
m.RpcMethodId = 0
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
m.RpcMethodId |= uint32(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
if wireType != 2 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field ServiceMethod", wireType)
|
|
||||||
}
|
|
||||||
var stringLen uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
stringLen |= uint64(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
intStringLen := int(stringLen)
|
|
||||||
if intStringLen < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
postIndex := iNdEx + intStringLen
|
|
||||||
if postIndex < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
if postIndex > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.ServiceMethod = string(dAtA[iNdEx:postIndex])
|
|
||||||
iNdEx = postIndex
|
|
||||||
case 4:
|
|
||||||
if wireType != 0 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field NoReply", wireType)
|
|
||||||
}
|
|
||||||
var v int
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
v |= int(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.NoReply = bool(v != 0)
|
|
||||||
case 5:
|
|
||||||
if wireType != 2 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field InParam", wireType)
|
|
||||||
}
|
|
||||||
var byteLen int
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
byteLen |= int(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if byteLen < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
postIndex := iNdEx + byteLen
|
|
||||||
if postIndex < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
if postIndex > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.InParam = append(m.InParam[:0], dAtA[iNdEx:postIndex]...)
|
|
||||||
if m.InParam == nil {
|
|
||||||
m.InParam = []byte{}
|
|
||||||
}
|
|
||||||
iNdEx = postIndex
|
|
||||||
default:
|
|
||||||
iNdEx = preIndex
|
|
||||||
skippy, err := skipGogorpc(dAtA[iNdEx:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if skippy < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
if (iNdEx + skippy) < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
if (iNdEx + skippy) > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
|
||||||
iNdEx += skippy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if iNdEx > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (m *GoGoPBRpcResponseData) Unmarshal(dAtA []byte) error {
|
|
||||||
l := len(dAtA)
|
|
||||||
iNdEx := 0
|
|
||||||
for iNdEx < l {
|
|
||||||
preIndex := iNdEx
|
|
||||||
var wire uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
wire |= uint64(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fieldNum := int32(wire >> 3)
|
|
||||||
wireType := int(wire & 0x7)
|
|
||||||
if wireType == 4 {
|
|
||||||
return fmt.Errorf("proto: GoGoPBRpcResponseData: wiretype end group for non-group")
|
|
||||||
}
|
|
||||||
if fieldNum <= 0 {
|
|
||||||
return fmt.Errorf("proto: GoGoPBRpcResponseData: illegal tag %d (wire type %d)", fieldNum, wire)
|
|
||||||
}
|
|
||||||
switch fieldNum {
|
|
||||||
case 1:
|
|
||||||
if wireType != 0 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field Seq", wireType)
|
|
||||||
}
|
|
||||||
m.Seq = 0
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
m.Seq |= uint64(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
if wireType != 2 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType)
|
|
||||||
}
|
|
||||||
var stringLen uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
stringLen |= uint64(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
intStringLen := int(stringLen)
|
|
||||||
if intStringLen < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
postIndex := iNdEx + intStringLen
|
|
||||||
if postIndex < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
if postIndex > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.Error = string(dAtA[iNdEx:postIndex])
|
|
||||||
iNdEx = postIndex
|
|
||||||
case 3:
|
|
||||||
if wireType != 2 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field Reply", wireType)
|
|
||||||
}
|
|
||||||
var byteLen int
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
byteLen |= int(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if byteLen < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
postIndex := iNdEx + byteLen
|
|
||||||
if postIndex < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
if postIndex > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.Reply = append(m.Reply[:0], dAtA[iNdEx:postIndex]...)
|
|
||||||
if m.Reply == nil {
|
|
||||||
m.Reply = []byte{}
|
|
||||||
}
|
|
||||||
iNdEx = postIndex
|
|
||||||
default:
|
|
||||||
iNdEx = preIndex
|
|
||||||
skippy, err := skipGogorpc(dAtA[iNdEx:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if skippy < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
if (iNdEx + skippy) < 0 {
|
|
||||||
return ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
if (iNdEx + skippy) > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
|
||||||
iNdEx += skippy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if iNdEx > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func skipGogorpc(dAtA []byte) (n int, err error) {
|
|
||||||
l := len(dAtA)
|
|
||||||
iNdEx := 0
|
|
||||||
depth := 0
|
|
||||||
for iNdEx < l {
|
|
||||||
var wire uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
wire |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wireType := int(wire & 0x7)
|
|
||||||
switch wireType {
|
|
||||||
case 0:
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
iNdEx++
|
|
||||||
if dAtA[iNdEx-1] < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
iNdEx += 8
|
|
||||||
case 2:
|
|
||||||
var length int
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflowGogorpc
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
length |= (int(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if length < 0 {
|
|
||||||
return 0, ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
iNdEx += length
|
|
||||||
case 3:
|
|
||||||
depth++
|
|
||||||
case 4:
|
|
||||||
if depth == 0 {
|
|
||||||
return 0, ErrUnexpectedEndOfGroupGogorpc
|
|
||||||
}
|
|
||||||
depth--
|
|
||||||
case 5:
|
|
||||||
iNdEx += 4
|
|
||||||
default:
|
|
||||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
|
||||||
}
|
|
||||||
if iNdEx < 0 {
|
|
||||||
return 0, ErrInvalidLengthGogorpc
|
|
||||||
}
|
|
||||||
if depth == 0 {
|
|
||||||
return iNdEx, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrInvalidLengthGogorpc = fmt.Errorf("proto: negative length found during unmarshaling")
|
|
||||||
ErrIntOverflowGogorpc = fmt.Errorf("proto: integer overflow")
|
|
||||||
ErrUnexpectedEndOfGroupGogorpc = fmt.Errorf("proto: unexpected end of group")
|
|
||||||
)
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/util/sync"
|
"github.com/duanhf2012/origin/v2/util/sync"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ package rpc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/network"
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//本结点的Client
|
//本结点的Client
|
||||||
@@ -36,15 +37,16 @@ func (lc *LClient) SetConn(conn *network.TCPConn){
|
|||||||
func (lc *LClient) Close(waitDone bool){
|
func (lc *LClient) Close(waitDone bool){
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LClient) Go(rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
|
func (lc *LClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
|
||||||
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
||||||
//判断是否是同一服务
|
//判断是否是同一服务
|
||||||
findIndex := strings.Index(serviceMethod, ".")
|
findIndex := strings.Index(serviceMethod, ".")
|
||||||
if findIndex == -1 {
|
if findIndex == -1 {
|
||||||
sErr := errors.New("Call serviceMethod " + serviceMethod + " is error!")
|
sErr := errors.New("Call serviceMethod " + serviceMethod + " is error!")
|
||||||
log.SError(sErr.Error())
|
log.Error("call rpc fail",log.String("error",sErr.Error()))
|
||||||
call := MakeCall()
|
call := MakeCall()
|
||||||
call.Err = sErr
|
call.DoError(sErr)
|
||||||
|
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,29 +55,31 @@ func (lc *LClient) Go(rpcHandler IRpcHandler,noReply bool, serviceMethod string,
|
|||||||
//调用自己rpcHandler处理器
|
//调用自己rpcHandler处理器
|
||||||
err := pLocalRpcServer.myselfRpcHandlerGo(lc.selfClient,serviceName, serviceMethod, args, requestHandlerNull,reply)
|
err := pLocalRpcServer.myselfRpcHandlerGo(lc.selfClient,serviceName, serviceMethod, args, requestHandlerNull,reply)
|
||||||
call := MakeCall()
|
call := MakeCall()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
call.Err = err
|
call.DoError(err)
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
call.done<-call
|
call.DoOK()
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
//其他的rpcHandler的处理器
|
//其他的rpcHandler的处理器
|
||||||
return pLocalRpcServer.selfNodeRpcHandlerGo(nil, lc.selfClient, noReply, serviceName, 0, serviceMethod, args, reply, nil)
|
return pLocalRpcServer.selfNodeRpcHandlerGo(timeout,nil, lc.selfClient, noReply, serviceName, 0, serviceMethod, args, reply, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (rc *LClient) RawGo(rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceName string, rawArgs []byte, reply interface{}) *Call {
|
func (rc *LClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceName string, rawArgs []byte, reply interface{}) *Call {
|
||||||
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
||||||
|
|
||||||
call := MakeCall()
|
|
||||||
call.ServiceMethod = serviceName
|
|
||||||
call.Reply = reply
|
|
||||||
|
|
||||||
//服务自我调用
|
//服务自我调用
|
||||||
if serviceName == rpcHandler.GetName() {
|
if serviceName == rpcHandler.GetName() {
|
||||||
|
call := MakeCall()
|
||||||
|
call.ServiceMethod = serviceName
|
||||||
|
call.Reply = reply
|
||||||
|
call.TimeOut = timeout
|
||||||
|
|
||||||
err := pLocalRpcServer.myselfRpcHandlerGo(rc.selfClient,serviceName, serviceName, rawArgs, requestHandlerNull,nil)
|
err := pLocalRpcServer.myselfRpcHandlerGo(rc.selfClient,serviceName, serviceName, rawArgs, requestHandlerNull,nil)
|
||||||
call.Err = err
|
call.Err = err
|
||||||
call.done <- call
|
call.done <- call
|
||||||
@@ -84,11 +88,11 @@ func (rc *LClient) RawGo(rpcHandler IRpcHandler,processor IRpcProcessor, noReply
|
|||||||
}
|
}
|
||||||
|
|
||||||
//其他的rpcHandler的处理器
|
//其他的rpcHandler的处理器
|
||||||
return pLocalRpcServer.selfNodeRpcHandlerGo(processor,rc.selfClient, true, serviceName, rpcMethodId, serviceName, nil, nil, rawArgs)
|
return pLocalRpcServer.selfNodeRpcHandlerGo(timeout,processor,rc.selfClient, true, serviceName, rpcMethodId, serviceName, nil, nil, rawArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (lc *LClient) AsyncCall(rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, reply interface{}) error {
|
func (lc *LClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, reply interface{},cancelable bool) (CancelRpc,error) {
|
||||||
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
||||||
|
|
||||||
//判断是否是同一服务
|
//判断是否是同一服务
|
||||||
@@ -96,36 +100,38 @@ func (lc *LClient) AsyncCall(rpcHandler IRpcHandler, serviceMethod string, callb
|
|||||||
if findIndex == -1 {
|
if findIndex == -1 {
|
||||||
err := errors.New("Call serviceMethod " + serviceMethod + " is error!")
|
err := errors.New("Call serviceMethod " + serviceMethod + " is error!")
|
||||||
callback.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
|
callback.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
|
||||||
log.SError(err.Error())
|
log.Error("serviceMethod format is error",log.String("error",err.Error()))
|
||||||
return nil
|
return emptyCancelRpc,nil
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceName := serviceMethod[:findIndex]
|
serviceName := serviceMethod[:findIndex]
|
||||||
//调用自己rpcHandler处理器
|
//调用自己rpcHandler处理器
|
||||||
if serviceName == rpcHandler.GetName() { //自己服务调用
|
if serviceName == rpcHandler.GetName() { //自己服务调用
|
||||||
return pLocalRpcServer.myselfRpcHandlerGo(lc.selfClient,serviceName, serviceMethod, args,callback ,reply)
|
return emptyCancelRpc,pLocalRpcServer.myselfRpcHandlerGo(lc.selfClient,serviceName, serviceMethod, args,callback ,reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
//其他的rpcHandler的处理器
|
//其他的rpcHandler的处理器
|
||||||
err := pLocalRpcServer.selfNodeRpcHandlerAsyncGo(lc.selfClient, rpcHandler, false, serviceName, serviceMethod, args, reply, callback)
|
calcelRpc,err := pLocalRpcServer.selfNodeRpcHandlerAsyncGo(timeout,lc.selfClient, rpcHandler, false, serviceName, serviceMethod, args, reply, callback,cancelable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
callback.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
|
callback.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return calcelRpc,nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLClient(nodeId int) *Client{
|
func NewLClient(localNodeId string,callSet *CallSet) *Client{
|
||||||
client := &Client{}
|
client := &Client{}
|
||||||
client.clientId = atomic.AddUint32(&clientSeq, 1)
|
client.clientId = atomic.AddUint32(&clientSeq, 1)
|
||||||
client.nodeId = nodeId
|
client.targetNodeId = localNodeId
|
||||||
client.maxCheckCallRpcCount = MaxCheckCallRpcCount
|
//client.maxCheckCallRpcCount = DefaultMaxCheckCallRpcCount
|
||||||
client.callRpcTimeout = DefaultRpcTimeout
|
//client.callRpcTimeout = DefaultRpcTimeout
|
||||||
|
|
||||||
lClient := &LClient{}
|
lClient := &LClient{}
|
||||||
lClient.selfClient = client
|
lClient.selfClient = client
|
||||||
client.IRealClient = lClient
|
client.IRealClient = lClient
|
||||||
client.InitPending()
|
client.CallSet = callSet
|
||||||
go client.checkRpcCallTimeout()
|
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rc *LClient) Bind(server IServer){
|
||||||
|
}
|
||||||
291
rpc/lserver.go
Normal file
291
rpc/lserver.go
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
package rpc
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
"strings"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type BaseServer struct {
|
||||||
|
localNodeId string
|
||||||
|
compressBytesLen int
|
||||||
|
|
||||||
|
rpcHandleFinder RpcHandleFinder
|
||||||
|
iServer IServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *BaseServer) initBaseServer(compressBytesLen int,rpcHandleFinder RpcHandleFinder){
|
||||||
|
ls.compressBytesLen = compressBytesLen
|
||||||
|
ls.rpcHandleFinder = rpcHandleFinder
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *BaseServer) myselfRpcHandlerGo(client *Client,handlerName string, serviceMethod string, args interface{},callBack reflect.Value, reply interface{}) error {
|
||||||
|
rpcHandler := ls.rpcHandleFinder.FindRpcHandler(handlerName)
|
||||||
|
if rpcHandler == nil {
|
||||||
|
err := errors.New("service method " + serviceMethod + " not config!")
|
||||||
|
log.Error("service method not config",log.String("serviceMethod",serviceMethod))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rpcHandler.CallMethod(client,serviceMethod, args,callBack, reply)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call {
|
||||||
|
pCall := MakeCall()
|
||||||
|
pCall.Seq = client.generateSeq()
|
||||||
|
pCall.TimeOut = timeout
|
||||||
|
pCall.ServiceMethod = serviceMethod
|
||||||
|
|
||||||
|
rpcHandler := ls.rpcHandleFinder.FindRpcHandler(handlerName)
|
||||||
|
if rpcHandler == nil {
|
||||||
|
err := errors.New("service method " + serviceMethod + " not config!")
|
||||||
|
log.Error("service method not config",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err))
|
||||||
|
pCall.Seq = 0
|
||||||
|
pCall.DoError(err)
|
||||||
|
|
||||||
|
return pCall
|
||||||
|
}
|
||||||
|
|
||||||
|
var iParam interface{}
|
||||||
|
if processor == nil {
|
||||||
|
_, processor = GetProcessorType(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
if args != nil {
|
||||||
|
var err error
|
||||||
|
iParam,err = processor.Clone(args)
|
||||||
|
if err != nil {
|
||||||
|
sErr := errors.New("RpcHandler " + handlerName + "."+serviceMethod+" deep copy inParam is error:" + err.Error())
|
||||||
|
log.Error("deep copy inParam is failed",log.String("handlerName",handlerName),log.String("serviceMethod",serviceMethod))
|
||||||
|
pCall.Seq = 0
|
||||||
|
pCall.DoError(sErr)
|
||||||
|
|
||||||
|
return pCall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req := MakeRpcRequest(processor, 0, rpcMethodId, serviceMethod, noReply, nil)
|
||||||
|
req.inParam = iParam
|
||||||
|
req.localReply = reply
|
||||||
|
if rawArgs != nil {
|
||||||
|
var err error
|
||||||
|
req.inParam, err = rpcHandler.UnmarshalInParam(processor, serviceMethod, rpcMethodId, rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("unmarshalInParam is failed",log.String("serviceMethod",serviceMethod),log.Uint32("rpcMethodId",rpcMethodId),log.ErrorAttr("error",err))
|
||||||
|
pCall.Seq = 0
|
||||||
|
pCall.DoError(err)
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
return pCall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if noReply == false {
|
||||||
|
client.AddPending(pCall)
|
||||||
|
callSeq := pCall.Seq
|
||||||
|
req.requestHandle = func(Returns interface{}, Err RpcError) {
|
||||||
|
if reply != nil && Returns != reply && Returns != nil {
|
||||||
|
byteReturns, err := req.rpcProcessor.Marshal(Returns)
|
||||||
|
if err != nil {
|
||||||
|
Err = ConvertError(err)
|
||||||
|
log.Error("returns data cannot be marshal",log.Uint64("seq",callSeq),log.ErrorAttr("error",err))
|
||||||
|
}else{
|
||||||
|
err = req.rpcProcessor.Unmarshal(byteReturns, reply)
|
||||||
|
if err != nil {
|
||||||
|
Err = ConvertError(err)
|
||||||
|
log.Error("returns data cannot be Unmarshal",log.Uint64("seq",callSeq),log.ErrorAttr("error",err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
v := client.RemovePending(callSeq)
|
||||||
|
if v == nil {
|
||||||
|
log.Error("rpcClient cannot find seq",log.Uint64("seq",callSeq))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(Err) == 0 {
|
||||||
|
v.Err = nil
|
||||||
|
v.DoOK()
|
||||||
|
} else {
|
||||||
|
log.Error(Err.Error())
|
||||||
|
v.DoError(Err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := rpcHandler.PushRpcRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
pCall.DoError(err)
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pCall
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *BaseServer) selfNodeRpcHandlerAsyncGo(timeout time.Duration,client *Client, callerRpcHandler IRpcHandler, noReply bool, handlerName string, serviceMethod string, args interface{}, reply interface{}, callback reflect.Value,cancelable bool) (CancelRpc,error) {
|
||||||
|
rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
|
||||||
|
if rpcHandler == nil {
|
||||||
|
err := errors.New("service method " + serviceMethod + " not config!")
|
||||||
|
log.Error(err.Error())
|
||||||
|
return emptyCancelRpc,err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, processor := GetProcessorType(args)
|
||||||
|
iParam,err := processor.Clone(args)
|
||||||
|
if err != nil {
|
||||||
|
errM := errors.New("RpcHandler " + handlerName + "."+serviceMethod+" deep copy inParam is error:" + err.Error())
|
||||||
|
log.Error(errM.Error())
|
||||||
|
return emptyCancelRpc,errM
|
||||||
|
}
|
||||||
|
|
||||||
|
req := MakeRpcRequest(processor, 0, 0, serviceMethod, noReply, nil)
|
||||||
|
req.inParam = iParam
|
||||||
|
req.localReply = reply
|
||||||
|
|
||||||
|
cancelRpc := emptyCancelRpc
|
||||||
|
var callSeq uint64
|
||||||
|
if noReply == false {
|
||||||
|
callSeq = client.generateSeq()
|
||||||
|
pCall := MakeCall()
|
||||||
|
pCall.Seq = callSeq
|
||||||
|
pCall.rpcHandler = callerRpcHandler
|
||||||
|
pCall.callback = &callback
|
||||||
|
pCall.Reply = reply
|
||||||
|
pCall.ServiceMethod = serviceMethod
|
||||||
|
pCall.TimeOut = timeout
|
||||||
|
client.AddPending(pCall)
|
||||||
|
rpcCancel := RpcCancel{CallSeq: callSeq,Cli: client}
|
||||||
|
cancelRpc = rpcCancel.CancelRpc
|
||||||
|
|
||||||
|
req.requestHandle = func(Returns interface{}, Err RpcError) {
|
||||||
|
v := client.RemovePending(callSeq)
|
||||||
|
if v == nil {
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(Err) == 0 {
|
||||||
|
v.Err = nil
|
||||||
|
} else {
|
||||||
|
v.Err = Err
|
||||||
|
}
|
||||||
|
|
||||||
|
if Returns != nil {
|
||||||
|
v.Reply = Returns
|
||||||
|
}
|
||||||
|
v.rpcHandler.PushRpcResponse(v)
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = rpcHandler.PushRpcRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
if callSeq > 0 {
|
||||||
|
client.RemovePending(callSeq)
|
||||||
|
}
|
||||||
|
return emptyCancelRpc,err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cancelRpc,nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse writeResponse) error{
|
||||||
|
bCompress := (data[0]>>7) > 0
|
||||||
|
processor := GetProcessor(data[0]&0x7f)
|
||||||
|
if processor == nil {
|
||||||
|
return errors.New("cannot find processor")
|
||||||
|
}
|
||||||
|
|
||||||
|
//解析head
|
||||||
|
var compressBuff []byte
|
||||||
|
byteData := data[1:]
|
||||||
|
if bCompress == true {
|
||||||
|
var unCompressErr error
|
||||||
|
|
||||||
|
compressBuff,unCompressErr = compressor.UncompressBlock(byteData)
|
||||||
|
if unCompressErr!= nil {
|
||||||
|
return errors.New("UncompressBlock failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
byteData = compressBuff
|
||||||
|
}
|
||||||
|
|
||||||
|
req := MakeRpcRequest(processor, 0, 0, "", false, nil)
|
||||||
|
err := processor.Unmarshal(byteData, req.RpcRequestData)
|
||||||
|
if cap(compressBuff) > 0 {
|
||||||
|
compressor.UnCompressBufferCollection(compressBuff)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if req.RpcRequestData.GetSeq() > 0 {
|
||||||
|
rpcError := RpcError(err.Error())
|
||||||
|
if req.RpcRequestData.IsNoReply() == false {
|
||||||
|
wrResponse(processor,connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//交给程序处理
|
||||||
|
serviceMethod := strings.Split(req.RpcRequestData.GetServiceMethod(), ".")
|
||||||
|
if len(serviceMethod) < 1 {
|
||||||
|
rpcError := RpcError("rpc request req.ServiceMethod is error")
|
||||||
|
if req.RpcRequestData.IsNoReply() == false {
|
||||||
|
wrResponse(processor,connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
||||||
|
}
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
log.Error("rpc request req.ServiceMethod is error")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcHandler := bs.rpcHandleFinder.FindRpcHandler(serviceMethod[0])
|
||||||
|
if rpcHandler == nil {
|
||||||
|
rpcError := RpcError(fmt.Sprintf("service method %s not config!", req.RpcRequestData.GetServiceMethod()))
|
||||||
|
if req.RpcRequestData.IsNoReply() == false {
|
||||||
|
wrResponse(processor,connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
||||||
|
}
|
||||||
|
log.Error("serviceMethod not config",log.String("serviceMethod",req.RpcRequestData.GetServiceMethod()))
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.RpcRequestData.IsNoReply() == false {
|
||||||
|
req.requestHandle = func(Returns interface{}, Err RpcError) {
|
||||||
|
wrResponse(processor,connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), Returns, Err)
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req.inParam, err = rpcHandler.UnmarshalInParam(req.rpcProcessor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetRpcMethodId(), req.RpcRequestData.GetInParam())
|
||||||
|
if err != nil {
|
||||||
|
rErr := "Call Rpc " + req.RpcRequestData.GetServiceMethod() + " Param error " + err.Error()
|
||||||
|
log.Error("call rpc param error",log.String("serviceMethod",req.RpcRequestData.GetServiceMethod()),log.ErrorAttr("error",err))
|
||||||
|
if req.requestHandle != nil {
|
||||||
|
req.requestHandle(nil, RpcError(rErr))
|
||||||
|
} else {
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = rpcHandler.PushRpcRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
rpcError := RpcError(err.Error())
|
||||||
|
|
||||||
|
if req.RpcRequestData.IsNoReply() {
|
||||||
|
wrResponse(processor, connTag,req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseRpcRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -31,7 +31,7 @@ message DBQueueSubscribeReq {
|
|||||||
SubscribeType SubType = 1; //订阅类型
|
SubscribeType SubType = 1; //订阅类型
|
||||||
SubscribeMethod Method = 2; //订阅方法
|
SubscribeMethod Method = 2; //订阅方法
|
||||||
string CustomerId = 3; //消费者Id
|
string CustomerId = 3; //消费者Id
|
||||||
int32 FromNodeId = 4;
|
string FromNodeId = 4;
|
||||||
string RpcMethod = 5;
|
string RpcMethod = 5;
|
||||||
string TopicName = 6; //主题名称
|
string TopicName = 6; //主题名称
|
||||||
uint64 StartIndex = 7; //开始位置 ,格式前4位是时间戳秒,后面是序号。如果填0时,服务自动修改成:(4bit 当前时间秒)| (0000 4bit)
|
uint64 StartIndex = 7; //开始位置 ,格式前4位是时间戳秒,后面是序号。如果填0时,服务自动修改成:(4bit 当前时间秒)| (0000 4bit)
|
||||||
|
|||||||
90
rpc/natsclient.go
Normal file
90
rpc/natsclient.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package rpc
|
||||||
|
import (
|
||||||
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
"github.com/nats-io/nats.go"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
//跨结点连接的Client
|
||||||
|
type NatsClient struct {
|
||||||
|
localNodeId string
|
||||||
|
notifyEventFun NotifyEventFun
|
||||||
|
|
||||||
|
natsConn *nats.Conn
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nc *NatsClient) Start(natsConn *nats.Conn) error{
|
||||||
|
nc.natsConn = natsConn
|
||||||
|
_,err := nc.natsConn.QueueSubscribe("oc."+nc.localNodeId, "oc",nc.onSubscribe)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nc *NatsClient) onSubscribe(msg *nats.Msg){
|
||||||
|
//处理消息
|
||||||
|
nc.client.processRpcResponse(msg.Data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nc *NatsClient) SetConn(conn *network.TCPConn){
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nc *NatsClient) Close(waitDone bool){
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nc *NatsClient) Run(){
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nc *NatsClient) OnClose(){
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *NatsClient) Bind(server IServer){
|
||||||
|
s := server.(*NatsServer)
|
||||||
|
rc.natsConn = s.natsConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *NatsClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
|
||||||
|
_, processor := GetProcessorType(args)
|
||||||
|
InParam, err := processor.Marshal(args)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Marshal is fail",log.ErrorAttr("error",err))
|
||||||
|
call := MakeCall()
|
||||||
|
call.DoError(err)
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc.client.rawGo(nodeId,rc,timeout,rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *NatsClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call {
|
||||||
|
return rc.client.rawGo(nodeId,rc,timeout,rpcHandler,processor, noReply, rpcMethodId, serviceMethod, rawArgs, reply)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *NatsClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) {
|
||||||
|
cancelRpc,err := rc.client.asyncCall(nodeId,rc,timeout,rpcHandler, serviceMethod, callback, args, replyParam,cancelable)
|
||||||
|
if err != nil {
|
||||||
|
callback.Call([]reflect.Value{reflect.ValueOf(replyParam), reflect.ValueOf(err)})
|
||||||
|
}
|
||||||
|
|
||||||
|
return cancelRpc,nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *NatsClient) WriteMsg (nodeId string,args ...[]byte) error{
|
||||||
|
buff := make([]byte,0,4096)
|
||||||
|
for _,ar := range args {
|
||||||
|
buff = append(buff,ar...)
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg nats.Msg
|
||||||
|
msg.Subject = "os."+nodeId
|
||||||
|
msg.Data = buff
|
||||||
|
msg.Header = nats.Header{}
|
||||||
|
msg.Header.Set("fnode",rc.localNodeId)
|
||||||
|
return rc.natsConn.PublishMsg(&msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *NatsClient) IsConnected() bool{
|
||||||
|
return rc.natsConn!=nil && rc.natsConn.Status() == nats.CONNECTED
|
||||||
|
}
|
||||||
127
rpc/natsserver.go
Normal file
127
rpc/natsserver.go
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
package rpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nats-io/nats.go"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NatsServer struct {
|
||||||
|
BaseServer
|
||||||
|
natsUrl string
|
||||||
|
|
||||||
|
natsConn *nats.Conn
|
||||||
|
NoRandomize bool
|
||||||
|
|
||||||
|
nodeSubTopic string
|
||||||
|
compressBytesLen int
|
||||||
|
notifyEventFun NotifyEventFun
|
||||||
|
}
|
||||||
|
|
||||||
|
const reconnectWait = 3*time.Second
|
||||||
|
func (ns *NatsServer) Start() error{
|
||||||
|
var err error
|
||||||
|
var options []nats.Option
|
||||||
|
|
||||||
|
options = append(options,nats.DisconnectErrHandler(func(nc *nats.Conn, err error) {
|
||||||
|
log.Error("nats is disconnected",log.String("connUrl",nc.ConnectedUrl()))
|
||||||
|
ns.notifyEventFun(&NatsConnEvent{IsConnect:false})
|
||||||
|
}))
|
||||||
|
|
||||||
|
options = append(options,nats.ConnectHandler(func(nc *nats.Conn) {
|
||||||
|
log.Info("nats is connected",log.String("connUrl",nc.ConnectedUrl()))
|
||||||
|
ns.notifyEventFun(&NatsConnEvent{IsConnect:true})
|
||||||
|
//log.Error("nats is connect",log.String("connUrl",nc.ConnectedUrl()))
|
||||||
|
}))
|
||||||
|
|
||||||
|
options = append(options,nats.ReconnectHandler(func(nc *nats.Conn) {
|
||||||
|
ns.notifyEventFun(&NatsConnEvent{IsConnect:true})
|
||||||
|
log.Info("nats is reconnected",log.String("connUrl",nc.ConnectedUrl()))
|
||||||
|
}))
|
||||||
|
|
||||||
|
options = append(options,nats.MaxReconnects(-1))
|
||||||
|
options = append(options,nats.ReconnectWait(reconnectWait))
|
||||||
|
|
||||||
|
if ns.NoRandomize {
|
||||||
|
options = append(options,nats.DontRandomize())
|
||||||
|
}
|
||||||
|
|
||||||
|
ns.natsConn,err = nats.Connect(ns.natsUrl,options...)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Connect to nats fail",log.String("natsUrl",ns.natsUrl),log.ErrorAttr("err",err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//开始订阅
|
||||||
|
_,err = ns.natsConn.QueueSubscribe(ns.nodeSubTopic,"os", func(msg *nats.Msg) {
|
||||||
|
ns.processRpcRequest(msg.Data,msg.Header.Get("fnode"),ns.WriteResponse)
|
||||||
|
})
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NatsServer) WriteResponse(processor IRpcProcessor, nodeId string,serviceMethod string, seq uint64, reply interface{}, rpcError RpcError){
|
||||||
|
var mReply []byte
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if reply != nil {
|
||||||
|
mReply, err = processor.Marshal(reply)
|
||||||
|
if err != nil {
|
||||||
|
rpcError = ConvertError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rpcResponse RpcResponse
|
||||||
|
rpcResponse.RpcResponseData = processor.MakeRpcResponse(seq, rpcError, mReply)
|
||||||
|
bytes, err := processor.Marshal(rpcResponse.RpcResponseData)
|
||||||
|
defer processor.ReleaseRpcResponse(rpcResponse.RpcResponseData)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("mashal RpcResponseData failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var compressBuff[]byte
|
||||||
|
bCompress := uint8(0)
|
||||||
|
if ns.compressBytesLen >0 && len(bytes) >= ns.compressBytesLen {
|
||||||
|
compressBuff,err = compressor.CompressBlock(bytes)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("CompressBlock failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(compressBuff) < len(bytes) {
|
||||||
|
bytes = compressBuff
|
||||||
|
bCompress = 1<<7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendData := make([]byte,0,4096)
|
||||||
|
byteTypeAndCompress := []byte{uint8(processor.GetProcessorType())|bCompress}
|
||||||
|
sendData = append(sendData,byteTypeAndCompress...)
|
||||||
|
sendData = append(sendData,bytes...)
|
||||||
|
err = ns.natsConn.PublishMsg(&nats.Msg{Subject: "oc."+nodeId, Data: sendData})
|
||||||
|
|
||||||
|
if cap(compressBuff) >0 {
|
||||||
|
compressor.CompressBufferCollection(compressBuff)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("WriteMsg error,Rpc return is fail",log.String("nodeId",nodeId),log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NatsServer) Stop(){
|
||||||
|
if ns.natsConn != nil {
|
||||||
|
ns.natsConn.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NatsServer) initServer(natsUrl string, noRandomize bool,localNodeId string,compressBytesLen int,rpcHandleFinder RpcHandleFinder,notifyEventFun NotifyEventFun){
|
||||||
|
ns.natsUrl = natsUrl
|
||||||
|
ns.NoRandomize = noRandomize
|
||||||
|
ns.localNodeId = localNodeId
|
||||||
|
ns.compressBytesLen = compressBytesLen
|
||||||
|
ns.notifyEventFun = notifyEventFun
|
||||||
|
ns.initBaseServer(compressBytesLen,rpcHandleFinder)
|
||||||
|
ns.nodeSubTopic = "os."+localNodeId //服务器
|
||||||
|
}
|
||||||
662
rpc/origindiscover.pb.go
Normal file
662
rpc/origindiscover.pb.go
Normal file
@@ -0,0 +1,662 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.31.0
|
||||||
|
// protoc v4.24.0
|
||||||
|
// source: rpcproto/origindiscover.proto
|
||||||
|
|
||||||
|
package rpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type NodeInfo struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
NodeId string `protobuf:"bytes,1,opt,name=NodeId,proto3" json:"NodeId,omitempty"`
|
||||||
|
ListenAddr string `protobuf:"bytes,2,opt,name=ListenAddr,proto3" json:"ListenAddr,omitempty"`
|
||||||
|
MaxRpcParamLen uint32 `protobuf:"varint,3,opt,name=MaxRpcParamLen,proto3" json:"MaxRpcParamLen,omitempty"`
|
||||||
|
Private bool `protobuf:"varint,4,opt,name=Private,proto3" json:"Private,omitempty"`
|
||||||
|
Retire bool `protobuf:"varint,5,opt,name=Retire,proto3" json:"Retire,omitempty"`
|
||||||
|
PublicServiceList []string `protobuf:"bytes,6,rep,name=PublicServiceList,proto3" json:"PublicServiceList,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NodeInfo) Reset() {
|
||||||
|
*x = NodeInfo{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NodeInfo) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*NodeInfo) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *NodeInfo) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use NodeInfo.ProtoReflect.Descriptor instead.
|
||||||
|
func (*NodeInfo) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpcproto_origindiscover_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NodeInfo) GetNodeId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.NodeId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NodeInfo) GetListenAddr() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.ListenAddr
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NodeInfo) GetMaxRpcParamLen() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.MaxRpcParamLen
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NodeInfo) GetPrivate() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.Private
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NodeInfo) GetRetire() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.Retire
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NodeInfo) GetPublicServiceList() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.PublicServiceList
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client->Master
|
||||||
|
type RegServiceDiscoverReq struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
NodeInfo *NodeInfo `protobuf:"bytes,1,opt,name=nodeInfo,proto3" json:"nodeInfo,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RegServiceDiscoverReq) Reset() {
|
||||||
|
*x = RegServiceDiscoverReq{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RegServiceDiscoverReq) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*RegServiceDiscoverReq) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *RegServiceDiscoverReq) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use RegServiceDiscoverReq.ProtoReflect.Descriptor instead.
|
||||||
|
func (*RegServiceDiscoverReq) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpcproto_origindiscover_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RegServiceDiscoverReq) GetNodeInfo() *NodeInfo {
|
||||||
|
if x != nil {
|
||||||
|
return x.NodeInfo
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Master->Client
|
||||||
|
type SubscribeDiscoverNotify struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
MasterNodeId string `protobuf:"bytes,1,opt,name=MasterNodeId,proto3" json:"MasterNodeId,omitempty"`
|
||||||
|
IsFull bool `protobuf:"varint,2,opt,name=IsFull,proto3" json:"IsFull,omitempty"`
|
||||||
|
DelNodeId string `protobuf:"bytes,3,opt,name=DelNodeId,proto3" json:"DelNodeId,omitempty"`
|
||||||
|
NodeInfo []*NodeInfo `protobuf:"bytes,4,rep,name=nodeInfo,proto3" json:"nodeInfo,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SubscribeDiscoverNotify) Reset() {
|
||||||
|
*x = SubscribeDiscoverNotify{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SubscribeDiscoverNotify) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SubscribeDiscoverNotify) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *SubscribeDiscoverNotify) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[2]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use SubscribeDiscoverNotify.ProtoReflect.Descriptor instead.
|
||||||
|
func (*SubscribeDiscoverNotify) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpcproto_origindiscover_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SubscribeDiscoverNotify) GetMasterNodeId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.MasterNodeId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SubscribeDiscoverNotify) GetIsFull() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.IsFull
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SubscribeDiscoverNotify) GetDelNodeId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.DelNodeId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SubscribeDiscoverNotify) GetNodeInfo() []*NodeInfo {
|
||||||
|
if x != nil {
|
||||||
|
return x.NodeInfo
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client->Master
|
||||||
|
type NodeRetireReq struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
NodeInfo *NodeInfo `protobuf:"bytes,1,opt,name=nodeInfo,proto3" json:"nodeInfo,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NodeRetireReq) Reset() {
|
||||||
|
*x = NodeRetireReq{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NodeRetireReq) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*NodeRetireReq) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *NodeRetireReq) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[3]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use NodeRetireReq.ProtoReflect.Descriptor instead.
|
||||||
|
func (*NodeRetireReq) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpcproto_origindiscover_proto_rawDescGZIP(), []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NodeRetireReq) GetNodeInfo() *NodeInfo {
|
||||||
|
if x != nil {
|
||||||
|
return x.NodeInfo
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Master->Client
|
||||||
|
type Empty struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Empty) Reset() {
|
||||||
|
*x = Empty{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Empty) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Empty) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Empty) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[4]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Empty.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Empty) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpcproto_origindiscover_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client->Master
|
||||||
|
type Ping struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
NodeId string `protobuf:"bytes,1,opt,name=NodeId,proto3" json:"NodeId,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Ping) Reset() {
|
||||||
|
*x = Ping{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[5]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Ping) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Ping) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Ping) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[5]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Ping.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Ping) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpcproto_origindiscover_proto_rawDescGZIP(), []int{5}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Ping) GetNodeId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.NodeId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Master->Client
|
||||||
|
type Pong struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Pong) Reset() {
|
||||||
|
*x = Pong{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[6]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Pong) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Pong) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Pong) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[6]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Pong.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Pong) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpcproto_origindiscover_proto_rawDescGZIP(), []int{6}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Pong) GetOk() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.Ok
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnRegServiceDiscoverReq struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
NodeId string `protobuf:"bytes,1,opt,name=NodeId,proto3" json:"NodeId,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UnRegServiceDiscoverReq) Reset() {
|
||||||
|
*x = UnRegServiceDiscoverReq{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[7]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UnRegServiceDiscoverReq) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UnRegServiceDiscoverReq) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *UnRegServiceDiscoverReq) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpcproto_origindiscover_proto_msgTypes[7]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use UnRegServiceDiscoverReq.ProtoReflect.Descriptor instead.
|
||||||
|
func (*UnRegServiceDiscoverReq) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpcproto_origindiscover_proto_rawDescGZIP(), []int{7}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UnRegServiceDiscoverReq) GetNodeId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.NodeId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_rpcproto_origindiscover_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_rpcproto_origindiscover_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x1d, 0x72, 0x70, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x72, 0x69, 0x67, 0x69,
|
||||||
|
0x6e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
|
||||||
|
0x03, 0x72, 0x70, 0x63, 0x22, 0xca, 0x01, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66,
|
||||||
|
0x6f, 0x12, 0x16, 0x0a, 0x06, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
|
0x09, 0x52, 0x06, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x4c, 0x69, 0x73,
|
||||||
|
0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4c,
|
||||||
|
0x69, 0x73, 0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x61, 0x78,
|
||||||
|
0x52, 0x70, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x4c, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||||
|
0x0d, 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x52, 0x70, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x4c, 0x65,
|
||||||
|
0x6e, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01,
|
||||||
|
0x28, 0x08, 0x52, 0x07, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x52,
|
||||||
|
0x65, 0x74, 0x69, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x52, 0x65, 0x74,
|
||||||
|
0x69, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x53, 0x65, 0x72,
|
||||||
|
0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11,
|
||||||
|
0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73,
|
||||||
|
0x74, 0x22, 0x42, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44,
|
||||||
|
0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x29, 0x0a, 0x08, 0x6e, 0x6f,
|
||||||
|
0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x72,
|
||||||
|
0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6e, 0x6f, 0x64,
|
||||||
|
0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x9e, 0x01, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
|
||||||
|
0x69, 0x62, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x69, 0x66,
|
||||||
|
0x79, 0x12, 0x22, 0x0a, 0x0c, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x49,
|
||||||
|
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4e,
|
||||||
|
0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x73, 0x46, 0x75, 0x6c, 0x6c, 0x18,
|
||||||
|
0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x49, 0x73, 0x46, 0x75, 0x6c, 0x6c, 0x12, 0x1c, 0x0a,
|
||||||
|
0x09, 0x44, 0x65, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||||
|
0x52, 0x09, 0x44, 0x65, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x08, 0x6e,
|
||||||
|
0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e,
|
||||||
|
0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6e, 0x6f,
|
||||||
|
0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x3a, 0x0a, 0x0d, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65,
|
||||||
|
0x74, 0x69, 0x72, 0x65, 0x52, 0x65, 0x71, 0x12, 0x29, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x49,
|
||||||
|
0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x72, 0x70, 0x63, 0x2e,
|
||||||
|
0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x6e,
|
||||||
|
0x66, 0x6f, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x1e, 0x0a, 0x04, 0x50,
|
||||||
|
0x69, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x09, 0x52, 0x06, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0x16, 0x0a, 0x04, 0x50,
|
||||||
|
0x6f, 0x6e, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||||
|
0x02, 0x6f, 0x6b, 0x22, 0x31, 0x0a, 0x17, 0x55, 0x6e, 0x52, 0x65, 0x67, 0x53, 0x65, 0x72, 0x76,
|
||||||
|
0x69, 0x63, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x16,
|
||||||
|
0x0a, 0x06, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
|
||||||
|
0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x3b, 0x72, 0x70, 0x63, 0x62,
|
||||||
|
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_rpcproto_origindiscover_proto_rawDescOnce sync.Once
|
||||||
|
file_rpcproto_origindiscover_proto_rawDescData = file_rpcproto_origindiscover_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_rpcproto_origindiscover_proto_rawDescGZIP() []byte {
|
||||||
|
file_rpcproto_origindiscover_proto_rawDescOnce.Do(func() {
|
||||||
|
file_rpcproto_origindiscover_proto_rawDescData = protoimpl.X.CompressGZIP(file_rpcproto_origindiscover_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_rpcproto_origindiscover_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_rpcproto_origindiscover_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
|
||||||
|
var file_rpcproto_origindiscover_proto_goTypes = []interface{}{
|
||||||
|
(*NodeInfo)(nil), // 0: rpc.NodeInfo
|
||||||
|
(*RegServiceDiscoverReq)(nil), // 1: rpc.RegServiceDiscoverReq
|
||||||
|
(*SubscribeDiscoverNotify)(nil), // 2: rpc.SubscribeDiscoverNotify
|
||||||
|
(*NodeRetireReq)(nil), // 3: rpc.NodeRetireReq
|
||||||
|
(*Empty)(nil), // 4: rpc.Empty
|
||||||
|
(*Ping)(nil), // 5: rpc.Ping
|
||||||
|
(*Pong)(nil), // 6: rpc.Pong
|
||||||
|
(*UnRegServiceDiscoverReq)(nil), // 7: rpc.UnRegServiceDiscoverReq
|
||||||
|
}
|
||||||
|
var file_rpcproto_origindiscover_proto_depIdxs = []int32{
|
||||||
|
0, // 0: rpc.RegServiceDiscoverReq.nodeInfo:type_name -> rpc.NodeInfo
|
||||||
|
0, // 1: rpc.SubscribeDiscoverNotify.nodeInfo:type_name -> rpc.NodeInfo
|
||||||
|
0, // 2: rpc.NodeRetireReq.nodeInfo:type_name -> rpc.NodeInfo
|
||||||
|
3, // [3:3] is the sub-list for method output_type
|
||||||
|
3, // [3:3] is the sub-list for method input_type
|
||||||
|
3, // [3:3] is the sub-list for extension type_name
|
||||||
|
3, // [3:3] is the sub-list for extension extendee
|
||||||
|
0, // [0:3] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_rpcproto_origindiscover_proto_init() }
|
||||||
|
func file_rpcproto_origindiscover_proto_init() {
|
||||||
|
if File_rpcproto_origindiscover_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_rpcproto_origindiscover_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*NodeInfo); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_rpcproto_origindiscover_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*RegServiceDiscoverReq); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_rpcproto_origindiscover_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*SubscribeDiscoverNotify); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_rpcproto_origindiscover_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*NodeRetireReq); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_rpcproto_origindiscover_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Empty); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_rpcproto_origindiscover_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Ping); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_rpcproto_origindiscover_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Pong); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_rpcproto_origindiscover_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*UnRegServiceDiscoverReq); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_rpcproto_origindiscover_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 8,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_rpcproto_origindiscover_proto_goTypes,
|
||||||
|
DependencyIndexes: file_rpcproto_origindiscover_proto_depIdxs,
|
||||||
|
MessageInfos: file_rpcproto_origindiscover_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_rpcproto_origindiscover_proto = out.File
|
||||||
|
file_rpcproto_origindiscover_proto_rawDesc = nil
|
||||||
|
file_rpcproto_origindiscover_proto_goTypes = nil
|
||||||
|
file_rpcproto_origindiscover_proto_depIdxs = nil
|
||||||
|
}
|
||||||
49
rpc/origindiscover.proto
Normal file
49
rpc/origindiscover.proto
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package rpc;
|
||||||
|
option go_package = ".;rpc";
|
||||||
|
|
||||||
|
message NodeInfo{
|
||||||
|
string NodeId = 1;
|
||||||
|
string ListenAddr = 2;
|
||||||
|
uint32 MaxRpcParamLen = 3;
|
||||||
|
bool Private = 4;
|
||||||
|
bool Retire = 5;
|
||||||
|
repeated string PublicServiceList = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Client->Master
|
||||||
|
message RegServiceDiscoverReq{
|
||||||
|
NodeInfo nodeInfo = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Master->Client
|
||||||
|
message SubscribeDiscoverNotify{
|
||||||
|
string MasterNodeId = 1;
|
||||||
|
bool IsFull = 2;
|
||||||
|
string DelNodeId = 3;
|
||||||
|
repeated NodeInfo nodeInfo = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Client->Master
|
||||||
|
message NodeRetireReq{
|
||||||
|
NodeInfo nodeInfo = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Master->Client
|
||||||
|
message Empty{
|
||||||
|
}
|
||||||
|
|
||||||
|
//Client->Master
|
||||||
|
message Ping{
|
||||||
|
string NodeId = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Master->Client
|
||||||
|
message Pong{
|
||||||
|
bool ok = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UnRegServiceDiscoverReq{
|
||||||
|
string NodeId = 1;
|
||||||
|
}
|
||||||
106
rpc/pbprocessor.go
Normal file
106
rpc/pbprocessor.go
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
package rpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/duanhf2012/origin/v2/util/sync"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PBProcessor struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var rpcPbResponseDataPool =sync.NewPool(make(chan interface{},10240), func()interface{}{
|
||||||
|
return &PBRpcResponseData{}
|
||||||
|
})
|
||||||
|
|
||||||
|
var rpcPbRequestDataPool =sync.NewPool(make(chan interface{},10240), func()interface{}{
|
||||||
|
return &PBRpcRequestData{}
|
||||||
|
})
|
||||||
|
|
||||||
|
func (slf *PBRpcRequestData) MakeRequest(seq uint64,rpcMethodId uint32,serviceMethod string,noReply bool,inParam []byte) *PBRpcRequestData{
|
||||||
|
slf.Seq = seq
|
||||||
|
slf.RpcMethodId = rpcMethodId
|
||||||
|
slf.ServiceMethod = serviceMethod
|
||||||
|
slf.NoReply = noReply
|
||||||
|
slf.InParam = inParam
|
||||||
|
|
||||||
|
return slf
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (slf *PBRpcResponseData) MakeRespone(seq uint64,err RpcError,reply []byte) *PBRpcResponseData{
|
||||||
|
slf.Seq = seq
|
||||||
|
slf.Error = err.Error()
|
||||||
|
slf.Reply = reply
|
||||||
|
|
||||||
|
return slf
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *PBProcessor) Marshal(v interface{}) ([]byte, error){
|
||||||
|
return proto.Marshal(v.(proto.Message))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *PBProcessor) Unmarshal(data []byte, msg interface{}) error{
|
||||||
|
protoMsg,ok := msg.(proto.Message)
|
||||||
|
if ok == false {
|
||||||
|
return fmt.Errorf("%+v is not of proto.Message type",msg)
|
||||||
|
}
|
||||||
|
return proto.Unmarshal(data, protoMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *PBProcessor) MakeRpcRequest(seq uint64,rpcMethodId uint32,serviceMethod string,noReply bool,inParam []byte) IRpcRequestData{
|
||||||
|
pGogoPbRpcRequestData := rpcPbRequestDataPool.Get().(*PBRpcRequestData)
|
||||||
|
pGogoPbRpcRequestData.MakeRequest(seq,rpcMethodId,serviceMethod,noReply,inParam)
|
||||||
|
return pGogoPbRpcRequestData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *PBProcessor) MakeRpcResponse(seq uint64,err RpcError,reply []byte) IRpcResponseData {
|
||||||
|
pPBRpcResponseData := rpcPbResponseDataPool.Get().(*PBRpcResponseData)
|
||||||
|
pPBRpcResponseData.MakeRespone(seq,err,reply)
|
||||||
|
return pPBRpcResponseData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *PBProcessor) ReleaseRpcRequest(rpcRequestData IRpcRequestData){
|
||||||
|
rpcPbRequestDataPool.Put(rpcRequestData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *PBProcessor) ReleaseRpcResponse(rpcResponseData IRpcResponseData){
|
||||||
|
rpcPbResponseDataPool.Put(rpcResponseData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *PBProcessor) IsParse(param interface{}) bool {
|
||||||
|
_,ok := param.(proto.Message)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *PBProcessor) GetProcessorType() RpcProcessorType{
|
||||||
|
return RpcProcessorPB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *PBProcessor) Clone(src interface{}) (interface{},error){
|
||||||
|
srcMsg,ok := src.(proto.Message)
|
||||||
|
if ok == false {
|
||||||
|
return nil,fmt.Errorf("param is not of proto.message type")
|
||||||
|
}
|
||||||
|
|
||||||
|
return proto.Clone(srcMsg),nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *PBRpcRequestData) IsNoReply() bool{
|
||||||
|
return slf.GetNoReply()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *PBRpcResponseData) GetErr() *RpcError {
|
||||||
|
if slf.GetError() == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := RpcError(slf.GetError())
|
||||||
|
return &err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
263
rpc/protorpc.pb.go
Normal file
263
rpc/protorpc.pb.go
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.31.0
|
||||||
|
// protoc v3.11.4
|
||||||
|
// source: test/rpc/protorpc.proto
|
||||||
|
|
||||||
|
package rpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type PBRpcRequestData struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Seq uint64 `protobuf:"varint,1,opt,name=Seq,proto3" json:"Seq,omitempty"`
|
||||||
|
RpcMethodId uint32 `protobuf:"varint,2,opt,name=RpcMethodId,proto3" json:"RpcMethodId,omitempty"`
|
||||||
|
ServiceMethod string `protobuf:"bytes,3,opt,name=ServiceMethod,proto3" json:"ServiceMethod,omitempty"`
|
||||||
|
NoReply bool `protobuf:"varint,4,opt,name=NoReply,proto3" json:"NoReply,omitempty"`
|
||||||
|
InParam []byte `protobuf:"bytes,5,opt,name=InParam,proto3" json:"InParam,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcRequestData) Reset() {
|
||||||
|
*x = PBRpcRequestData{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_test_rpc_protorpc_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcRequestData) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*PBRpcRequestData) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *PBRpcRequestData) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_test_rpc_protorpc_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use PBRpcRequestData.ProtoReflect.Descriptor instead.
|
||||||
|
func (*PBRpcRequestData) Descriptor() ([]byte, []int) {
|
||||||
|
return file_test_rpc_protorpc_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcRequestData) GetSeq() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Seq
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcRequestData) GetRpcMethodId() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.RpcMethodId
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcRequestData) GetServiceMethod() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.ServiceMethod
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcRequestData) GetNoReply() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.NoReply
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcRequestData) GetInParam() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.InParam
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type PBRpcResponseData struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Seq uint64 `protobuf:"varint,1,opt,name=Seq,proto3" json:"Seq,omitempty"`
|
||||||
|
Error string `protobuf:"bytes,2,opt,name=Error,proto3" json:"Error,omitempty"`
|
||||||
|
Reply []byte `protobuf:"bytes,3,opt,name=Reply,proto3" json:"Reply,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcResponseData) Reset() {
|
||||||
|
*x = PBRpcResponseData{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_test_rpc_protorpc_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcResponseData) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*PBRpcResponseData) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *PBRpcResponseData) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_test_rpc_protorpc_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use PBRpcResponseData.ProtoReflect.Descriptor instead.
|
||||||
|
func (*PBRpcResponseData) Descriptor() ([]byte, []int) {
|
||||||
|
return file_test_rpc_protorpc_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcResponseData) GetSeq() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Seq
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcResponseData) GetError() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Error
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PBRpcResponseData) GetReply() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Reply
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_test_rpc_protorpc_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_test_rpc_protorpc_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x17, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
|
0x72, 0x70, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x72, 0x70, 0x63, 0x22, 0xa0,
|
||||||
|
0x01, 0x0a, 0x10, 0x50, 0x42, 0x52, 0x70, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44,
|
||||||
|
0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x53, 0x65, 0x71, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
|
||||||
|
0x52, 0x03, 0x53, 0x65, 0x71, 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x70, 0x63, 0x4d, 0x65, 0x74, 0x68,
|
||||||
|
0x6f, 0x64, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x52, 0x70, 0x63, 0x4d,
|
||||||
|
0x65, 0x74, 0x68, 0x6f, 0x64, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69,
|
||||||
|
0x63, 0x65, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
|
||||||
|
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x18, 0x0a,
|
||||||
|
0x07, 0x4e, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
|
||||||
|
0x4e, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x49, 0x6e, 0x50, 0x61, 0x72,
|
||||||
|
0x61, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x49, 0x6e, 0x50, 0x61, 0x72, 0x61,
|
||||||
|
0x6d, 0x22, 0x51, 0x0a, 0x11, 0x50, 0x42, 0x52, 0x70, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
|
0x73, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x53, 0x65, 0x71, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x04, 0x52, 0x03, 0x53, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f,
|
||||||
|
0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x14,
|
||||||
|
0x0a, 0x05, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x52,
|
||||||
|
0x65, 0x70, 0x6c, 0x79, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x3b, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_test_rpc_protorpc_proto_rawDescOnce sync.Once
|
||||||
|
file_test_rpc_protorpc_proto_rawDescData = file_test_rpc_protorpc_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_test_rpc_protorpc_proto_rawDescGZIP() []byte {
|
||||||
|
file_test_rpc_protorpc_proto_rawDescOnce.Do(func() {
|
||||||
|
file_test_rpc_protorpc_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_rpc_protorpc_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_test_rpc_protorpc_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_test_rpc_protorpc_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||||
|
var file_test_rpc_protorpc_proto_goTypes = []interface{}{
|
||||||
|
(*PBRpcRequestData)(nil), // 0: rpc.PBRpcRequestData
|
||||||
|
(*PBRpcResponseData)(nil), // 1: rpc.PBRpcResponseData
|
||||||
|
}
|
||||||
|
var file_test_rpc_protorpc_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_test_rpc_protorpc_proto_init() }
|
||||||
|
func file_test_rpc_protorpc_proto_init() {
|
||||||
|
if File_test_rpc_protorpc_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_test_rpc_protorpc_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*PBRpcRequestData); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_test_rpc_protorpc_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*PBRpcResponseData); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_test_rpc_protorpc_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 2,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_test_rpc_protorpc_proto_goTypes,
|
||||||
|
DependencyIndexes: file_test_rpc_protorpc_proto_depIdxs,
|
||||||
|
MessageInfos: file_test_rpc_protorpc_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_test_rpc_protorpc_proto = out.File
|
||||||
|
file_test_rpc_protorpc_proto_rawDesc = nil
|
||||||
|
file_test_rpc_protorpc_proto_goTypes = nil
|
||||||
|
file_test_rpc_protorpc_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
package rpc;
|
package rpc;
|
||||||
option go_package = "./rpc";
|
option go_package = ".;rpc";
|
||||||
|
|
||||||
message GoGoPBRpcRequestData{
|
message PBRpcRequestData{
|
||||||
uint64 Seq = 1;
|
uint64 Seq = 1;
|
||||||
uint32 RpcMethodId = 2;
|
uint32 RpcMethodId = 2;
|
||||||
string ServiceMethod = 3;
|
string ServiceMethod = 3;
|
||||||
@@ -10,7 +10,7 @@ message GoGoPBRpcRequestData{
|
|||||||
bytes InParam = 5;
|
bytes InParam = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GoGoPBRpcResponseData{
|
message PBRpcResponseData{
|
||||||
uint64 Seq = 1;
|
uint64 Seq = 1;
|
||||||
string Error = 2;
|
string Error = 2;
|
||||||
bytes Reply = 3;
|
bytes Reply = 3;
|
||||||
6224
rpc/rank.pb.go
6224
rpc/rank.pb.go
File diff suppressed because it is too large
Load Diff
201
rpc/rclient.go
201
rpc/rclient.go
@@ -1,14 +1,14 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/network"
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//跨结点连接的Client
|
//跨结点连接的Client
|
||||||
@@ -16,7 +16,8 @@ type RClient struct {
|
|||||||
selfClient *Client
|
selfClient *Client
|
||||||
network.TCPClient
|
network.TCPClient
|
||||||
conn *network.TCPConn
|
conn *network.TCPConn
|
||||||
TriggerRpcConnEvent
|
|
||||||
|
notifyEventFun NotifyEventFun
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RClient) IsConnected() bool {
|
func (rc *RClient) IsConnected() bool {
|
||||||
@@ -40,102 +41,34 @@ func (rc *RClient) SetConn(conn *network.TCPConn){
|
|||||||
rc.Unlock()
|
rc.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RClient) Go(rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
|
func (rc *RClient) WriteMsg (nodeId string,args ...[]byte) error{
|
||||||
|
return rc.conn.WriteMsg(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *RClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
|
||||||
_, processor := GetProcessorType(args)
|
_, processor := GetProcessorType(args)
|
||||||
InParam, err := processor.Marshal(args)
|
InParam, err := processor.Marshal(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("Marshal is fail",log.ErrorAttr("error",err))
|
||||||
call := MakeCall()
|
call := MakeCall()
|
||||||
call.Err = err
|
call.DoError(err)
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc.RawGo(rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply)
|
return rc.selfClient.rawGo(nodeId,rc,timeout,rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rc *RClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call {
|
||||||
func (rc *RClient) RawGo(rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call {
|
return rc.selfClient.rawGo(nodeId,rc,timeout,rpcHandler,processor, noReply, rpcMethodId, serviceMethod, rawArgs, reply)
|
||||||
call := MakeCall()
|
|
||||||
call.ServiceMethod = serviceMethod
|
|
||||||
call.Reply = reply
|
|
||||||
call.Seq = rc.selfClient.generateSeq()
|
|
||||||
|
|
||||||
request := MakeRpcRequest(processor, call.Seq, rpcMethodId, serviceMethod, noReply, rawArgs)
|
|
||||||
bytes, err := processor.Marshal(request.RpcRequestData)
|
|
||||||
ReleaseRpcRequest(request)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
call.Seq = 0
|
|
||||||
call.Err = err
|
|
||||||
return call
|
|
||||||
}
|
|
||||||
|
|
||||||
conn := rc.GetConn()
|
|
||||||
if conn == nil || conn.IsConnected()==false {
|
|
||||||
call.Seq = 0
|
|
||||||
call.Err = errors.New(serviceMethod + " was called failed,rpc client is disconnect")
|
|
||||||
return call
|
|
||||||
}
|
|
||||||
|
|
||||||
if noReply == false {
|
|
||||||
rc.selfClient.AddPending(call)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = conn.WriteMsg([]byte{uint8(processor.GetProcessorType())}, bytes)
|
|
||||||
if err != nil {
|
|
||||||
rc.selfClient.RemovePending(call.Seq)
|
|
||||||
call.Seq = 0
|
|
||||||
call.Err = err
|
|
||||||
}
|
|
||||||
|
|
||||||
return call
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rc *RClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) {
|
||||||
func (rc *RClient) AsyncCall(rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) error {
|
cancelRpc,err := rc.selfClient.asyncCall(nodeId,rc,timeout,rpcHandler, serviceMethod, callback, args, replyParam,cancelable)
|
||||||
err := rc.asyncCall(rpcHandler, serviceMethod, callback, args, replyParam)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
callback.Call([]reflect.Value{reflect.ValueOf(replyParam), reflect.ValueOf(err)})
|
callback.Call([]reflect.Value{reflect.ValueOf(replyParam), reflect.ValueOf(err)})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return cancelRpc,nil
|
||||||
}
|
|
||||||
|
|
||||||
func (rc *RClient) asyncCall(rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) error {
|
|
||||||
processorType, processor := GetProcessorType(args)
|
|
||||||
InParam, herr := processor.Marshal(args)
|
|
||||||
if herr != nil {
|
|
||||||
return herr
|
|
||||||
}
|
|
||||||
|
|
||||||
seq := rc.selfClient.generateSeq()
|
|
||||||
request := MakeRpcRequest(processor, seq, 0, serviceMethod, false, InParam)
|
|
||||||
bytes, err := processor.Marshal(request.RpcRequestData)
|
|
||||||
ReleaseRpcRequest(request)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
conn := rc.GetConn()
|
|
||||||
if conn == nil || conn.IsConnected()==false {
|
|
||||||
return errors.New("Rpc server is disconnect,call " + serviceMethod)
|
|
||||||
}
|
|
||||||
|
|
||||||
call := MakeCall()
|
|
||||||
call.Reply = replyParam
|
|
||||||
call.callback = &callback
|
|
||||||
call.rpcHandler = rpcHandler
|
|
||||||
call.ServiceMethod = serviceMethod
|
|
||||||
call.Seq = seq
|
|
||||||
rc.selfClient.AddPending(call)
|
|
||||||
|
|
||||||
err = conn.WriteMsg([]byte{uint8(processorType)}, bytes)
|
|
||||||
if err != nil {
|
|
||||||
rc.selfClient.RemovePending(call.Seq)
|
|
||||||
ReleaseCall(call)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RClient) Run() {
|
func (rc *RClient) Run() {
|
||||||
@@ -144,86 +77,53 @@ func (rc *RClient) Run() {
|
|||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
l := runtime.Stack(buf, false)
|
l := runtime.Stack(buf, false)
|
||||||
errString := fmt.Sprint(r)
|
errString := fmt.Sprint(r)
|
||||||
log.SError("core dump info[", errString, "]\n", string(buf[:l]))
|
log.Dump(string(buf[:l]),log.String("error",errString))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
rc.TriggerRpcConnEvent(true, rc.selfClient.GetClientId(), rc.selfClient.GetNodeId())
|
var eventData RpcConnEvent
|
||||||
|
eventData.IsConnect = true
|
||||||
|
eventData.NodeId = rc.selfClient.GetTargetNodeId()
|
||||||
|
rc.notifyEventFun(&eventData)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
bytes, err := rc.conn.ReadMsg()
|
bytes, err := rc.conn.ReadMsg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("rpcClient ", rc.Addr, " ReadMsg error:", err.Error())
|
log.Error("rclient read msg is failed",log.ErrorAttr("error",err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
processor := GetProcessor(bytes[0])
|
err = rc.selfClient.processRpcResponse(bytes)
|
||||||
if processor == nil {
|
|
||||||
rc.conn.ReleaseReadMsg(bytes)
|
|
||||||
log.SError("rpcClient ", rc.Addr, " ReadMsg head error:", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//1.解析head
|
|
||||||
response := RpcResponse{}
|
|
||||||
response.RpcResponseData = processor.MakeRpcResponse(0, "", nil)
|
|
||||||
|
|
||||||
err = processor.Unmarshal(bytes[1:], response.RpcResponseData)
|
|
||||||
rc.conn.ReleaseReadMsg(bytes)
|
rc.conn.ReleaseReadMsg(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
processor.ReleaseRpcResponse(response.RpcResponseData)
|
return
|
||||||
log.SError("rpcClient Unmarshal head error:", err.Error())
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v := rc.selfClient.RemovePending(response.RpcResponseData.GetSeq())
|
|
||||||
if v == nil {
|
|
||||||
log.SError("rpcClient cannot find seq ", response.RpcResponseData.GetSeq(), " in pending")
|
|
||||||
} else {
|
|
||||||
v.Err = nil
|
|
||||||
if len(response.RpcResponseData.GetReply()) > 0 {
|
|
||||||
err = processor.Unmarshal(response.RpcResponseData.GetReply(), v.Reply)
|
|
||||||
if err != nil {
|
|
||||||
log.SError("rpcClient Unmarshal body error:", err.Error())
|
|
||||||
v.Err = err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if response.RpcResponseData.GetErr() != nil {
|
|
||||||
v.Err = response.RpcResponseData.GetErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.callback != nil && v.callback.IsValid() {
|
|
||||||
v.rpcHandler.PushRpcResponse(v)
|
|
||||||
} else {
|
|
||||||
v.done <- v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processor.ReleaseRpcResponse(response.RpcResponseData)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RClient) OnClose() {
|
func (rc *RClient) OnClose() {
|
||||||
rc.TriggerRpcConnEvent(false, rc.selfClient.GetClientId(), rc.selfClient.GetNodeId())
|
var connEvent RpcConnEvent
|
||||||
|
connEvent.IsConnect = false
|
||||||
|
connEvent.NodeId = rc.selfClient.GetTargetNodeId()
|
||||||
|
rc.notifyEventFun(&connEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRClient(nodeId int, addr string, maxRpcParamLen uint32,triggerRpcConnEvent TriggerRpcConnEvent) *Client{
|
func NewRClient(targetNodeId string, addr string, maxRpcParamLen uint32,compressBytesLen int,callSet *CallSet,notifyEventFun NotifyEventFun) *Client{
|
||||||
client := &Client{}
|
client := &Client{}
|
||||||
client.clientId = atomic.AddUint32(&clientSeq, 1)
|
client.clientId = atomic.AddUint32(&clientSeq, 1)
|
||||||
client.nodeId = nodeId
|
client.targetNodeId = targetNodeId
|
||||||
client.maxCheckCallRpcCount = MaxCheckCallRpcCount
|
client.compressBytesLen = compressBytesLen
|
||||||
client.callRpcTimeout = DefaultRpcTimeout
|
|
||||||
|
|
||||||
c:= &RClient{}
|
c:= &RClient{}
|
||||||
c.selfClient = client
|
c.selfClient = client
|
||||||
c.Addr = addr
|
c.Addr = addr
|
||||||
c.ConnectInterval = ConnectInterval
|
c.ConnectInterval = DefaultConnectInterval
|
||||||
c.PendingWriteNum = MaxPendingWriteNum
|
c.PendingWriteNum = DefaultMaxPendingWriteNum
|
||||||
c.AutoReconnect = true
|
c.AutoReconnect = true
|
||||||
c.TriggerRpcConnEvent = triggerRpcConnEvent
|
c.notifyEventFun = notifyEventFun
|
||||||
c.ConnNum = RpcConnNum
|
c.ConnNum = DefaultRpcConnNum
|
||||||
c.LenMsgLen = RpcLenMsgLen
|
c.LenMsgLen = DefaultRpcLenMsgLen
|
||||||
c.MinMsgLen = RpcMinMsgLen
|
c.MinMsgLen = DefaultRpcMinMsgLen
|
||||||
c.ReadDeadline = Default_ReadWriteDeadline
|
c.ReadDeadline = Default_ReadWriteDeadline
|
||||||
c.WriteDeadline = Default_ReadWriteDeadline
|
c.WriteDeadline = Default_ReadWriteDeadline
|
||||||
c.LittleEndian = LittleEndian
|
c.LittleEndian = LittleEndian
|
||||||
@@ -235,8 +135,7 @@ func NewRClient(nodeId int, addr string, maxRpcParamLen uint32,triggerRpcConnEve
|
|||||||
c.MaxMsgLen = math.MaxUint32
|
c.MaxMsgLen = math.MaxUint32
|
||||||
}
|
}
|
||||||
client.IRealClient = c
|
client.IRealClient = c
|
||||||
client.InitPending()
|
client.CallSet = callSet
|
||||||
go client.checkRpcCallTimeout()
|
|
||||||
c.Start()
|
c.Start()
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
@@ -244,18 +143,10 @@ func NewRClient(nodeId int, addr string, maxRpcParamLen uint32,triggerRpcConnEve
|
|||||||
|
|
||||||
func (rc *RClient) Close(waitDone bool) {
|
func (rc *RClient) Close(waitDone bool) {
|
||||||
rc.TCPClient.Close(waitDone)
|
rc.TCPClient.Close(waitDone)
|
||||||
|
rc.selfClient.cleanPending()
|
||||||
rc.selfClient.pendingLock.Lock()
|
|
||||||
for {
|
|
||||||
pElem := rc.selfClient.pendingTimer.Front()
|
|
||||||
if pElem == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
pCall := pElem.Value.(*Call)
|
|
||||||
pCall.Err = errors.New("nodeid is disconnect ")
|
|
||||||
rc.selfClient.makeCallFail(pCall)
|
|
||||||
}
|
|
||||||
rc.selfClient.pendingLock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (rc *RClient) Bind(server IServer){
|
||||||
|
|
||||||
|
}
|
||||||
24
rpc/rpc.go
24
rpc/rpc.go
@@ -1,7 +1,7 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/util/sync"
|
"github.com/duanhf2012/origin/v2/util/sync"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -68,7 +68,16 @@ type Call struct {
|
|||||||
connId int
|
connId int
|
||||||
callback *reflect.Value
|
callback *reflect.Value
|
||||||
rpcHandler IRpcHandler
|
rpcHandler IRpcHandler
|
||||||
callTime time.Time
|
TimeOut time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
type RpcCancel struct {
|
||||||
|
Cli *Client
|
||||||
|
CallSeq uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *RpcCancel) CancelRpc(){
|
||||||
|
rc.Cli.RemovePending(rc.CallSeq)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *RpcRequest) Clear() *RpcRequest{
|
func (slf *RpcRequest) Clear() *RpcRequest{
|
||||||
@@ -102,6 +111,15 @@ func (rpcResponse *RpcResponse) Clear() *RpcResponse{
|
|||||||
return rpcResponse
|
return rpcResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (call *Call) DoError(err error){
|
||||||
|
call.Err = err
|
||||||
|
call.done <- call
|
||||||
|
}
|
||||||
|
|
||||||
|
func (call *Call) DoOK(){
|
||||||
|
call.done <- call
|
||||||
|
}
|
||||||
|
|
||||||
func (call *Call) Clear() *Call{
|
func (call *Call) Clear() *Call{
|
||||||
call.Seq = 0
|
call.Seq = 0
|
||||||
call.ServiceMethod = ""
|
call.ServiceMethod = ""
|
||||||
@@ -115,6 +133,8 @@ func (call *Call) Clear() *Call{
|
|||||||
call.connId = 0
|
call.connId = 0
|
||||||
call.callback = nil
|
call.callback = nil
|
||||||
call.rpcHandler = nil
|
call.rpcHandler = nil
|
||||||
|
call.TimeOut = 0
|
||||||
|
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
rpc/rpcevent.go
Normal file
23
rpc/rpcevent.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package rpc
|
||||||
|
|
||||||
|
import "github.com/duanhf2012/origin/v2/event"
|
||||||
|
|
||||||
|
type NotifyEventFun func (event event.IEvent)
|
||||||
|
|
||||||
|
// RpcConnEvent Node结点连接事件
|
||||||
|
type RpcConnEvent struct{
|
||||||
|
IsConnect bool
|
||||||
|
NodeId string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *RpcConnEvent) GetEventType() event.EventType{
|
||||||
|
return event.Sys_Event_Node_Conn_Event
|
||||||
|
}
|
||||||
|
|
||||||
|
type NatsConnEvent struct {
|
||||||
|
IsConnect bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nc *NatsConnEvent) GetEventType() event.EventType{
|
||||||
|
return event.Sys_Event_Nats_Conn_Event
|
||||||
|
}
|
||||||
@@ -3,19 +3,21 @@ package rpc
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxClusterNode int = 128
|
const maxClusterNode int = 32
|
||||||
|
|
||||||
type FuncRpcClient func(nodeId int, serviceMethod string, client []*Client) (error, int)
|
|
||||||
type FuncRpcServer func() *Server
|
|
||||||
|
|
||||||
|
type FuncRpcClient func(nodeId string, serviceMethod string,filterRetire bool, client []*Client) (error, []*Client)
|
||||||
|
type FuncRpcServer func() IServer
|
||||||
|
const NodeIdNull = ""
|
||||||
|
|
||||||
var nilError = reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())
|
var nilError = reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())
|
||||||
|
|
||||||
@@ -61,20 +63,30 @@ type RpcHandler struct {
|
|||||||
funcRpcClient FuncRpcClient
|
funcRpcClient FuncRpcClient
|
||||||
funcRpcServer FuncRpcServer
|
funcRpcServer FuncRpcServer
|
||||||
|
|
||||||
pClientList []*Client
|
//pClientList []*Client
|
||||||
}
|
}
|
||||||
|
|
||||||
type TriggerRpcConnEvent func(bConnect bool, clientSeq uint32, nodeId int)
|
//type TriggerRpcConnEvent func(bConnect bool, clientSeq uint32, nodeId string)
|
||||||
type INodeListener interface {
|
type NotifyEventToAllService func(event event.IEvent)
|
||||||
OnNodeConnected(nodeId int)
|
|
||||||
OnNodeDisconnect(nodeId int)
|
type INodeConnListener interface {
|
||||||
|
OnNodeConnected(nodeId string)
|
||||||
|
OnNodeDisconnect(nodeId string)
|
||||||
|
}
|
||||||
|
|
||||||
|
type INatsConnListener interface {
|
||||||
|
OnNatsConnected()
|
||||||
|
OnNatsDisconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
type IDiscoveryServiceListener interface {
|
type IDiscoveryServiceListener interface {
|
||||||
OnDiscoveryService(nodeId int, serviceName []string)
|
OnDiscoveryService(nodeId string, serviceName []string)
|
||||||
OnUnDiscoveryService(nodeId int, serviceName []string)
|
OnUnDiscoveryService(nodeId string, serviceName []string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CancelRpc func()
|
||||||
|
func emptyCancelRpc(){}
|
||||||
|
|
||||||
type IRpcHandler interface {
|
type IRpcHandler interface {
|
||||||
IRpcHandlerChannel
|
IRpcHandlerChannel
|
||||||
GetName() string
|
GetName() string
|
||||||
@@ -83,15 +95,21 @@ type IRpcHandler interface {
|
|||||||
HandlerRpcRequest(request *RpcRequest)
|
HandlerRpcRequest(request *RpcRequest)
|
||||||
HandlerRpcResponseCB(call *Call)
|
HandlerRpcResponseCB(call *Call)
|
||||||
CallMethod(client *Client,ServiceMethod string, param interface{},callBack reflect.Value, reply interface{}) error
|
CallMethod(client *Client,ServiceMethod string, param interface{},callBack reflect.Value, reply interface{}) error
|
||||||
AsyncCall(serviceMethod string, args interface{}, callback interface{}) error
|
|
||||||
Call(serviceMethod string, args interface{}, reply interface{}) error
|
Call(serviceMethod string, args interface{}, reply interface{}) error
|
||||||
|
CallNode(nodeId string, serviceMethod string, args interface{}, reply interface{}) error
|
||||||
|
AsyncCall(serviceMethod string, args interface{}, callback interface{}) error
|
||||||
|
AsyncCallNode(nodeId string, serviceMethod string, args interface{}, callback interface{}) error
|
||||||
|
|
||||||
|
CallWithTimeout(timeout time.Duration,serviceMethod string, args interface{}, reply interface{}) error
|
||||||
|
CallNodeWithTimeout(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, reply interface{}) error
|
||||||
|
AsyncCallWithTimeout(timeout time.Duration,serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error)
|
||||||
|
AsyncCallNodeWithTimeout(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error)
|
||||||
|
|
||||||
Go(serviceMethod string, args interface{}) error
|
Go(serviceMethod string, args interface{}) error
|
||||||
AsyncCallNode(nodeId int, serviceMethod string, args interface{}, callback interface{}) error
|
GoNode(nodeId string, serviceMethod string, args interface{}) error
|
||||||
CallNode(nodeId int, serviceMethod string, args interface{}, reply interface{}) error
|
RawGoNode(rpcProcessorType RpcProcessorType, nodeId string, rpcMethodId uint32, serviceName string, rawArgs []byte) error
|
||||||
GoNode(nodeId int, serviceMethod string, args interface{}) error
|
|
||||||
RawGoNode(rpcProcessorType RpcProcessorType, nodeId int, rpcMethodId uint32, serviceName string, rawArgs []byte) error
|
|
||||||
CastGo(serviceMethod string, args interface{}) error
|
CastGo(serviceMethod string, args interface{}) error
|
||||||
IsSingleCoroutine() bool
|
|
||||||
UnmarshalInParam(rpcProcessor IRpcProcessor, serviceMethod string, rawRpcMethodId uint32, inParam []byte) (interface{}, error)
|
UnmarshalInParam(rpcProcessor IRpcProcessor, serviceMethod string, rawRpcMethodId uint32, inParam []byte) (interface{}, error)
|
||||||
GetRpcServer() FuncRpcServer
|
GetRpcServer() FuncRpcServer
|
||||||
}
|
}
|
||||||
@@ -116,7 +134,6 @@ func (handler *RpcHandler) InitRpcHandler(rpcHandler IRpcHandler, getClientFun F
|
|||||||
handler.mapFunctions = map[string]RpcMethodInfo{}
|
handler.mapFunctions = map[string]RpcMethodInfo{}
|
||||||
handler.funcRpcClient = getClientFun
|
handler.funcRpcClient = getClientFun
|
||||||
handler.funcRpcServer = getServerFun
|
handler.funcRpcServer = getServerFun
|
||||||
handler.pClientList = make([]*Client, maxClusterNode)
|
|
||||||
handler.RegisterRpc(rpcHandler)
|
handler.RegisterRpc(rpcHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +221,7 @@ func (handler *RpcHandler) HandlerRpcResponseCB(call *Call) {
|
|||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
l := runtime.Stack(buf, false)
|
l := runtime.Stack(buf, false)
|
||||||
errString := fmt.Sprint(r)
|
errString := fmt.Sprint(r)
|
||||||
log.SError("core dump info[", errString, "]\n", string(buf[:l]))
|
log.Dump(string(buf[:l]),log.String("error",errString))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -226,7 +243,7 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
|
|||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
l := runtime.Stack(buf, false)
|
l := runtime.Stack(buf, false)
|
||||||
errString := fmt.Sprint(r)
|
errString := fmt.Sprint(r)
|
||||||
log.SError("Handler Rpc ", request.RpcRequestData.GetServiceMethod(), " Core dump info[", errString, "]\n", string(buf[:l]))
|
log.Dump(string(buf[:l]),log.String("error",errString))
|
||||||
rpcErr := RpcError("call error : core dumps")
|
rpcErr := RpcError("call error : core dumps")
|
||||||
if request.requestHandle != nil {
|
if request.requestHandle != nil {
|
||||||
request.requestHandle(nil, rpcErr)
|
request.requestHandle(nil, rpcErr)
|
||||||
@@ -239,12 +256,12 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
|
|||||||
if rawRpcId > 0 {
|
if rawRpcId > 0 {
|
||||||
v, ok := handler.mapRawFunctions[rawRpcId]
|
v, ok := handler.mapRawFunctions[rawRpcId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
log.SError("RpcHandler cannot find request rpc id", rawRpcId)
|
log.Error("RpcHandler cannot find request rpc id",log.Uint32("rawRpcId",rawRpcId))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rawData,ok := request.inParam.([]byte)
|
rawData,ok := request.inParam.([]byte)
|
||||||
if ok == false {
|
if ok == false {
|
||||||
log.SError("RpcHandler " + handler.rpcHandler.GetName()," cannot convert in param to []byte", rawRpcId)
|
log.Error("RpcHandler cannot convert",log.String("RpcHandlerName",handler.rpcHandler.GetName()),log.Uint32("rawRpcId",rawRpcId))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,8 +272,8 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
|
|||||||
//普通的rpc请求
|
//普通的rpc请求
|
||||||
v, ok := handler.mapFunctions[request.RpcRequestData.GetServiceMethod()]
|
v, ok := handler.mapFunctions[request.RpcRequestData.GetServiceMethod()]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
err := "RpcHandler " + handler.rpcHandler.GetName() + "cannot find " + request.RpcRequestData.GetServiceMethod()
|
err := "RpcHandler " + handler.rpcHandler.GetName() + " cannot find " + request.RpcRequestData.GetServiceMethod()
|
||||||
log.SError(err)
|
log.Error("HandlerRpcRequest cannot find serviceMethod",log.String("RpcHandlerName",handler.rpcHandler.GetName()),log.String("serviceMethod",request.RpcRequestData.GetServiceMethod()))
|
||||||
if request.requestHandle != nil {
|
if request.requestHandle != nil {
|
||||||
request.requestHandle(nil, RpcError(err))
|
request.requestHandle(nil, RpcError(err))
|
||||||
}
|
}
|
||||||
@@ -287,18 +304,20 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
|
|||||||
paramList = append(paramList, oParam) //输出参数
|
paramList = append(paramList, oParam) //输出参数
|
||||||
} else if request.requestHandle != nil && v.hasResponder == false { //调用方有返回值,但被调用函数没有返回参数
|
} else if request.requestHandle != nil && v.hasResponder == false { //调用方有返回值,但被调用函数没有返回参数
|
||||||
rErr := "Call Rpc " + request.RpcRequestData.GetServiceMethod() + " without return parameter!"
|
rErr := "Call Rpc " + request.RpcRequestData.GetServiceMethod() + " without return parameter!"
|
||||||
log.SError(rErr)
|
log.Error("call serviceMethod without return parameter",log.String("serviceMethod",request.RpcRequestData.GetServiceMethod()))
|
||||||
request.requestHandle(nil, RpcError(rErr))
|
request.requestHandle(nil, RpcError(rErr))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requestHanle := request.requestHandle
|
||||||
returnValues := v.method.Func.Call(paramList)
|
returnValues := v.method.Func.Call(paramList)
|
||||||
errInter := returnValues[0].Interface()
|
errInter := returnValues[0].Interface()
|
||||||
if errInter != nil {
|
if errInter != nil {
|
||||||
err = errInter.(error)
|
err = errInter.(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.requestHandle != nil && v.hasResponder == false {
|
if v.hasResponder == false && requestHanle != nil {
|
||||||
request.requestHandle(oParam.Interface(), ConvertError(err))
|
requestHanle(oParam.Interface(), ConvertError(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +326,7 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
|
|||||||
v, ok := handler.mapFunctions[ServiceMethod]
|
v, ok := handler.mapFunctions[ServiceMethod]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
err = errors.New("RpcHandler " + handler.rpcHandler.GetName() + " cannot find" + ServiceMethod)
|
err = errors.New("RpcHandler " + handler.rpcHandler.GetName() + " cannot find" + ServiceMethod)
|
||||||
log.SError(err.Error())
|
log.Error("CallMethod cannot find serviceMethod",log.String("rpcHandlerName",handler.rpcHandler.GetName()),log.String("serviceMethod",ServiceMethod))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +340,8 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
|
|||||||
pCall.callback = &callBack
|
pCall.callback = &callBack
|
||||||
pCall.Seq = client.generateSeq()
|
pCall.Seq = client.generateSeq()
|
||||||
callSeq = pCall.Seq
|
callSeq = pCall.Seq
|
||||||
|
pCall.TimeOut = DefaultRpcTimeout
|
||||||
|
pCall.ServiceMethod = ServiceMethod
|
||||||
client.AddPending(pCall)
|
client.AddPending(pCall)
|
||||||
|
|
||||||
//有返回值时
|
//有返回值时
|
||||||
@@ -330,7 +350,7 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
|
|||||||
hander :=func(Returns interface{}, Err RpcError) {
|
hander :=func(Returns interface{}, Err RpcError) {
|
||||||
rpcCall := client.RemovePending(callSeq)
|
rpcCall := client.RemovePending(callSeq)
|
||||||
if rpcCall == nil {
|
if rpcCall == nil {
|
||||||
log.SError("cannot find call seq ",callSeq)
|
log.Error("cannot find call seq",log.Uint64("seq",callSeq))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,26 +432,26 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) goRpc(processor IRpcProcessor, bCast bool, nodeId int, serviceMethod string, args interface{}) error {
|
func (handler *RpcHandler) goRpc(processor IRpcProcessor, bCast bool, nodeId string, serviceMethod string, args interface{}) error {
|
||||||
var pClientList [maxClusterNode]*Client
|
pClientList :=make([]*Client,0,maxClusterNode)
|
||||||
err, count := handler.funcRpcClient(nodeId, serviceMethod, pClientList[:])
|
err, pClientList := handler.funcRpcClient(nodeId, serviceMethod,false, pClientList)
|
||||||
if count == 0 {
|
if len(pClientList) == 0 {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("Call ", serviceMethod, " is error:", err.Error())
|
log.Error("call serviceMethod is failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err))
|
||||||
} else {
|
} else {
|
||||||
log.SError("Can not find ", serviceMethod)
|
log.Error("cannot find serviceMethod",log.String("serviceMethod",serviceMethod))
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if count > 1 && bCast == false {
|
if len(pClientList) > 1 && bCast == false {
|
||||||
log.SError("Cannot call %s more then 1 node!", serviceMethod)
|
log.Error("cannot call serviceMethod more then 1 node",log.String("serviceMethod",serviceMethod))
|
||||||
return errors.New("cannot call more then 1 node")
|
return errors.New("cannot call more then 1 node")
|
||||||
}
|
}
|
||||||
|
|
||||||
//2.rpcClient调用
|
//2.rpcClient调用
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < len(pClientList); i++ {
|
||||||
pCall := pClientList[i].Go(handler.rpcHandler,true, serviceMethod, args, nil)
|
pCall := pClientList[i].Go(pClientList[i].GetTargetNodeId(),DefaultRpcTimeout,handler.rpcHandler,true, serviceMethod, args, nil)
|
||||||
if pCall.Err != nil {
|
if pCall.Err != nil {
|
||||||
err = pCall.Err
|
err = pCall.Err
|
||||||
}
|
}
|
||||||
@@ -442,28 +462,23 @@ func (handler *RpcHandler) goRpc(processor IRpcProcessor, bCast bool, nodeId int
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) callRpc(nodeId int, serviceMethod string, args interface{}, reply interface{}) error {
|
func (handler *RpcHandler) callRpc(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, reply interface{}) error {
|
||||||
var pClientList [maxClusterNode]*Client
|
pClientList :=make([]*Client,0,maxClusterNode)
|
||||||
err, count := handler.funcRpcClient(nodeId, serviceMethod, pClientList[:])
|
err, pClientList := handler.funcRpcClient(nodeId, serviceMethod,false, pClientList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("Call serviceMethod is error:", err.Error())
|
log.Error("Call serviceMethod is failed",log.ErrorAttr("error",err))
|
||||||
return err
|
return err
|
||||||
} else if count <= 0 {
|
} else if len(pClientList) <= 0 {
|
||||||
err = errors.New("Call serviceMethod is error:cannot find " + serviceMethod)
|
err = errors.New("Call serviceMethod is error:cannot find " + serviceMethod)
|
||||||
log.SError(err.Error())
|
log.Error("cannot find serviceMethod",log.String("serviceMethod",serviceMethod))
|
||||||
return err
|
return err
|
||||||
} else if count > 1 {
|
} else if len(pClientList) > 1 {
|
||||||
log.SError("Cannot call more then 1 node!")
|
log.Error("Cannot call more then 1 node!",log.String("serviceMethod",serviceMethod))
|
||||||
return errors.New("cannot call more then 1 node")
|
return errors.New("cannot call more then 1 node")
|
||||||
}
|
}
|
||||||
|
|
||||||
pClient := pClientList[0]
|
pClient := pClientList[0]
|
||||||
pCall := pClient.Go(handler.rpcHandler,false, serviceMethod, args, reply)
|
pCall := pClient.Go(pClient.GetTargetNodeId(),timeout,handler.rpcHandler,false, serviceMethod, args, reply)
|
||||||
if pCall.Err != nil {
|
|
||||||
err = pCall.Err
|
|
||||||
ReleaseCall(pCall)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = pCall.Done().Err
|
err = pCall.Done().Err
|
||||||
pClient.RemovePending(pCall.Seq)
|
pClient.RemovePending(pCall.Seq)
|
||||||
@@ -471,117 +486,129 @@ func (handler *RpcHandler) callRpc(nodeId int, serviceMethod string, args interf
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) asyncCallRpc(nodeId int, serviceMethod string, args interface{}, callback interface{}) error {
|
func (handler *RpcHandler) asyncCallRpc(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error) {
|
||||||
fVal := reflect.ValueOf(callback)
|
fVal := reflect.ValueOf(callback)
|
||||||
if fVal.Kind() != reflect.Func {
|
if fVal.Kind() != reflect.Func {
|
||||||
err := errors.New("call " + serviceMethod + " input callback param is error!")
|
err := errors.New("call " + serviceMethod + " input callback param is error!")
|
||||||
log.SError(err.Error())
|
log.Error("input callback param is error",log.String("serviceMethod",serviceMethod))
|
||||||
return err
|
return emptyCancelRpc,err
|
||||||
}
|
}
|
||||||
|
|
||||||
if fVal.Type().NumIn() != 2 {
|
if fVal.Type().NumIn() != 2 {
|
||||||
err := errors.New("call " + serviceMethod + " callback param function is error!")
|
err := errors.New("call " + serviceMethod + " callback param function is error!")
|
||||||
log.SError(err.Error())
|
log.Error("callback param function is error",log.String("serviceMethod",serviceMethod))
|
||||||
return err
|
return emptyCancelRpc,err
|
||||||
}
|
}
|
||||||
|
|
||||||
if fVal.Type().In(0).Kind() != reflect.Ptr || fVal.Type().In(1).String() != "error" {
|
if fVal.Type().In(0).Kind() != reflect.Ptr || fVal.Type().In(1).String() != "error" {
|
||||||
err := errors.New("call " + serviceMethod + " callback param function is error!")
|
err := errors.New("call " + serviceMethod + " callback param function is error!")
|
||||||
log.SError(err.Error())
|
log.Error("callback param function is error",log.String("serviceMethod",serviceMethod))
|
||||||
return err
|
return emptyCancelRpc,err
|
||||||
}
|
}
|
||||||
|
|
||||||
reply := reflect.New(fVal.Type().In(0).Elem()).Interface()
|
reply := reflect.New(fVal.Type().In(0).Elem()).Interface()
|
||||||
var pClientList [2]*Client
|
pClientList :=make([]*Client,0,1)
|
||||||
err, count := handler.funcRpcClient(nodeId, serviceMethod, pClientList[:])
|
err, pClientList := handler.funcRpcClient(nodeId, serviceMethod,false, pClientList[:])
|
||||||
if count == 0 || err != nil {
|
if len(pClientList) == 0 || err != nil {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if nodeId > 0 {
|
if nodeId != NodeIdNull {
|
||||||
err = fmt.Errorf("cannot find %s from nodeId %d",serviceMethod,nodeId)
|
err = fmt.Errorf("cannot find %s from nodeId %d",serviceMethod,nodeId)
|
||||||
}else {
|
}else {
|
||||||
err = fmt.Errorf("No %s service found in the origin network",serviceMethod)
|
err = fmt.Errorf("No %s service found in the origin network",serviceMethod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fVal.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
|
fVal.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
|
||||||
log.SError("Call serviceMethod is error:", err.Error())
|
log.Error("cannot find serviceMethod from node",log.String("serviceMethod",serviceMethod),log.String("nodeId",nodeId))
|
||||||
return nil
|
return emptyCancelRpc,nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if count > 1 {
|
if len(pClientList) > 1 {
|
||||||
err := errors.New("cannot call more then 1 node")
|
err := errors.New("cannot call more then 1 node")
|
||||||
fVal.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
|
fVal.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
|
||||||
log.SError(err.Error())
|
log.Error("cannot call more then 1 node",log.String("serviceMethod",serviceMethod))
|
||||||
return nil
|
return emptyCancelRpc,nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//2.rpcClient调用
|
//2.rpcClient调用
|
||||||
//如果调用本结点服务
|
//如果调用本结点服务
|
||||||
pClient := pClientList[0]
|
return pClientList[0].AsyncCall(pClientList[0].GetTargetNodeId(),timeout,handler.rpcHandler, serviceMethod, fVal, args, reply,false)
|
||||||
pClient.AsyncCall(handler.rpcHandler, serviceMethod, fVal, args, reply)
|
|
||||||
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) GetName() string {
|
func (handler *RpcHandler) GetName() string {
|
||||||
return handler.rpcHandler.GetName()
|
return handler.rpcHandler.GetName()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) IsSingleCoroutine() bool {
|
func (handler *RpcHandler) CallWithTimeout(timeout time.Duration,serviceMethod string, args interface{}, reply interface{}) error {
|
||||||
return handler.rpcHandler.IsSingleCoroutine()
|
return handler.callRpc(timeout,NodeIdNull, serviceMethod, args, reply)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *RpcHandler) CallNodeWithTimeout(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, reply interface{}) error{
|
||||||
|
return handler.callRpc(timeout,nodeId, serviceMethod, args, reply)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *RpcHandler) AsyncCallWithTimeout(timeout time.Duration,serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error){
|
||||||
|
return handler.asyncCallRpc(timeout,NodeIdNull, serviceMethod, args, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *RpcHandler) AsyncCallNodeWithTimeout(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error){
|
||||||
|
return handler.asyncCallRpc(timeout,nodeId, serviceMethod, args, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) AsyncCall(serviceMethod string, args interface{}, callback interface{}) error {
|
func (handler *RpcHandler) AsyncCall(serviceMethod string, args interface{}, callback interface{}) error {
|
||||||
return handler.asyncCallRpc(0, serviceMethod, args, callback)
|
_,err := handler.asyncCallRpc(DefaultRpcTimeout,NodeIdNull, serviceMethod, args, callback)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) Call(serviceMethod string, args interface{}, reply interface{}) error {
|
func (handler *RpcHandler) Call(serviceMethod string, args interface{}, reply interface{}) error {
|
||||||
return handler.callRpc(0, serviceMethod, args, reply)
|
return handler.callRpc(DefaultRpcTimeout,NodeIdNull, serviceMethod, args, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) Go(serviceMethod string, args interface{}) error {
|
func (handler *RpcHandler) Go(serviceMethod string, args interface{}) error {
|
||||||
return handler.goRpc(nil, false, 0, serviceMethod, args)
|
return handler.goRpc(nil, false, NodeIdNull, serviceMethod, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) AsyncCallNode(nodeId int, serviceMethod string, args interface{}, callback interface{}) error {
|
func (handler *RpcHandler) AsyncCallNode(nodeId string, serviceMethod string, args interface{}, callback interface{}) error {
|
||||||
return handler.asyncCallRpc(nodeId, serviceMethod, args, callback)
|
_,err:= handler.asyncCallRpc(DefaultRpcTimeout,nodeId, serviceMethod, args, callback)
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) CallNode(nodeId int, serviceMethod string, args interface{}, reply interface{}) error {
|
func (handler *RpcHandler) CallNode(nodeId string, serviceMethod string, args interface{}, reply interface{}) error {
|
||||||
return handler.callRpc(nodeId, serviceMethod, args, reply)
|
return handler.callRpc(DefaultRpcTimeout,nodeId, serviceMethod, args, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) GoNode(nodeId int, serviceMethod string, args interface{}) error {
|
func (handler *RpcHandler) GoNode(nodeId string, serviceMethod string, args interface{}) error {
|
||||||
return handler.goRpc(nil, false, nodeId, serviceMethod, args)
|
return handler.goRpc(nil, false, nodeId, serviceMethod, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) CastGo(serviceMethod string, args interface{}) error {
|
func (handler *RpcHandler) CastGo(serviceMethod string, args interface{}) error {
|
||||||
return handler.goRpc(nil, true, 0, serviceMethod, args)
|
return handler.goRpc(nil, true, NodeIdNull, serviceMethod, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) RawGoNode(rpcProcessorType RpcProcessorType, nodeId int, rpcMethodId uint32, serviceName string, rawArgs []byte) error {
|
func (handler *RpcHandler) RawGoNode(rpcProcessorType RpcProcessorType, nodeId string, rpcMethodId uint32, serviceName string, rawArgs []byte) error {
|
||||||
processor := GetProcessor(uint8(rpcProcessorType))
|
processor := GetProcessor(uint8(rpcProcessorType))
|
||||||
err, count := handler.funcRpcClient(nodeId, serviceName, handler.pClientList)
|
pClientList := make([]*Client,0,1)
|
||||||
if count == 0 || err != nil {
|
err, pClientList := handler.funcRpcClient(nodeId, serviceName,false, pClientList)
|
||||||
log.SError("Call serviceMethod is error:", err.Error())
|
if len(pClientList) == 0 || err != nil {
|
||||||
|
log.Error("call serviceMethod is failed",log.ErrorAttr("error",err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if count > 1 {
|
if len(pClientList) > 1 {
|
||||||
err := errors.New("cannot call more then 1 node")
|
err := errors.New("cannot call more then 1 node")
|
||||||
log.SError(err.Error())
|
log.Error("cannot call more then 1 node",log.String("serviceName",serviceName))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//2.rpcClient调用
|
//2.rpcClient调用
|
||||||
//如果调用本结点服务
|
//如果调用本结点服务
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < len(pClientList); i++ {
|
||||||
//跨node调用
|
//跨node调用
|
||||||
pCall := handler.pClientList[i].RawGo(handler.rpcHandler,processor, true, rpcMethodId, serviceName, rawArgs, nil)
|
pCall := pClientList[i].RawGo(pClientList[i].GetTargetNodeId(),DefaultRpcTimeout,handler.rpcHandler,processor, true, rpcMethodId, serviceName, rawArgs, nil)
|
||||||
if pCall.Err != nil {
|
if pCall.Err != nil {
|
||||||
err = pCall.Err
|
err = pCall.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.pClientList[i].RemovePending(pCall.Seq)
|
pClientList[i].RemovePending(pCall.Seq)
|
||||||
ReleaseCall(pCall)
|
ReleaseCall(pCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
42
rpc/rpcnats.go
Normal file
42
rpc/rpcnats.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package rpc
|
||||||
|
|
||||||
|
import "sync/atomic"
|
||||||
|
|
||||||
|
type RpcNats struct {
|
||||||
|
NatsServer
|
||||||
|
NatsClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rn *RpcNats) Start() error{
|
||||||
|
err := rn.NatsServer.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rn.NatsClient.Start(rn.NatsServer.natsConn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rn *RpcNats) Init(natsUrl string, noRandomize bool, nodeId string,compressBytesLen int,rpcHandleFinder RpcHandleFinder,notifyEventFun NotifyEventFun){
|
||||||
|
rn.NatsClient.localNodeId = nodeId
|
||||||
|
rn.NatsServer.initServer(natsUrl,noRandomize, nodeId,compressBytesLen,rpcHandleFinder,notifyEventFun)
|
||||||
|
rn.NatsServer.iServer = rn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rn *RpcNats) NewNatsClient(targetNodeId string,localNodeId string,callSet *CallSet,notifyEventFun NotifyEventFun) *Client{
|
||||||
|
var client Client
|
||||||
|
|
||||||
|
client.clientId = atomic.AddUint32(&clientSeq, 1)
|
||||||
|
client.targetNodeId = targetNodeId
|
||||||
|
//client.maxCheckCallRpcCount = DefaultMaxCheckCallRpcCount
|
||||||
|
//client.callRpcTimeout = DefaultRpcTimeout
|
||||||
|
|
||||||
|
natsClient := &rn.NatsClient
|
||||||
|
natsClient.localNodeId = localNodeId
|
||||||
|
natsClient.client = &client
|
||||||
|
natsClient.notifyEventFun = notifyEventFun
|
||||||
|
|
||||||
|
client.IRealClient = natsClient
|
||||||
|
client.CallSet = callSet
|
||||||
|
|
||||||
|
return &client
|
||||||
|
}
|
||||||
89
rpc/rpctimer.go
Normal file
89
rpc/rpctimer.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
package rpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"container/heap"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CallTimer struct {
|
||||||
|
SeqId uint64
|
||||||
|
FireTime int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type CallTimerHeap struct {
|
||||||
|
callTimer []CallTimer
|
||||||
|
mapSeqIndex map[uint64]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CallTimerHeap) Init() {
|
||||||
|
h.mapSeqIndex = make(map[uint64]int, 4096)
|
||||||
|
h.callTimer = make([]CallTimer, 0, 4096)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CallTimerHeap) Len() int {
|
||||||
|
return len(h.callTimer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CallTimerHeap) Less(i, j int) bool {
|
||||||
|
return h.callTimer[i].FireTime < h.callTimer[j].FireTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CallTimerHeap) Swap(i, j int) {
|
||||||
|
h.callTimer[i], h.callTimer[j] = h.callTimer[j], h.callTimer[i]
|
||||||
|
h.mapSeqIndex[h.callTimer[i].SeqId] = i
|
||||||
|
h.mapSeqIndex[h.callTimer[j].SeqId] = j
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CallTimerHeap) Push(t any) {
|
||||||
|
callTimer := t.(CallTimer)
|
||||||
|
h.mapSeqIndex[callTimer.SeqId] = len(h.callTimer)
|
||||||
|
h.callTimer = append(h.callTimer, callTimer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CallTimerHeap) Pop() any {
|
||||||
|
l := len(h.callTimer)
|
||||||
|
seqId := h.callTimer[l-1].SeqId
|
||||||
|
|
||||||
|
h.callTimer = h.callTimer[:l-1]
|
||||||
|
delete(h.mapSeqIndex, seqId)
|
||||||
|
return seqId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CallTimerHeap) Cancel(seq uint64) bool {
|
||||||
|
index, ok := h.mapSeqIndex[seq]
|
||||||
|
if ok == false {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
heap.Remove(h, index)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CallTimerHeap) AddTimer(seqId uint64,d time.Duration){
|
||||||
|
heap.Push(h, CallTimer{
|
||||||
|
SeqId: seqId,
|
||||||
|
FireTime: time.Now().Add(d).UnixNano(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CallTimerHeap) PopTimeout() uint64 {
|
||||||
|
if h.Len() == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
nextFireTime := h.callTimer[0].FireTime
|
||||||
|
if nextFireTime > time.Now().UnixNano() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return heap.Pop(h).(uint64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CallTimerHeap) PopFirst() uint64 {
|
||||||
|
if h.Len() == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return heap.Pop(h).(uint64)
|
||||||
|
}
|
||||||
|
|
||||||
339
rpc/server.go
339
rpc/server.go
@@ -1,32 +1,48 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/network"
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const Default_ReadWriteDeadline = 15*time.Second
|
||||||
type RpcProcessorType uint8
|
type RpcProcessorType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RpcProcessorJson RpcProcessorType = 0
|
RpcProcessorJson RpcProcessorType = 0
|
||||||
RpcProcessorGoGoPB RpcProcessorType = 1
|
RpcProcessorPB RpcProcessorType = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
var arrayProcessor = []IRpcProcessor{&JsonProcessor{}, &GoGoPBProcessor{}}
|
var arrayProcessor = []IRpcProcessor{&JsonProcessor{}, &PBProcessor{}}
|
||||||
var arrayProcessorLen uint8 = 2
|
var arrayProcessorLen uint8 = 2
|
||||||
var LittleEndian bool
|
var LittleEndian bool
|
||||||
|
|
||||||
|
type IServer interface {
|
||||||
|
Start() error
|
||||||
|
Stop()
|
||||||
|
|
||||||
|
selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call
|
||||||
|
myselfRpcHandlerGo(client *Client,handlerName string, serviceMethod string, args interface{},callBack reflect.Value, reply interface{}) error
|
||||||
|
selfNodeRpcHandlerAsyncGo(timeout time.Duration,client *Client, callerRpcHandler IRpcHandler, noReply bool, handlerName string, serviceMethod string, args interface{}, reply interface{}, callback reflect.Value,cancelable bool) (CancelRpc,error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type writeResponse func(processor IRpcProcessor,connTag string, serviceMethod string, seq uint64, reply interface{}, rpcError RpcError)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
|
BaseServer
|
||||||
|
|
||||||
functions map[interface{}]interface{}
|
functions map[interface{}]interface{}
|
||||||
rpcHandleFinder RpcHandleFinder
|
|
||||||
rpcServer *network.TCPServer
|
rpcServer *network.TCPServer
|
||||||
|
|
||||||
|
listenAddr string
|
||||||
|
maxRpcParamLen uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type RpcAgent struct {
|
type RpcAgent struct {
|
||||||
@@ -57,24 +73,25 @@ func GetProcessor(processorType uint8) IRpcProcessor {
|
|||||||
return arrayProcessor[processorType]
|
return arrayProcessor[processorType]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) Init(rpcHandleFinder RpcHandleFinder) {
|
func (server *Server) Init(listenAddr string, maxRpcParamLen uint32,compressBytesLen int,rpcHandleFinder RpcHandleFinder) {
|
||||||
server.rpcHandleFinder = rpcHandleFinder
|
server.initBaseServer(compressBytesLen,rpcHandleFinder)
|
||||||
|
server.listenAddr = listenAddr
|
||||||
|
server.maxRpcParamLen = maxRpcParamLen
|
||||||
|
|
||||||
server.rpcServer = &network.TCPServer{}
|
server.rpcServer = &network.TCPServer{}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Default_ReadWriteDeadline = 15*time.Second
|
func (server *Server) Start() error{
|
||||||
|
splitAddr := strings.Split(server.listenAddr, ":")
|
||||||
func (server *Server) Start(listenAddr string, maxRpcParamLen uint32) {
|
|
||||||
splitAddr := strings.Split(listenAddr, ":")
|
|
||||||
if len(splitAddr) != 2 {
|
if len(splitAddr) != 2 {
|
||||||
log.SFatal("listen addr is error :", listenAddr)
|
return fmt.Errorf("listen addr is failed,listenAddr:%s", server.listenAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
server.rpcServer.Addr = ":" + splitAddr[1]
|
server.rpcServer.Addr = ":" + splitAddr[1]
|
||||||
server.rpcServer.LenMsgLen = 4 //uint16
|
|
||||||
server.rpcServer.MinMsgLen = 2
|
server.rpcServer.MinMsgLen = 2
|
||||||
if maxRpcParamLen > 0 {
|
server.compressBytesLen = server.compressBytesLen
|
||||||
server.rpcServer.MaxMsgLen = maxRpcParamLen
|
if server.maxRpcParamLen > 0 {
|
||||||
|
server.rpcServer.MaxMsgLen = server.maxRpcParamLen
|
||||||
} else {
|
} else {
|
||||||
server.rpcServer.MaxMsgLen = math.MaxUint32
|
server.rpcServer.MaxMsgLen = math.MaxUint32
|
||||||
}
|
}
|
||||||
@@ -85,12 +102,18 @@ func (server *Server) Start(listenAddr string, maxRpcParamLen uint32) {
|
|||||||
server.rpcServer.LittleEndian = LittleEndian
|
server.rpcServer.LittleEndian = LittleEndian
|
||||||
server.rpcServer.WriteDeadline = Default_ReadWriteDeadline
|
server.rpcServer.WriteDeadline = Default_ReadWriteDeadline
|
||||||
server.rpcServer.ReadDeadline = Default_ReadWriteDeadline
|
server.rpcServer.ReadDeadline = Default_ReadWriteDeadline
|
||||||
server.rpcServer.Start()
|
server.rpcServer.LenMsgLen = DefaultRpcLenMsgLen
|
||||||
|
|
||||||
|
return server.rpcServer.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) Stop(){
|
||||||
|
server.rpcServer.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (agent *RpcAgent) OnDestroy() {}
|
func (agent *RpcAgent) OnDestroy() {}
|
||||||
|
|
||||||
func (agent *RpcAgent) WriteResponse(processor IRpcProcessor, serviceMethod string, seq uint64, reply interface{}, rpcError RpcError) {
|
func (agent *RpcAgent) WriteResponse(processor IRpcProcessor, connTag string, serviceMethod string, seq uint64, reply interface{}, rpcError RpcError) {
|
||||||
var mReply []byte
|
var mReply []byte
|
||||||
var errM error
|
var errM error
|
||||||
|
|
||||||
@@ -107,103 +130,59 @@ func (agent *RpcAgent) WriteResponse(processor IRpcProcessor, serviceMethod stri
|
|||||||
defer processor.ReleaseRpcResponse(rpcResponse.RpcResponseData)
|
defer processor.ReleaseRpcResponse(rpcResponse.RpcResponseData)
|
||||||
|
|
||||||
if errM != nil {
|
if errM != nil {
|
||||||
log.SError("service method ", serviceMethod, " Marshal error:", errM.Error())
|
log.Error("mashal RpcResponseData failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",errM))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
errM = agent.conn.WriteMsg([]byte{uint8(processor.GetProcessorType())}, bytes)
|
var compressBuff[]byte
|
||||||
|
bCompress := uint8(0)
|
||||||
|
if agent.rpcServer.compressBytesLen >0 && len(bytes) >= agent.rpcServer.compressBytesLen {
|
||||||
|
var cErr error
|
||||||
|
|
||||||
|
compressBuff,cErr = compressor.CompressBlock(bytes)
|
||||||
|
if cErr != nil {
|
||||||
|
log.Error("CompressBlock failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",cErr))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(compressBuff) < len(bytes) {
|
||||||
|
bytes = compressBuff
|
||||||
|
bCompress = 1<<7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errM = agent.conn.WriteMsg([]byte{uint8(processor.GetProcessorType())|bCompress}, bytes)
|
||||||
|
if cap(compressBuff) >0 {
|
||||||
|
compressor.CompressBufferCollection(compressBuff)
|
||||||
|
}
|
||||||
if errM != nil {
|
if errM != nil {
|
||||||
log.SError("Rpc ", serviceMethod, " return is error:", errM.Error())
|
log.Error("WriteMsg error,Rpc return is fail",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",errM))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (agent *RpcAgent) Run() {
|
func (agent *RpcAgent) Run() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
l := runtime.Stack(buf, false)
|
||||||
|
errString := fmt.Sprint(r)
|
||||||
|
log.Dump(string(buf[:l]),log.String("error",errString))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
data, err := agent.conn.ReadMsg()
|
data, err := agent.conn.ReadMsg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("remoteAddress:", agent.conn.RemoteAddr().String(), ",read message: ", err.Error())
|
log.Error("read message is error",log.String("remoteAddress",agent.conn.RemoteAddr().String()),log.ErrorAttr("error",err))
|
||||||
//will close tcpconn
|
//will close tcpconn
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
processor := GetProcessor(data[0])
|
defer agent.conn.ReleaseReadMsg(data)
|
||||||
if processor == nil {
|
err = agent.rpcServer.processRpcRequest( data,"",agent.WriteResponse)
|
||||||
agent.conn.ReleaseReadMsg(data)
|
|
||||||
log.SError("remote rpc ", agent.conn.RemoteAddr(), " cannot find processor:", data[0])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//解析head
|
|
||||||
req := MakeRpcRequest(processor, 0, 0, "", false, nil)
|
|
||||||
err = processor.Unmarshal(data[1:], req.RpcRequestData)
|
|
||||||
agent.conn.ReleaseReadMsg(data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("rpc Unmarshal request is error:", err.Error())
|
log.Error("processRpcRequest is error",log.String("remoteAddress",agent.conn.RemoteAddr().String()),log.ErrorAttr("error",err))
|
||||||
if req.RpcRequestData.GetSeq() > 0 {
|
//will close tcpconn
|
||||||
rpcError := RpcError(err.Error())
|
break
|
||||||
if req.RpcRequestData.IsNoReply() == false {
|
|
||||||
agent.WriteResponse(processor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
|
||||||
}
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//交给程序处理
|
|
||||||
serviceMethod := strings.Split(req.RpcRequestData.GetServiceMethod(), ".")
|
|
||||||
if len(serviceMethod) < 1 {
|
|
||||||
rpcError := RpcError("rpc request req.ServiceMethod is error")
|
|
||||||
if req.RpcRequestData.IsNoReply() == false {
|
|
||||||
agent.WriteResponse(processor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
|
||||||
}
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
log.SError("rpc request req.ServiceMethod is error")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
rpcHandler := agent.rpcServer.rpcHandleFinder.FindRpcHandler(serviceMethod[0])
|
|
||||||
if rpcHandler == nil {
|
|
||||||
rpcError := RpcError(fmt.Sprintf("service method %s not config!", req.RpcRequestData.GetServiceMethod()))
|
|
||||||
if req.RpcRequestData.IsNoReply() == false {
|
|
||||||
agent.WriteResponse(processor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.SError("service method ", req.RpcRequestData.GetServiceMethod(), " not config!")
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.RpcRequestData.IsNoReply() == false {
|
|
||||||
req.requestHandle = func(Returns interface{}, Err RpcError) {
|
|
||||||
agent.WriteResponse(processor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), Returns, Err)
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req.inParam, err = rpcHandler.UnmarshalInParam(req.rpcProcessor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetRpcMethodId(), req.RpcRequestData.GetInParam())
|
|
||||||
if err != nil {
|
|
||||||
rErr := "Call Rpc " + req.RpcRequestData.GetServiceMethod() + " Param error " + err.Error()
|
|
||||||
if req.requestHandle != nil {
|
|
||||||
req.requestHandle(nil, RpcError(rErr))
|
|
||||||
} else {
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
}
|
|
||||||
log.SError(rErr)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err = rpcHandler.PushRpcRequest(req)
|
|
||||||
if err != nil {
|
|
||||||
rpcError := RpcError(err.Error())
|
|
||||||
|
|
||||||
if req.RpcRequestData.IsNoReply() {
|
|
||||||
agent.WriteResponse(processor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,165 +215,3 @@ func (server *Server) NewAgent(c *network.TCPConn) network.Agent {
|
|||||||
return agent
|
return agent
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) myselfRpcHandlerGo(client *Client,handlerName string, serviceMethod string, args interface{},callBack reflect.Value, reply interface{}) error {
|
|
||||||
rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
|
|
||||||
if rpcHandler == nil {
|
|
||||||
err := errors.New("service method " + serviceMethod + " not config!")
|
|
||||||
log.SError(err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return rpcHandler.CallMethod(client,serviceMethod, args,callBack, reply)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (server *Server) selfNodeRpcHandlerGo(processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call {
|
|
||||||
pCall := MakeCall()
|
|
||||||
pCall.Seq = client.generateSeq()
|
|
||||||
|
|
||||||
rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
|
|
||||||
if rpcHandler == nil {
|
|
||||||
pCall.Seq = 0
|
|
||||||
pCall.Err = errors.New("service method " + serviceMethod + " not config!")
|
|
||||||
pCall.done <- pCall
|
|
||||||
log.SError(pCall.Err.Error())
|
|
||||||
|
|
||||||
return pCall
|
|
||||||
}
|
|
||||||
|
|
||||||
var iParam interface{}
|
|
||||||
if processor == nil {
|
|
||||||
_, processor = GetProcessorType(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
if args != nil {
|
|
||||||
var err error
|
|
||||||
iParam,err = processor.Clone(args)
|
|
||||||
if err != nil {
|
|
||||||
pCall.Seq = 0
|
|
||||||
pCall.Err = errors.New("RpcHandler " + handlerName + "."+serviceMethod+" deep copy inParam is error:" + err.Error())
|
|
||||||
pCall.done <- pCall
|
|
||||||
log.SError(pCall.Err.Error())
|
|
||||||
|
|
||||||
return pCall
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req := MakeRpcRequest(processor, 0, rpcMethodId, serviceMethod, noReply, nil)
|
|
||||||
req.inParam = iParam
|
|
||||||
req.localReply = reply
|
|
||||||
if rawArgs != nil {
|
|
||||||
var err error
|
|
||||||
req.inParam, err = rpcHandler.UnmarshalInParam(processor, serviceMethod, rpcMethodId, rawArgs)
|
|
||||||
if err != nil {
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
pCall.Err = err
|
|
||||||
pCall.done <- pCall
|
|
||||||
return pCall
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if noReply == false {
|
|
||||||
client.AddPending(pCall)
|
|
||||||
callSeq := pCall.Seq
|
|
||||||
req.requestHandle = func(Returns interface{}, Err RpcError) {
|
|
||||||
if reply != nil && Returns != reply && Returns != nil {
|
|
||||||
byteReturns, err := req.rpcProcessor.Marshal(Returns)
|
|
||||||
if err != nil {
|
|
||||||
Err = ConvertError(err)
|
|
||||||
log.SError("returns data cannot be marshal,callSeq is ", callSeq," error is ",err.Error())
|
|
||||||
}else{
|
|
||||||
err = req.rpcProcessor.Unmarshal(byteReturns, reply)
|
|
||||||
if err != nil {
|
|
||||||
Err = ConvertError(err)
|
|
||||||
log.SError("returns data cannot be Unmarshal,callSeq is ", callSeq," error is ",err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
v := client.RemovePending(callSeq)
|
|
||||||
if v == nil {
|
|
||||||
log.SError("rpcClient cannot find seq ",callSeq, " in pending")
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(Err) == 0 {
|
|
||||||
v.Err = nil
|
|
||||||
} else {
|
|
||||||
v.Err = Err
|
|
||||||
}
|
|
||||||
v.done <- v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err := rpcHandler.PushRpcRequest(req)
|
|
||||||
if err != nil {
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
pCall.Err = err
|
|
||||||
pCall.done <- pCall
|
|
||||||
}
|
|
||||||
|
|
||||||
return pCall
|
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) selfNodeRpcHandlerAsyncGo(client *Client, callerRpcHandler IRpcHandler, noReply bool, handlerName string, serviceMethod string, args interface{}, reply interface{}, callback reflect.Value) error {
|
|
||||||
rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
|
|
||||||
if rpcHandler == nil {
|
|
||||||
err := errors.New("service method " + serviceMethod + " not config!")
|
|
||||||
log.SError(err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, processor := GetProcessorType(args)
|
|
||||||
iParam,err := processor.Clone(args)
|
|
||||||
if err != nil {
|
|
||||||
errM := errors.New("RpcHandler " + handlerName + "."+serviceMethod+" deep copy inParam is error:" + err.Error())
|
|
||||||
log.SError(errM.Error())
|
|
||||||
return errM
|
|
||||||
}
|
|
||||||
|
|
||||||
req := MakeRpcRequest(processor, 0, 0, serviceMethod, noReply, nil)
|
|
||||||
req.inParam = iParam
|
|
||||||
req.localReply = reply
|
|
||||||
|
|
||||||
if noReply == false {
|
|
||||||
callSeq := client.generateSeq()
|
|
||||||
pCall := MakeCall()
|
|
||||||
pCall.Seq = callSeq
|
|
||||||
pCall.rpcHandler = callerRpcHandler
|
|
||||||
pCall.callback = &callback
|
|
||||||
pCall.Reply = reply
|
|
||||||
pCall.ServiceMethod = serviceMethod
|
|
||||||
client.AddPending(pCall)
|
|
||||||
req.requestHandle = func(Returns interface{}, Err RpcError) {
|
|
||||||
v := client.RemovePending(callSeq)
|
|
||||||
if v == nil {
|
|
||||||
log.SError("rpcClient cannot find seq ", pCall.Seq, " in pending")
|
|
||||||
//ReleaseCall(pCall)
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(Err) == 0 {
|
|
||||||
pCall.Err = nil
|
|
||||||
} else {
|
|
||||||
pCall.Err = Err
|
|
||||||
}
|
|
||||||
|
|
||||||
if Returns != nil {
|
|
||||||
pCall.Reply = Returns
|
|
||||||
}
|
|
||||||
pCall.rpcHandler.PushRpcResponse(pCall)
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = rpcHandler.PushRpcRequest(req)
|
|
||||||
if err != nil {
|
|
||||||
ReleaseRpcRequest(req)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/duanhf2012/origin/event"
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
rpcHandle "github.com/duanhf2012/origin/rpc"
|
rpcHandle "github.com/duanhf2012/origin/v2/rpc"
|
||||||
"github.com/duanhf2012/origin/util/timer"
|
"github.com/duanhf2012/origin/v2/util/timer"
|
||||||
"github.com/duanhf2012/origin/concurrent"
|
"github.com/duanhf2012/origin/v2/concurrent"
|
||||||
)
|
)
|
||||||
|
|
||||||
const InitModuleId = 1e9
|
const InitModuleId = 1e9
|
||||||
@@ -117,7 +117,7 @@ func (m *Module) AddModule(module IModule) (uint32, error) {
|
|||||||
m.child[module.GetModuleId()] = module
|
m.child[module.GetModuleId()] = module
|
||||||
m.ancestor.getBaseModule().(*Module).descendants[module.GetModuleId()] = module
|
m.ancestor.getBaseModule().(*Module).descendants[module.GetModuleId()] = module
|
||||||
|
|
||||||
log.SDebug("Add module ", module.GetModuleName(), " completed")
|
log.Debug("Add module "+module.GetModuleName()+ " completed")
|
||||||
return module.GetModuleId(), nil
|
return module.GetModuleId(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ func (m *Module) ReleaseModule(moduleId uint32) {
|
|||||||
|
|
||||||
pModule.self.OnRelease()
|
pModule.self.OnRelease()
|
||||||
pModule.GetEventHandler().Destroy()
|
pModule.GetEventHandler().Destroy()
|
||||||
log.SDebug("Release module ", pModule.GetModuleName())
|
log.Debug("Release module "+ pModule.GetModuleName())
|
||||||
for pTimer := range pModule.mapActiveTimer {
|
for pTimer := range pModule.mapActiveTimer {
|
||||||
pTimer.Cancel()
|
pTimer.Cancel()
|
||||||
}
|
}
|
||||||
@@ -278,18 +278,18 @@ func (m *Module) SafeNewTicker(tickerId *uint64, d time.Duration, AdditionData i
|
|||||||
|
|
||||||
func (m *Module) CancelTimerId(timerId *uint64) bool {
|
func (m *Module) CancelTimerId(timerId *uint64) bool {
|
||||||
if timerId==nil || *timerId == 0 {
|
if timerId==nil || *timerId == 0 {
|
||||||
log.SWarning("timerId is invalid")
|
log.Warning("timerId is invalid")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.mapActiveIdTimer == nil {
|
if m.mapActiveIdTimer == nil {
|
||||||
log.SError("mapActiveIdTimer is nil")
|
log.Error("mapActiveIdTimer is nil")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
t, ok := m.mapActiveIdTimer[*timerId]
|
t, ok := m.mapActiveIdTimer[*timerId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
log.SStack("cannot find timer id ", timerId)
|
log.Stack("cannot find timer id ", log.Uint64("timerId",*timerId))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,23 +3,27 @@ package service
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/event"
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/profiler"
|
"github.com/duanhf2012/origin/v2/profiler"
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
"github.com/duanhf2012/origin/util/timer"
|
"github.com/duanhf2012/origin/v2/util/timer"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"github.com/duanhf2012/origin/concurrent"
|
"github.com/duanhf2012/origin/v2/concurrent"
|
||||||
|
"encoding/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
var timerDispatcherLen = 100000
|
var timerDispatcherLen = 100000
|
||||||
var maxServiceEventChannelNum = 2000000
|
var maxServiceEventChannelNum = 2000000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type IService interface {
|
type IService interface {
|
||||||
|
concurrent.IConcurrent
|
||||||
Init(iService IService,getClientFun rpc.FuncRpcClient,getServerFun rpc.FuncRpcServer,serviceCfg interface{})
|
Init(iService IService,getClientFun rpc.FuncRpcClient,getServerFun rpc.FuncRpcServer,serviceCfg interface{})
|
||||||
Stop()
|
Stop()
|
||||||
Start()
|
Start()
|
||||||
@@ -27,6 +31,7 @@ type IService interface {
|
|||||||
OnSetup(iService IService)
|
OnSetup(iService IService)
|
||||||
OnInit() error
|
OnInit() error
|
||||||
OnStart()
|
OnStart()
|
||||||
|
OnRetire()
|
||||||
OnRelease()
|
OnRelease()
|
||||||
|
|
||||||
SetName(serviceName string)
|
SetName(serviceName string)
|
||||||
@@ -39,6 +44,9 @@ type IService interface {
|
|||||||
|
|
||||||
SetEventChannelNum(num int)
|
SetEventChannelNum(num int)
|
||||||
OpenProfiler()
|
OpenProfiler()
|
||||||
|
|
||||||
|
SetRetire() //设置服务退休状态
|
||||||
|
IsRetire() bool //服务是否退休
|
||||||
}
|
}
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
@@ -50,25 +58,35 @@ type Service struct {
|
|||||||
serviceCfg interface{}
|
serviceCfg interface{}
|
||||||
goroutineNum int32
|
goroutineNum int32
|
||||||
startStatus bool
|
startStatus bool
|
||||||
|
isRelease int32
|
||||||
|
retire int32
|
||||||
eventProcessor event.IEventProcessor
|
eventProcessor event.IEventProcessor
|
||||||
profiler *profiler.Profiler //性能分析器
|
profiler *profiler.Profiler //性能分析器
|
||||||
nodeEventLister rpc.INodeListener
|
nodeConnLister rpc.INodeConnListener
|
||||||
|
natsConnListener rpc.INatsConnListener
|
||||||
discoveryServiceLister rpc.IDiscoveryServiceListener
|
discoveryServiceLister rpc.IDiscoveryServiceListener
|
||||||
chanEvent chan event.IEvent
|
chanEvent chan event.IEvent
|
||||||
closeSig chan struct{}
|
closeSig chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RpcConnEvent Node结点连接事件
|
|
||||||
type RpcConnEvent struct{
|
|
||||||
IsConnect bool
|
|
||||||
NodeId int
|
|
||||||
}
|
|
||||||
|
|
||||||
// DiscoveryServiceEvent 发现服务结点
|
// DiscoveryServiceEvent 发现服务结点
|
||||||
type DiscoveryServiceEvent struct{
|
type DiscoveryServiceEvent struct{
|
||||||
IsDiscovery bool
|
IsDiscovery bool
|
||||||
ServiceName []string
|
ServiceName []string
|
||||||
NodeId int
|
NodeId string
|
||||||
|
}
|
||||||
|
|
||||||
|
type EtcdServiceRecordEvent struct {
|
||||||
|
NetworkName string
|
||||||
|
TTLSecond int64
|
||||||
|
RecordKey string
|
||||||
|
RecordInfo string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Empty struct {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetMaxServiceChannel(maxEventChannel int){
|
func SetMaxServiceChannel(maxEventChannel int){
|
||||||
@@ -79,9 +97,6 @@ func (rpcEventData *DiscoveryServiceEvent) GetEventType() event.EventType{
|
|||||||
return event.Sys_Event_DiscoverService
|
return event.Sys_Event_DiscoverService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rpcEventData *RpcConnEvent) GetEventType() event.EventType{
|
|
||||||
return event.Sys_Event_Node_Event
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) OnSetup(iService IService){
|
func (s *Service) OnSetup(iService IService){
|
||||||
if iService.GetName() == "" {
|
if iService.GetName() == "" {
|
||||||
@@ -92,10 +107,23 @@ func (s *Service) OnSetup(iService IService){
|
|||||||
func (s *Service) OpenProfiler() {
|
func (s *Service) OpenProfiler() {
|
||||||
s.profiler = profiler.RegProfiler(s.GetName())
|
s.profiler = profiler.RegProfiler(s.GetName())
|
||||||
if s.profiler==nil {
|
if s.profiler==nil {
|
||||||
log.SFatal("rofiler.RegProfiler ",s.GetName()," fail.")
|
log.Fatal("rofiler.RegProfiler "+s.GetName()+" fail.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) IsRetire() bool{
|
||||||
|
return atomic.LoadInt32(&s.retire) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) SetRetire(){
|
||||||
|
atomic.StoreInt32(&s.retire,1)
|
||||||
|
|
||||||
|
ev := event.NewEvent()
|
||||||
|
ev.Type = event.Sys_Event_Retire
|
||||||
|
|
||||||
|
s.pushEvent(ev)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) Init(iService IService,getClientFun rpc.FuncRpcClient,getServerFun rpc.FuncRpcServer,serviceCfg interface{}) {
|
func (s *Service) Init(iService IService,getClientFun rpc.FuncRpcClient,getServerFun rpc.FuncRpcServer,serviceCfg interface{}) {
|
||||||
s.closeSig = make(chan struct{})
|
s.closeSig = make(chan struct{})
|
||||||
s.dispatcher =timer.NewDispatcher(timerDispatcherLen)
|
s.dispatcher =timer.NewDispatcher(timerDispatcherLen)
|
||||||
@@ -121,13 +149,14 @@ func (s *Service) Init(iService IService,getClientFun rpc.FuncRpcClient,getServe
|
|||||||
|
|
||||||
func (s *Service) Start() {
|
func (s *Service) Start() {
|
||||||
s.startStatus = true
|
s.startStatus = true
|
||||||
|
atomic.StoreInt32(&s.isRelease,0)
|
||||||
var waitRun sync.WaitGroup
|
var waitRun sync.WaitGroup
|
||||||
|
|
||||||
for i:=int32(0);i< s.goroutineNum;i++{
|
for i:=int32(0);i< s.goroutineNum;i++{
|
||||||
s.wg.Add(1)
|
s.wg.Add(1)
|
||||||
waitRun.Add(1)
|
waitRun.Add(1)
|
||||||
go func(){
|
go func(){
|
||||||
log.SRelease(s.GetName()," service is running",)
|
log.Info(s.GetName()+" service is running",)
|
||||||
waitRun.Done()
|
waitRun.Done()
|
||||||
s.Run()
|
s.Run()
|
||||||
}()
|
}()
|
||||||
@@ -149,20 +178,24 @@ func (s *Service) Run() {
|
|||||||
select {
|
select {
|
||||||
case <- s.closeSig:
|
case <- s.closeSig:
|
||||||
bStop = true
|
bStop = true
|
||||||
|
s.Release()
|
||||||
concurrent.Close()
|
concurrent.Close()
|
||||||
case cb:=<-concurrentCBChannel:
|
case cb:=<-concurrentCBChannel:
|
||||||
concurrent.DoCallback(cb)
|
concurrent.DoCallback(cb)
|
||||||
case ev := <- s.chanEvent:
|
case ev := <- s.chanEvent:
|
||||||
switch ev.GetEventType() {
|
switch ev.GetEventType() {
|
||||||
|
case event.Sys_Event_Retire:
|
||||||
|
log.Info("service OnRetire",log.String("servceName",s.GetName()))
|
||||||
|
s.self.(IService).OnRetire()
|
||||||
case event.ServiceRpcRequestEvent:
|
case event.ServiceRpcRequestEvent:
|
||||||
cEvent,ok := ev.(*event.Event)
|
cEvent,ok := ev.(*event.Event)
|
||||||
if ok == false {
|
if ok == false {
|
||||||
log.SError("Type event conversion error")
|
log.Error("Type event conversion error")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
rpcRequest,ok := cEvent.Data.(*rpc.RpcRequest)
|
rpcRequest,ok := cEvent.Data.(*rpc.RpcRequest)
|
||||||
if ok == false {
|
if ok == false {
|
||||||
log.SError("Type *rpc.RpcRequest conversion error")
|
log.Error("Type *rpc.RpcRequest conversion error")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if s.profiler!=nil {
|
if s.profiler!=nil {
|
||||||
@@ -178,12 +211,12 @@ func (s *Service) Run() {
|
|||||||
case event.ServiceRpcResponseEvent:
|
case event.ServiceRpcResponseEvent:
|
||||||
cEvent,ok := ev.(*event.Event)
|
cEvent,ok := ev.(*event.Event)
|
||||||
if ok == false {
|
if ok == false {
|
||||||
log.SError("Type event conversion error")
|
log.Error("Type event conversion error")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
rpcResponseCB,ok := cEvent.Data.(*rpc.Call)
|
rpcResponseCB,ok := cEvent.Data.(*rpc.Call)
|
||||||
if ok == false {
|
if ok == false {
|
||||||
log.SError("Type *rpc.Call conversion error")
|
log.Error("Type *rpc.Call conversion error")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if s.profiler!=nil {
|
if s.profiler!=nil {
|
||||||
@@ -218,10 +251,6 @@ func (s *Service) Run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if bStop == true {
|
if bStop == true {
|
||||||
if atomic.AddInt32(&s.goroutineNum,-1)<=0 {
|
|
||||||
s.startStatus = false
|
|
||||||
s.Release()
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,11 +270,14 @@ func (s *Service) Release(){
|
|||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
l := runtime.Stack(buf, false)
|
l := runtime.Stack(buf, false)
|
||||||
errString := fmt.Sprint(r)
|
errString := fmt.Sprint(r)
|
||||||
log.SError("core dump info[",errString,"]\n",string(buf[:l]))
|
log.Dump(string(buf[:l]),log.String("error",errString))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
s.self.OnRelease()
|
if atomic.AddInt32(&s.isRelease,-1) == -1{
|
||||||
|
s.self.OnRelease()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) OnRelease(){
|
func (s *Service) OnRelease(){
|
||||||
@@ -256,16 +288,34 @@ func (s *Service) OnInit() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Stop(){
|
func (s *Service) Stop(){
|
||||||
log.SRelease("stop ",s.GetName()," service ")
|
log.Info("stop "+s.GetName()+" service ")
|
||||||
close(s.closeSig)
|
close(s.closeSig)
|
||||||
s.wg.Wait()
|
s.wg.Wait()
|
||||||
log.SRelease(s.GetName()," service has been stopped")
|
log.Info(s.GetName()+" service has been stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetServiceCfg()interface{}{
|
func (s *Service) GetServiceCfg()interface{}{
|
||||||
return s.serviceCfg
|
return s.serviceCfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) ParseServiceCfg(cfg interface{}) error{
|
||||||
|
if s.serviceCfg == nil {
|
||||||
|
return errors.New("no service configuration found")
|
||||||
|
}
|
||||||
|
|
||||||
|
rv := reflect.ValueOf(s.serviceCfg)
|
||||||
|
if rv.Kind() == reflect.Ptr && rv.IsNil() {
|
||||||
|
return errors.New("no service configuration found")
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes,err := json.Marshal(s.serviceCfg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Unmarshal(bytes,cfg)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) GetProfiler() *profiler.Profiler{
|
func (s *Service) GetProfiler() *profiler.Profiler{
|
||||||
return s.profiler
|
return s.profiler
|
||||||
}
|
}
|
||||||
@@ -278,10 +328,6 @@ func (s *Service) UnRegEventReceiverFunc(eventType event.EventType, receiver eve
|
|||||||
s.eventProcessor.UnRegEventReceiverFun(eventType, receiver)
|
s.eventProcessor.UnRegEventReceiverFun(eventType, receiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) IsSingleCoroutine() bool {
|
|
||||||
return s.goroutineNum == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) RegRawRpc(rpcMethodId uint32,rawRpcCB rpc.RawRpcCallBack){
|
func (s *Service) RegRawRpc(rpcMethodId uint32,rawRpcCB rpc.RawRpcCallBack){
|
||||||
s.rpcHandler.RegRawRpc(rpcMethodId,rawRpcCB)
|
s.rpcHandler.RegRawRpc(rpcMethodId,rawRpcCB)
|
||||||
}
|
}
|
||||||
@@ -289,12 +335,21 @@ func (s *Service) RegRawRpc(rpcMethodId uint32,rawRpcCB rpc.RawRpcCallBack){
|
|||||||
func (s *Service) OnStart(){
|
func (s *Service) OnStart(){
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) OnNodeEvent(ev event.IEvent){
|
func (s *Service) OnNodeConnEvent(ev event.IEvent){
|
||||||
event := ev.(*RpcConnEvent)
|
event := ev.(*rpc.RpcConnEvent)
|
||||||
if event.IsConnect {
|
if event.IsConnect {
|
||||||
s.nodeEventLister.OnNodeConnected(event.NodeId)
|
s.nodeConnLister.OnNodeConnected(event.NodeId)
|
||||||
}else{
|
}else{
|
||||||
s.nodeEventLister.OnNodeDisconnect(event.NodeId)
|
s.nodeConnLister.OnNodeDisconnect(event.NodeId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) OnNatsConnEvent(ev event.IEvent){
|
||||||
|
event := ev.(*rpc.NatsConnEvent)
|
||||||
|
if event.IsConnect {
|
||||||
|
s.natsConnListener.OnNatsConnected()
|
||||||
|
}else{
|
||||||
|
s.natsConnListener.OnNatsDisconnect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,26 +362,37 @@ func (s *Service) OnDiscoverServiceEvent(ev event.IEvent){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) RegRpcListener(rpcEventLister rpc.INodeListener) {
|
func (s *Service) RegNodeConnListener(nodeConnListener rpc.INodeConnListener) {
|
||||||
s.nodeEventLister = rpcEventLister
|
s.nodeConnLister = nodeConnListener
|
||||||
s.RegEventReceiverFunc(event.Sys_Event_Node_Event,s.GetEventHandler(),s.OnNodeEvent)
|
s.RegEventReceiverFunc(event.Sys_Event_Node_Conn_Event,s.GetEventHandler(),s.OnNodeConnEvent)
|
||||||
RegRpcEventFun(s.GetName())
|
RegRpcEventFun(s.GetName())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UnRegRpcListener(rpcLister rpc.INodeListener) {
|
func (s *Service) UnRegNodeConnListener() {
|
||||||
s.UnRegEventReceiverFunc(event.Sys_Event_Node_Event,s.GetEventHandler())
|
s.UnRegEventReceiverFunc(event.Sys_Event_Node_Conn_Event,s.GetEventHandler())
|
||||||
|
UnRegRpcEventFun(s.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) RegNatsConnListener(natsConnListener rpc.INatsConnListener) {
|
||||||
|
s.natsConnListener = natsConnListener
|
||||||
|
s.RegEventReceiverFunc(event.Sys_Event_Nats_Conn_Event,s.GetEventHandler(),s.OnNatsConnEvent)
|
||||||
|
RegRpcEventFun(s.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) UnRegNatsConnListener() {
|
||||||
|
s.UnRegEventReceiverFunc(event.Sys_Event_Nats_Conn_Event,s.GetEventHandler())
|
||||||
UnRegRpcEventFun(s.GetName())
|
UnRegRpcEventFun(s.GetName())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) RegDiscoverListener(discoveryServiceListener rpc.IDiscoveryServiceListener) {
|
func (s *Service) RegDiscoverListener(discoveryServiceListener rpc.IDiscoveryServiceListener) {
|
||||||
s.discoveryServiceLister = discoveryServiceListener
|
s.discoveryServiceLister = discoveryServiceListener
|
||||||
s.RegEventReceiverFunc(event.Sys_Event_DiscoverService,s.GetEventHandler(),s.OnDiscoverServiceEvent)
|
s.RegEventReceiverFunc(event.Sys_Event_DiscoverService,s.GetEventHandler(),s.OnDiscoverServiceEvent)
|
||||||
RegDiscoveryServiceEventFun(s.GetName())
|
RegRpcEventFun(s.GetName())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UnRegDiscoverListener(rpcLister rpc.INodeListener) {
|
func (s *Service) UnRegDiscoverListener() {
|
||||||
s.UnRegEventReceiverFunc(event.Sys_Event_DiscoverService,s.GetEventHandler())
|
s.UnRegEventReceiverFunc(event.Sys_Event_DiscoverService,s.GetEventHandler())
|
||||||
UnRegDiscoveryServiceEventFun(s.GetName())
|
UnRegRpcEventFun(s.GetName())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) PushRpcRequest(rpcRequest *rpc.RpcRequest) error{
|
func (s *Service) PushRpcRequest(rpcRequest *rpc.RpcRequest) error{
|
||||||
@@ -352,7 +418,7 @@ func (s *Service) PushEvent(ev event.IEvent) error{
|
|||||||
func (s *Service) pushEvent(ev event.IEvent) error{
|
func (s *Service) pushEvent(ev event.IEvent) error{
|
||||||
if len(s.chanEvent) >= maxServiceEventChannelNum {
|
if len(s.chanEvent) >= maxServiceEventChannelNum {
|
||||||
err := errors.New("The event channel in the service is full")
|
err := errors.New("The event channel in the service is full")
|
||||||
log.SError(err.Error())
|
log.Error(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,10 +445,13 @@ func (s *Service) SetEventChannelNum(num int){
|
|||||||
func (s *Service) SetGoRoutineNum(goroutineNum int32) bool {
|
func (s *Service) SetGoRoutineNum(goroutineNum int32) bool {
|
||||||
//已经开始状态不允许修改协程数量,打开性能分析器不允许开多线程
|
//已经开始状态不允许修改协程数量,打开性能分析器不允许开多线程
|
||||||
if s.startStatus == true || s.profiler!=nil {
|
if s.startStatus == true || s.profiler!=nil {
|
||||||
log.SError("open profiler mode is not allowed to set Multi-coroutine.")
|
log.Error("open profiler mode is not allowed to set Multi-coroutine.")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
s.goroutineNum = goroutineNum
|
s.goroutineNum = goroutineNum
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) OnRetire(){
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
//本地所有的service
|
//本地所有的service
|
||||||
var mapServiceName map[string]IService
|
var mapServiceName map[string]IService
|
||||||
@@ -11,9 +14,6 @@ type RegDiscoveryServiceEventFunType func(serviceName string)
|
|||||||
var RegRpcEventFun RegRpcEventFunType
|
var RegRpcEventFun RegRpcEventFunType
|
||||||
var UnRegRpcEventFun RegRpcEventFunType
|
var UnRegRpcEventFun RegRpcEventFunType
|
||||||
|
|
||||||
var RegDiscoveryServiceEventFun RegDiscoveryServiceEventFunType
|
|
||||||
var UnRegDiscoveryServiceEventFun RegDiscoveryServiceEventFunType
|
|
||||||
|
|
||||||
func init(){
|
func init(){
|
||||||
mapServiceName = map[string]IService{}
|
mapServiceName = map[string]IService{}
|
||||||
setupServiceList = []IService{}
|
setupServiceList = []IService{}
|
||||||
@@ -23,8 +23,8 @@ func Init() {
|
|||||||
for _,s := range setupServiceList {
|
for _,s := range setupServiceList {
|
||||||
err := s.OnInit()
|
err := s.OnInit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs := errors.New("Failed to initialize "+s.GetName()+" service:"+err.Error())
|
log.Error("Failed to initialize "+s.GetName()+" service",log.ErrorAttr("err",err))
|
||||||
panic(errs)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,3 +60,9 @@ func StopAllService(){
|
|||||||
setupServiceList[i].Stop()
|
setupServiceList[i].Stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NotifyAllServiceRetire(){
|
||||||
|
for i := len(setupServiceList) - 1; i >= 0; i-- {
|
||||||
|
setupServiceList[i].SetRetire()
|
||||||
|
}
|
||||||
|
}
|
||||||
314
sysmodule/ginmodule/GinModule.go
Normal file
314
sysmodule/ginmodule/GinModule.go
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
package ginmodule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IGinProcessor interface {
|
||||||
|
Process(data *gin.Context) (*gin.Context, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type GinModule struct {
|
||||||
|
service.Module
|
||||||
|
|
||||||
|
*gin.Engine
|
||||||
|
srv *http.Server
|
||||||
|
|
||||||
|
listenAddr string
|
||||||
|
handleTimeout time.Duration
|
||||||
|
processor []IGinProcessor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gm *GinModule) Init(addr string, handleTimeout time.Duration,engine *gin.Engine) {
|
||||||
|
gm.listenAddr = addr
|
||||||
|
gm.handleTimeout = handleTimeout
|
||||||
|
gm.Engine = engine
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gm *GinModule) SetupDataProcessor(processor ...IGinProcessor) {
|
||||||
|
gm.processor = processor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gm *GinModule) AppendDataProcessor(processor ...IGinProcessor) {
|
||||||
|
gm.processor = append(gm.processor, processor...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gm *GinModule) OnInit() error {
|
||||||
|
if gm.Engine == nil {
|
||||||
|
gm.Engine = gin.Default()
|
||||||
|
}
|
||||||
|
|
||||||
|
gm.srv = &http.Server{
|
||||||
|
Addr: gm.listenAddr,
|
||||||
|
Handler: gm.Engine,
|
||||||
|
}
|
||||||
|
|
||||||
|
gm.Engine.Use(Logger())
|
||||||
|
gm.Engine.Use(gin.Recovery())
|
||||||
|
gm.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_Gin_Event, gm.GetEventHandler(), gm.eventHandler)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gm *GinModule) eventHandler(ev event.IEvent) {
|
||||||
|
ginEvent := ev.(*GinEvent)
|
||||||
|
for _, handler := range ginEvent.handlersChain {
|
||||||
|
handler(&ginEvent.c)
|
||||||
|
}
|
||||||
|
|
||||||
|
//ginEvent.chanWait <- struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gm *GinModule) Start() {
|
||||||
|
gm.srv.Addr = gm.listenAddr
|
||||||
|
log.Info("http start listen", slog.Any("addr", gm.listenAddr))
|
||||||
|
go func() {
|
||||||
|
err := gm.srv.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("ListenAndServe error", slog.Any("error", err.Error()))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gm *GinModule) StartTLS(certFile, keyFile string) {
|
||||||
|
log.Info("http start listen", slog.Any("addr", gm.listenAddr))
|
||||||
|
go func() {
|
||||||
|
err := gm.srv.ListenAndServeTLS(certFile, keyFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("ListenAndServeTLS error", slog.Any("error", err.Error()))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gm *GinModule) Stop(ctx context.Context) {
|
||||||
|
if err := gm.srv.Shutdown(ctx); err != nil {
|
||||||
|
log.SError("Server Shutdown", slog.Any("error", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type SafeContext struct {
|
||||||
|
*gin.Context
|
||||||
|
chanWait chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) JSONAndDone(code int, obj any) {
|
||||||
|
c.Context.JSON(code,obj)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) AsciiJSONAndDone(code int, obj any){
|
||||||
|
c.Context.AsciiJSON(code,obj)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) PureJSONAndDone(code int, obj any){
|
||||||
|
c.Context.PureJSON(code,obj)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) XMLAndDone(code int, obj any){
|
||||||
|
c.Context.XML(code,obj)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) YAMLAndDone(code int, obj any){
|
||||||
|
c.Context.YAML(code,obj)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) TOMLAndDone(code int, obj any){
|
||||||
|
c.Context.TOML(code,obj)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) ProtoBufAndDone(code int, obj any){
|
||||||
|
c.Context.ProtoBuf(code,obj)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) StringAndDone(code int, format string, values ...any){
|
||||||
|
c.Context.String(code,format,values...)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) RedirectAndDone(code int, location string){
|
||||||
|
c.Context.Redirect(code,location)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) DataAndDone(code int, contentType string, data []byte){
|
||||||
|
c.Context.Data(code,contentType,data)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) DataFromReaderAndDone(code int, contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string){
|
||||||
|
c.DataFromReader(code,contentLength,contentType,reader,extraHeaders)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) HTMLAndDone(code int, name string, obj any){
|
||||||
|
c.Context.HTML(code,name,obj)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) IndentedJSONAndDone(code int, obj any){
|
||||||
|
c.Context.IndentedJSON(code,obj)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) SecureJSONAndDone(code int, obj any){
|
||||||
|
c.Context.SecureJSON(code,obj)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) JSONPAndDone(code int, obj any){
|
||||||
|
c.Context.JSONP(code,obj)
|
||||||
|
c.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SafeContext) Done(){
|
||||||
|
c.chanWait <- struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GinEvent struct {
|
||||||
|
handlersChain []SafeHandlerFunc
|
||||||
|
c SafeContext
|
||||||
|
}
|
||||||
|
|
||||||
|
type SafeHandlerFunc func(*SafeContext)
|
||||||
|
|
||||||
|
func (ge *GinEvent) GetEventType() event.EventType {
|
||||||
|
return event.Sys_Event_Gin_Event
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gm *GinModule) handleMethod(httpMethod, relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
|
||||||
|
return gm.Engine.Handle(httpMethod, relativePath, func(c *gin.Context) {
|
||||||
|
for _, p := range gm.processor {
|
||||||
|
_, err := p.Process(c)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ev GinEvent
|
||||||
|
chanWait := make(chan struct{},2)
|
||||||
|
ev.c.chanWait = chanWait
|
||||||
|
ev.handlersChain = handlers
|
||||||
|
ev.c.Context = c
|
||||||
|
gm.NotifyEvent(&ev)
|
||||||
|
|
||||||
|
ctx,cancel := context.WithTimeout(context.Background(), gm.handleTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
select{
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.Error("GinModule process timeout", slog.Any("path", c.Request.URL.Path))
|
||||||
|
c.AbortWithStatus(http.StatusRequestTimeout)
|
||||||
|
case <-chanWait:
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET 回调处理是在gin协程中
|
||||||
|
func (gm *GinModule) GET(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
|
||||||
|
return gm.Engine.GET(relativePath, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST 回调处理是在gin协程中
|
||||||
|
func (gm *GinModule) POST(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
|
||||||
|
return gm.Engine.POST(relativePath, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE 回调处理是在gin协程中
|
||||||
|
func (gm *GinModule) DELETE(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
|
||||||
|
return gm.Engine.DELETE(relativePath, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PATCH 回调处理是在gin协程中
|
||||||
|
func (gm *GinModule) PATCH(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
|
||||||
|
return gm.Engine.PATCH(relativePath, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put 回调处理是在gin协程中
|
||||||
|
func (gm *GinModule) Put(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
|
||||||
|
return gm.Engine.PUT(relativePath, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafeGET 回调处理是在service协程中
|
||||||
|
func (gm *GinModule) SafeGET(relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
|
||||||
|
return gm.handleMethod(http.MethodGet, relativePath, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafePOST 回调处理是在service协程中
|
||||||
|
func (gm *GinModule) SafePOST(relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
|
||||||
|
return gm.handleMethod(http.MethodPost, relativePath, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafeDELETE 回调处理是在service协程中
|
||||||
|
func (gm *GinModule) SafeDELETE(relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
|
||||||
|
return gm.handleMethod(http.MethodDelete, relativePath, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafePATCH 回调处理是在service协程中
|
||||||
|
func (gm *GinModule) SafePATCH(relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
|
||||||
|
return gm.handleMethod(http.MethodPatch, relativePath, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafePut 回调处理是在service协程中
|
||||||
|
func (gm *GinModule) SafePut(relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
|
||||||
|
return gm.handleMethod(http.MethodPut, relativePath, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIPWithProxyHeaders(c *gin.Context) string {
|
||||||
|
// 尝试从 X-Real-IP 头部获取真实 IP
|
||||||
|
ip := c.GetHeader("X-Real-IP")
|
||||||
|
|
||||||
|
// 如果 X-Real-IP 头部不存在,则尝试从 X-Forwarded-For 头部获取
|
||||||
|
if ip == "" {
|
||||||
|
ip = c.GetHeader("X-Forwarded-For")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果两者都不存在,则使用默认的 ClientIP 方法获取 IP
|
||||||
|
if ip == "" {
|
||||||
|
ip = c.ClientIP()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIPWithValidatedProxyHeaders(c *gin.Context) string {
|
||||||
|
// 获取代理头部
|
||||||
|
proxyHeaders := c.Request.Header.Get("X-Real-IP,X-Forwarded-For")
|
||||||
|
|
||||||
|
// 分割代理头部,取第一个 IP 作为真实 IP
|
||||||
|
ips := strings.Split(proxyHeaders, ",")
|
||||||
|
ip := strings.TrimSpace(ips[0])
|
||||||
|
|
||||||
|
// 如果 IP 格式合法,则使用获取到的 IP,否则使用默认的 ClientIP 方法获取
|
||||||
|
if isValidIP(ip) {
|
||||||
|
return ip
|
||||||
|
} else {
|
||||||
|
ip = c.ClientIP()
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// isValidIP 判断 IP 格式是否合法
|
||||||
|
func isValidIP(ip string) bool {
|
||||||
|
// 此处添加自定义的 IP 格式验证逻辑
|
||||||
|
// 例如,使用正则表达式验证 IP 格式
|
||||||
|
// ...
|
||||||
|
if ip == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
79
sysmodule/ginmodule/logger.go
Normal file
79
sysmodule/ginmodule/logger.go
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package ginmodule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Logger 是一个自定义的日志中间件
|
||||||
|
func Logger() gin.HandlerFunc {
|
||||||
|
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
// 处理请求前记录日志
|
||||||
|
// 开始时间
|
||||||
|
startTime := time.Now()
|
||||||
|
// 调用该请求的剩余处理程序
|
||||||
|
c.Next()
|
||||||
|
// 结束时间
|
||||||
|
endTime := time.Now()
|
||||||
|
// 执行时间
|
||||||
|
latencyTime := endTime.Sub(startTime)
|
||||||
|
|
||||||
|
// 请求IP
|
||||||
|
clientIP := c.ClientIP()
|
||||||
|
// remoteIP := c.RemoteIP()
|
||||||
|
|
||||||
|
// 请求方式
|
||||||
|
reqMethod := c.Request.Method
|
||||||
|
// 请求路由
|
||||||
|
reqUri := c.Request.RequestURI
|
||||||
|
// 请求协议
|
||||||
|
reqProto := c.Request.Proto
|
||||||
|
// 请求来源
|
||||||
|
repReferer := c.Request.Referer()
|
||||||
|
// 请求UA
|
||||||
|
reqUA := c.Request.UserAgent()
|
||||||
|
|
||||||
|
// 请求响应内容长度
|
||||||
|
resLength := c.Writer.Size()
|
||||||
|
if resLength < 0 {
|
||||||
|
resLength = 0
|
||||||
|
}
|
||||||
|
// 响应状态码
|
||||||
|
statusCode := c.Writer.Status()
|
||||||
|
|
||||||
|
log.SDebug(fmt.Sprintf(
|
||||||
|
"%s | %3d | %s %10s | \033[44;37m%-6s\033[0m %s %s | %10v | \"%s\" \"%s\"",
|
||||||
|
colorForStatus(statusCode),
|
||||||
|
statusCode,
|
||||||
|
colorForStatus(0),
|
||||||
|
clientIP,
|
||||||
|
// remoteIP,
|
||||||
|
reqMethod,
|
||||||
|
reqUri,
|
||||||
|
reqProto,
|
||||||
|
latencyTime,
|
||||||
|
reqUA,
|
||||||
|
repReferer,
|
||||||
|
))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// colorForStatus 根据 HTTP 状态码返回 ANSI 颜色代码
|
||||||
|
func colorForStatus(code int) string {
|
||||||
|
switch {
|
||||||
|
case code >= 200 && code < 300:
|
||||||
|
return "\033[42;1;37m" // green
|
||||||
|
case code >= 300 && code < 400:
|
||||||
|
return "\033[34m" // blue
|
||||||
|
case code >= 400 && code < 500:
|
||||||
|
return "\033[33m" // yellow
|
||||||
|
case code == 0:
|
||||||
|
return "\033[0m" // cancel
|
||||||
|
default:
|
||||||
|
return "\033[31m" // red
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HttpClientModule struct {
|
type HttpClientModule struct {
|
||||||
@@ -43,7 +43,15 @@ func (slf *SyncHttpResponse) Get(timeoutMs int) HttpResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *HttpClientModule) Init(maxpool int, proxyUrl string) {
|
func (m *HttpClientModule) InitHttpClient(transport http.RoundTripper,timeout time.Duration,checkRedirect func(req *http.Request, via []*http.Request) error){
|
||||||
|
m.client = &http.Client{
|
||||||
|
Transport: transport,
|
||||||
|
Timeout: timeout,
|
||||||
|
CheckRedirect: checkRedirect,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *HttpClientModule) Init(proxyUrl string, maxpool int, dialTimeout time.Duration,dialKeepAlive time.Duration,idleConnTimeout time.Duration,timeout time.Duration) {
|
||||||
type ProxyFun func(_ *http.Request) (*url.URL, error)
|
type ProxyFun func(_ *http.Request) (*url.URL, error)
|
||||||
var proxyFun ProxyFun
|
var proxyFun ProxyFun
|
||||||
if proxyUrl != "" {
|
if proxyUrl != "" {
|
||||||
@@ -55,16 +63,16 @@ func (m *HttpClientModule) Init(maxpool int, proxyUrl string) {
|
|||||||
m.client = &http.Client{
|
m.client = &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
DialContext: (&net.Dialer{
|
DialContext: (&net.Dialer{
|
||||||
Timeout: 5 * time.Second,
|
Timeout: dialTimeout,
|
||||||
KeepAlive: 30 * time.Second,
|
KeepAlive: dialKeepAlive,
|
||||||
}).DialContext,
|
}).DialContext,
|
||||||
MaxIdleConns: maxpool,
|
MaxIdleConns: maxpool,
|
||||||
MaxIdleConnsPerHost: maxpool,
|
MaxIdleConnsPerHost: maxpool,
|
||||||
IdleConnTimeout: 60 * time.Second,
|
IdleConnTimeout: idleConnTimeout,
|
||||||
Proxy: proxyFun,
|
Proxy: proxyFun,
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
},
|
},
|
||||||
Timeout: 5 * time.Second,
|
Timeout: timeout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
65
sysmodule/kafkamodule/Admin.go
Normal file
65
sysmodule/kafkamodule/Admin.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package kafkamodule
|
||||||
|
|
||||||
|
import "github.com/IBM/sarama"
|
||||||
|
|
||||||
|
type KafkaAdmin struct {
|
||||||
|
sarama.ClusterAdmin
|
||||||
|
|
||||||
|
mapTopic map[string]sarama.TopicDetail
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ka *KafkaAdmin) Setup(kafkaVersion string, addrs []string) error {
|
||||||
|
config := sarama.NewConfig()
|
||||||
|
var err error
|
||||||
|
config.Version, err = sarama.ParseKafkaVersion(kafkaVersion)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ka.ClusterAdmin, err = sarama.NewClusterAdmin(addrs, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ka.mapTopic, err = ka.GetTopics()
|
||||||
|
if err != nil {
|
||||||
|
ka.ClusterAdmin.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ka *KafkaAdmin) RefreshTopic() error {
|
||||||
|
var err error
|
||||||
|
ka.mapTopic, err = ka.GetTopics()
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ka *KafkaAdmin) HasTopic(topic string) bool {
|
||||||
|
_, ok := ka.mapTopic[topic]
|
||||||
|
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ka *KafkaAdmin) GetTopicDetail(topic string) *sarama.TopicDetail {
|
||||||
|
topicDetail, ok := ka.mapTopic[topic]
|
||||||
|
if ok == false {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &topicDetail
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ka *KafkaAdmin) GetTopics() (map[string]sarama.TopicDetail, error) {
|
||||||
|
return ka.ListTopics()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTopic 创建主题
|
||||||
|
// numPartitions分区数
|
||||||
|
// replicationFactor副本数
|
||||||
|
// validateOnly参数执行操作时只进行参数验证而不实际执行操作
|
||||||
|
func (ka *KafkaAdmin) CreateTopic(topic string, numPartitions int32, replicationFactor int16, validateOnly bool) error {
|
||||||
|
return ka.ClusterAdmin.CreateTopic(topic, &sarama.TopicDetail{NumPartitions: numPartitions, ReplicationFactor: replicationFactor}, validateOnly)
|
||||||
|
}
|
||||||
289
sysmodule/kafkamodule/Consumer.go
Normal file
289
sysmodule/kafkamodule/Consumer.go
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
package kafkamodule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/IBM/sarama"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConsumerGroup struct {
|
||||||
|
sarama.ConsumerGroup
|
||||||
|
waitGroup sync.WaitGroup
|
||||||
|
|
||||||
|
chanExit chan error
|
||||||
|
ready chan bool
|
||||||
|
cancel context.CancelFunc
|
||||||
|
groupId string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConsumerConfig(kafkaVersion string, assignor string, offsetsInitial int64) (*sarama.Config, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
config := sarama.NewConfig()
|
||||||
|
config.Version, err = sarama.ParseKafkaVersion(kafkaVersion)
|
||||||
|
config.Consumer.Offsets.Initial = offsetsInitial
|
||||||
|
config.Consumer.Offsets.AutoCommit.Enable = false
|
||||||
|
|
||||||
|
switch assignor {
|
||||||
|
case "sticky":
|
||||||
|
// 黏性roundRobin,rebalance之后首先保证前面的分配,从后面剥离
|
||||||
|
// topic:T0{P0,P1,P2,P3,P4,P5},消费者:C1,C2
|
||||||
|
// ---------------before rebalance:即roundRobin
|
||||||
|
// C1: T0{P0} T0{P2} T0{P4}
|
||||||
|
// C2: T0{P1} T0{P3} T0{P5}
|
||||||
|
// ----------------after rebalance:增加了一个消费者
|
||||||
|
// C1: T0{P0} T0{P2}
|
||||||
|
// C2: T0{P1} T0{P3}
|
||||||
|
// C3: T0{P4} T0{P5} until每个消费者的分区数误差不超过1
|
||||||
|
config.Consumer.Group.Rebalance.GroupStrategies = []sarama.BalanceStrategy{sarama.NewBalanceStrategySticky()}
|
||||||
|
case "roundrobin":
|
||||||
|
// roundRobin --逐个平均分发
|
||||||
|
// topic: T0{P0,P1,P2},T1{P0,P1,P2,P3}两个消费者C1,C2
|
||||||
|
// C1: T0{P0} T0{P2} T1{P1} T1{P3}
|
||||||
|
// C2: T0{P1} T1{P0} T1{P2}
|
||||||
|
config.Consumer.Group.Rebalance.GroupStrategies = []sarama.BalanceStrategy{sarama.NewBalanceStrategyRoundRobin()}
|
||||||
|
case "range":
|
||||||
|
// 默认值 --一次平均分发
|
||||||
|
// topic: T0{P0,P1,P2,P3},T1{P0,P1,P2,P3},两个消费者C1,C2
|
||||||
|
// T1分区总数6 / 消费者数2 = 3 ,即该会话的分区每个消费者分3个
|
||||||
|
// T2分区总数4 / 消费者数2 = 2 ,即该会话的分区每个消费者分2个
|
||||||
|
// C1: T0{P0, P1, P2} T1{P0, P1}
|
||||||
|
// C2: T0{P3, P4, P5} T1{P2, P3}
|
||||||
|
config.Consumer.Group.Rebalance.GroupStrategies = []sarama.BalanceStrategy{sarama.NewBalanceStrategyRange()}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Unrecognized consumer group partition assignor: %s", assignor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type IMsgReceiver interface {
|
||||||
|
Receiver(msgs []*sarama.ConsumerMessage) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConsumerGroup) Setup(addr []string, topics []string, groupId string, config *sarama.Config, receiverInterval time.Duration, maxReceiverNum int, msgReceiver IMsgReceiver) error {
|
||||||
|
var err error
|
||||||
|
c.ConsumerGroup, err = sarama.NewConsumerGroup(addr, groupId, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
c.groupId = groupId
|
||||||
|
c.chanExit = make(chan error, 1)
|
||||||
|
|
||||||
|
var handler ConsumerGroupHandler
|
||||||
|
handler.receiver = msgReceiver
|
||||||
|
handler.maxReceiverNum = maxReceiverNum
|
||||||
|
handler.receiverInterval = receiverInterval
|
||||||
|
handler.chanExit = c.chanExit
|
||||||
|
|
||||||
|
var ctx context.Context
|
||||||
|
ctx, c.cancel = context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
c.waitGroup.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer c.waitGroup.Done()
|
||||||
|
|
||||||
|
for {
|
||||||
|
if err = c.Consume(ctx, topics, &handler); err != nil {
|
||||||
|
// 当setup失败的时候,error会返回到这里
|
||||||
|
log.Error("Error from consumer", log.Any("err", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if context was cancelled, signaling that the consumer should stop
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
log.Info("consumer stop", log.Any("info", ctx.Err()))
|
||||||
|
}
|
||||||
|
|
||||||
|
c.chanExit <- err
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = <-c.chanExit
|
||||||
|
//已经准备好了
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConsumerGroup) Close() {
|
||||||
|
log.Info("close consumerGroup")
|
||||||
|
//1.cancel掉
|
||||||
|
c.cancel()
|
||||||
|
|
||||||
|
//2.关闭连接
|
||||||
|
err := c.ConsumerGroup.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("close consumerGroup fail", log.Any("err", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
//3.等待退出
|
||||||
|
c.waitGroup.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConsumerGroupHandler struct {
|
||||||
|
receiver IMsgReceiver
|
||||||
|
|
||||||
|
receiverInterval time.Duration
|
||||||
|
maxReceiverNum int
|
||||||
|
|
||||||
|
//mapTopicOffset map[string]map[int32]int //map[topic]map[partitionId]offsetInfo
|
||||||
|
mapTopicData map[string]*MsgData
|
||||||
|
mx sync.Mutex
|
||||||
|
|
||||||
|
chanExit chan error
|
||||||
|
isRebalance bool //是否为再平衡
|
||||||
|
//stopSig *int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type MsgData struct {
|
||||||
|
sync.Mutex
|
||||||
|
msg []*sarama.ConsumerMessage
|
||||||
|
|
||||||
|
mapPartitionOffset map[int32]int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *ConsumerGroupHandler) Flush(session sarama.ConsumerGroupSession, topic string) {
|
||||||
|
if topic != "" {
|
||||||
|
msgData := ch.GetMsgData(topic)
|
||||||
|
msgData.flush(session, ch.receiver, topic)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for tp, msgData := range ch.mapTopicData {
|
||||||
|
msgData.flush(session, ch.receiver, tp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *ConsumerGroupHandler) GetMsgData(topic string) *MsgData {
|
||||||
|
ch.mx.Lock()
|
||||||
|
defer ch.mx.Unlock()
|
||||||
|
|
||||||
|
msgData := ch.mapTopicData[topic]
|
||||||
|
if msgData == nil {
|
||||||
|
msgData = &MsgData{}
|
||||||
|
msgData.msg = make([]*sarama.ConsumerMessage, 0, ch.maxReceiverNum)
|
||||||
|
ch.mapTopicData[topic] = msgData
|
||||||
|
}
|
||||||
|
|
||||||
|
return msgData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (md *MsgData) flush(session sarama.ConsumerGroupSession, receiver IMsgReceiver, topic string) {
|
||||||
|
if len(md.msg) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送给接收者
|
||||||
|
for {
|
||||||
|
ok := receiver.Receiver(md.msg)
|
||||||
|
if ok == true {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for pId, offset := range md.mapPartitionOffset {
|
||||||
|
|
||||||
|
session.MarkOffset(topic, pId, offset+1, "")
|
||||||
|
log.Info(fmt.Sprintf("topic %s,pid %d,offset %d", topic, pId, offset+1))
|
||||||
|
}
|
||||||
|
session.Commit()
|
||||||
|
//log.Info("commit")
|
||||||
|
//time.Sleep(1000 * time.Second)
|
||||||
|
//置空
|
||||||
|
md.msg = md.msg[:0]
|
||||||
|
clear(md.mapPartitionOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (md *MsgData) appendMsg(session sarama.ConsumerGroupSession, msg *sarama.ConsumerMessage, receiver IMsgReceiver, maxReceiverNum int) {
|
||||||
|
md.Lock()
|
||||||
|
defer md.Unlock()
|
||||||
|
|
||||||
|
//收到的offset只会越来越大在
|
||||||
|
if md.mapPartitionOffset == nil {
|
||||||
|
md.mapPartitionOffset = make(map[int32]int64, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
md.mapPartitionOffset[msg.Partition] = msg.Offset
|
||||||
|
|
||||||
|
md.msg = append(md.msg, msg)
|
||||||
|
if len(md.msg) < maxReceiverNum {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
md.flush(session, receiver, msg.Topic)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *ConsumerGroupHandler) AppendMsg(session sarama.ConsumerGroupSession, msg *sarama.ConsumerMessage) {
|
||||||
|
dataMsg := ch.GetMsgData(msg.Topic)
|
||||||
|
dataMsg.appendMsg(session, msg, ch.receiver, ch.maxReceiverNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *ConsumerGroupHandler) Setup(session sarama.ConsumerGroupSession) error {
|
||||||
|
ch.mapTopicData = make(map[string]*MsgData, 128)
|
||||||
|
|
||||||
|
if ch.isRebalance == false {
|
||||||
|
ch.chanExit <- nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ch.isRebalance = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *ConsumerGroupHandler) Cleanup(session sarama.ConsumerGroupSession) error {
|
||||||
|
ch.Flush(session, "")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *ConsumerGroupHandler) ConsumeClaim(session sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error {
|
||||||
|
|
||||||
|
ticker := time.NewTicker(ch.receiverInterval)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case msg := <-claim.Messages():
|
||||||
|
if msg == nil {
|
||||||
|
log.SWarning("claim will exit", log.Any("topic", claim.Topic()), log.Any("Partition", claim.Partition()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ch.AppendMsg(session, msg)
|
||||||
|
case <-ticker.C:
|
||||||
|
ch.Flush(session, claim.Topic())
|
||||||
|
case <-session.Context().Done():
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
阿里云参数说明:https://sls.aliyun.com/doc/oscompatibledemo/sarama_go_kafka_consume.html
|
||||||
|
conf.Net.TLS.Enable = true
|
||||||
|
conf.Net.SASL.Enable = true
|
||||||
|
conf.Net.SASL.User = project
|
||||||
|
conf.Net.SASL.Password = fmt.Sprintf("%s#%s", accessId, accessKey)
|
||||||
|
conf.Net.SASL.Mechanism = "PLAIN"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
conf.Net.TLS.Enable = true
|
||||||
|
conf.Net.SASL.Enable = true
|
||||||
|
conf.Net.SASL.User = project
|
||||||
|
conf.Net.SASL.Password = fmt.Sprintf("%s#%s", accessId, accessKey)
|
||||||
|
conf.Net.SASL.Mechanism = "PLAIN"
|
||||||
|
|
||||||
|
conf.Consumer.Fetch.Min = 1
|
||||||
|
conf.Consumer.Fetch.Default = 1024 * 1024
|
||||||
|
conf.Consumer.Retry.Backoff = 2 * time.Second
|
||||||
|
conf.Consumer.MaxWaitTime = 250 * time.Millisecond
|
||||||
|
conf.Consumer.MaxProcessingTime = 100 * time.Millisecond
|
||||||
|
conf.Consumer.Return.Errors = false
|
||||||
|
conf.Consumer.Offsets.AutoCommit.Enable = true
|
||||||
|
conf.Consumer.Offsets.AutoCommit.Interval = 1 * time.Second
|
||||||
|
conf.Consumer.Offsets.Initial = sarama.OffsetOldest
|
||||||
|
conf.Consumer.Offsets.Retry.Max = 3
|
||||||
|
*/
|
||||||
146
sysmodule/kafkamodule/Producer.go
Normal file
146
sysmodule/kafkamodule/Producer.go
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
package kafkamodule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/IBM/sarama"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IProducer interface {
|
||||||
|
}
|
||||||
|
|
||||||
|
type SyncProducer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type AsyncProducer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type Producer struct {
|
||||||
|
service.Module
|
||||||
|
|
||||||
|
sarama.SyncProducer
|
||||||
|
|
||||||
|
sarama.AsyncProducer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProducerConfig 新建producerConfig
|
||||||
|
// kafkaVersion kafka版本
|
||||||
|
// returnErr,returnSucc 是否返回错误与成功
|
||||||
|
// requiredAcks -1 #全量同步确认,强可靠性保证(当所有的 leader 和 follower 都接收成功时)#WaitForAll 1 #leader 确认收到, 默认(仅 leader 反馈)#WaitForLocal 0 #不确认,但是吞吐量大(不 care 结果) #NoResponse
|
||||||
|
// Idempotent(幂等) 确保信息都准确写入一份副本,用于幂等生产者,当这一项设置为true的时候,生产者将保证生产的消息一定是有序且精确一次的
|
||||||
|
// partitioner 生成分区器,用于选择向哪个分区发送信息,默认情况下对消息密钥进行散列
|
||||||
|
func NewProducerConfig(kafkaVersion string, returnErr bool, returnSucc bool, requiredAcks sarama.RequiredAcks, Idempotent bool,
|
||||||
|
partitioner sarama.PartitionerConstructor) (*sarama.Config, error) {
|
||||||
|
config := sarama.NewConfig()
|
||||||
|
var err error
|
||||||
|
config.Version, err = sarama.ParseKafkaVersion(kafkaVersion)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Producer.Return.Errors = returnErr
|
||||||
|
config.Producer.Return.Successes = returnSucc
|
||||||
|
config.Producer.RequiredAcks = requiredAcks
|
||||||
|
config.Producer.Partitioner = partitioner
|
||||||
|
config.Producer.Timeout = 10 * time.Second
|
||||||
|
|
||||||
|
config.Producer.Idempotent = Idempotent
|
||||||
|
if Idempotent == true {
|
||||||
|
config.Net.MaxOpenRequests = 1
|
||||||
|
}
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Producer) SyncSetup(addr []string, config *sarama.Config) error {
|
||||||
|
var err error
|
||||||
|
p.SyncProducer, err = sarama.NewSyncProducer(addr, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Producer) ASyncSetup(addr []string, config *sarama.Config) error {
|
||||||
|
var err error
|
||||||
|
p.AsyncProducer, err = sarama.NewAsyncProducer(addr, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
p.asyncRun()
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Producer) asyncRun() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case sm := <-p.Successes():
|
||||||
|
if sm.Metadata == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
asyncReturn := sm.Metadata.(*AsyncReturn)
|
||||||
|
asyncReturn.chanReturn <- asyncReturn
|
||||||
|
case em := <-p.Errors():
|
||||||
|
log.Error("async kafkamodule error", log.ErrorAttr("err", em.Err))
|
||||||
|
if em.Msg.Metadata == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
asyncReturn := em.Msg.Metadata.(*AsyncReturn)
|
||||||
|
asyncReturn.Err = em.Err
|
||||||
|
asyncReturn.chanReturn <- asyncReturn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type AsyncReturn struct {
|
||||||
|
Msg *sarama.ProducerMessage
|
||||||
|
Err error
|
||||||
|
chanReturn chan *AsyncReturn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ar *AsyncReturn) WaitOk(ctx context.Context) (*sarama.ProducerMessage, error) {
|
||||||
|
asyncReturn := ar.Msg.Metadata.(*AsyncReturn)
|
||||||
|
select {
|
||||||
|
case <-asyncReturn.chanReturn:
|
||||||
|
return asyncReturn.Msg, asyncReturn.Err
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil, ctx.Err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Producer) AsyncSendMessage(msg *sarama.ProducerMessage) *AsyncReturn {
|
||||||
|
asyncReturn := AsyncReturn{Msg: msg, chanReturn: make(chan *AsyncReturn, 1)}
|
||||||
|
msg.Metadata = &asyncReturn
|
||||||
|
p.AsyncProducer.Input() <- msg
|
||||||
|
|
||||||
|
return &asyncReturn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Producer) AsyncPushMessage(msg *sarama.ProducerMessage) {
|
||||||
|
p.AsyncProducer.Input() <- msg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Producer) Close() {
|
||||||
|
if p.SyncProducer != nil {
|
||||||
|
p.SyncProducer.Close()
|
||||||
|
p.SyncProducer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.AsyncProducer != nil {
|
||||||
|
p.AsyncProducer.Close()
|
||||||
|
p.AsyncProducer = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Producer) SendMessage(msg *sarama.ProducerMessage) (partition int32, offset int64, err error) {
|
||||||
|
return p.SyncProducer.SendMessage(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Producer) SendMessages(msgs []*sarama.ProducerMessage) error {
|
||||||
|
return p.SyncProducer.SendMessages(msgs)
|
||||||
|
}
|
||||||
151
sysmodule/kafkamodule/ProducerAndConsumer_test.go
Normal file
151
sysmodule/kafkamodule/ProducerAndConsumer_test.go
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
package kafkamodule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/IBM/sarama"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 对各参数和机制名称的说明:https://blog.csdn.net/u013311345/article/details/129217728
|
||||||
|
type MsgReceiver struct {
|
||||||
|
t *testing.T
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mr *MsgReceiver) Receiver(msgs []*sarama.ConsumerMessage) bool {
|
||||||
|
for _, m := range msgs {
|
||||||
|
mr.t.Logf("time:%s, topic:%s, partition:%d, offset:%d, key:%s, value:%s", time.Now().Format("2006-01-02 15:04:05.000"), m.Topic, m.Partition, m.Offset, m.Key, string(m.Value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var addr = []string{"192.168.13.24:9092", "192.168.13.24:9093", "192.168.13.24:9094", "192.168.13.24:9095"}
|
||||||
|
var topicName = []string{"test_topic_1", "test_topic_2"}
|
||||||
|
var kafkaVersion = "3.3.1"
|
||||||
|
|
||||||
|
func producer(t *testing.T) {
|
||||||
|
var admin KafkaAdmin
|
||||||
|
err := admin.Setup(kafkaVersion, addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tName := range topicName {
|
||||||
|
if admin.HasTopic(tName) == false {
|
||||||
|
err = admin.CreateTopic(tName, 2, 2, false)
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var pd Producer
|
||||||
|
cfg, err := NewProducerConfig(kafkaVersion, true, true, sarama.WaitForAll, false, sarama.NewHashPartitioner)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pd.SyncSetup(addr, cfg)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
//msgs := make([]*sarama.ProducerMessage, 0, 20000)
|
||||||
|
for i := 0; i < 20000; i++ {
|
||||||
|
var msg sarama.ProducerMessage
|
||||||
|
msg.Key = sarama.StringEncoder(fmt.Sprintf("%d", i))
|
||||||
|
msg.Topic = topicName[0]
|
||||||
|
msg.Value = sarama.StringEncoder(fmt.Sprintf("i'm %d", i))
|
||||||
|
pd.SendMessage(&msg)
|
||||||
|
//msgs = append(msgs, &msg)
|
||||||
|
}
|
||||||
|
//err = pd.SendMessages(msgs)
|
||||||
|
//t.Log(err)
|
||||||
|
t.Log(time.Now().Sub(now).Milliseconds())
|
||||||
|
pd.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func producer_async(t *testing.T) {
|
||||||
|
var admin KafkaAdmin
|
||||||
|
err := admin.Setup(kafkaVersion, addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tName := range topicName {
|
||||||
|
if admin.HasTopic(tName) == false {
|
||||||
|
err = admin.CreateTopic(tName, 10, 2, false)
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var pd Producer
|
||||||
|
cfg, err := NewProducerConfig(kafkaVersion, true, true, sarama.WaitForAll, false, sarama.NewHashPartitioner)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pd.ASyncSetup(addr, cfg)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
msgs := make([]*AsyncReturn, 0, 20000)
|
||||||
|
for i := 0; i < 200000; i++ {
|
||||||
|
var msg sarama.ProducerMessage
|
||||||
|
msg.Key = sarama.StringEncoder(fmt.Sprintf("%d", i))
|
||||||
|
msg.Topic = topicName[0]
|
||||||
|
msg.Value = sarama.StringEncoder(fmt.Sprintf("i'm %d", i))
|
||||||
|
|
||||||
|
r := pd.AsyncSendMessage(&msg)
|
||||||
|
msgs = append(msgs, r)
|
||||||
|
}
|
||||||
|
//err = pd.SendMessages(msgs)
|
||||||
|
//t.Log(err)
|
||||||
|
|
||||||
|
for _, r := range msgs {
|
||||||
|
r.WaitOk(context.Background())
|
||||||
|
//t.Log(m, e)
|
||||||
|
}
|
||||||
|
t.Log(time.Now().Sub(now).Milliseconds())
|
||||||
|
|
||||||
|
time.Sleep(1000 * time.Second)
|
||||||
|
pd.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func consumer(t *testing.T) {
|
||||||
|
var admin KafkaAdmin
|
||||||
|
err := admin.Setup(kafkaVersion, addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tName := range topicName {
|
||||||
|
if admin.HasTopic(tName) == false {
|
||||||
|
err = admin.CreateTopic(tName, 10, 2, false)
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cg ConsumerGroup
|
||||||
|
cfg, err := NewConsumerConfig(kafkaVersion, "sticky", sarama.OffsetOldest)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = cg.Setup(addr, topicName, "test_groupId", cfg, 50*time.Second, 10, &MsgReceiver{t: t})
|
||||||
|
t.Log(err)
|
||||||
|
time.Sleep(10000 * time.Second)
|
||||||
|
cg.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConsumerAndProducer(t *testing.T) {
|
||||||
|
producer_async(t)
|
||||||
|
//go producer(t)
|
||||||
|
//producer(t)
|
||||||
|
//consumer(t)
|
||||||
|
}
|
||||||
7
sysmodule/kafkamodule/Sasl.go
Normal file
7
sysmodule/kafkamodule/Sasl.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package kafkamodule
|
||||||
|
|
||||||
|
type Sasl struct {
|
||||||
|
UserName string `json:"UserName"`
|
||||||
|
Passwd string `json:"Passwd"`
|
||||||
|
InstanceId string `json:"InstanceId"`
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
"go.mongodb.org/mongo-driver/x/bsonx"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -86,12 +85,12 @@ func (s *Session) EnsureUniqueIndex(db string, collection string, indexKeys [][]
|
|||||||
func (s *Session) ensureIndex(db string, collection string, indexKeys [][]string, bBackground bool, unique bool, sparse bool, asc bool) error {
|
func (s *Session) ensureIndex(db string, collection string, indexKeys [][]string, bBackground bool, unique bool, sparse bool, asc bool) error {
|
||||||
var indexes []mongo.IndexModel
|
var indexes []mongo.IndexModel
|
||||||
for _, keys := range indexKeys {
|
for _, keys := range indexKeys {
|
||||||
keysDoc := bsonx.Doc{}
|
keysDoc := bson.D{}
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
if asc {
|
if asc {
|
||||||
keysDoc = keysDoc.Append(key, bsonx.Int32(1))
|
keysDoc = append(keysDoc, bson.E{Key:key,Value:1})
|
||||||
} else {
|
} else {
|
||||||
keysDoc = keysDoc.Append(key, bsonx.Int32(-1))
|
keysDoc = append(keysDoc, bson.E{Key:key,Value:-1})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,181 +0,0 @@
|
|||||||
package mongomodule
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/duanhf2012/origin/log"
|
|
||||||
"gopkg.in/mgo.v2"
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
"container/heap"
|
|
||||||
_ "gopkg.in/mgo.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// session
|
|
||||||
type Session struct {
|
|
||||||
*mgo.Session
|
|
||||||
ref int
|
|
||||||
index int
|
|
||||||
}
|
|
||||||
|
|
||||||
type SessionHeap []*Session
|
|
||||||
|
|
||||||
func (h SessionHeap) Len() int {
|
|
||||||
return len(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h SessionHeap) Less(i, j int) bool {
|
|
||||||
return h[i].ref < h[j].ref
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h SessionHeap) Swap(i, j int) {
|
|
||||||
h[i], h[j] = h[j], h[i]
|
|
||||||
h[i].index = i
|
|
||||||
h[j].index = j
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *SessionHeap) Push(s interface{}) {
|
|
||||||
s.(*Session).index = len(*h)
|
|
||||||
*h = append(*h, s.(*Session))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *SessionHeap) Pop() interface{} {
|
|
||||||
l := len(*h)
|
|
||||||
s := (*h)[l-1]
|
|
||||||
s.index = -1
|
|
||||||
*h = (*h)[:l-1]
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
type DialContext struct {
|
|
||||||
sync.Mutex
|
|
||||||
sessions SessionHeap
|
|
||||||
}
|
|
||||||
|
|
||||||
type MongoModule struct {
|
|
||||||
dailContext *DialContext
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *MongoModule) Init(url string,sessionNum uint32,dialTimeout time.Duration, timeout time.Duration) error {
|
|
||||||
var err error
|
|
||||||
slf.dailContext, err = dialWithTimeout(url, sessionNum, dialTimeout, timeout)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *MongoModule) Ref() *Session{
|
|
||||||
return slf.dailContext.Ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *MongoModule) UnRef(s *Session) {
|
|
||||||
slf.dailContext.UnRef(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// goroutine safe
|
|
||||||
func dialWithTimeout(url string, sessionNum uint32, dialTimeout time.Duration, timeout time.Duration) (*DialContext, error) {
|
|
||||||
if sessionNum <= 0 {
|
|
||||||
sessionNum = 100
|
|
||||||
log.Release("invalid sessionNum, reset to %v", sessionNum)
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err := mgo.DialWithTimeout(url, dialTimeout)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.SetMode(mgo.Strong,true)
|
|
||||||
s.SetSyncTimeout(timeout)
|
|
||||||
s.SetSocketTimeout(timeout)
|
|
||||||
|
|
||||||
c := new(DialContext)
|
|
||||||
|
|
||||||
// sessions
|
|
||||||
c.sessions = make(SessionHeap, sessionNum)
|
|
||||||
c.sessions[0] = &Session{s, 0, 0}
|
|
||||||
for i := 1; i < int(sessionNum); i++ {
|
|
||||||
c.sessions[i] = &Session{s.New(), 0, i}
|
|
||||||
}
|
|
||||||
heap.Init(&c.sessions)
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// goroutine safe
|
|
||||||
func (c *DialContext) Close() {
|
|
||||||
c.Lock()
|
|
||||||
for _, s := range c.sessions {
|
|
||||||
s.Close()
|
|
||||||
}
|
|
||||||
c.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// goroutine safe
|
|
||||||
func (c *DialContext) Ref() *Session {
|
|
||||||
c.Lock()
|
|
||||||
s := c.sessions[0]
|
|
||||||
if s.ref == 0 {
|
|
||||||
s.Refresh()
|
|
||||||
}
|
|
||||||
s.ref++
|
|
||||||
heap.Fix(&c.sessions, 0)
|
|
||||||
c.Unlock()
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// goroutine safe
|
|
||||||
func (c *DialContext) UnRef(s *Session) {
|
|
||||||
if s == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Lock()
|
|
||||||
s.ref--
|
|
||||||
heap.Fix(&c.sessions, s.index)
|
|
||||||
c.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// goroutine safe
|
|
||||||
func (s *Session) EnsureCounter(db string, collection string, id string) error {
|
|
||||||
err := s.DB(db).C(collection).Insert(bson.M{
|
|
||||||
"_id": id,
|
|
||||||
"seq": 0,
|
|
||||||
})
|
|
||||||
if mgo.IsDup(err) {
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// goroutine safe
|
|
||||||
func (s *Session) NextSeq(db string, collection string, id string) (int, error) {
|
|
||||||
var res struct {
|
|
||||||
Seq int
|
|
||||||
}
|
|
||||||
_, err := s.DB(db).C(collection).FindId(id).Apply(mgo.Change{
|
|
||||||
Update: bson.M{"$inc": bson.M{"seq": 1}},
|
|
||||||
ReturnNew: true,
|
|
||||||
}, &res)
|
|
||||||
|
|
||||||
return res.Seq, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// goroutine safe
|
|
||||||
func (s *Session) EnsureIndex(db string, collection string, key []string, bBackground bool) error {
|
|
||||||
return s.DB(db).C(collection).EnsureIndex(mgo.Index{
|
|
||||||
Key: key,
|
|
||||||
Unique: false,
|
|
||||||
Sparse: true,
|
|
||||||
Background: bBackground,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// goroutine safe
|
|
||||||
func (s *Session) EnsureUniqueIndex(db string, collection string, key []string, bBackground bool) error {
|
|
||||||
return s.DB(db).C(collection).EnsureIndex(mgo.Index{
|
|
||||||
Key: key,
|
|
||||||
Unique: true,
|
|
||||||
Sparse: true,
|
|
||||||
Background: bBackground,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
package mongomodule
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
_ "gopkg.in/mgo.v2"
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type Student struct {
|
|
||||||
ID bson.ObjectId `bson:"_id"`
|
|
||||||
Name string `bson: "name"`
|
|
||||||
Age int `bson: "age"`
|
|
||||||
Sid string `bson: "sid"`
|
|
||||||
Status int `bson: "status"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type StudentName struct {
|
|
||||||
Name string `bson: "name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func Test_Example(t *testing.T) {
|
|
||||||
module:=MongoModule{}
|
|
||||||
module.Init("mongodb://admin:123456@192.168.2.119:27017",100, 5*time.Second,5*time.Second)
|
|
||||||
|
|
||||||
// take session
|
|
||||||
s := module.Take()
|
|
||||||
c := s.DB("test2").C("t_student")
|
|
||||||
|
|
||||||
//2.定义对象
|
|
||||||
insertData := Student{
|
|
||||||
ID:bson.NewObjectId(),
|
|
||||||
Name: "seeta11",
|
|
||||||
Age: 35, //*^_^*
|
|
||||||
Sid: "s20180907",
|
|
||||||
Status: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
updateData := Student{
|
|
||||||
Name: "seeta11",
|
|
||||||
Age: 18,
|
|
||||||
Sid: "s20180907",
|
|
||||||
Status: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//3.插入数据
|
|
||||||
err := c.Insert(&insertData)
|
|
||||||
|
|
||||||
//4.查找数据
|
|
||||||
selector := bson.M{"_id":bson.ObjectIdHex("5f25303e999c622d361989b0")}
|
|
||||||
m:=Student{}
|
|
||||||
err = c.Find(selector).One(&m)
|
|
||||||
|
|
||||||
//5.更新数据
|
|
||||||
//selector2 := bson.M{"_id":bson.ObjectIdHex("5f25303e999c622d361989b0")}
|
|
||||||
updateData.ID = bson.ObjectIdHex("5f25303e999c622d361989b0")
|
|
||||||
err = c.UpdateId(bson.ObjectIdHex("5f25303e999c622d361989b0"),&updateData)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Print(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
//6.删除数据
|
|
||||||
err = c.RemoveId(bson.ObjectIdHex("5f252f09999c622d36198951"))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Print(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
//7.序号自增
|
|
||||||
s.EnsureCounter("test2","t_student","5f252f09999c622d36198951")
|
|
||||||
for i := 0; i < 3; i++ {
|
|
||||||
id, err := s.NextSeq("test2", "t_student", "5f252f09999c622d36198951")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
//8.setoninsert使用
|
|
||||||
info,uErr := c.Upsert(bson.M{"_id":bson.ObjectIdHex("5f252f09999c622d36198951")},bson.M{
|
|
||||||
"$setOnInsert":bson.M{"Name":"setoninsert","Age":55}})
|
|
||||||
|
|
||||||
|
|
||||||
//9.修改部分数字数据
|
|
||||||
selector1 := bson.M{"_id":bson.ObjectIdHex("60473de655f1012e7453b369")}
|
|
||||||
update1 := bson.M{"$set":bson.M{"name":"xxxxx","age":1111}}
|
|
||||||
c.Update(selector1,update1)
|
|
||||||
|
|
||||||
fmt.Println(info,uErr)
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package mysqlmondule
|
package mysqlmodule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package mysqlmondule
|
package mysqlmodule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/gomodule/redigo/redis"
|
"github.com/gomodule/redigo/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package httpservice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/event"
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
"github.com/duanhf2012/origin/network"
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/duanhf2012/origin/util/uuid"
|
"github.com/duanhf2012/origin/v2/util/uuid"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package messagequeueservice
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/cluster"
|
"github.com/duanhf2012/origin/v2/cluster"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
"github.com/duanhf2012/origin/util/coroutine"
|
"github.com/duanhf2012/origin/v2/util/coroutine"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -16,7 +16,7 @@ type CustomerSubscriber struct {
|
|||||||
rpc.IRpcHandler
|
rpc.IRpcHandler
|
||||||
topic string
|
topic string
|
||||||
subscriber *Subscriber
|
subscriber *Subscriber
|
||||||
fromNodeId int
|
fromNodeId string
|
||||||
callBackRpcMethod string
|
callBackRpcMethod string
|
||||||
serviceName string
|
serviceName string
|
||||||
StartIndex uint64
|
StartIndex uint64
|
||||||
@@ -37,7 +37,7 @@ const (
|
|||||||
MethodLast SubscribeMethod = 1 //Last模式,以该消费者上次记录的位置开始订阅
|
MethodLast SubscribeMethod = 1 //Last模式,以该消费者上次记录的位置开始订阅
|
||||||
)
|
)
|
||||||
|
|
||||||
func (cs *CustomerSubscriber) trySetSubscriberBaseInfo(rpcHandler rpc.IRpcHandler, ss *Subscriber, topic string, subscribeMethod SubscribeMethod, customerId string, fromNodeId int, callBackRpcMethod string, startIndex uint64, oneBatchQuantity int32) error {
|
func (cs *CustomerSubscriber) trySetSubscriberBaseInfo(rpcHandler rpc.IRpcHandler, ss *Subscriber, topic string, subscribeMethod SubscribeMethod, customerId string, fromNodeId string, callBackRpcMethod string, startIndex uint64, oneBatchQuantity int32) error {
|
||||||
cs.subscriber = ss
|
cs.subscriber = ss
|
||||||
cs.fromNodeId = fromNodeId
|
cs.fromNodeId = fromNodeId
|
||||||
cs.callBackRpcMethod = callBackRpcMethod
|
cs.callBackRpcMethod = callBackRpcMethod
|
||||||
@@ -85,7 +85,7 @@ func (cs *CustomerSubscriber) trySetSubscriberBaseInfo(rpcHandler rpc.IRpcHandle
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 开始订阅
|
// 开始订阅
|
||||||
func (cs *CustomerSubscriber) Subscribe(rpcHandler rpc.IRpcHandler, ss *Subscriber, topic string, subscribeMethod SubscribeMethod, customerId string, fromNodeId int, callBackRpcMethod string, startIndex uint64, oneBatchQuantity int32) error {
|
func (cs *CustomerSubscriber) Subscribe(rpcHandler rpc.IRpcHandler, ss *Subscriber, topic string, subscribeMethod SubscribeMethod, customerId string, fromNodeId string, callBackRpcMethod string, startIndex uint64, oneBatchQuantity int32) error {
|
||||||
err := cs.trySetSubscriberBaseInfo(rpcHandler, ss, topic, subscribeMethod, customerId, fromNodeId, callBackRpcMethod, startIndex, oneBatchQuantity)
|
err := cs.trySetSubscriberBaseInfo(rpcHandler, ss, topic, subscribeMethod, customerId, fromNodeId, callBackRpcMethod, startIndex, oneBatchQuantity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -104,11 +104,11 @@ func (cs *CustomerSubscriber) UnSubscribe() {
|
|||||||
func (cs *CustomerSubscriber) LoadLastIndex() {
|
func (cs *CustomerSubscriber) LoadLastIndex() {
|
||||||
for {
|
for {
|
||||||
if atomic.LoadInt32(&cs.isStop) != 0 {
|
if atomic.LoadInt32(&cs.isStop) != 0 {
|
||||||
log.SRelease("topic ", cs.topic, " out of subscription")
|
log.Info("topic ", cs.topic, " out of subscription")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SRelease("customer ", cs.customerId, " start load last index ")
|
log.Info("customer ", cs.customerId, " start load last index ")
|
||||||
lastIndex, ret := cs.subscriber.dataPersist.LoadCustomerIndex(cs.topic, cs.customerId)
|
lastIndex, ret := cs.subscriber.dataPersist.LoadCustomerIndex(cs.topic, cs.customerId)
|
||||||
if ret == true {
|
if ret == true {
|
||||||
if lastIndex > 0 {
|
if lastIndex > 0 {
|
||||||
@@ -116,18 +116,18 @@ func (cs *CustomerSubscriber) LoadLastIndex() {
|
|||||||
} else {
|
} else {
|
||||||
//否则直接使用客户端发回来的
|
//否则直接使用客户端发回来的
|
||||||
}
|
}
|
||||||
log.SRelease("customer ", cs.customerId, " load finish,start index is ", cs.StartIndex)
|
log.Info("customer ", cs.customerId, " load finish,start index is ", cs.StartIndex)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SRelease("customer ", cs.customerId, " load last index is fail...")
|
log.Info("customer ", cs.customerId, " load last index is fail...")
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CustomerSubscriber) SubscribeRun() {
|
func (cs *CustomerSubscriber) SubscribeRun() {
|
||||||
defer cs.subscriber.queueWait.Done()
|
defer cs.subscriber.queueWait.Done()
|
||||||
log.SRelease("topic ", cs.topic, " start subscription")
|
log.Info("topic ", cs.topic, " start subscription")
|
||||||
|
|
||||||
//加载之前的位置
|
//加载之前的位置
|
||||||
if cs.subscribeMethod == MethodLast {
|
if cs.subscribeMethod == MethodLast {
|
||||||
@@ -136,7 +136,7 @@ func (cs *CustomerSubscriber) SubscribeRun() {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
if atomic.LoadInt32(&cs.isStop) != 0 {
|
if atomic.LoadInt32(&cs.isStop) != 0 {
|
||||||
log.SRelease("topic ", cs.topic, " out of subscription")
|
log.Info("topic ", cs.topic, " out of subscription")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,14 +146,14 @@ func (cs *CustomerSubscriber) SubscribeRun() {
|
|||||||
|
|
||||||
//todo 检测退出
|
//todo 检测退出
|
||||||
if cs.subscribe() == false {
|
if cs.subscribe() == false {
|
||||||
log.SRelease("topic ", cs.topic, " out of subscription")
|
log.Info("topic ", cs.topic, " out of subscription")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除订阅关系
|
//删除订阅关系
|
||||||
cs.subscriber.removeCustomer(cs.customerId, cs)
|
cs.subscriber.removeCustomer(cs.customerId, cs)
|
||||||
log.SRelease("topic ", cs.topic, " unsubscription")
|
log.Info("topic ", cs.topic, " unsubscription")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CustomerSubscriber) subscribe() bool {
|
func (cs *CustomerSubscriber) subscribe() bool {
|
||||||
@@ -213,7 +213,7 @@ func (cs *CustomerSubscriber) publishToCustomer(topicData []TopicData) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//推送数据
|
//推送数据
|
||||||
err := cs.CallNode(cs.fromNodeId, cs.callBackRpcMethod, &dbQueuePublishReq, &dbQueuePushRes)
|
err := cs.CallNodeWithTimeout(4*time.Minute,cs.fromNodeId, cs.callBackRpcMethod, &dbQueuePublishReq, &dbQueuePushRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package messagequeueservice
|
package messagequeueservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/util/algorithms"
|
"github.com/duanhf2012/origin/v2/util/algorithms"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package messagequeueservice
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ func (ms *MessageQueueService) ReadCfg() error {
|
|||||||
maxProcessTopicBacklogNum, ok := mapDBServiceCfg["MaxProcessTopicBacklogNum"]
|
maxProcessTopicBacklogNum, ok := mapDBServiceCfg["MaxProcessTopicBacklogNum"]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
ms.maxProcessTopicBacklogNum = DefaultMaxTopicBacklogNum
|
ms.maxProcessTopicBacklogNum = DefaultMaxTopicBacklogNum
|
||||||
log.SRelease("MaxProcessTopicBacklogNum config is set to the default value of ", maxProcessTopicBacklogNum)
|
log.Info("MaxProcessTopicBacklogNum config is set to the default value of ", maxProcessTopicBacklogNum)
|
||||||
} else {
|
} else {
|
||||||
ms.maxProcessTopicBacklogNum = int32(maxProcessTopicBacklogNum.(float64))
|
ms.maxProcessTopicBacklogNum = int32(maxProcessTopicBacklogNum.(float64))
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ func (ms *MessageQueueService) ReadCfg() error {
|
|||||||
memoryQueueLen, ok := mapDBServiceCfg["MemoryQueueLen"]
|
memoryQueueLen, ok := mapDBServiceCfg["MemoryQueueLen"]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
ms.memoryQueueLen = DefaultMemoryQueueLen
|
ms.memoryQueueLen = DefaultMemoryQueueLen
|
||||||
log.SRelease("MemoryQueueLen config is set to the default value of ", DefaultMemoryQueueLen)
|
log.Info("MemoryQueueLen config is set to the default value of ", DefaultMemoryQueueLen)
|
||||||
} else {
|
} else {
|
||||||
ms.memoryQueueLen = int32(memoryQueueLen.(float64))
|
ms.memoryQueueLen = int32(memoryQueueLen.(float64))
|
||||||
}
|
}
|
||||||
@@ -122,5 +122,5 @@ func (ms *MessageQueueService) RPC_Publish(inParam *rpc.DBQueuePublishReq, outPa
|
|||||||
|
|
||||||
func (ms *MessageQueueService) RPC_Subscribe(req *rpc.DBQueueSubscribeReq, res *rpc.DBQueueSubscribeRes) error {
|
func (ms *MessageQueueService) RPC_Subscribe(req *rpc.DBQueueSubscribeReq, res *rpc.DBQueueSubscribeRes) error {
|
||||||
topicRoom := ms.GetTopicRoom(req.TopicName)
|
topicRoom := ms.GetTopicRoom(req.TopicName)
|
||||||
return topicRoom.TopicSubscribe(ms.GetRpcHandler(), req.SubType, int32(req.Method), int(req.FromNodeId), req.RpcMethod, req.TopicName, req.CustomerId, req.StartIndex, req.OneBatchQuantity)
|
return topicRoom.TopicSubscribe(ms.GetRpcHandler(), req.SubType, int32(req.Method), req.FromNodeId, req.RpcMethod, req.TopicName, req.CustomerId, req.StartIndex, req.OneBatchQuantity)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,49 @@
|
|||||||
package messagequeueservice
|
package messagequeueservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/duanhf2012/origin/sysmodule/mongodbmodule"
|
"github.com/duanhf2012/origin/v2/sysmodule/mongodbmodule"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
"sunserver/common/util"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const MaxDays = 180
|
const MaxDays = 180
|
||||||
|
|
||||||
|
type DataType interface {
|
||||||
|
int | uint | int64 | uint64 | float32 | float64 | int32 | uint32 | int16 | uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToNumber[DType DataType](val interface{}) (error, DType) {
|
||||||
|
switch val.(type) {
|
||||||
|
case int64:
|
||||||
|
return nil, DType(val.(int64))
|
||||||
|
case int:
|
||||||
|
return nil, DType(val.(int))
|
||||||
|
case uint:
|
||||||
|
return nil, DType(val.(uint))
|
||||||
|
case uint64:
|
||||||
|
return nil, DType(val.(uint64))
|
||||||
|
case float32:
|
||||||
|
return nil, DType(val.(float32))
|
||||||
|
case float64:
|
||||||
|
return nil, DType(val.(float64))
|
||||||
|
case int32:
|
||||||
|
return nil, DType(val.(int32))
|
||||||
|
case uint32:
|
||||||
|
return nil, DType(val.(uint32))
|
||||||
|
case int16:
|
||||||
|
return nil, DType(val.(int16))
|
||||||
|
case uint16:
|
||||||
|
return nil, DType(val.(uint16))
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New("unsupported type"), 0
|
||||||
|
}
|
||||||
|
|
||||||
type MongoPersist struct {
|
type MongoPersist struct {
|
||||||
service.Module
|
service.Module
|
||||||
mongo mongodbmodule.MongoModule
|
mongo mongodbmodule.MongoModule
|
||||||
@@ -363,7 +394,7 @@ func (mp *MongoPersist) GetIndex(topicData *TopicData) uint64 {
|
|||||||
|
|
||||||
for _, e := range document {
|
for _, e := range document {
|
||||||
if e.Key == "_id" {
|
if e.Key == "_id" {
|
||||||
errC, seq := util.ConvertToNumber[uint64](e.Value)
|
errC, seq := convertToNumber[uint64](e.Value)
|
||||||
if errC != nil {
|
if errC != nil {
|
||||||
log.Error("value is error:%s,%+v, ", errC.Error(), e.Value)
|
log.Error("value is error:%s,%+v, ", errC.Error(), e.Value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package messagequeueservice
|
package messagequeueservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
|
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@@ -31,7 +31,7 @@ func (ss *Subscriber) PersistTopicData(topic string, topics []TopicData, retryCo
|
|||||||
return ss.dataPersist.PersistTopicData(topic, topics, retryCount)
|
return ss.dataPersist.PersistTopicData(topic, topics, retryCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *Subscriber) TopicSubscribe(rpcHandler rpc.IRpcHandler, subScribeType rpc.SubscribeType, subscribeMethod SubscribeMethod, fromNodeId int, callBackRpcMethod string, topic string, customerId string, StartIndex uint64, oneBatchQuantity int32) error {
|
func (ss *Subscriber) TopicSubscribe(rpcHandler rpc.IRpcHandler, subScribeType rpc.SubscribeType, subscribeMethod SubscribeMethod, fromNodeId string, callBackRpcMethod string, topic string, customerId string, StartIndex uint64, oneBatchQuantity int32) error {
|
||||||
//取消订阅时
|
//取消订阅时
|
||||||
if subScribeType == rpc.SubscribeType_Unsubscribe {
|
if subScribeType == rpc.SubscribeType_Unsubscribe {
|
||||||
ss.UnSubscribe(customerId)
|
ss.UnSubscribe(customerId)
|
||||||
@@ -56,9 +56,9 @@ func (ss *Subscriber) TopicSubscribe(rpcHandler rpc.IRpcHandler, subScribeType r
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ok == true {
|
if ok == true {
|
||||||
log.SRelease("repeat subscription for customer ", customerId)
|
log.Info("repeat subscription for customer ", customerId)
|
||||||
} else {
|
} else {
|
||||||
log.SRelease("subscription for customer ", customerId)
|
log.Info("subscription for customer ", customerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package messagequeueservice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/util/coroutine"
|
"github.com/duanhf2012/origin/v2/util/coroutine"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -93,7 +93,7 @@ func (tr *TopicRoom) Stop() {
|
|||||||
func (tr *TopicRoom) topicRoomRun() {
|
func (tr *TopicRoom) topicRoomRun() {
|
||||||
defer tr.queueWait.Done()
|
defer tr.queueWait.Done()
|
||||||
|
|
||||||
log.SRelease("topic room ", tr.topic, " is running..")
|
log.Info("topic room ", tr.topic, " is running..")
|
||||||
for {
|
for {
|
||||||
if atomic.LoadInt32(&tr.isStop) != 0 {
|
if atomic.LoadInt32(&tr.isStop) != 0 {
|
||||||
break
|
break
|
||||||
@@ -145,5 +145,5 @@ func (tr *TopicRoom) topicRoomRun() {
|
|||||||
}
|
}
|
||||||
tr.customerLocker.Unlock()
|
tr.customerLocker.Unlock()
|
||||||
|
|
||||||
log.SRelease("topic room ", tr.topic, " is stop")
|
log.Info("topic room ", tr.topic, " is stop")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ package rankservice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/duanhf2012/origin/sysmodule/mongodbmodule"
|
"github.com/duanhf2012/origin/v2/sysmodule/mongodbmodule"
|
||||||
"github.com/duanhf2012/origin/util/coroutine"
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -71,7 +71,9 @@ func (mp *MongoPersist) OnInit() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//开启协程
|
//开启协程
|
||||||
coroutine.GoRecover(mp.persistCoroutine,-1)
|
mp.waitGroup.Add(1)
|
||||||
|
go mp.persistCoroutine()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,13 +142,13 @@ func (mp *MongoPersist) OnSetupRank(manual bool,rankSkip *RankSkip) error{
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SRelease("start load rank ",rankSkip.GetRankName()," from mongodb.")
|
log.Info("start load rank ",rankSkip.GetRankName()," from mongodb.")
|
||||||
err := mp.loadFromDB(rankSkip.GetRankID(),rankSkip.GetRankName())
|
err := mp.loadFromDB(rankSkip.GetRankID(),rankSkip.GetRankName())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("load from db is fail :%s",err.Error())
|
log.SError("load from db is fail :%s",err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.SRelease("finish load rank ",rankSkip.GetRankName()," from mongodb.")
|
log.Info("finish load rank ",rankSkip.GetRankName()," from mongodb.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,9 +262,8 @@ func (mp *MongoPersist) JugeTimeoutSave() bool{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (mp *MongoPersist) persistCoroutine(){
|
func (mp *MongoPersist) persistCoroutine(){
|
||||||
mp.waitGroup.Add(1)
|
|
||||||
defer mp.waitGroup.Done()
|
defer mp.waitGroup.Done()
|
||||||
for atomic.LoadInt32(&mp.stop)==0 || mp.hasPersistData(){
|
for atomic.LoadInt32(&mp.stop)==0 {
|
||||||
//间隔时间sleep
|
//间隔时间sleep
|
||||||
time.Sleep(time.Second*1)
|
time.Sleep(time.Second*1)
|
||||||
|
|
||||||
@@ -291,6 +292,15 @@ func (mp *MongoPersist) hasPersistData() bool{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (mp *MongoPersist) saveToDB(){
|
func (mp *MongoPersist) saveToDB(){
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
l := runtime.Stack(buf, false)
|
||||||
|
errString := fmt.Sprint(r)
|
||||||
|
log.Dump(string(buf[:l]),log.String("error",errString))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
//1.copy数据
|
//1.copy数据
|
||||||
mp.Lock()
|
mp.Lock()
|
||||||
mapRemoveRankData := mp.mapRemoveRankData
|
mapRemoveRankData := mp.mapRemoveRankData
|
||||||
@@ -347,7 +357,7 @@ func (mp *MongoPersist) removeRankData(rankId uint64,keys []uint64) bool {
|
|||||||
|
|
||||||
func (mp *MongoPersist) upsertToDB(collectName string,rankData *RankData) error{
|
func (mp *MongoPersist) upsertToDB(collectName string,rankData *RankData) error{
|
||||||
condition := bson.D{{"_id", rankData.Key}}
|
condition := bson.D{{"_id", rankData.Key}}
|
||||||
upsert := bson.M{"_id":rankData.Key,"RefreshTime": rankData.refreshTimestamp, "SortData": rankData.SortData, "Data": rankData.Data,"ExData":rankData.ExData}
|
upsert := bson.M{"_id":rankData.Key,"RefreshTime": rankData.RefreshTimestamp, "SortData": rankData.SortData, "Data": rankData.Data,"ExData":rankData.ExData}
|
||||||
update := bson.M{"$set": upsert}
|
update := bson.M{"$set": upsert}
|
||||||
|
|
||||||
s := mp.mongo.TakeSession()
|
s := mp.mongo.TakeSession()
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package rankservice
|
package rankservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
"github.com/duanhf2012/origin/util/algorithms/skip"
|
"github.com/duanhf2012/origin/v2/util/algorithms/skip"
|
||||||
"github.com/duanhf2012/origin/util/sync"
|
"github.com/duanhf2012/origin/v2/util/sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
var emptyRankData RankData
|
var emptyRankData RankData
|
||||||
@@ -19,7 +19,7 @@ type RankData struct {
|
|||||||
Data []byte
|
Data []byte
|
||||||
ExData []int64
|
ExData []int64
|
||||||
|
|
||||||
refreshTimestamp int64 //刷新时间
|
RefreshTimestamp int64 //刷新时间
|
||||||
//bRelease bool
|
//bRelease bool
|
||||||
ref bool
|
ref bool
|
||||||
compareFunc func(other skip.Comparator) int
|
compareFunc func(other skip.Comparator) int
|
||||||
@@ -39,7 +39,7 @@ func NewRankData(isDec bool, data *rpc.RankData,refreshTimestamp int64) *RankDat
|
|||||||
ret.ExData = append(ret.ExData,d.InitValue+d.IncreaseValue)
|
ret.ExData = append(ret.ExData,d.InitValue+d.IncreaseValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.refreshTimestamp = refreshTimestamp
|
ret.RefreshTimestamp = refreshTimestamp
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package rankservice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"container/heap"
|
"container/heap"
|
||||||
"github.com/duanhf2012/origin/util/sync"
|
"github.com/duanhf2012/origin/v2/util/sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package rankservice
|
package rankservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RankDataChangeType int8
|
type RankDataChangeType int8
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
const PreMapRankSkipLen = 10
|
const PreMapRankSkipLen = 10
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
"github.com/duanhf2012/origin/util/algorithms/skip"
|
"github.com/duanhf2012/origin/v2/util/algorithms/skip"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RankSkip struct {
|
type RankSkip struct {
|
||||||
@@ -250,7 +250,7 @@ func (rs *RankSkip) UpsetRank(upsetData *rpc.RankData, refreshTimestamp int64, f
|
|||||||
//找到的情况对比排名数据是否有变化,无变化进行data更新,有变化则进行删除更新
|
//找到的情况对比排名数据是否有变化,无变化进行data更新,有变化则进行删除更新
|
||||||
if compareIsEqual(rankNode.SortData, upsetData.SortData) {
|
if compareIsEqual(rankNode.SortData, upsetData.SortData) {
|
||||||
rankNode.Data = upsetData.GetData()
|
rankNode.Data = upsetData.GetData()
|
||||||
rankNode.refreshTimestamp = refreshTimestamp
|
rankNode.RefreshTimestamp = refreshTimestamp
|
||||||
|
|
||||||
if fromLoad == false {
|
if fromLoad == false {
|
||||||
rs.rankModule.OnChangeRankData(rs, rankNode)
|
rs.rankModule.OnChangeRankData(rs, rankNode)
|
||||||
@@ -356,12 +356,12 @@ func (rs *RankSkip) GetRankNodeDataByRank(rank uint64) (*RankData, uint64) {
|
|||||||
// GetRankKeyPrevToLimit 获取key前count名的数据
|
// GetRankKeyPrevToLimit 获取key前count名的数据
|
||||||
func (rs *RankSkip) GetRankKeyPrevToLimit(findKey, count uint64, result *rpc.RankDataList) error {
|
func (rs *RankSkip) GetRankKeyPrevToLimit(findKey, count uint64, result *rpc.RankDataList) error {
|
||||||
if rs.GetRankLen() <= 0 {
|
if rs.GetRankLen() <= 0 {
|
||||||
return fmt.Errorf("rank[", rs.rankId, "] no data")
|
return fmt.Errorf("rank[%d] no data", rs.rankId)
|
||||||
}
|
}
|
||||||
|
|
||||||
findData, ok := rs.mapRankData[findKey]
|
findData, ok := rs.mapRankData[findKey]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return fmt.Errorf("rank[", rs.rankId, "] no data")
|
return fmt.Errorf("rank[%d] no data", rs.rankId)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, rankPos := rs.skipList.GetWithPosition(findData)
|
_, rankPos := rs.skipList.GetWithPosition(findData)
|
||||||
@@ -385,12 +385,12 @@ func (rs *RankSkip) GetRankKeyPrevToLimit(findKey, count uint64, result *rpc.Ran
|
|||||||
// GetRankKeyPrevToLimit 获取key前count名的数据
|
// GetRankKeyPrevToLimit 获取key前count名的数据
|
||||||
func (rs *RankSkip) GetRankKeyNextToLimit(findKey, count uint64, result *rpc.RankDataList) error {
|
func (rs *RankSkip) GetRankKeyNextToLimit(findKey, count uint64, result *rpc.RankDataList) error {
|
||||||
if rs.GetRankLen() <= 0 {
|
if rs.GetRankLen() <= 0 {
|
||||||
return fmt.Errorf("rank[", rs.rankId, "] no data")
|
return fmt.Errorf("rank[%d] no data", rs.rankId)
|
||||||
}
|
}
|
||||||
|
|
||||||
findData, ok := rs.mapRankData[findKey]
|
findData, ok := rs.mapRankData[findKey]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return fmt.Errorf("rank[", rs.rankId, "] no data")
|
return fmt.Errorf("rank[%d] no data", rs.rankId)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, rankPos := rs.skipList.GetWithPosition(findData)
|
_, rankPos := rs.skipList.GetWithPosition(findData)
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ package tcpservice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/event"
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/network"
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
"github.com/duanhf2012/origin/network/processor"
|
"github.com/duanhf2012/origin/v2/network/processor"
|
||||||
"github.com/duanhf2012/origin/node"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/util/bytespool"
|
||||||
"sync/atomic"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"time"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TcpService struct {
|
type TcpService struct {
|
||||||
@@ -19,7 +20,7 @@ type TcpService struct {
|
|||||||
service.Service
|
service.Service
|
||||||
|
|
||||||
mapClientLocker sync.RWMutex
|
mapClientLocker sync.RWMutex
|
||||||
mapClient map[uint64] *Client
|
mapClient map[string] *Client
|
||||||
process processor.IProcessor
|
process processor.IProcessor
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,41 +32,18 @@ const(
|
|||||||
TPT_UnknownPack TcpPackType = 3
|
TPT_UnknownPack TcpPackType = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
MaxNodeId = 1<<14 - 1 //最大值 16383
|
|
||||||
MaxSeed = 1<<19 - 1 //最大值 524287
|
|
||||||
MaxTime = 1<<31 - 1 //最大值 2147483647
|
|
||||||
)
|
|
||||||
|
|
||||||
var seed uint32
|
|
||||||
|
|
||||||
type TcpPack struct {
|
type TcpPack struct {
|
||||||
Type TcpPackType //0表示连接 1表示断开 2表示数据
|
Type TcpPackType //0表示连接 1表示断开 2表示数据
|
||||||
ClientId uint64
|
ClientId string
|
||||||
Data interface{}
|
Data interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
id uint64
|
id string
|
||||||
tcpConn *network.TCPConn
|
tcpConn *network.TCPConn
|
||||||
tcpService *TcpService
|
tcpService *TcpService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpService *TcpService) genId() uint64 {
|
|
||||||
if node.GetNodeId()>MaxNodeId{
|
|
||||||
panic("nodeId exceeds the maximum!")
|
|
||||||
}
|
|
||||||
|
|
||||||
newSeed := atomic.AddUint32(&seed,1) % MaxSeed
|
|
||||||
nowTime := uint64(time.Now().Unix())%MaxTime
|
|
||||||
return (uint64(node.GetNodeId())<<50)|(nowTime<<19)|uint64(newSeed)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func GetNodeId(agentId uint64) int {
|
|
||||||
return int(agentId>>50)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpService *TcpService) OnInit() error{
|
func (tcpService *TcpService) OnInit() error{
|
||||||
iConfig := tcpService.GetServiceCfg()
|
iConfig := tcpService.GetServiceCfg()
|
||||||
if iConfig == nil {
|
if iConfig == nil {
|
||||||
@@ -82,6 +60,7 @@ func (tcpService *TcpService) OnInit() error{
|
|||||||
if ok == true {
|
if ok == true {
|
||||||
tcpService.tcpServer.MaxConnNum = int(MaxConnNum.(float64))
|
tcpService.tcpServer.MaxConnNum = int(MaxConnNum.(float64))
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingWriteNum,ok := tcpCfg["PendingWriteNum"]
|
PendingWriteNum,ok := tcpCfg["PendingWriteNum"]
|
||||||
if ok == true {
|
if ok == true {
|
||||||
tcpService.tcpServer.PendingWriteNum = int(PendingWriteNum.(float64))
|
tcpService.tcpServer.PendingWriteNum = int(PendingWriteNum.(float64))
|
||||||
@@ -90,6 +69,10 @@ func (tcpService *TcpService) OnInit() error{
|
|||||||
if ok == true {
|
if ok == true {
|
||||||
tcpService.tcpServer.LittleEndian = LittleEndian.(bool)
|
tcpService.tcpServer.LittleEndian = LittleEndian.(bool)
|
||||||
}
|
}
|
||||||
|
LenMsgLen,ok := tcpCfg["LenMsgLen"]
|
||||||
|
if ok == true {
|
||||||
|
tcpService.tcpServer.LenMsgLen = int(LenMsgLen.(float64))
|
||||||
|
}
|
||||||
MinMsgLen,ok := tcpCfg["MinMsgLen"]
|
MinMsgLen,ok := tcpCfg["MinMsgLen"]
|
||||||
if ok == true {
|
if ok == true {
|
||||||
tcpService.tcpServer.MinMsgLen = uint32(MinMsgLen.(float64))
|
tcpService.tcpServer.MinMsgLen = uint32(MinMsgLen.(float64))
|
||||||
@@ -109,7 +92,7 @@ func (tcpService *TcpService) OnInit() error{
|
|||||||
tcpService.tcpServer.WriteDeadline = time.Second*time.Duration(writeDeadline.(float64))
|
tcpService.tcpServer.WriteDeadline = time.Second*time.Duration(writeDeadline.(float64))
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpService.mapClient = make( map[uint64] *Client, tcpService.tcpServer.MaxConnNum)
|
tcpService.mapClient = make( map[string] *Client, tcpService.tcpServer.MaxConnNum)
|
||||||
tcpService.tcpServer.NewAgent = tcpService.NewClient
|
tcpService.tcpServer.NewAgent = tcpService.NewClient
|
||||||
tcpService.tcpServer.Start()
|
tcpService.tcpServer.Start()
|
||||||
|
|
||||||
@@ -124,12 +107,16 @@ func (tcpService *TcpService) TcpEventHandler(ev event.IEvent) {
|
|||||||
case TPT_DisConnected:
|
case TPT_DisConnected:
|
||||||
tcpService.process.DisConnectedRoute(pack.ClientId)
|
tcpService.process.DisConnectedRoute(pack.ClientId)
|
||||||
case TPT_UnknownPack:
|
case TPT_UnknownPack:
|
||||||
tcpService.process.UnknownMsgRoute(pack.ClientId,pack.Data)
|
tcpService.process.UnknownMsgRoute(pack.ClientId,pack.Data,tcpService.recyclerReaderBytes)
|
||||||
case TPT_Pack:
|
case TPT_Pack:
|
||||||
tcpService.process.MsgRoute(pack.ClientId,pack.Data)
|
tcpService.process.MsgRoute(pack.ClientId,pack.Data,tcpService.recyclerReaderBytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tcpService *TcpService) recyclerReaderBytes(data []byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (tcpService *TcpService) SetProcessor(process processor.IProcessor,handler event.IEventHandler){
|
func (tcpService *TcpService) SetProcessor(process processor.IProcessor,handler event.IEventHandler){
|
||||||
tcpService.process = process
|
tcpService.process = process
|
||||||
tcpService.RegEventReceiverFunc(event.Sys_Event_Tcp,handler, tcpService.TcpEventHandler)
|
tcpService.RegEventReceiverFunc(event.Sys_Event_Tcp,handler, tcpService.TcpEventHandler)
|
||||||
@@ -139,24 +126,16 @@ func (tcpService *TcpService) NewClient(conn *network.TCPConn) network.Agent {
|
|||||||
tcpService.mapClientLocker.Lock()
|
tcpService.mapClientLocker.Lock()
|
||||||
defer tcpService.mapClientLocker.Unlock()
|
defer tcpService.mapClientLocker.Unlock()
|
||||||
|
|
||||||
for {
|
uuId,_ := uuid.NewUUID()
|
||||||
clientId := tcpService.genId()
|
clientId := strings.ReplaceAll(uuId.String(), "-", "")
|
||||||
_,ok := tcpService.mapClient[clientId]
|
pClient := &Client{tcpConn: conn, id: clientId}
|
||||||
if ok == true {
|
pClient.tcpService = tcpService
|
||||||
continue
|
tcpService.mapClient[clientId] = pClient
|
||||||
}
|
|
||||||
|
|
||||||
pClient := &Client{tcpConn:conn, id:clientId}
|
return pClient
|
||||||
pClient.tcpService = tcpService
|
|
||||||
tcpService.mapClient[clientId] = pClient
|
|
||||||
|
|
||||||
return pClient
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *Client) GetId() uint64 {
|
func (slf *Client) GetId() string {
|
||||||
return slf.id
|
return slf.id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +145,7 @@ func (slf *Client) Run() {
|
|||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
l := runtime.Stack(buf, false)
|
l := runtime.Stack(buf, false)
|
||||||
errString := fmt.Sprint(r)
|
errString := fmt.Sprint(r)
|
||||||
log.SError("core dump info[",errString,"]\n",string(buf[:l]))
|
log.Dump(string(buf[:l]),log.String("error",errString))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -179,7 +158,7 @@ func (slf *Client) Run() {
|
|||||||
slf.tcpConn.SetReadDeadline(slf.tcpService.tcpServer.ReadDeadline)
|
slf.tcpConn.SetReadDeadline(slf.tcpService.tcpServer.ReadDeadline)
|
||||||
bytes,err := slf.tcpConn.ReadMsg()
|
bytes,err := slf.tcpConn.ReadMsg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SDebug("read client id ",slf.id," is error:",err.Error())
|
log.Debug("read client failed",log.ErrorAttr("error",err),log.String("clientId",slf.id))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
data,err:=slf.tcpService.process.Unmarshal(slf.id,bytes)
|
data,err:=slf.tcpService.process.Unmarshal(slf.id,bytes)
|
||||||
@@ -199,7 +178,7 @@ func (slf *Client) OnClose(){
|
|||||||
delete (slf.tcpService.mapClient,slf.GetId())
|
delete (slf.tcpService.mapClient,slf.GetId())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpService *TcpService) SendMsg(clientId uint64,msg interface{}) error{
|
func (tcpService *TcpService) SendMsg(clientId string,msg interface{}) error{
|
||||||
tcpService.mapClientLocker.Lock()
|
tcpService.mapClientLocker.Lock()
|
||||||
client,ok := tcpService.mapClient[clientId]
|
client,ok := tcpService.mapClient[clientId]
|
||||||
if ok == false{
|
if ok == false{
|
||||||
@@ -215,7 +194,7 @@ func (tcpService *TcpService) SendMsg(clientId uint64,msg interface{}) error{
|
|||||||
return client.tcpConn.WriteMsg(bytes)
|
return client.tcpConn.WriteMsg(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpService *TcpService) Close(clientId uint64) {
|
func (tcpService *TcpService) Close(clientId string) {
|
||||||
tcpService.mapClientLocker.Lock()
|
tcpService.mapClientLocker.Lock()
|
||||||
defer tcpService.mapClientLocker.Unlock()
|
defer tcpService.mapClientLocker.Unlock()
|
||||||
|
|
||||||
@@ -231,7 +210,7 @@ func (tcpService *TcpService) Close(clientId uint64) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpService *TcpService) GetClientIp(clientid uint64) string{
|
func (tcpService *TcpService) GetClientIp(clientid string) string{
|
||||||
tcpService.mapClientLocker.Lock()
|
tcpService.mapClientLocker.Lock()
|
||||||
defer tcpService.mapClientLocker.Unlock()
|
defer tcpService.mapClientLocker.Unlock()
|
||||||
pClient,ok := tcpService.mapClient[clientid]
|
pClient,ok := tcpService.mapClient[clientid]
|
||||||
@@ -243,7 +222,7 @@ func (tcpService *TcpService) GetClientIp(clientid uint64) string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (tcpService *TcpService) SendRawMsg(clientId uint64,msg []byte) error{
|
func (tcpService *TcpService) SendRawMsg(clientId string,msg []byte) error{
|
||||||
tcpService.mapClientLocker.Lock()
|
tcpService.mapClientLocker.Lock()
|
||||||
client,ok := tcpService.mapClient[clientId]
|
client,ok := tcpService.mapClient[clientId]
|
||||||
if ok == false{
|
if ok == false{
|
||||||
@@ -254,7 +233,7 @@ func (tcpService *TcpService) SendRawMsg(clientId uint64,msg []byte) error{
|
|||||||
return client.tcpConn.WriteMsg(msg)
|
return client.tcpConn.WriteMsg(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpService *TcpService) SendRawData(clientId uint64,data []byte) error{
|
func (tcpService *TcpService) SendRawData(clientId string,data []byte) error{
|
||||||
tcpService.mapClientLocker.Lock()
|
tcpService.mapClientLocker.Lock()
|
||||||
client,ok := tcpService.mapClient[clientId]
|
client,ok := tcpService.mapClient[clientId]
|
||||||
if ok == false{
|
if ok == false{
|
||||||
@@ -273,14 +252,14 @@ func (tcpService *TcpService) GetConnNum() int {
|
|||||||
return connNum
|
return connNum
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TcpService) SetNetMempool(mempool network.INetMempool){
|
func (server *TcpService) SetNetMempool(mempool bytespool.IBytesMempool){
|
||||||
server.tcpServer.SetNetMempool(mempool)
|
server.tcpServer.SetNetMempool(mempool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TcpService) GetNetMempool() network.INetMempool{
|
func (server *TcpService) GetNetMempool() bytespool.IBytesMempool {
|
||||||
return server.tcpServer.GetNetMempool()
|
return server.tcpServer.GetNetMempool()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TcpService) ReleaseNetMem(byteBuff []byte) {
|
func (server *TcpService) ReleaseNetMem(byteBuff []byte) {
|
||||||
server.tcpServer.GetNetMempool().ReleaseByteSlice(byteBuff)
|
server.tcpServer.GetNetMempool().ReleaseBytes(byteBuff)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,32 +2,25 @@ package wsservice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/event"
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/network"
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
"github.com/duanhf2012/origin/network/processor"
|
"github.com/duanhf2012/origin/v2/network/processor"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/duanhf2012/origin/node"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"github.com/google/uuid"
|
||||||
"time"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type WSService struct {
|
type WSService struct {
|
||||||
service.Service
|
service.Service
|
||||||
wsServer network.WSServer
|
wsServer network.WSServer
|
||||||
|
|
||||||
mapClientLocker sync.RWMutex
|
mapClientLocker sync.RWMutex
|
||||||
mapClient map[uint64] *WSClient
|
mapClient map[string] *WSClient
|
||||||
process processor.IProcessor
|
process processor.IProcessor
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var seed uint32
|
|
||||||
|
|
||||||
type WSPackType int8
|
type WSPackType int8
|
||||||
const(
|
const(
|
||||||
WPT_Connected WSPackType = 0
|
WPT_Connected WSPackType = 0
|
||||||
@@ -40,14 +33,8 @@ const Default_WS_MaxConnNum = 3000
|
|||||||
const Default_WS_PendingWriteNum = 10000
|
const Default_WS_PendingWriteNum = 10000
|
||||||
const Default_WS_MaxMsgLen = 65535
|
const Default_WS_MaxMsgLen = 65535
|
||||||
|
|
||||||
const (
|
|
||||||
MaxNodeId = 1<<14 - 1 //最大值 16383
|
|
||||||
MaxSeed = 1<<19 - 1 //最大值 524287
|
|
||||||
MaxTime = 1<<31 - 1 //最大值 2147483647
|
|
||||||
)
|
|
||||||
|
|
||||||
type WSClient struct {
|
type WSClient struct {
|
||||||
id uint64
|
id string
|
||||||
wsConn *network.WSConn
|
wsConn *network.WSConn
|
||||||
wsService *WSService
|
wsService *WSService
|
||||||
}
|
}
|
||||||
@@ -55,7 +42,7 @@ type WSClient struct {
|
|||||||
type WSPack struct {
|
type WSPack struct {
|
||||||
Type WSPackType //0表示连接 1表示断开 2表示数据
|
Type WSPackType //0表示连接 1表示断开 2表示数据
|
||||||
MsgProcessor processor.IProcessor
|
MsgProcessor processor.IProcessor
|
||||||
ClientId uint64
|
ClientId string
|
||||||
Data interface{}
|
Data interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +66,7 @@ func (ws *WSService) OnInit() error{
|
|||||||
if ok == true {
|
if ok == true {
|
||||||
ws.wsServer.MaxConnNum = int(MaxConnNum.(float64))
|
ws.wsServer.MaxConnNum = int(MaxConnNum.(float64))
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingWriteNum,ok := wsCfg["PendingWriteNum"]
|
PendingWriteNum,ok := wsCfg["PendingWriteNum"]
|
||||||
if ok == true {
|
if ok == true {
|
||||||
ws.wsServer.PendingWriteNum = int(PendingWriteNum.(float64))
|
ws.wsServer.PendingWriteNum = int(PendingWriteNum.(float64))
|
||||||
@@ -89,7 +77,7 @@ func (ws *WSService) OnInit() error{
|
|||||||
ws.wsServer.MaxMsgLen = uint32(MaxMsgLen.(float64))
|
ws.wsServer.MaxMsgLen = uint32(MaxMsgLen.(float64))
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.mapClient = make( map[uint64] *WSClient, ws.wsServer.MaxConnNum)
|
ws.mapClient = make( map[string] *WSClient, ws.wsServer.MaxConnNum)
|
||||||
ws.wsServer.NewAgent = ws.NewWSClient
|
ws.wsServer.NewAgent = ws.NewWSClient
|
||||||
ws.wsServer.Start()
|
ws.wsServer.Start()
|
||||||
return nil
|
return nil
|
||||||
@@ -107,9 +95,9 @@ func (ws *WSService) WSEventHandler(ev event.IEvent) {
|
|||||||
case WPT_DisConnected:
|
case WPT_DisConnected:
|
||||||
pack.MsgProcessor.DisConnectedRoute(pack.ClientId)
|
pack.MsgProcessor.DisConnectedRoute(pack.ClientId)
|
||||||
case WPT_UnknownPack:
|
case WPT_UnknownPack:
|
||||||
pack.MsgProcessor.UnknownMsgRoute(pack.ClientId,pack.Data)
|
pack.MsgProcessor.UnknownMsgRoute(pack.ClientId,pack.Data,ws.recyclerReaderBytes)
|
||||||
case WPT_Pack:
|
case WPT_Pack:
|
||||||
pack.MsgProcessor.MsgRoute(pack.ClientId,pack.Data)
|
pack.MsgProcessor.MsgRoute(pack.ClientId,pack.Data,ws.recyclerReaderBytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,37 +106,21 @@ func (ws *WSService) SetProcessor(process processor.IProcessor,handler event.IEv
|
|||||||
ws.RegEventReceiverFunc(event.Sys_Event_WebSocket,handler, ws.WSEventHandler)
|
ws.RegEventReceiverFunc(event.Sys_Event_WebSocket,handler, ws.WSEventHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WSService) genId() uint64 {
|
|
||||||
if node.GetNodeId()>MaxNodeId{
|
|
||||||
panic("nodeId exceeds the maximum!")
|
|
||||||
}
|
|
||||||
|
|
||||||
newSeed := atomic.AddUint32(&seed,1) % MaxSeed
|
|
||||||
nowTime := uint64(time.Now().Unix())%MaxTime
|
|
||||||
return (uint64(node.GetNodeId())<<50)|(nowTime<<19)|uint64(newSeed)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ws *WSService) NewWSClient(conn *network.WSConn) network.Agent {
|
func (ws *WSService) NewWSClient(conn *network.WSConn) network.Agent {
|
||||||
ws.mapClientLocker.Lock()
|
ws.mapClientLocker.Lock()
|
||||||
defer ws.mapClientLocker.Unlock()
|
defer ws.mapClientLocker.Unlock()
|
||||||
|
|
||||||
for {
|
uuId, _ := uuid.NewUUID()
|
||||||
clientId := ws.genId()
|
clientId := strings.ReplaceAll(uuId.String(), "-", "")
|
||||||
_,ok := ws.mapClient[clientId]
|
pClient := &WSClient{wsConn: conn, id: clientId}
|
||||||
if ok == true {
|
pClient.wsService = ws
|
||||||
continue
|
ws.mapClient[clientId] = pClient
|
||||||
}
|
return pClient
|
||||||
|
|
||||||
pClient := &WSClient{wsConn:conn, id: clientId}
|
|
||||||
pClient.wsService = ws
|
|
||||||
ws.mapClient[clientId] = pClient
|
|
||||||
return pClient
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *WSClient) GetId() uint64 {
|
func (slf *WSClient) GetId() string {
|
||||||
return slf.id
|
return slf.id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +129,7 @@ func (slf *WSClient) Run() {
|
|||||||
for{
|
for{
|
||||||
bytes,err := slf.wsConn.ReadMsg()
|
bytes,err := slf.wsConn.ReadMsg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("read client id %d is error:%+v",slf.id,err)
|
log.Debug("read client id %s is error:%+v",slf.id,err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
data,err:=slf.wsService.process.Unmarshal(slf.id,bytes)
|
data,err:=slf.wsService.process.Unmarshal(slf.id,bytes)
|
||||||
@@ -176,12 +148,12 @@ func (slf *WSClient) OnClose(){
|
|||||||
delete (slf.wsService.mapClient,slf.GetId())
|
delete (slf.wsService.mapClient,slf.GetId())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WSService) SendMsg(clientid uint64,msg interface{}) error{
|
func (ws *WSService) SendMsg(clientid string,msg interface{}) error{
|
||||||
ws.mapClientLocker.Lock()
|
ws.mapClientLocker.Lock()
|
||||||
client,ok := ws.mapClient[clientid]
|
client,ok := ws.mapClient[clientid]
|
||||||
if ok == false{
|
if ok == false{
|
||||||
ws.mapClientLocker.Unlock()
|
ws.mapClientLocker.Unlock()
|
||||||
return fmt.Errorf("client %d is disconnect!",clientid)
|
return fmt.Errorf("client %s is disconnect!",clientid)
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.mapClientLocker.Unlock()
|
ws.mapClientLocker.Unlock()
|
||||||
@@ -192,7 +164,7 @@ func (ws *WSService) SendMsg(clientid uint64,msg interface{}) error{
|
|||||||
return client.wsConn.WriteMsg(bytes)
|
return client.wsConn.WriteMsg(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WSService) Close(clientid uint64) {
|
func (ws *WSService) Close(clientid string) {
|
||||||
ws.mapClientLocker.Lock()
|
ws.mapClientLocker.Lock()
|
||||||
defer ws.mapClientLocker.Unlock()
|
defer ws.mapClientLocker.Unlock()
|
||||||
|
|
||||||
@@ -208,3 +180,5 @@ func (ws *WSService) Close(clientid uint64) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ws *WSService) recyclerReaderBytes(data []byte) {
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package buildtime
|
package buildtime
|
||||||
|
|
||||||
/*
|
/*
|
||||||
//查询buildtime包中的位置,在github.com/duanhf2012/origin/util/buildtime.BuildTime中
|
//查询buildtime包中的位置,在github.com/duanhf2012/origin/v2/util/buildtime.BuildTime中
|
||||||
go tool nm ./originserver.exe |grep buildtime
|
go tool nm ./originserver.exe |grep buildtime
|
||||||
|
|
||||||
//编译传入编译时间信息
|
//编译传入编译时间信息
|
||||||
go build -ldflags "-X 'github.com/duanhf2012/origin/util/buildtime.BuildTime=20200101'"
|
go build -ldflags "-X 'github.com/duanhf2012/origin/v2/util/buildtime.BuildTime=20200101'"
|
||||||
go build -ldflags "-X github.com/duanhf2012/origin/util/buildtime.BuildTime=20200101 -X github.com/duanhf2012/origin/util/buildtime.BuildTag=debug"
|
go build -ldflags "-X github.com/duanhf2012/origin/v2/util/buildtime.BuildTime=20200101 -X github.com/duanhf2012/origin/v2/util/buildtime.BuildTag=debug"
|
||||||
*/
|
*/
|
||||||
var BuildTime string
|
var BuildTime string
|
||||||
var BuildTag string
|
var BuildTag string
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package network
|
package bytespool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type INetMempool interface {
|
type IBytesMempool interface {
|
||||||
MakeByteSlice(size int) []byte
|
MakeBytes(size int) []byte
|
||||||
ReleaseByteSlice(byteBuff []byte) bool
|
ReleaseBytes(byteBuff []byte) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type memAreaPool struct {
|
type memAreaPool struct {
|
||||||
@@ -16,7 +16,7 @@ type memAreaPool struct {
|
|||||||
pool []sync.Pool
|
pool []sync.Pool
|
||||||
}
|
}
|
||||||
|
|
||||||
var memAreaPoolList = [3]*memAreaPool{&memAreaPool{minAreaValue: 1, maxAreaValue: 4096, growthValue: 512}, &memAreaPool{minAreaValue: 4097, maxAreaValue: 40960, growthValue: 4096}, &memAreaPool{minAreaValue: 40961, maxAreaValue: 417792, growthValue: 16384}}
|
var memAreaPoolList = [4]*memAreaPool{&memAreaPool{minAreaValue: 1, maxAreaValue: 4096, growthValue: 512}, &memAreaPool{minAreaValue: 4097, maxAreaValue: 40960, growthValue: 4096}, &memAreaPool{minAreaValue: 40961, maxAreaValue: 417792, growthValue: 16384}, &memAreaPool{minAreaValue: 417793, maxAreaValue: 1925120, growthValue: 65536}}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
for i := 0; i < len(memAreaPoolList); i++ {
|
for i := 0; i < len(memAreaPoolList); i++ {
|
||||||
@@ -68,7 +68,7 @@ func (areaPool *memAreaPool) releaseByteSlice(byteBuff []byte) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (areaPool *memAreaPool) MakeByteSlice(size int) []byte {
|
func (areaPool *memAreaPool) MakeBytes(size int) []byte {
|
||||||
for i := 0; i < len(memAreaPoolList); i++ {
|
for i := 0; i < len(memAreaPoolList); i++ {
|
||||||
if size <= memAreaPoolList[i].maxAreaValue {
|
if size <= memAreaPoolList[i].maxAreaValue {
|
||||||
return memAreaPoolList[i].makeByteSlice(size)
|
return memAreaPoolList[i].makeByteSlice(size)
|
||||||
@@ -78,7 +78,7 @@ func (areaPool *memAreaPool) MakeByteSlice(size int) []byte {
|
|||||||
return make([]byte, size)
|
return make([]byte, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (areaPool *memAreaPool) ReleaseByteSlice(byteBuff []byte) bool {
|
func (areaPool *memAreaPool) ReleaseBytes(byteBuff []byte) bool {
|
||||||
for i := 0; i < len(memAreaPoolList); i++ {
|
for i := 0; i < len(memAreaPoolList); i++ {
|
||||||
if cap(byteBuff) <= memAreaPoolList[i].maxAreaValue {
|
if cap(byteBuff) <= memAreaPoolList[i].maxAreaValue {
|
||||||
return memAreaPoolList[i].releaseByteSlice(byteBuff)
|
return memAreaPoolList[i].releaseByteSlice(byteBuff)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user