mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-14 15:54:42 +08:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa6039e2cb | ||
|
|
25a672ca53 | ||
|
|
75f881be28 | ||
|
|
ef8182eec7 | ||
|
|
4ad8204fde | ||
|
|
8f15546fb1 | ||
|
|
0f3a965d73 | ||
|
|
dfb6959843 | ||
|
|
dd4aaf9c57 | ||
|
|
6ef98a2104 | ||
|
|
1890b300ee | ||
|
|
6fea2226e1 | ||
|
|
ec1c2b4517 | ||
|
|
4b84d9a1d5 | ||
|
|
85a8ec58e5 | ||
|
|
962016d476 | ||
|
|
a61979e985 |
40
README.md
40
README.md
@@ -64,17 +64,19 @@ cluster.json如下:
|
|||||||
"Private": false,
|
"Private": false,
|
||||||
"ListenAddr":"127.0.0.1:8001",
|
"ListenAddr":"127.0.0.1:8001",
|
||||||
"MaxRpcParamLen": 409600,
|
"MaxRpcParamLen": 409600,
|
||||||
|
"CompressBytesLen": 20480,
|
||||||
"NodeName": "Node_Test1",
|
"NodeName": "Node_Test1",
|
||||||
"remark":"//以_打头的,表示只在本机进程,不对整个子网公开",
|
"remark":"//以_打头的,表示只在本机进程,不对整个子网公开",
|
||||||
"ServiceList": ["TestService1","TestService2","TestServiceCall","GateService","_TcpService","HttpService","WSService"]
|
"ServiceList": ["TestService1","TestService2","TestServiceCall","GateService","_TcpService","HttpService","WSService"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"NodeId": 2,
|
"NodeId": 2,
|
||||||
"Private": false,
|
"Private": false,
|
||||||
"ListenAddr":"127.0.0.1:8002",
|
"ListenAddr":"127.0.0.1:8002",
|
||||||
"MaxRpcParamLen": 409600,
|
"MaxRpcParamLen": 409600,
|
||||||
|
"CompressBytesLen": 20480,
|
||||||
"NodeName": "Node_Test1",
|
"NodeName": "Node_Test1",
|
||||||
"remark":"//以_打头的,表示只在本机进程,不对整个子网公开",
|
"remark":"//以_打头的,表示只在本机进程,不对整个子网公开",
|
||||||
"ServiceList": ["TestService1","TestService2","TestServiceCall","GateService","TcpService","HttpService","WSService"]
|
"ServiceList": ["TestService1","TestService2","TestServiceCall","GateService","TcpService","HttpService","WSService"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -88,6 +90,7 @@ cluster.json如下:
|
|||||||
* Private: 是否私有结点,如果为true,表示其他结点不会发现它,但可以自我运行。
|
* Private: 是否私有结点,如果为true,表示其他结点不会发现它,但可以自我运行。
|
||||||
* ListenAddr:Rpc通信服务的监听地址
|
* ListenAddr:Rpc通信服务的监听地址
|
||||||
* MaxRpcParamLen:Rpc参数数据包最大长度,该参数可以缺省,默认一次Rpc调用支持最大4294967295byte长度数据。
|
* MaxRpcParamLen:Rpc参数数据包最大长度,该参数可以缺省,默认一次Rpc调用支持最大4294967295byte长度数据。
|
||||||
|
* CompressBytesLen:Rpc网络数据压缩,当数据>=20480byte时将被压缩。该参数可以缺省或者填0时不进行压缩。
|
||||||
* NodeName:结点名称
|
* NodeName:结点名称
|
||||||
* remark:备注,可选项
|
* remark:备注,可选项
|
||||||
* ServiceList:该Node拥有的服务列表,注意:origin按配置的顺序进行安装初始化。但停止服务的顺序是相反。
|
* ServiceList:该Node拥有的服务列表,注意:origin按配置的顺序进行安装初始化。但停止服务的顺序是相反。
|
||||||
@@ -715,6 +718,15 @@ func (slf *TestService7) CallTest(){
|
|||||||
}else{
|
}else{
|
||||||
fmt.Printf("Call output %d\n",output)
|
fmt.Printf("Call output %d\n",output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//自定义超时,默认rpc超时时间为15s
|
||||||
|
err = slf.CallWithTimeout(time.Second*1, "TestService6.RPC_Sum", &input, &output)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Call error :%+v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Call output %d\n", output)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -726,13 +738,27 @@ func (slf *TestService7) AsyncCallTest(){
|
|||||||
})*/
|
})*/
|
||||||
//异步调用,在数据返回时,会回调传入函数
|
//异步调用,在数据返回时,会回调传入函数
|
||||||
//注意函数的第一个参数一定是RPC_Sum函数的第二个参数,err error为RPC_Sum返回值
|
//注意函数的第一个参数一定是RPC_Sum函数的第二个参数,err error为RPC_Sum返回值
|
||||||
slf.AsyncCall("TestService6.RPC_Sum",&input,func(output *int,err error){
|
err := slf.AsyncCall("TestService6.RPC_Sum", &input, func(output *int, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("AsyncCall error :%+v\n",err)
|
fmt.Printf("AsyncCall error :%+v\n", err)
|
||||||
}else{
|
} else {
|
||||||
fmt.Printf("AsyncCall output %d\n",*output)
|
fmt.Printf("AsyncCall output %d\n", *output)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
//自定义超时,返回一个cancel函数,可以在业务需要时取消rpc调用
|
||||||
|
rpcCancel, err := slf.AsyncCallWithTimeout(time.Second*1, "TestService6.RPC_Sum", &input, func(output *int, err error) {
|
||||||
|
//如果下面注释的rpcCancel()函数被调用,这里可能将不再返回
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("AsyncCall error :%+v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("AsyncCall output %d\n", *output)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
//rpcCancel()
|
||||||
|
fmt.Println(err, rpcCancel)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *TestService7) GoTest(){
|
func (slf *TestService7) GoTest(){
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ type NodeInfo struct {
|
|||||||
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 []string //筛选发现的服务,如果不配置,不进行筛选
|
||||||
@@ -73,7 +74,7 @@ func SetServiceDiscovery(serviceDiscovery IServiceDiscovery) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) Start() {
|
func (cls *Cluster) Start() {
|
||||||
cls.rpcServer.Start(cls.localNodeInfo.ListenAddr, cls.localNodeInfo.MaxRpcParamLen)
|
cls.rpcServer.Start(cls.localNodeInfo.ListenAddr, cls.localNodeInfo.MaxRpcParamLen,cls.localNodeInfo.CompressBytesLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) Stop() {
|
func (cls *Cluster) Stop() {
|
||||||
@@ -113,7 +114,7 @@ func (cls *Cluster) DelNode(nodeId int, immediately bool) {
|
|||||||
//正在连接中不主动断开,只断开没有连接中的
|
//正在连接中不主动断开,只断开没有连接中的
|
||||||
if rpc.client.IsConnected() {
|
if rpc.client.IsConnected() {
|
||||||
nodeInfo.status = Discard
|
nodeInfo.status = Discard
|
||||||
log.SRelease("Discard node ", nodeInfo.NodeId, " ", nodeInfo.ListenAddr)
|
log.Info("Discard node",log.Int("nodeId",nodeInfo.NodeId),log.String("ListenAddr", nodeInfo.ListenAddr))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +131,7 @@ func (cls *Cluster) DelNode(nodeId int, immediately bool) {
|
|||||||
rpc.client.Close(false)
|
rpc.client.Close(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SRelease("remove node ", nodeInfo.NodeId, " ", nodeInfo.ListenAddr)
|
log.Info("remove node ",log.Int("NodeId", nodeInfo.NodeId),log.String("ListenAddr", nodeInfo.ListenAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) serviceDiscoveryDelNode(nodeId int, immediately bool) {
|
func (cls *Cluster) serviceDiscoveryDelNode(nodeId int, immediately bool) {
|
||||||
@@ -175,7 +176,7 @@ func (cls *Cluster) serviceDiscoverySetNodeInfo(nodeInfo *NodeInfo) {
|
|||||||
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
|
||||||
@@ -185,8 +186,7 @@ func (cls *Cluster) serviceDiscoverySetNodeInfo(nodeInfo *NodeInfo) {
|
|||||||
cls.mapServiceNode[serviceName][nodeInfo.NodeId] = struct{}{}
|
cls.mapServiceNode[serviceName][nodeInfo.NodeId] = struct{}{}
|
||||||
}
|
}
|
||||||
cls.mapIdNode[nodeInfo.NodeId] = *nodeInfo
|
cls.mapIdNode[nodeInfo.NodeId] = *nodeInfo
|
||||||
|
log.Info("Discovery nodeId",log.Int("NodeId", nodeInfo.NodeId),log.Any("services:", nodeInfo.PublicServiceList))
|
||||||
log.SRelease("Discovery nodeId: ", nodeInfo.NodeId, " services:", nodeInfo.PublicServiceList)
|
|
||||||
|
|
||||||
//已经存在连接,则不需要进行设置
|
//已经存在连接,则不需要进行设置
|
||||||
if _, rpcInfoOK := cls.mapRpc[nodeInfo.NodeId]; rpcInfoOK == true {
|
if _, rpcInfoOK := cls.mapRpc[nodeInfo.NodeId]; rpcInfoOK == true {
|
||||||
@@ -195,7 +195,7 @@ func (cls *Cluster) serviceDiscoverySetNodeInfo(nodeInfo *NodeInfo) {
|
|||||||
|
|
||||||
rpcInfo := NodeRpcInfo{}
|
rpcInfo := NodeRpcInfo{}
|
||||||
rpcInfo.nodeInfo = *nodeInfo
|
rpcInfo.nodeInfo = *nodeInfo
|
||||||
rpcInfo.client =rpc.NewRClient(nodeInfo.NodeId, nodeInfo.ListenAddr, nodeInfo.MaxRpcParamLen,cls.triggerRpcEvent)
|
rpcInfo.client =rpc.NewRClient(nodeInfo.NodeId, nodeInfo.ListenAddr, nodeInfo.MaxRpcParamLen,cls.localNodeInfo.CompressBytesLen,cls.triggerRpcEvent)
|
||||||
cls.mapRpc[nodeInfo.NodeId] = rpcInfo
|
cls.mapRpc[nodeInfo.NodeId] = rpcInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,7 +367,7 @@ func (cls *Cluster) triggerRpcEvent(bConnect bool, clientId uint32, nodeId int)
|
|||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +385,7 @@ func (cls *Cluster) TriggerDiscoveryEvent(bDiscovery bool, nodeId int, serviceNa
|
|||||||
for sName, _ := range cls.mapServiceListenDiscoveryEvent {
|
for sName, _ := range cls.mapServiceListenDiscoveryEvent {
|
||||||
ser := service.GetService(sName)
|
ser := service.GetService(sName)
|
||||||
if ser == nil {
|
if ser == nil {
|
||||||
log.SError("cannot find service name ", serviceName)
|
log.Error("cannot find service",log.Any("services",serviceName))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import (
|
|||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/log"
|
||||||
"github.com/duanhf2012/origin/rpc"
|
"github.com/duanhf2012/origin/rpc"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/service"
|
||||||
|
"time"
|
||||||
|
"github.com/duanhf2012/origin/util/timer"
|
||||||
)
|
)
|
||||||
|
|
||||||
const DynamicDiscoveryMasterName = "DiscoveryMaster"
|
const DynamicDiscoveryMasterName = "DiscoveryMaster"
|
||||||
@@ -140,7 +142,7 @@ func (ds *DynamicDiscoveryMaster) RpcCastGo(serviceMethod string, args interface
|
|||||||
func (ds *DynamicDiscoveryMaster) RPC_RegServiceDiscover(req *rpc.ServiceDiscoverReq, res *rpc.Empty) error {
|
func (ds *DynamicDiscoveryMaster) RPC_RegServiceDiscover(req *rpc.ServiceDiscoverReq, res *rpc.Empty) error {
|
||||||
if req.NodeInfo == nil {
|
if req.NodeInfo == nil {
|
||||||
err := errors.New("RPC_RegServiceDiscover req is error.")
|
err := errors.New("RPC_RegServiceDiscover req is error.")
|
||||||
log.SError(err.Error())
|
log.Error(err.Error())
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -341,6 +343,10 @@ func (dc *DynamicDiscoveryClient) isDiscoverNode(nodeId int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dc *DynamicDiscoveryClient) OnNodeConnected(nodeId int) {
|
func (dc *DynamicDiscoveryClient) OnNodeConnected(nodeId int) {
|
||||||
|
dc.regServiceDiscover(nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *DynamicDiscoveryClient) regServiceDiscover(nodeId int){
|
||||||
nodeInfo := cluster.GetMasterDiscoveryNodeInfo(nodeId)
|
nodeInfo := cluster.GetMasterDiscoveryNodeInfo(nodeId)
|
||||||
if nodeInfo == nil {
|
if nodeInfo == nil {
|
||||||
return
|
return
|
||||||
@@ -363,12 +369,16 @@ func (dc *DynamicDiscoveryClient) OnNodeConnected(nodeId int) {
|
|||||||
//向Master服务同步本Node服务信息
|
//向Master服务同步本Node服务信息
|
||||||
err := dc.AsyncCallNode(nodeId, RegServiceDiscover, &req, func(res *rpc.Empty, err error) {
|
err := dc.AsyncCallNode(nodeId, RegServiceDiscover, &req, func(res *rpc.Empty, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("call ", RegServiceDiscover, " is fail :", err.Error())
|
log.Error("call "+RegServiceDiscover+" is fail :"+ err.Error())
|
||||||
|
dc.AfterFunc(time.Second*3, func(timer *timer.Timer) {
|
||||||
|
dc.regServiceDiscover(nodeId)
|
||||||
|
})
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("call ", RegServiceDiscover, " is fail :", err.Error())
|
log.Error("call "+ RegServiceDiscover+" is fail :"+ err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ 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[int(nodeId.(float64))] = serviceCfg
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func (c *Concurrent) AsyncDoByQueue(queueId int64, fn func() bool, cb func(err e
|
|||||||
}
|
}
|
||||||
|
|
||||||
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ func (c *Concurrent) AsyncDoByQueue(queueId int64, fn func() bool, cb func(err e
|
|||||||
select {
|
select {
|
||||||
case c.tasks <- task{queueId, fn, cb}:
|
case c.tasks <- task{queueId, fn, cb}:
|
||||||
default:
|
default:
|
||||||
log.SError("tasks channel is full")
|
log.Error("tasks channel is full")
|
||||||
if cb != nil {
|
if cb != nil {
|
||||||
c.pushAsyncDoCallbackEvent(func(err error) {
|
c.pushAsyncDoCallbackEvent(func(err error) {
|
||||||
cb(errors.New("tasks channel is full"))
|
cb(errors.New("tasks channel is full"))
|
||||||
@@ -81,11 +81,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) {
|
||||||
|
|||||||
@@ -187,8 +187,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]))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@@ -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,9 +59,8 @@ 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(true,t)
|
w.endCallFun(true,t)
|
||||||
log.SError("core dump info[", errString, "]\n", string(buf[:l]))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,13 @@ 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.")
|
log.Debug("event is not listen",log.Int("event type",int(event.GetEventType())))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -1,6 +1,6 @@
|
|||||||
module github.com/duanhf2012/origin
|
module github.com/duanhf2012/origin
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
146
log/handler.go
Normal file
146
log/handler.go
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
"io"
|
||||||
|
"path/filepath"
|
||||||
|
"context"
|
||||||
|
"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]
|
||||||
|
}
|
||||||
|
}
|
||||||
987
log/log.go
987
log/log.go
File diff suppressed because it is too large
Load Diff
@@ -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"
|
|
||||||
"reflect"
|
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/log"
|
||||||
|
"github.com/duanhf2012/origin/util/bytespool"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MessageJsonInfo struct {
|
type MessageJsonInfo struct {
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ func (jsonProcessor *JsonProcessor ) MsgRoute(clientId uint64,msg interface{}) e
|
|||||||
|
|
||||||
func (jsonProcessor *JsonProcessor) Unmarshal(clientId uint64,data []byte) (interface{}, error) {
|
func (jsonProcessor *JsonProcessor) Unmarshal(clientId uint64,data []byte) (interface{}, error) {
|
||||||
typeStruct := struct {Type int `json:"typ"`}{}
|
typeStruct := struct {Type int `json:"typ"`}{}
|
||||||
defer jsonProcessor.ReleaseByteSlice(data)
|
defer jsonProcessor.ReleaseBytes(data)
|
||||||
err := json.Unmarshal(data, &typeStruct)
|
err := json.Unmarshal(data, &typeStruct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -106,7 +106,7 @@ func (jsonProcessor *JsonProcessor) MakeRawMsg(msgType uint16,msg []byte) *JsonP
|
|||||||
|
|
||||||
func (jsonProcessor *JsonProcessor) UnknownMsgRoute(clientId uint64,msg interface{}){
|
func (jsonProcessor *JsonProcessor) UnknownMsgRoute(clientId uint64,msg interface{}){
|
||||||
if jsonProcessor.unknownMessageHandler==nil {
|
if jsonProcessor.unknownMessageHandler==nil {
|
||||||
log.SDebug("Unknown message received from ",clientId)
|
log.Debug("Unknown message",log.Uint64("clientId",clientId))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package processor
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/network"
|
"github.com/duanhf2012/origin/util/bytespool"
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +67,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 uint64, data []byte) (interface{}, error) {
|
||||||
defer pbProcessor.ReleaseByteSlice(data)
|
defer pbProcessor.ReleaseBytes(data)
|
||||||
|
return pbProcessor.UnmarshalWithOutRelease(clientId, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unmarshal but not release data
|
||||||
|
func (pbProcessor *PBProcessor) UnmarshalWithOutRelease(clientId uint64, 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])
|
||||||
|
|||||||
@@ -40,29 +40,29 @@ 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.MinMsgLen == 0 {
|
if client.MinMsgLen == 0 {
|
||||||
@@ -77,7 +77,7 @@ func (client *TCPClient) init() {
|
|||||||
maxMsgLen := client.MsgParser.getMaxMsgLen(client.LenMsgLen)
|
maxMsgLen := client.MsgParser.getMaxMsgLen(client.LenMsgLen)
|
||||||
if client.MaxMsgLen > maxMsgLen {
|
if client.MaxMsgLen > maxMsgLen {
|
||||||
client.MaxMsgLen = maxMsgLen
|
client.MaxMsgLen = maxMsgLen
|
||||||
log.SRelease("invalid MaxMsgLen, reset to ", maxMsgLen)
|
log.Info("invalid MaxMsgLen",log.Uint32("reset", maxMsgLen))
|
||||||
}
|
}
|
||||||
|
|
||||||
client.cons = make(ConnSet)
|
client.cons = make(ConnSet)
|
||||||
@@ -102,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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,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
|
||||||
@@ -92,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")
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,7 @@ func (tcpConn *TCPConn) ReadMsg() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package network
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/duanhf2012/origin/util/bytespool"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
@@ -16,7 +17,7 @@ type MsgParser struct {
|
|||||||
MaxMsgLen uint32
|
MaxMsgLen uint32
|
||||||
LittleEndian bool
|
LittleEndian bool
|
||||||
|
|
||||||
INetMempool
|
bytespool.IBytesMempool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ func (p *MsgParser) getMaxMsgLen(lenMsgLen int) uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *MsgParser) init(){
|
func (p *MsgParser) init(){
|
||||||
p.INetMempool = NewMemAreaPool()
|
p.IBytesMempool = bytespool.NewMemAreaPool()
|
||||||
}
|
}
|
||||||
|
|
||||||
// goroutine safe
|
// goroutine safe
|
||||||
@@ -74,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,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:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package network
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/log"
|
||||||
|
"github.com/duanhf2012/origin/util/bytespool"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -43,52 +44,52 @@ func (server *TCPServer) Start() {
|
|||||||
func (server *TCPServer) init() {
|
func (server *TCPServer) init() {
|
||||||
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())
|
log.Fatal("Listen tcp fail",log.String("error", 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 {
|
if server.PendingWriteNum <= 0 {
|
||||||
server.PendingWriteNum = Default_PendingWriteNum
|
server.PendingWriteNum = Default_PendingWriteNum
|
||||||
log.SRelease("invalid PendingWriteNum, reset to ", server.PendingWriteNum)
|
log.Info("invalid PendingWriteNum",log.Int("reset", server.PendingWriteNum))
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.LenMsgLen <= 0 {
|
if server.LenMsgLen <= 0 {
|
||||||
server.LenMsgLen = Default_LenMsgLen
|
server.LenMsgLen = Default_LenMsgLen
|
||||||
log.SRelease("invalid LenMsgLen, reset to ", server.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)
|
maxMsgLen := server.MsgParser.getMaxMsgLen(server.LenMsgLen)
|
||||||
if server.MaxMsgLen > maxMsgLen {
|
if server.MaxMsgLen > maxMsgLen {
|
||||||
server.MaxMsgLen = maxMsgLen
|
server.MaxMsgLen = maxMsgLen
|
||||||
log.SRelease("invalid MaxMsgLen, reset to ", maxMsgLen)
|
log.Info("invalid MaxMsgLen",log.Uint32("reset", maxMsgLen))
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.MinMsgLen <= 0 {
|
if server.MinMsgLen <= 0 {
|
||||||
server.MinMsgLen = Default_MinMsgLen
|
server.MinMsgLen = Default_MinMsgLen
|
||||||
log.SRelease("invalid MinMsgLen, reset to ", server.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.NewAgent == nil {
|
if server.NewAgent == nil {
|
||||||
log.SFatal("NewAgent must not be nil")
|
log.Fatal("NewAgent must not be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
server.ln = ln
|
server.ln = ln
|
||||||
@@ -96,12 +97,12 @@ func (server *TCPServer) init() {
|
|||||||
server.MsgParser.init()
|
server.MsgParser.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
||||||
@@ -121,7 +122,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
|
||||||
}
|
}
|
||||||
@@ -135,7 +136,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
88
node/node.go
88
node/node.go
@@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/duanhf2012/origin/util/buildtime"
|
"github.com/duanhf2012/origin/util/buildtime"
|
||||||
"github.com/duanhf2012/origin/util/timer"
|
"github.com/duanhf2012/origin/util/timer"
|
||||||
"io"
|
"io"
|
||||||
slog "log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
"os"
|
"os"
|
||||||
@@ -28,8 +27,8 @@ var preSetupService []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
|
|
||||||
type BuildOSType = int8
|
type BuildOSType = int8
|
||||||
|
|
||||||
const(
|
const(
|
||||||
@@ -50,6 +49,8 @@ func init() {
|
|||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +145,7 @@ func initNode(id int) {
|
|||||||
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.Fatal("read system config is error ",log.ErrorAttr("error",err))
|
||||||
}
|
}
|
||||||
|
|
||||||
err = initLog()
|
err = initLog()
|
||||||
@@ -168,7 +169,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,13 +178,13 @@ 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_%d_", localnodeinfo.NodeName, 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
|
||||||
@@ -248,7 +249,7 @@ func startNode(args interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
timer.StartTimer(10*time.Millisecond, 1000000)
|
timer.StartTimer(10*time.Millisecond, 1000000)
|
||||||
log.SRelease("Start running server.")
|
log.Info("Start running server.")
|
||||||
//2.初始化node
|
//2.初始化node
|
||||||
initNode(nodeId)
|
initNode(nodeId)
|
||||||
|
|
||||||
@@ -270,7 +271,7 @@ func startNode(args interface{}) error {
|
|||||||
for bRun {
|
for bRun {
|
||||||
select {
|
select {
|
||||||
case <-sig:
|
case <-sig:
|
||||||
log.SRelease("receipt stop signal.")
|
log.Info("receipt stop signal.")
|
||||||
bRun = false
|
bRun = false
|
||||||
case <-pProfilerTicker.C:
|
case <-pProfilerTicker.C:
|
||||||
profiler.Report()
|
profiler.Report()
|
||||||
@@ -280,7 +281,8 @@ func startNode(args interface{}) error {
|
|||||||
//7.退出
|
//7.退出
|
||||||
service.StopAllService()
|
service.StopAllService()
|
||||||
|
|
||||||
log.SRelease("Server is stop.")
|
log.Info("Server is stop.")
|
||||||
|
log.Close()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,11 +306,6 @@ 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 +330,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 +356,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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
104
rpc/client.go
104
rpc/client.go
@@ -1,7 +1,6 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/duanhf2012/origin/network"
|
"github.com/duanhf2012/origin/network"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -9,6 +8,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
"github.com/duanhf2012/origin/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
const(
|
const(
|
||||||
@@ -20,7 +20,7 @@ const(
|
|||||||
|
|
||||||
|
|
||||||
DefaultConnectInterval = 2*time.Second
|
DefaultConnectInterval = 2*time.Second
|
||||||
DefaultCheckRpcCallTimeoutInterval = 5*time.Second
|
DefaultCheckRpcCallTimeoutInterval = 1*time.Second
|
||||||
DefaultRpcTimeout = 15*time.Second
|
DefaultRpcTimeout = 15*time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,9 +30,9 @@ 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(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(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(timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call
|
||||||
IsConnected() bool
|
IsConnected() bool
|
||||||
|
|
||||||
Run()
|
Run()
|
||||||
@@ -44,11 +44,11 @@ type Client struct {
|
|||||||
nodeId int
|
nodeId int
|
||||||
pendingLock sync.RWMutex
|
pendingLock sync.RWMutex
|
||||||
startSeq uint64
|
startSeq uint64
|
||||||
pending map[uint64]*list.Element
|
pending map[uint64]*Call
|
||||||
pendingTimer *list.List
|
|
||||||
callRpcTimeout time.Duration
|
callRpcTimeout time.Duration
|
||||||
maxCheckCallRpcCount int
|
maxCheckCallRpcCount int
|
||||||
|
|
||||||
|
callTimerHeap CallTimerHeap
|
||||||
IRealClient
|
IRealClient
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,6 @@ func (client *Client) NewClientAgent(conn *network.TCPConn) network.Agent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (bc *Client) makeCallFail(call *Call) {
|
func (bc *Client) makeCallFail(call *Call) {
|
||||||
bc.removePending(call.Seq)
|
|
||||||
if call.callback != nil && call.callback.IsValid() {
|
if call.callback != nil && call.callback.IsValid() {
|
||||||
call.rpcHandler.PushRpcResponse(call)
|
call.rpcHandler.PushRpcResponse(call)
|
||||||
} else {
|
} else {
|
||||||
@@ -70,54 +69,52 @@ func (bc *Client) makeCallFail(call *Call) {
|
|||||||
func (bc *Client) checkRpcCallTimeout() {
|
func (bc *Client) checkRpcCallTimeout() {
|
||||||
for{
|
for{
|
||||||
time.Sleep(DefaultCheckRpcCallTimeoutInterval)
|
time.Sleep(DefaultCheckRpcCallTimeoutInterval)
|
||||||
now := time.Now()
|
|
||||||
|
|
||||||
for i := 0; i < bc.maxCheckCallRpcCount; i++ {
|
for i := 0; i < bc.maxCheckCallRpcCount; i++ {
|
||||||
bc.pendingLock.Lock()
|
bc.pendingLock.Lock()
|
||||||
if bc.pendingTimer == nil {
|
|
||||||
|
callSeq := bc.callTimerHeap.PopTimeout()
|
||||||
|
if callSeq == 0 {
|
||||||
bc.pendingLock.Unlock()
|
bc.pendingLock.Unlock()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
pElem := bc.pendingTimer.Front()
|
pCall := bc.pending[callSeq]
|
||||||
if pElem == nil {
|
if pCall == 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()
|
bc.pendingLock.Unlock()
|
||||||
|
log.Error("call seq is not find",log.Uint64("seq", callSeq))
|
||||||
continue
|
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()
|
bc.pendingLock.Unlock()
|
||||||
break
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) InitPending() {
|
func (client *Client) InitPending() {
|
||||||
client.pendingLock.Lock()
|
client.pendingLock.Lock()
|
||||||
if client.pending != nil {
|
client.callTimerHeap.Init()
|
||||||
for _, v := range client.pending {
|
client.pending = make(map[uint64]*Call,4096)
|
||||||
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()
|
client.pendingLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (bc *Client) AddPending(call *Call) {
|
func (bc *Client) AddPending(call *Call) {
|
||||||
bc.pendingLock.Lock()
|
bc.pendingLock.Lock()
|
||||||
call.callTime = time.Now()
|
|
||||||
elemTimer := bc.pendingTimer.PushBack(call)
|
if call.Seq == 0 {
|
||||||
bc.pending[call.Seq] = elemTimer //如果下面发送失败,将会一一直存在这里
|
bc.pendingLock.Unlock()
|
||||||
|
log.Stack("call is error.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bc.pending[call.Seq] = call
|
||||||
|
bc.callTimerHeap.AddTimer(call.Seq,call.TimeOut)
|
||||||
|
|
||||||
bc.pendingLock.Unlock()
|
bc.pendingLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,30 +133,45 @@ func (bc *Client) removePending(seq uint64) *Call {
|
|||||||
if ok == false {
|
if ok == false {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
call := v.Value.(*Call)
|
|
||||||
bc.pendingTimer.Remove(v)
|
bc.callTimerHeap.Cancel(seq)
|
||||||
delete(bc.pending, seq)
|
delete(bc.pending, seq)
|
||||||
return call
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *Client) FindPending(seq uint64) *Call {
|
func (bc *Client) FindPending(seq uint64) (pCall *Call) {
|
||||||
if seq == 0 {
|
if seq == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
bc.pendingLock.Lock()
|
bc.pendingLock.Lock()
|
||||||
v, ok := bc.pending[seq]
|
pCall = bc.pending[seq]
|
||||||
if ok == false {
|
|
||||||
bc.pendingLock.Unlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pCall := v.Value.(*Call)
|
|
||||||
bc.pendingLock.Unlock()
|
bc.pendingLock.Unlock()
|
||||||
|
|
||||||
return pCall
|
return pCall
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bc *Client) 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 *Client) generateSeq() uint64 {
|
func (bc *Client) generateSeq() uint64 {
|
||||||
return atomic.AddUint64(&bc.startSeq, 1)
|
return atomic.AddUint64(&bc.startSeq, 1)
|
||||||
}
|
}
|
||||||
|
|||||||
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/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)
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//本结点的Client
|
//本结点的Client
|
||||||
@@ -36,13 +37,13 @@ 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(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.DoError(sErr)
|
call.DoError(sErr)
|
||||||
|
|
||||||
@@ -65,19 +66,20 @@ func (lc *LClient) Go(rpcHandler IRpcHandler,noReply bool, serviceMethod string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//其他的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(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
|
||||||
@@ -86,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(timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, reply interface{},cancelable bool) (CancelRpc,error) {
|
||||||
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
||||||
|
|
||||||
//判断是否是同一服务
|
//判断是否是同一服务
|
||||||
@@ -98,23 +100,23 @@ 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(nodeId int) *Client{
|
||||||
|
|||||||
142
rpc/rclient.go
142
rpc/rclient.go
@@ -9,10 +9,12 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//跨结点连接的Client
|
//跨结点连接的Client
|
||||||
type RClient struct {
|
type RClient struct {
|
||||||
|
compressBytesLen int
|
||||||
selfClient *Client
|
selfClient *Client
|
||||||
network.TCPClient
|
network.TCPClient
|
||||||
conn *network.TCPConn
|
conn *network.TCPConn
|
||||||
@@ -40,25 +42,25 @@ 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) Go(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.SError(err.Error())
|
log.Error("Marshal is fail",log.ErrorAttr("error",err))
|
||||||
call := MakeCall()
|
call := MakeCall()
|
||||||
call.DoError(err)
|
call.DoError(err)
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc.RawGo(rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply)
|
return rc.RawGo(timeout,rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rc *RClient) RawGo(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 {
|
|
||||||
call := MakeCall()
|
call := MakeCall()
|
||||||
call.ServiceMethod = serviceMethod
|
call.ServiceMethod = serviceMethod
|
||||||
call.Reply = reply
|
call.Reply = reply
|
||||||
call.Seq = rc.selfClient.generateSeq()
|
call.Seq = rc.selfClient.generateSeq()
|
||||||
|
call.TimeOut = timeout
|
||||||
|
|
||||||
request := MakeRpcRequest(processor, call.Seq, rpcMethodId, serviceMethod, noReply, rawArgs)
|
request := MakeRpcRequest(processor, call.Seq, rpcMethodId, serviceMethod, noReply, rawArgs)
|
||||||
bytes, err := processor.Marshal(request.RpcRequestData)
|
bytes, err := processor.Marshal(request.RpcRequestData)
|
||||||
@@ -66,7 +68,7 @@ func (rc *RClient) RawGo(rpcHandler IRpcHandler,processor IRpcProcessor, noReply
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
call.Seq = 0
|
call.Seq = 0
|
||||||
log.SError(err.Error())
|
log.Error("marshal is fail",log.String("error",err.Error()))
|
||||||
call.DoError(err)
|
call.DoError(err)
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
@@ -75,21 +77,39 @@ func (rc *RClient) RawGo(rpcHandler IRpcHandler,processor IRpcProcessor, noReply
|
|||||||
if conn == nil || conn.IsConnected()==false {
|
if conn == nil || conn.IsConnected()==false {
|
||||||
call.Seq = 0
|
call.Seq = 0
|
||||||
sErr := errors.New(serviceMethod + " was called failed,rpc client is disconnect")
|
sErr := errors.New(serviceMethod + " was called failed,rpc client is disconnect")
|
||||||
log.SError(sErr.Error())
|
log.Error("conn is disconnect",log.String("error",sErr.Error()))
|
||||||
call.DoError(sErr)
|
call.DoError(sErr)
|
||||||
return call
|
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 {
|
if noReply == false {
|
||||||
rc.selfClient.AddPending(call)
|
rc.selfClient.AddPending(call)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = conn.WriteMsg([]byte{uint8(processor.GetProcessorType())}, bytes)
|
err = conn.WriteMsg([]byte{uint8(processor.GetProcessorType())|bCompress}, bytes)
|
||||||
|
if cap(compressBuff) >0 {
|
||||||
|
compressor.CompressBufferCollection(compressBuff)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rc.selfClient.RemovePending(call.Seq)
|
rc.selfClient.RemovePending(call.Seq)
|
||||||
|
log.Error("WiteMsg is fail",log.ErrorAttr("error",err))
|
||||||
log.SError(err.Error())
|
|
||||||
|
|
||||||
call.Seq = 0
|
call.Seq = 0
|
||||||
call.DoError(err)
|
call.DoError(err)
|
||||||
}
|
}
|
||||||
@@ -98,20 +118,20 @@ func (rc *RClient) RawGo(rpcHandler IRpcHandler,processor IRpcProcessor, noReply
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (rc *RClient) AsyncCall(rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) error {
|
func (rc *RClient) AsyncCall(timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) {
|
||||||
err := rc.asyncCall(rpcHandler, serviceMethod, callback, args, replyParam)
|
cancelRpc,err := rc.asyncCall(timeout,rpcHandler, serviceMethod, callback, args, replyParam,cancelable)
|
||||||
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 {
|
func (rc *RClient) asyncCall(timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) {
|
||||||
processorType, processor := GetProcessorType(args)
|
processorType, processor := GetProcessorType(args)
|
||||||
InParam, herr := processor.Marshal(args)
|
InParam, herr := processor.Marshal(args)
|
||||||
if herr != nil {
|
if herr != nil {
|
||||||
return herr
|
return emptyCancelRpc,herr
|
||||||
}
|
}
|
||||||
|
|
||||||
seq := rc.selfClient.generateSeq()
|
seq := rc.selfClient.generateSeq()
|
||||||
@@ -119,12 +139,27 @@ func (rc *RClient) asyncCall(rpcHandler IRpcHandler, serviceMethod string, callb
|
|||||||
bytes, err := processor.Marshal(request.RpcRequestData)
|
bytes, err := processor.Marshal(request.RpcRequestData)
|
||||||
ReleaseRpcRequest(request)
|
ReleaseRpcRequest(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return emptyCancelRpc,err
|
||||||
}
|
}
|
||||||
|
|
||||||
conn := rc.GetConn()
|
conn := rc.GetConn()
|
||||||
if conn == nil || conn.IsConnected()==false {
|
if conn == nil || conn.IsConnected()==false {
|
||||||
return errors.New("Rpc server is disconnect,call " + serviceMethod)
|
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 := MakeCall()
|
||||||
@@ -133,16 +168,25 @@ func (rc *RClient) asyncCall(rpcHandler IRpcHandler, serviceMethod string, callb
|
|||||||
call.rpcHandler = rpcHandler
|
call.rpcHandler = rpcHandler
|
||||||
call.ServiceMethod = serviceMethod
|
call.ServiceMethod = serviceMethod
|
||||||
call.Seq = seq
|
call.Seq = seq
|
||||||
|
call.TimeOut = timeout
|
||||||
rc.selfClient.AddPending(call)
|
rc.selfClient.AddPending(call)
|
||||||
|
|
||||||
err = conn.WriteMsg([]byte{uint8(processorType)}, bytes)
|
err = conn.WriteMsg([]byte{uint8(processorType)|bCompress}, bytes)
|
||||||
|
if cap(compressBuff) >0 {
|
||||||
|
compressor.CompressBufferCollection(compressBuff)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rc.selfClient.RemovePending(call.Seq)
|
rc.selfClient.RemovePending(call.Seq)
|
||||||
ReleaseCall(call)
|
ReleaseCall(call)
|
||||||
return err
|
return emptyCancelRpc,err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
if cancelable {
|
||||||
|
rpcCancel := RpcCancel{CallSeq:seq,Cli: rc.selfClient}
|
||||||
|
return rpcCancel.CancelRpc,nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return emptyCancelRpc,nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RClient) Run() {
|
func (rc *RClient) Run() {
|
||||||
@@ -151,7 +195,7 @@ 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))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -159,14 +203,15 @@ func (rc *RClient) Run() {
|
|||||||
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])
|
bCompress := (bytes[0]>>7) > 0
|
||||||
|
processor := GetProcessor(bytes[0]&0x7f)
|
||||||
if processor == nil {
|
if processor == nil {
|
||||||
rc.conn.ReleaseReadMsg(bytes)
|
rc.conn.ReleaseReadMsg(bytes)
|
||||||
log.SError("rpcClient ", rc.Addr, " ReadMsg head error:", err.Error())
|
log.Error("cannot find process",log.Uint8("process type",bytes[0]&0x7f))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,23 +219,42 @@ func (rc *RClient) Run() {
|
|||||||
response := RpcResponse{}
|
response := RpcResponse{}
|
||||||
response.RpcResponseData = processor.MakeRpcResponse(0, "", nil)
|
response.RpcResponseData = processor.MakeRpcResponse(0, "", nil)
|
||||||
|
|
||||||
err = processor.Unmarshal(bytes[1:], response.RpcResponseData)
|
//解压缩
|
||||||
|
byteData := bytes[1:]
|
||||||
|
var compressBuff []byte
|
||||||
|
|
||||||
|
if bCompress == true {
|
||||||
|
var unCompressErr error
|
||||||
|
compressBuff,unCompressErr = compressor.UncompressBlock(byteData)
|
||||||
|
if unCompressErr!= nil {
|
||||||
|
rc.conn.ReleaseReadMsg(bytes)
|
||||||
|
log.Error("uncompressBlock failed",log.ErrorAttr("error",unCompressErr))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
byteData = compressBuff
|
||||||
|
}
|
||||||
|
|
||||||
|
err = processor.Unmarshal(byteData, response.RpcResponseData)
|
||||||
|
if cap(compressBuff) > 0 {
|
||||||
|
compressor.UnCompressBufferCollection(compressBuff)
|
||||||
|
}
|
||||||
|
|
||||||
rc.conn.ReleaseReadMsg(bytes)
|
rc.conn.ReleaseReadMsg(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
processor.ReleaseRpcResponse(response.RpcResponseData)
|
processor.ReleaseRpcResponse(response.RpcResponseData)
|
||||||
log.SError("rpcClient Unmarshal head error:", err.Error())
|
log.Error("rpcClient Unmarshal head error",log.ErrorAttr("error",err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
v := rc.selfClient.RemovePending(response.RpcResponseData.GetSeq())
|
v := rc.selfClient.RemovePending(response.RpcResponseData.GetSeq())
|
||||||
if v == nil {
|
if v == nil {
|
||||||
log.SError("rpcClient cannot find seq ", response.RpcResponseData.GetSeq(), " in pending")
|
log.Error("rpcClient cannot find seq",log.Uint64("seq",response.RpcResponseData.GetSeq()))
|
||||||
} else {
|
} else {
|
||||||
v.Err = nil
|
v.Err = nil
|
||||||
if len(response.RpcResponseData.GetReply()) > 0 {
|
if len(response.RpcResponseData.GetReply()) > 0 {
|
||||||
err = processor.Unmarshal(response.RpcResponseData.GetReply(), v.Reply)
|
err = processor.Unmarshal(response.RpcResponseData.GetReply(), v.Reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("rpcClient Unmarshal body error:", err.Error())
|
log.Error("rpcClient Unmarshal body failed",log.ErrorAttr("error",err))
|
||||||
v.Err = err
|
v.Err = err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,14 +278,14 @@ func (rc *RClient) OnClose() {
|
|||||||
rc.TriggerRpcConnEvent(false, rc.selfClient.GetClientId(), rc.selfClient.GetNodeId())
|
rc.TriggerRpcConnEvent(false, rc.selfClient.GetClientId(), rc.selfClient.GetNodeId())
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRClient(nodeId int, addr string, maxRpcParamLen uint32,triggerRpcConnEvent TriggerRpcConnEvent) *Client{
|
func NewRClient(nodeId int, addr string, maxRpcParamLen uint32,compressBytesLen int,triggerRpcConnEvent TriggerRpcConnEvent) *Client{
|
||||||
client := &Client{}
|
client := &Client{}
|
||||||
client.clientId = atomic.AddUint32(&clientSeq, 1)
|
client.clientId = atomic.AddUint32(&clientSeq, 1)
|
||||||
client.nodeId = nodeId
|
client.nodeId = nodeId
|
||||||
client.maxCheckCallRpcCount = DefaultMaxCheckCallRpcCount
|
client.maxCheckCallRpcCount = DefaultMaxCheckCallRpcCount
|
||||||
client.callRpcTimeout = DefaultRpcTimeout
|
client.callRpcTimeout = DefaultRpcTimeout
|
||||||
|
|
||||||
c:= &RClient{}
|
c:= &RClient{}
|
||||||
|
c.compressBytesLen = compressBytesLen
|
||||||
c.selfClient = client
|
c.selfClient = client
|
||||||
c.Addr = addr
|
c.Addr = addr
|
||||||
c.ConnectInterval = DefaultConnectInterval
|
c.ConnectInterval = DefaultConnectInterval
|
||||||
@@ -251,18 +315,6 @@ 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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
rpc/rpc.go
13
rpc/rpc.go
@@ -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{
|
||||||
@@ -124,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxClusterNode int = 128
|
const maxClusterNode int = 128
|
||||||
@@ -75,6 +76,9 @@ type IDiscoveryServiceListener interface {
|
|||||||
OnUnDiscoveryService(nodeId int, serviceName []string)
|
OnUnDiscoveryService(nodeId int, serviceName []string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CancelRpc func()
|
||||||
|
func emptyCancelRpc(){}
|
||||||
|
|
||||||
type IRpcHandler interface {
|
type IRpcHandler interface {
|
||||||
IRpcHandlerChannel
|
IRpcHandlerChannel
|
||||||
GetName() string
|
GetName() string
|
||||||
@@ -83,11 +87,18 @@ 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
|
||||||
Go(serviceMethod string, args interface{}) error
|
|
||||||
AsyncCallNode(nodeId int, serviceMethod string, args interface{}, callback interface{}) error
|
|
||||||
CallNode(nodeId int, serviceMethod string, args interface{}, reply interface{}) error
|
CallNode(nodeId int, serviceMethod string, args interface{}, reply interface{}) error
|
||||||
|
AsyncCall(serviceMethod string, args interface{}, callback interface{}) error
|
||||||
|
AsyncCallNode(nodeId int, serviceMethod string, args interface{}, callback interface{}) error
|
||||||
|
|
||||||
|
CallWithTimeout(timeout time.Duration,serviceMethod string, args interface{}, reply interface{}) error
|
||||||
|
CallNodeWithTimeout(timeout time.Duration,nodeId int, serviceMethod string, args interface{}, reply interface{}) error
|
||||||
|
AsyncCallWithTimeout(timeout time.Duration,serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error)
|
||||||
|
AsyncCallNodeWithTimeout(timeout time.Duration,nodeId int, serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error)
|
||||||
|
|
||||||
|
Go(serviceMethod string, args interface{}) error
|
||||||
GoNode(nodeId int, serviceMethod string, args interface{}) error
|
GoNode(nodeId int, serviceMethod string, args interface{}) error
|
||||||
RawGoNode(rpcProcessorType RpcProcessorType, nodeId int, rpcMethodId uint32, serviceName string, rawArgs []byte) 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
|
||||||
@@ -204,7 +215,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 +237,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 +250,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +267,7 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
|
|||||||
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,7 +298,7 @@ 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
|
||||||
}
|
}
|
||||||
@@ -309,7 +320,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +334,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)
|
||||||
|
|
||||||
//有返回值时
|
//有返回值时
|
||||||
@@ -332,7 +344,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,21 +431,21 @@ func (handler *RpcHandler) goRpc(processor IRpcProcessor, bCast bool, nodeId int
|
|||||||
err, count := handler.funcRpcClient(nodeId, serviceMethod, pClientList[:])
|
err, count := handler.funcRpcClient(nodeId, serviceMethod, pClientList[:])
|
||||||
if count == 0 {
|
if count == 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 count > 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 < count; i++ {
|
||||||
pCall := pClientList[i].Go(handler.rpcHandler,true, serviceMethod, args, nil)
|
pCall := pClientList[i].Go(DefaultRpcTimeout,handler.rpcHandler,true, serviceMethod, args, nil)
|
||||||
if pCall.Err != nil {
|
if pCall.Err != nil {
|
||||||
err = pCall.Err
|
err = pCall.Err
|
||||||
}
|
}
|
||||||
@@ -444,23 +456,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 int, serviceMethod string, args interface{}, reply interface{}) error {
|
||||||
var pClientList [maxClusterNode]*Client
|
var pClientList [maxClusterNode]*Client
|
||||||
err, count := handler.funcRpcClient(nodeId, serviceMethod, pClientList[:])
|
err, count := handler.funcRpcClient(nodeId, serviceMethod, 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 count <= 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 count > 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(timeout,handler.rpcHandler,false, serviceMethod, args, reply)
|
||||||
|
|
||||||
err = pCall.Done().Err
|
err = pCall.Done().Err
|
||||||
pClient.RemovePending(pCall.Seq)
|
pClient.RemovePending(pCall.Seq)
|
||||||
@@ -468,24 +480,24 @@ 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 int, 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()
|
||||||
@@ -500,24 +512,20 @@ func (handler *RpcHandler) asyncCallRpc(nodeId int, serviceMethod string, args i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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.Int("nodeId",nodeId))
|
||||||
return nil
|
return emptyCancelRpc,nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if count > 1 {
|
if count > 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(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 {
|
||||||
@@ -528,12 +536,29 @@ func (handler *RpcHandler) IsSingleCoroutine() bool {
|
|||||||
return handler.rpcHandler.IsSingleCoroutine()
|
return handler.rpcHandler.IsSingleCoroutine()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (handler *RpcHandler) CallWithTimeout(timeout time.Duration,serviceMethod string, args interface{}, reply interface{}) error {
|
||||||
|
return handler.callRpc(timeout,0, serviceMethod, args, reply)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *RpcHandler) CallNodeWithTimeout(timeout time.Duration,nodeId int, 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,0, serviceMethod, args, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *RpcHandler) AsyncCallNodeWithTimeout(timeout time.Duration,nodeId int, 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,0, 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,0, serviceMethod, args, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) Go(serviceMethod string, args interface{}) error {
|
func (handler *RpcHandler) Go(serviceMethod string, args interface{}) error {
|
||||||
@@ -541,11 +566,13 @@ func (handler *RpcHandler) Go(serviceMethod string, args interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) AsyncCallNode(nodeId int, serviceMethod string, args interface{}, callback interface{}) error {
|
func (handler *RpcHandler) AsyncCallNode(nodeId int, 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 int, 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 int, serviceMethod string, args interface{}) error {
|
||||||
@@ -560,12 +587,12 @@ func (handler *RpcHandler) RawGoNode(rpcProcessorType RpcProcessorType, nodeId i
|
|||||||
processor := GetProcessor(uint8(rpcProcessorType))
|
processor := GetProcessor(uint8(rpcProcessorType))
|
||||||
err, count := handler.funcRpcClient(nodeId, serviceName, handler.pClientList)
|
err, count := handler.funcRpcClient(nodeId, serviceName, handler.pClientList)
|
||||||
if count == 0 || err != nil {
|
if count == 0 || err != nil {
|
||||||
log.SError("Call serviceMethod is error:", err.Error())
|
log.Error("call serviceMethod is failed",log.ErrorAttr("error",err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if count > 1 {
|
if count > 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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,7 +600,7 @@ func (handler *RpcHandler) RawGoNode(rpcProcessorType RpcProcessorType, nodeId i
|
|||||||
//如果调用本结点服务
|
//如果调用本结点服务
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
//跨node调用
|
//跨node调用
|
||||||
pCall := handler.pClientList[i].RawGo(handler.rpcHandler,processor, true, rpcMethodId, serviceName, rawArgs, nil)
|
pCall := handler.pClientList[i].RawGo(DefaultRpcTimeout,handler.rpcHandler,processor, true, rpcMethodId, serviceName, rawArgs, nil)
|
||||||
if pCall.Err != nil {
|
if pCall.Err != nil {
|
||||||
err = pCall.Err
|
err = pCall.Err
|
||||||
}
|
}
|
||||||
|
|||||||
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)
|
||||||
|
}
|
||||||
|
|
||||||
127
rpc/server.go
127
rpc/server.go
@@ -27,6 +27,8 @@ type Server struct {
|
|||||||
functions map[interface{}]interface{}
|
functions map[interface{}]interface{}
|
||||||
rpcHandleFinder RpcHandleFinder
|
rpcHandleFinder RpcHandleFinder
|
||||||
rpcServer *network.TCPServer
|
rpcServer *network.TCPServer
|
||||||
|
|
||||||
|
compressBytesLen int
|
||||||
}
|
}
|
||||||
|
|
||||||
type RpcAgent struct {
|
type RpcAgent struct {
|
||||||
@@ -64,14 +66,15 @@ func (server *Server) Init(rpcHandleFinder RpcHandleFinder) {
|
|||||||
|
|
||||||
const Default_ReadWriteDeadline = 15*time.Second
|
const Default_ReadWriteDeadline = 15*time.Second
|
||||||
|
|
||||||
func (server *Server) Start(listenAddr string, maxRpcParamLen uint32) {
|
func (server *Server) Start(listenAddr string, maxRpcParamLen uint32,compressBytesLen int) {
|
||||||
splitAddr := strings.Split(listenAddr, ":")
|
splitAddr := strings.Split(listenAddr, ":")
|
||||||
if len(splitAddr) != 2 {
|
if len(splitAddr) != 2 {
|
||||||
log.SFatal("listen addr is error :", listenAddr)
|
log.Fatal("listen addr is failed", log.String("listenAddr",listenAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
server.rpcServer.Addr = ":" + splitAddr[1]
|
server.rpcServer.Addr = ":" + splitAddr[1]
|
||||||
server.rpcServer.MinMsgLen = 2
|
server.rpcServer.MinMsgLen = 2
|
||||||
|
server.compressBytesLen = compressBytesLen
|
||||||
if maxRpcParamLen > 0 {
|
if maxRpcParamLen > 0 {
|
||||||
server.rpcServer.MaxMsgLen = maxRpcParamLen
|
server.rpcServer.MaxMsgLen = maxRpcParamLen
|
||||||
} else {
|
} else {
|
||||||
@@ -108,13 +111,32 @@ 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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,24 +144,42 @@ func (agent *RpcAgent) Run() {
|
|||||||
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])
|
bCompress := (data[0]>>7) > 0
|
||||||
|
processor := GetProcessor(data[0]&0x7f)
|
||||||
if processor == nil {
|
if processor == nil {
|
||||||
agent.conn.ReleaseReadMsg(data)
|
agent.conn.ReleaseReadMsg(data)
|
||||||
log.SError("remote rpc ", agent.conn.RemoteAddr(), " cannot find processor:", data[0])
|
log.Warning("cannot find processor",log.String("RemoteAddr",agent.conn.RemoteAddr().String()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//解析head
|
//解析head
|
||||||
|
var compressBuff []byte
|
||||||
|
byteData := data[1:]
|
||||||
|
if bCompress == true {
|
||||||
|
var unCompressErr error
|
||||||
|
|
||||||
|
compressBuff,unCompressErr = compressor.UncompressBlock(byteData)
|
||||||
|
if unCompressErr!= nil {
|
||||||
|
agent.conn.ReleaseReadMsg(data)
|
||||||
|
log.Error("UncompressBlock failed",log.String("RemoteAddr",agent.conn.RemoteAddr().String()),log.ErrorAttr("error",unCompressErr))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
byteData = compressBuff
|
||||||
|
}
|
||||||
|
|
||||||
req := MakeRpcRequest(processor, 0, 0, "", false, nil)
|
req := MakeRpcRequest(processor, 0, 0, "", false, nil)
|
||||||
err = processor.Unmarshal(data[1:], req.RpcRequestData)
|
err = processor.Unmarshal(byteData, req.RpcRequestData)
|
||||||
|
if cap(compressBuff) > 0 {
|
||||||
|
compressor.UnCompressBufferCollection(compressBuff)
|
||||||
|
}
|
||||||
agent.conn.ReleaseReadMsg(data)
|
agent.conn.ReleaseReadMsg(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("rpc Unmarshal request is error:", err.Error())
|
log.Error("Unmarshal failed",log.String("RemoteAddr",agent.conn.RemoteAddr().String()),log.ErrorAttr("error",err))
|
||||||
if req.RpcRequestData.GetSeq() > 0 {
|
if req.RpcRequestData.GetSeq() > 0 {
|
||||||
rpcError := RpcError(err.Error())
|
rpcError := RpcError(err.Error())
|
||||||
if req.RpcRequestData.IsNoReply() == false {
|
if req.RpcRequestData.IsNoReply() == false {
|
||||||
@@ -161,7 +201,7 @@ func (agent *RpcAgent) Run() {
|
|||||||
agent.WriteResponse(processor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
agent.WriteResponse(processor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
||||||
}
|
}
|
||||||
ReleaseRpcRequest(req)
|
ReleaseRpcRequest(req)
|
||||||
log.SError("rpc request req.ServiceMethod is error")
|
log.Error("rpc request req.ServiceMethod is error")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,8 +211,7 @@ func (agent *RpcAgent) Run() {
|
|||||||
if req.RpcRequestData.IsNoReply() == false {
|
if req.RpcRequestData.IsNoReply() == false {
|
||||||
agent.WriteResponse(processor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
agent.WriteResponse(processor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
|
||||||
}
|
}
|
||||||
|
log.Error("serviceMethod not config",log.String("serviceMethod",req.RpcRequestData.GetServiceMethod()))
|
||||||
log.SError("service method ", req.RpcRequestData.GetServiceMethod(), " not config!")
|
|
||||||
ReleaseRpcRequest(req)
|
ReleaseRpcRequest(req)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -192,7 +231,7 @@ func (agent *RpcAgent) Run() {
|
|||||||
} else {
|
} else {
|
||||||
ReleaseRpcRequest(req)
|
ReleaseRpcRequest(req)
|
||||||
}
|
}
|
||||||
log.SError(rErr)
|
log.Error("call rpc param error",log.String("serviceMethod",req.RpcRequestData.GetServiceMethod()),log.ErrorAttr("error",err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,23 +280,23 @@ func (server *Server) myselfRpcHandlerGo(client *Client,handlerName string, serv
|
|||||||
rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
|
rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
|
||||||
if rpcHandler == nil {
|
if rpcHandler == nil {
|
||||||
err := errors.New("service method " + serviceMethod + " not config!")
|
err := errors.New("service method " + serviceMethod + " not config!")
|
||||||
log.SError(err.Error())
|
log.Error("service method not config",log.String("serviceMethod",serviceMethod))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpcHandler.CallMethod(client,serviceMethod, args,callBack, reply)
|
return rpcHandler.CallMethod(client,serviceMethod, args,callBack, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (server *Server) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call {
|
||||||
|
|
||||||
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 := MakeCall()
|
||||||
pCall.Seq = client.generateSeq()
|
pCall.Seq = client.generateSeq()
|
||||||
|
pCall.TimeOut = timeout
|
||||||
|
pCall.ServiceMethod = serviceMethod
|
||||||
|
|
||||||
rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
|
rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
|
||||||
if rpcHandler == nil {
|
if rpcHandler == nil {
|
||||||
err := errors.New("service method " + serviceMethod + " not config!")
|
err := errors.New("service method " + serviceMethod + " not config!")
|
||||||
log.SError(err.Error())
|
log.Error("service method not config",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err))
|
||||||
pCall.Seq = 0
|
pCall.Seq = 0
|
||||||
pCall.DoError(err)
|
pCall.DoError(err)
|
||||||
|
|
||||||
@@ -274,7 +313,7 @@ func (server *Server) selfNodeRpcHandlerGo(processor IRpcProcessor, client *Clie
|
|||||||
iParam,err = processor.Clone(args)
|
iParam,err = processor.Clone(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sErr := errors.New("RpcHandler " + handlerName + "."+serviceMethod+" deep copy inParam is error:" + err.Error())
|
sErr := errors.New("RpcHandler " + handlerName + "."+serviceMethod+" deep copy inParam is error:" + err.Error())
|
||||||
log.SError(sErr.Error())
|
log.Error("deep copy inParam is failed",log.String("handlerName",handlerName),log.String("serviceMethod",serviceMethod))
|
||||||
pCall.Seq = 0
|
pCall.Seq = 0
|
||||||
pCall.DoError(sErr)
|
pCall.DoError(sErr)
|
||||||
|
|
||||||
@@ -289,7 +328,7 @@ func (server *Server) selfNodeRpcHandlerGo(processor IRpcProcessor, client *Clie
|
|||||||
var err error
|
var err error
|
||||||
req.inParam, err = rpcHandler.UnmarshalInParam(processor, serviceMethod, rpcMethodId, rawArgs)
|
req.inParam, err = rpcHandler.UnmarshalInParam(processor, serviceMethod, rpcMethodId, rawArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError(err.Error())
|
log.Error("unmarshalInParam is failed",log.String("serviceMethod",serviceMethod),log.Uint32("rpcMethodId",rpcMethodId),log.ErrorAttr("error",err))
|
||||||
pCall.Seq = 0
|
pCall.Seq = 0
|
||||||
pCall.DoError(err)
|
pCall.DoError(err)
|
||||||
ReleaseRpcRequest(req)
|
ReleaseRpcRequest(req)
|
||||||
@@ -305,12 +344,12 @@ func (server *Server) selfNodeRpcHandlerGo(processor IRpcProcessor, client *Clie
|
|||||||
byteReturns, err := req.rpcProcessor.Marshal(Returns)
|
byteReturns, err := req.rpcProcessor.Marshal(Returns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Err = ConvertError(err)
|
Err = ConvertError(err)
|
||||||
log.SError("returns data cannot be marshal,callSeq is ", callSeq," error is ",err.Error())
|
log.Error("returns data cannot be marshal",log.Uint64("seq",callSeq),log.ErrorAttr("error",err))
|
||||||
}else{
|
}else{
|
||||||
err = req.rpcProcessor.Unmarshal(byteReturns, reply)
|
err = req.rpcProcessor.Unmarshal(byteReturns, reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Err = ConvertError(err)
|
Err = ConvertError(err)
|
||||||
log.SError("returns data cannot be Unmarshal,callSeq is ", callSeq," error is ",err.Error())
|
log.Error("returns data cannot be Unmarshal",log.Uint64("seq",callSeq),log.ErrorAttr("error",err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -318,8 +357,7 @@ func (server *Server) selfNodeRpcHandlerGo(processor IRpcProcessor, client *Clie
|
|||||||
ReleaseRpcRequest(req)
|
ReleaseRpcRequest(req)
|
||||||
v := client.RemovePending(callSeq)
|
v := client.RemovePending(callSeq)
|
||||||
if v == nil {
|
if v == nil {
|
||||||
log.SError("rpcClient cannot find seq ",callSeq, " in pending")
|
log.Error("rpcClient cannot find seq",log.Uint64("seq",callSeq))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +365,7 @@ func (server *Server) selfNodeRpcHandlerGo(processor IRpcProcessor, client *Clie
|
|||||||
v.Err = nil
|
v.Err = nil
|
||||||
v.DoOK()
|
v.DoOK()
|
||||||
} else {
|
} else {
|
||||||
log.SError(Err.Error())
|
log.Error(Err.Error())
|
||||||
v.DoError(Err)
|
v.DoError(Err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,7 +373,7 @@ func (server *Server) selfNodeRpcHandlerGo(processor IRpcProcessor, client *Clie
|
|||||||
|
|
||||||
err := rpcHandler.PushRpcRequest(req)
|
err := rpcHandler.PushRpcRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError(err.Error())
|
log.Error(err.Error())
|
||||||
pCall.DoError(err)
|
pCall.DoError(err)
|
||||||
ReleaseRpcRequest(req)
|
ReleaseRpcRequest(req)
|
||||||
}
|
}
|
||||||
@@ -343,53 +381,57 @@ func (server *Server) selfNodeRpcHandlerGo(processor IRpcProcessor, client *Clie
|
|||||||
return 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 {
|
func (server *Server) 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)
|
rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
|
||||||
if rpcHandler == nil {
|
if rpcHandler == nil {
|
||||||
err := errors.New("service method " + serviceMethod + " not config!")
|
err := errors.New("service method " + serviceMethod + " not config!")
|
||||||
log.SError(err.Error())
|
log.Error(err.Error())
|
||||||
return err
|
return emptyCancelRpc,err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, processor := GetProcessorType(args)
|
_, processor := GetProcessorType(args)
|
||||||
iParam,err := processor.Clone(args)
|
iParam,err := processor.Clone(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errM := errors.New("RpcHandler " + handlerName + "."+serviceMethod+" deep copy inParam is error:" + err.Error())
|
errM := errors.New("RpcHandler " + handlerName + "."+serviceMethod+" deep copy inParam is error:" + err.Error())
|
||||||
log.SError(errM.Error())
|
log.Error(errM.Error())
|
||||||
return errM
|
return emptyCancelRpc,errM
|
||||||
}
|
}
|
||||||
|
|
||||||
req := MakeRpcRequest(processor, 0, 0, serviceMethod, noReply, nil)
|
req := MakeRpcRequest(processor, 0, 0, serviceMethod, noReply, nil)
|
||||||
req.inParam = iParam
|
req.inParam = iParam
|
||||||
req.localReply = reply
|
req.localReply = reply
|
||||||
|
|
||||||
|
cancelRpc := emptyCancelRpc
|
||||||
|
var callSeq uint64
|
||||||
if noReply == false {
|
if noReply == false {
|
||||||
callSeq := client.generateSeq()
|
callSeq = client.generateSeq()
|
||||||
pCall := MakeCall()
|
pCall := MakeCall()
|
||||||
pCall.Seq = callSeq
|
pCall.Seq = callSeq
|
||||||
pCall.rpcHandler = callerRpcHandler
|
pCall.rpcHandler = callerRpcHandler
|
||||||
pCall.callback = &callback
|
pCall.callback = &callback
|
||||||
pCall.Reply = reply
|
pCall.Reply = reply
|
||||||
pCall.ServiceMethod = serviceMethod
|
pCall.ServiceMethod = serviceMethod
|
||||||
|
pCall.TimeOut = timeout
|
||||||
client.AddPending(pCall)
|
client.AddPending(pCall)
|
||||||
|
rpcCancel := RpcCancel{CallSeq: callSeq,Cli: client}
|
||||||
|
cancelRpc = rpcCancel.CancelRpc
|
||||||
|
|
||||||
req.requestHandle = func(Returns interface{}, Err RpcError) {
|
req.requestHandle = func(Returns interface{}, Err RpcError) {
|
||||||
v := client.RemovePending(callSeq)
|
v := client.RemovePending(callSeq)
|
||||||
if v == nil {
|
if v == nil {
|
||||||
log.SError("rpcClient cannot find seq ", pCall.Seq, " in pending")
|
|
||||||
//ReleaseCall(pCall)
|
|
||||||
ReleaseRpcRequest(req)
|
ReleaseRpcRequest(req)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(Err) == 0 {
|
if len(Err) == 0 {
|
||||||
pCall.Err = nil
|
v.Err = nil
|
||||||
} else {
|
} else {
|
||||||
pCall.Err = Err
|
v.Err = Err
|
||||||
}
|
}
|
||||||
|
|
||||||
if Returns != nil {
|
if Returns != nil {
|
||||||
pCall.Reply = Returns
|
v.Reply = Returns
|
||||||
}
|
}
|
||||||
pCall.rpcHandler.PushRpcResponse(pCall)
|
v.rpcHandler.PushRpcResponse(v)
|
||||||
ReleaseRpcRequest(req)
|
ReleaseRpcRequest(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,8 +439,11 @@ func (server *Server) selfNodeRpcHandlerAsyncGo(client *Client, callerRpcHandler
|
|||||||
err = rpcHandler.PushRpcRequest(req)
|
err = rpcHandler.PushRpcRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ReleaseRpcRequest(req)
|
ReleaseRpcRequest(req)
|
||||||
return err
|
if callSeq > 0 {
|
||||||
|
client.RemovePending(callSeq)
|
||||||
|
}
|
||||||
|
return emptyCancelRpc,err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return cancelRpc,nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ 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.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ func (s *Service) Start() {
|
|||||||
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()
|
||||||
}()
|
}()
|
||||||
@@ -158,12 +158,12 @@ func (s *Service) Run() {
|
|||||||
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 {
|
||||||
@@ -179,12 +179,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 {
|
||||||
@@ -242,7 +242,7 @@ 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))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -257,10 +257,10 @@ 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{}{
|
||||||
@@ -353,7 +353,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +380,7 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package mysqlmondule
|
package mysqlmodule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package mysqlmondule
|
package mysqlmodule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,49 @@
|
|||||||
package messagequeueservice
|
package messagequeueservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/log"
|
"github.com/duanhf2012/origin/log"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/service"
|
||||||
"github.com/duanhf2012/origin/sysmodule/mongodbmodule"
|
"github.com/duanhf2012/origin/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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +297,7 @@ func (mp *MongoPersist) saveToDB(){
|
|||||||
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))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ import (
|
|||||||
"github.com/duanhf2012/origin/network/processor"
|
"github.com/duanhf2012/origin/network/processor"
|
||||||
"github.com/duanhf2012/origin/node"
|
"github.com/duanhf2012/origin/node"
|
||||||
"github.com/duanhf2012/origin/service"
|
"github.com/duanhf2012/origin/service"
|
||||||
"sync/atomic"
|
"github.com/duanhf2012/origin/util/bytespool"
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TcpService struct {
|
type TcpService struct {
|
||||||
@@ -170,7 +171,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))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -183,7 +184,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.Uint64("clientId",slf.id))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
data,err:=slf.tcpService.process.Unmarshal(slf.id,bytes)
|
data,err:=slf.tcpService.process.Unmarshal(slf.id,bytes)
|
||||||
@@ -277,14 +278,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -42,9 +42,9 @@ func Abs[NumType SignedNumberType](Num NumType) NumType {
|
|||||||
func Add[NumType NumberType](number1 NumType, number2 NumType) NumType {
|
func Add[NumType NumberType](number1 NumType, number2 NumType) NumType {
|
||||||
ret := number1 + number2
|
ret := number1 + number2
|
||||||
if number2> 0 && ret < number1 {
|
if number2> 0 && ret < number1 {
|
||||||
log.SStack("Calculation overflow , number1 is ",number1," number2 is ",number2)
|
log.Stack("Calculation overflow" ,log.Any("number1",number1),log.Any("number2",number2))
|
||||||
}else if (number2<0 && ret > number1){
|
}else if (number2<0 && ret > number1){
|
||||||
log.SStack("Calculation overflow , number1 is ",number1," number2 is ",number2)
|
log.Stack("Calculation overflow" ,log.Any("number1",number1),log.Any("number2",number2))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
@@ -53,9 +53,9 @@ func Add[NumType NumberType](number1 NumType, number2 NumType) NumType {
|
|||||||
func Sub[NumType NumberType](number1 NumType, number2 NumType) NumType {
|
func Sub[NumType NumberType](number1 NumType, number2 NumType) NumType {
|
||||||
ret := number1 - number2
|
ret := number1 - number2
|
||||||
if number2> 0 && ret > number1 {
|
if number2> 0 && ret > number1 {
|
||||||
log.SStack("Calculation overflow , number1 is ",number1," number2 is ",number2)
|
log.Stack("Calculation overflow" ,log.Any("number1",number1),log.Any("number2",number2))
|
||||||
}else if (number2<0 && ret < number1){
|
}else if (number2<0 && ret < number1){
|
||||||
log.SStack("Calculation overflow , number1 is ",number1," number2 is ",number2)
|
log.Stack("Calculation overflow" ,log.Any("number1",number1),log.Any("number2",number2))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
@@ -71,8 +71,8 @@ func Mul[NumType NumberType](number1 NumType, number2 NumType) NumType {
|
|||||||
if ret / number2 == number1 {
|
if ret / number2 == number1 {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SStack("Calculation overflow , number1 is ",number1," number2 is ",number2)
|
log.Stack("Calculation overflow" ,log.Any("number1",number1),log.Any("number2",number2))
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ITimer
|
// ITimer
|
||||||
@@ -29,7 +30,7 @@ type OnAddTimer func(timer ITimer)
|
|||||||
// Timer
|
// Timer
|
||||||
type Timer struct {
|
type Timer struct {
|
||||||
Id uint64
|
Id uint64
|
||||||
cancelled bool //是否关闭
|
cancelled int32 //是否关闭
|
||||||
C chan ITimer //定时器管道
|
C chan ITimer //定时器管道
|
||||||
interval time.Duration // 时间间隔(用于循环定时器)
|
interval time.Duration // 时间间隔(用于循环定时器)
|
||||||
fireTime time.Time // 触发时间
|
fireTime time.Time // 触发时间
|
||||||
@@ -131,7 +132,7 @@ func (t *Timer) Do() {
|
|||||||
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))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -171,12 +172,12 @@ func (t *Timer) GetInterval() time.Duration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Timer) Cancel() {
|
func (t *Timer) Cancel() {
|
||||||
t.cancelled = true
|
atomic.StoreInt32(&t.cancelled,1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断定时器是否已经取消
|
// 判断定时器是否已经取消
|
||||||
func (t *Timer) IsActive() bool {
|
func (t *Timer) IsActive() bool {
|
||||||
return !t.cancelled
|
return atomic.LoadInt32(&t.cancelled) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Timer) GetName() string {
|
func (t *Timer) GetName() string {
|
||||||
@@ -217,7 +218,7 @@ func (c *Cron) Do() {
|
|||||||
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))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -273,7 +274,7 @@ func (c *Ticker) Do() {
|
|||||||
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))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user