mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-26 16:54:52 +08:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d36e525a5 | ||
|
|
3a4350769c | ||
|
|
d4966ea129 | ||
|
|
3b10eeb792 | ||
|
|
e3275e9f2a | ||
|
|
16745b34f0 | ||
|
|
f34dc7d53f | ||
|
|
0a09dc2fee | ||
|
|
f01a93c446 | ||
|
|
4d2ab4ee4f | ||
|
|
ffcc5a3489 | ||
|
|
cf6ca0483b | ||
|
|
97a21e6f71 | ||
|
|
f60a55d03a | ||
|
|
2c32d6eec9 | ||
|
|
da45f97fa8 | ||
|
|
d29abc0813 | ||
|
|
c9507f9ee9 | ||
|
|
61de4bba3a | ||
|
|
000853b479 | ||
|
|
387e83d65c | ||
|
|
07a102c6ea | ||
|
|
e9bbf5b592 | ||
|
|
3f4189fd40 | ||
|
|
c72f2e4582 | ||
|
|
f600c2a573 | ||
|
|
6a29ba2c88 | ||
|
|
64c14eb326 | ||
|
|
75790302ec | ||
|
|
b943ea9a83 | ||
|
|
39116c4402 |
55
README.md
55
README.md
@@ -14,17 +14,7 @@ origin 解决的问题:
|
|||||||
Hello world!
|
Hello world!
|
||||||
------------
|
------------
|
||||||
|
|
||||||
下面我们来一步步的建立origin服务器,先下载[origin引擎](https://github.com/duanhf2012/origin "origin引擎"),或者使用如下命令:
|
下面我们来一步步的建立origin服务器,建议使用origin v2版本,内容如下:
|
||||||
|
|
||||||
```go
|
|
||||||
go get -v -u github.com/duanhf2012/origin/v2
|
|
||||||
```
|
|
||||||
建议使用origin v2版本(import引用中都加入v2)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[README.md](README.md)
|
|
||||||
于是下载到GOPATH环境目录中,在src中加入main.go,内容如下:
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -43,11 +33,19 @@ func main() {
|
|||||||
一个origin进程需要创建一个node对象,Start开始运行。您也可以直接下载origin引擎示例:
|
一个origin进程需要创建一个node对象,Start开始运行。您也可以直接下载origin引擎示例:
|
||||||
|
|
||||||
```
|
```
|
||||||
go get -v -u github.com/duanhf2012/originserver_v2
|
git clone https://github.com/duanhf2012/originserver_v2.git
|
||||||
```
|
```
|
||||||
|
|
||||||
本文所有的说明都是基于该示例为主。
|
本文所有的说明都是基于该示例为主。
|
||||||
|
|
||||||
|
我们也提供了示例项目,包含网络模块(支持tcp,kcp,websocket)、角色加载登录流程,存档,配置读取等功能。请参照:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/duanhf2012/origingame.git
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
origin引擎三大对象关系
|
origin引擎三大对象关系
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
@@ -69,16 +67,10 @@ origin的配置文件以json格式,主要包含Discovery、RpcMode、NodeList
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Discovery部分
|
### Discovery部分
|
||||||
|
|
||||||
origin目前支持etcd与origin自带的服务发现类型。
|
origin目前支持etcd与origin自带的服务发现类型。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Etcd方式示例:
|
Etcd方式示例:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@@ -106,8 +98,6 @@ NetworkName:所在的网络名称,可以配置多个。node会往对应的
|
|||||||
|
|
||||||
Endpoints:Etcd服务器地址
|
Endpoints:Etcd服务器地址
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Origin方式示例:
|
Origin方式示例:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@@ -130,8 +120,6 @@ TTLSecond:表示健康检查TTL失效时间10秒
|
|||||||
|
|
||||||
MasterNodeList:指定哪些Node为服务发现Master结点,需要配置NodeId与ListenAddr,注意它们要与实际的Node配置一致。
|
MasterNodeList:指定哪些Node为服务发现Master结点,需要配置NodeId与ListenAddr,注意它们要与实际的Node配置一致。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### RpcMode部分
|
### RpcMode部分
|
||||||
|
|
||||||
默认模式
|
默认模式
|
||||||
@@ -146,8 +134,6 @@ MasterNodeList:指定哪些Node为服务发现Master结点,需要配置NodeI
|
|||||||
|
|
||||||
默认模式下,origin的node之前通过tcp连接组网。
|
默认模式下,origin的node之前通过tcp连接组网。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Nats模式
|
Nats模式
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@@ -167,8 +153,6 @@ NatsUrl:Nats连接url串
|
|||||||
|
|
||||||
NoRandomize:在多连接集群模式下,连接nats节点是否顺序策略。false表示随机连接,true表示顺序连接。
|
NoRandomize:在多连接集群模式下,连接nats节点是否顺序策略。false表示随机连接,true表示顺序连接。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### NodeList部分
|
### NodeList部分
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -212,8 +196,6 @@ NoRandomize:在多连接集群模式下,连接nats节点是否顺序策略。f
|
|||||||
在启动程序命令originserver -start nodeid="node_1"中nodeid就是根据该配置装载服务。
|
在启动程序命令originserver -start nodeid="node_1"中nodeid就是根据该配置装载服务。
|
||||||
更多参数使用,请使用originserver -help查看。
|
更多参数使用,请使用originserver -help查看。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Service 部分
|
### Service 部分
|
||||||
|
|
||||||
service.json如下:
|
service.json如下:
|
||||||
@@ -318,8 +300,6 @@ service.json如下:
|
|||||||
* PendingWriteNum:发送网络队列最大数量
|
* PendingWriteNum:发送网络队列最大数量
|
||||||
* MaxMsgLen:包最大长度
|
* MaxMsgLen:包最大长度
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Global部分
|
### Global部分
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@@ -342,8 +322,6 @@ if ok == false {
|
|||||||
areaId, ok := mapGlobal["AreaId"]
|
areaId, ok := mapGlobal["AreaId"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
第一章:origin基础:
|
第一章:origin基础:
|
||||||
@@ -510,7 +488,6 @@ func (slf *TestService1) OnInit() error {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
性能监控功能:
|
性能监控功能:
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@@ -887,10 +864,11 @@ func (slf *TestService7) GoTest(){
|
|||||||
|
|
||||||
您可以把TestService6配置到其他的Node中,比如NodeId为2中。只要在一个子网,origin引擎可以无差别调用。开发者只需要关注Service关系。同样它也是您服务器架构设计的核心需要思考的部分。
|
您可以把TestService6配置到其他的Node中,比如NodeId为2中。只要在一个子网,origin引擎可以无差别调用。开发者只需要关注Service关系。同样它也是您服务器架构设计的核心需要思考的部分。
|
||||||
|
|
||||||
|
|
||||||
第六章:并发函数调用
|
第六章:并发函数调用
|
||||||
---------------
|
--------------------
|
||||||
|
|
||||||
在开发中经常会有将某些任务放到其他协程中并发执行,执行完成后,将服务的工作线程去回调。使用方式很简单,先打开该功能如下代码:
|
在开发中经常会有将某些任务放到其他协程中并发执行,执行完成后,将服务的工作线程去回调。使用方式很简单,先打开该功能如下代码:
|
||||||
|
|
||||||
```
|
```
|
||||||
//以下通过cpu数量来定开启协程并发数量,建议:(1)cpu密集型计算使用1.0 (2)i/o密集型使用2.0或者更高
|
//以下通过cpu数量来定开启协程并发数量,建议:(1)cpu密集型计算使用1.0 (2)i/o密集型使用2.0或者更高
|
||||||
slf.OpenConcurrentByNumCPU(1.0)
|
slf.OpenConcurrentByNumCPU(1.0)
|
||||||
@@ -901,6 +879,7 @@ func (slf *TestService7) GoTest(){
|
|||||||
```
|
```
|
||||||
|
|
||||||
使用示例如下:
|
使用示例如下:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
func (slf *TestService13) testAsyncDo() {
|
func (slf *TestService13) testAsyncDo() {
|
||||||
@@ -954,9 +933,8 @@ func (slf *TestService13) testAsyncDo() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
第七章:服务发现
|
第七章:服务发现
|
||||||
--------------------
|
----------------
|
||||||
|
|
||||||
origin引擎默认使用读取所有结点配置的进行确认结点有哪些Service。引擎也支持动态服务发现的方式,支持etcd与origin类型,具体请参照【配置说明】部分,Node结点可以配置只发现某些服务,如下示例:
|
origin引擎默认使用读取所有结点配置的进行确认结点有哪些Service。引擎也支持动态服务发现的方式,支持etcd与origin类型,具体请参照【配置说明】部分,Node结点可以配置只发现某些服务,如下示例:
|
||||||
|
|
||||||
@@ -979,12 +957,11 @@ origin引擎默认使用读取所有结点配置的进行确认结点有哪些Se
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
DiscoveryService:在当前nodeid为nodeid_test的结点中,只发现 MasterNodeId为nodeid_1或NetworkName为networkname1网络中的TestService8服务。
|
DiscoveryService:在当前nodeid为nodeid_test的结点中,只发现 MasterNodeId为nodeid_1或NetworkName为networkname1网络中的TestService8服务。
|
||||||
|
|
||||||
**注意**:MasterNodeId与NetworkName只配置一个,分别在模式为origin或者etcd服务发现类型时。
|
**注意**:MasterNodeId与NetworkName只配置一个,分别在模式为origin或者etcd服务发现类型时。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
第八章:HttpService使用
|
第八章:HttpService使用
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package cluster
|
package cluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/v2/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
"github.com/duanhf2012/origin/v2/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"github.com/duanhf2012/origin/v2/event"
|
|
||||||
"errors"
|
|
||||||
"reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var configDir = "./config/"
|
var configDir = "./config/"
|
||||||
@@ -113,22 +113,22 @@ func (cls *Cluster) DelNode(nodeId string) {
|
|||||||
cls.locker.Lock()
|
cls.locker.Lock()
|
||||||
defer cls.locker.Unlock()
|
defer cls.locker.Unlock()
|
||||||
|
|
||||||
rpc, ok := cls.mapRpc[nodeId]
|
nodeRpc, ok := cls.mapRpc[nodeId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cls.TriggerDiscoveryEvent(false,nodeId,rpc.nodeInfo.ServiceList)
|
cls.TriggerDiscoveryEvent(false, nodeId, nodeRpc.nodeInfo.ServiceList)
|
||||||
for _, serviceName := range rpc.nodeInfo.ServiceList {
|
for _, serviceName := range nodeRpc.nodeInfo.ServiceList {
|
||||||
cls.delServiceNode(serviceName, nodeId)
|
cls.delServiceNode(serviceName, nodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(cls.mapRpc, nodeId)
|
delete(cls.mapRpc, nodeId)
|
||||||
if ok == true {
|
if ok == true {
|
||||||
rpc.client.Close(false)
|
nodeRpc.client.Close(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("remove node ",log.String("NodeId", rpc.nodeInfo.NodeId),log.String("ListenAddr", rpc.nodeInfo.ListenAddr))
|
log.Info("remove node ", log.String("NodeId", nodeRpc.nodeInfo.NodeId), log.String("ListenAddr", nodeRpc.nodeInfo.ListenAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) serviceDiscoveryDelNode(nodeId string) {
|
func (cls *Cluster) serviceDiscoveryDelNode(nodeId string) {
|
||||||
@@ -230,7 +230,6 @@ func (cls *Cluster) serviceDiscoverySetNodeInfo(nodeInfo *NodeInfo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (cls *Cluster) Init(localNodeId string, setupServiceFun SetupServiceFun) error {
|
func (cls *Cluster) Init(localNodeId string, setupServiceFun SetupServiceFun) error {
|
||||||
//1.初始化配置
|
//1.初始化配置
|
||||||
err := cls.InitCfg(localNodeId)
|
err := cls.InitCfg(localNodeId)
|
||||||
@@ -251,7 +250,7 @@ func (cls *Cluster) Init(localNodeId string, setupServiceFun SetupServiceFun) er
|
|||||||
//2.安装服务发现结点
|
//2.安装服务发现结点
|
||||||
err = cls.setupDiscovery(localNodeId, setupServiceFun)
|
err = cls.setupDiscovery(localNodeId, setupServiceFun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("setupDiscovery fail",log.ErrorAttr("err",err))
|
log.Error("setupDiscovery fail", log.ErrorField("err", err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
service.RegRpcEventFun = cls.RegRpcEvent
|
service.RegRpcEventFun = cls.RegRpcEvent
|
||||||
@@ -315,7 +314,6 @@ func GetRpcClient(nodeId string, serviceMethod string,filterRetire bool, clientL
|
|||||||
}
|
}
|
||||||
serviceName := serviceMethod[:findIndex]
|
serviceName := serviceMethod[:findIndex]
|
||||||
|
|
||||||
//1.找到对应的rpcNodeid
|
|
||||||
return GetCluster().GetNodeIdByService(serviceName, clientList, filterRetire)
|
return GetCluster().GetNodeIdByService(serviceName, clientList, filterRetire)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +338,7 @@ func (cls *Cluster) NotifyAllService(event event.IEvent){
|
|||||||
cls.rpcEventLocker.Lock()
|
cls.rpcEventLocker.Lock()
|
||||||
defer cls.rpcEventLocker.Unlock()
|
defer cls.rpcEventLocker.Unlock()
|
||||||
|
|
||||||
for serviceName, _ := range cls.mapServiceListenRpcEvent {
|
for serviceName := range cls.mapServiceListenRpcEvent {
|
||||||
ser := service.GetService(serviceName)
|
ser := service.GetService(serviceName)
|
||||||
if ser == nil {
|
if ser == nil {
|
||||||
log.Error("cannot find service name " + serviceName)
|
log.Error("cannot find service name " + serviceName)
|
||||||
@@ -403,7 +401,7 @@ func GetNodeByServiceName(serviceName string) map[string]struct{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mapNodeId := map[string]struct{}{}
|
mapNodeId := map[string]struct{}{}
|
||||||
for nodeId,_ := range mapNode {
|
for nodeId := range mapNode {
|
||||||
mapNodeId[nodeId] = struct{}{}
|
mapNodeId[nodeId] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,7 +421,7 @@ func GetNodeByTemplateServiceName(templateServiceName string) map[string]string
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for nodeId,_ := range mapNode {
|
for nodeId := range mapNode {
|
||||||
mapNodeId[serviceName] = nodeId
|
mapNodeId[serviceName] = nodeId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,7 +433,6 @@ func (cls *Cluster) GetGlobalCfg() interface{} {
|
|||||||
return cls.globalCfg
|
return cls.globalCfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (cls *Cluster) ParseGlobalCfg(cfg interface{}) error {
|
func (cls *Cluster) ParseGlobalCfg(cfg interface{}) error {
|
||||||
if cls.globalCfg == nil {
|
if cls.globalCfg == nil {
|
||||||
return errors.New("no service configuration found")
|
return errors.New("no service configuration found")
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package cluster
|
package cluster
|
||||||
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/v2/event"
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
@@ -11,19 +10,18 @@ import (
|
|||||||
"go.etcd.io/etcd/client/v3"
|
"go.etcd.io/etcd/client/v3"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go.uber.org/zap"
|
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"io/ioutil"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
const originDir = "/origin"
|
const originDir = "/origin"
|
||||||
const testKey = originDir+"/_inner/_test_7501f3ed-b716-44c2-0090-fc1ed0166d7a"
|
|
||||||
|
|
||||||
type etcdClientInfo struct {
|
type etcdClientInfo struct {
|
||||||
watchKeys []string
|
watchKeys []string
|
||||||
@@ -44,11 +42,16 @@ type EtcdDiscoveryService struct {
|
|||||||
mapDiscoveryNodeId map[string]map[string]struct{} //map[networkName]map[nodeId]
|
mapDiscoveryNodeId map[string]map[string]struct{} //map[networkName]map[nodeId]
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEtcdDiscovery() (IServiceDiscovery) {
|
var etcdDiscovery *EtcdDiscoveryService
|
||||||
etcdDiscovery := &EtcdDiscoveryService{}
|
func getEtcdDiscovery() IServiceDiscovery {
|
||||||
|
if etcdDiscovery == nil {
|
||||||
|
etcdDiscovery = &EtcdDiscoveryService{}
|
||||||
|
}
|
||||||
|
|
||||||
return etcdDiscovery
|
return etcdDiscovery
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (ed *EtcdDiscoveryService) InitDiscovery(localNodeId string, funDelNode FunDelNode, funSetNode FunSetNode) error {
|
func (ed *EtcdDiscoveryService) InitDiscovery(localNodeId string, funDelNode FunDelNode, funSetNode FunSetNode) error {
|
||||||
ed.localNodeId = localNodeId
|
ed.localNodeId = localNodeId
|
||||||
|
|
||||||
@@ -91,21 +94,50 @@ func (ed *EtcdDiscoveryService) OnInit() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(etcdDiscoveryCfg.EtcdList); i++ {
|
for i := 0; i < len(etcdDiscoveryCfg.EtcdList); i++ {
|
||||||
client, cerr := clientv3.New(clientv3.Config{
|
var client *clientv3.Client
|
||||||
|
var tlsConfig *tls.Config
|
||||||
|
|
||||||
|
if etcdDiscoveryCfg.EtcdList[i].Cert != "" {
|
||||||
|
// load cert
|
||||||
|
cert, cerr := tls.LoadX509KeyPair(etcdDiscoveryCfg.EtcdList[i].Cert, etcdDiscoveryCfg.EtcdList[i].CertKey)
|
||||||
|
if cerr != nil {
|
||||||
|
log.Error("load cert error", log.ErrorField("err", cerr))
|
||||||
|
return cerr
|
||||||
|
}
|
||||||
|
|
||||||
|
// load root ca
|
||||||
|
caData, cerr := ioutil.ReadFile(etcdDiscoveryCfg.EtcdList[i].Ca)
|
||||||
|
if cerr != nil {
|
||||||
|
log.Error("load root ca error", log.ErrorField("err", cerr))
|
||||||
|
return cerr
|
||||||
|
}
|
||||||
|
pool := x509.NewCertPool()
|
||||||
|
pool.AppendCertsFromPEM(caData)
|
||||||
|
tlsConfig = &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
RootCAs: pool,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err = clientv3.New(clientv3.Config{
|
||||||
Endpoints: etcdDiscoveryCfg.EtcdList[i].Endpoints,
|
Endpoints: etcdDiscoveryCfg.EtcdList[i].Endpoints,
|
||||||
DialTimeout: etcdDiscoveryCfg.DialTimeoutMillisecond,
|
DialTimeout: etcdDiscoveryCfg.DialTimeoutMillisecond,
|
||||||
Logger: zap.NewNop(),
|
Username: etcdDiscoveryCfg.EtcdList[i].UserName,
|
||||||
|
Password: etcdDiscoveryCfg.EtcdList[i].Password,
|
||||||
|
Logger: log.GetLogger().Logger,
|
||||||
|
TLS: tlsConfig,
|
||||||
})
|
})
|
||||||
|
|
||||||
if cerr != nil {
|
|
||||||
log.Error("etcd discovery init fail",log.ErrorAttr("err",cerr))
|
if err != nil {
|
||||||
return cerr
|
log.Error("etcd discovery init fail", log.ErrorField("err", err))
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
|
ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
|
||||||
_, err = client.Leases(ctx)
|
_, err = client.Leases(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("etcd discovery init fail",log.Any("endpoint",etcdDiscoveryCfg.EtcdList[i].Endpoints),log.ErrorAttr("err",err))
|
log.Error("etcd discovery init fail", log.Any("endpoint", etcdDiscoveryCfg.EtcdList[i].Endpoints), log.ErrorField("err", err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +162,7 @@ func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client,
|
|||||||
var resp *clientv3.LeaseGrantResponse
|
var resp *clientv3.LeaseGrantResponse
|
||||||
resp, err = client.Grant(context.Background(), cluster.GetEtcdDiscovery().TTLSecond)
|
resp, err = client.Grant(context.Background(), cluster.GetEtcdDiscovery().TTLSecond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("etcd registerService fail",log.ErrorAttr("err",err))
|
log.Error("etcd registerService fail", log.ErrorField("err", err))
|
||||||
ed.tryRegisterService(client, etcdClient)
|
ed.tryRegisterService(client, etcdClient)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -140,7 +172,7 @@ func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client,
|
|||||||
// 注册服务节点到 etcd
|
// 注册服务节点到 etcd
|
||||||
_, err = client.Put(context.Background(), ed.getRegisterKey(watchKey), ed.byteLocalNodeInfo, clientv3.WithLease(resp.ID))
|
_, err = client.Put(context.Background(), ed.getRegisterKey(watchKey), ed.byteLocalNodeInfo, clientv3.WithLease(resp.ID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("etcd Put fail",log.ErrorAttr("err",err))
|
log.Error("etcd Put fail", log.ErrorField("err", err))
|
||||||
ed.tryRegisterService(client, etcdClient)
|
ed.tryRegisterService(client, etcdClient)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -148,7 +180,7 @@ func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client,
|
|||||||
|
|
||||||
etcdClient.keepAliveChan, err = client.KeepAlive(context.Background(), etcdClient.leaseID)
|
etcdClient.keepAliveChan, err = client.KeepAlive(context.Background(), etcdClient.leaseID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("etcd KeepAlive fail",log.ErrorAttr("err",err))
|
log.Error("etcd KeepAlive fail", log.ErrorField("err", err))
|
||||||
ed.tryRegisterService(client, etcdClient)
|
ed.tryRegisterService(client, etcdClient)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -168,7 +200,6 @@ func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client,
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (ed *EtcdDiscoveryService) tryRegisterService(client *clientv3.Client, etcdClient *etcdClientInfo) {
|
func (ed *EtcdDiscoveryService) tryRegisterService(client *clientv3.Client, etcdClient *etcdClientInfo) {
|
||||||
if ed.isStop() {
|
if ed.isStop() {
|
||||||
return
|
return
|
||||||
@@ -203,7 +234,7 @@ func (ed *EtcdDiscoveryService) retire() error{
|
|||||||
// 注册服务节点到 etcd
|
// 注册服务节点到 etcd
|
||||||
_, err := c.Put(context.Background(), ed.getRegisterKey(watchKey), ed.byteLocalNodeInfo, clientv3.WithLease(ec.leaseID))
|
_, err := c.Put(context.Background(), ed.getRegisterKey(watchKey), ed.byteLocalNodeInfo, clientv3.WithLease(ec.leaseID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("etcd Put fail", log.ErrorAttr("err", err))
|
log.Error("etcd Put fail", log.ErrorField("err", err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,10 +261,10 @@ func (ed *EtcdDiscoveryService) isStop() bool{
|
|||||||
return atomic.LoadInt32(&ed.isClose) == 1
|
return atomic.LoadInt32(&ed.isClose) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nd *EtcdDiscoveryService) OnStart() {
|
func (ed *EtcdDiscoveryService) OnStart() {
|
||||||
for c, ec := range nd.mapClient {
|
for c, ec := range ed.mapClient {
|
||||||
nd.tryRegisterService(c,ec)
|
ed.tryRegisterService(c, ec)
|
||||||
nd.tryWatch(c,ec)
|
ed.tryWatch(c, ec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,12 +319,12 @@ func (ed *EtcdDiscoveryService) setNodeInfo(networkName string,nodeInfo *rpc.Nod
|
|||||||
func (ed *EtcdDiscoveryService) close() {
|
func (ed *EtcdDiscoveryService) close() {
|
||||||
for c, ec := range ed.mapClient {
|
for c, ec := range ed.mapClient {
|
||||||
if _, err := c.Revoke(context.Background(), ec.leaseID); err != nil {
|
if _, err := c.Revoke(context.Background(), ec.leaseID); err != nil {
|
||||||
log.Error("etcd Revoke fail",log.ErrorAttr("err",err))
|
log.Error("etcd Revoke fail", log.ErrorField("err", err))
|
||||||
}
|
}
|
||||||
c.Watcher.Close()
|
c.Watcher.Close()
|
||||||
err := c.Close()
|
err := c.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("etcd Close fail",log.ErrorAttr("err",err))
|
log.Error("etcd Close fail", log.ErrorField("err", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,7 +333,7 @@ func (ed *EtcdDiscoveryService) getServices(client *clientv3.Client,etcdClient *
|
|||||||
// 根据前缀获取现有的key
|
// 根据前缀获取现有的key
|
||||||
resp, err := client.Get(context.Background(), watchKey, clientv3.WithPrefix())
|
resp, err := client.Get(context.Background(), watchKey, clientv3.WithPrefix())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("etcd Get fail", log.ErrorAttr("err", err))
|
log.Error("etcd Get fail", log.ErrorField("err", err))
|
||||||
ed.tryWatch(client, etcdClient)
|
ed.tryWatch(client, etcdClient)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -325,11 +356,7 @@ func (ed *EtcdDiscoveryService) watchByClient(client *clientv3.Client,etcdClient
|
|||||||
func (ed *EtcdDiscoveryService) watcher(client *clientv3.Client, etcdClient *etcdClientInfo, watchKey string) {
|
func (ed *EtcdDiscoveryService) watcher(client *clientv3.Client, etcdClient *etcdClientInfo, watchKey string) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.Dump(string(buf[:l]),log.String("error",errString))
|
|
||||||
|
|
||||||
ed.tryWatch(client, etcdClient)
|
ed.tryWatch(client, etcdClient)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -358,7 +385,7 @@ func (ed *EtcdDiscoveryService) setNode(netWorkName string,byteNode []byte) stri
|
|||||||
var nodeInfo rpc.NodeInfo
|
var nodeInfo rpc.NodeInfo
|
||||||
err := proto.Unmarshal(byteNode, &nodeInfo)
|
err := proto.Unmarshal(byteNode, &nodeInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unmarshal fail",log.String("netWorkName",netWorkName),log.ErrorAttr("err",err))
|
log.Error("Unmarshal fail", log.String("netWorkName", netWorkName), log.ErrorField("err", err))
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,7 +524,7 @@ func (ed *EtcdDiscoveryService) RPC_ServiceRecord(etcdServiceRecord *service.Etc
|
|||||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
|
ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
|
||||||
lg, err = client.Grant(ctx, etcdServiceRecord.TTLSecond)
|
lg, err = client.Grant(ctx, etcdServiceRecord.TTLSecond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("etcd record fail,cannot grant lease",log.ErrorAttr("err",err))
|
log.Error("etcd record fail,cannot grant lease", log.ErrorField("err", err))
|
||||||
return errors.New("cannot grant lease")
|
return errors.New("cannot grant lease")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -506,14 +533,14 @@ func (ed *EtcdDiscoveryService) RPC_ServiceRecord(etcdServiceRecord *service.Etc
|
|||||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
|
ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
|
||||||
_, err = client.Put(ctx, path.Join(originDir, etcdServiceRecord.RecordKey), etcdServiceRecord.RecordInfo, clientv3.WithLease(lg.ID))
|
_, err = client.Put(ctx, path.Join(originDir, etcdServiceRecord.RecordKey), etcdServiceRecord.RecordInfo, clientv3.WithLease(lg.ID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("etcd record fail,cannot put record",log.ErrorAttr("err",err))
|
log.Error("etcd record fail,cannot put record", log.ErrorField("err", err))
|
||||||
}
|
}
|
||||||
return errors.New("cannot put record")
|
return errors.New("cannot put record")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = client.Put(context.Background(), path.Join(originDir, etcdServiceRecord.RecordKey), etcdServiceRecord.RecordInfo)
|
_, err = client.Put(context.Background(), path.Join(originDir, etcdServiceRecord.RecordKey), etcdServiceRecord.RecordInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("etcd record fail,cannot put record",log.ErrorAttr("err",err))
|
log.Error("etcd record fail,cannot put record", log.ErrorField("err", err))
|
||||||
return errors.New("cannot put record")
|
return errors.New("cannot put record")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package cluster
|
package cluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
"container/list"
|
"container/list"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type nodeTTL struct {
|
type nodeTTL struct {
|
||||||
@@ -46,7 +46,7 @@ func (ns *nodeSetTTL) addAndRefreshNode(nodeId string){
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ns *nodeSetTTL) checkTTL(cb func(nodeIdList []string)) {
|
func (ns *nodeSetTTL) checkTTL(cb func(nodeIdList []string)) {
|
||||||
nodeIdList := []string{}
|
var nodeIdList []string
|
||||||
for {
|
for {
|
||||||
f := ns.l.Front()
|
f := ns.l.Front()
|
||||||
if f == nil {
|
if f == nil {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ const OriginDiscoveryMasterName = "DiscoveryMaster"
|
|||||||
const OriginDiscoveryClientName = "DiscoveryClient"
|
const OriginDiscoveryClientName = "DiscoveryClient"
|
||||||
const RegServiceDiscover = OriginDiscoveryMasterName + ".RPC_RegServiceDiscover"
|
const RegServiceDiscover = OriginDiscoveryMasterName + ".RPC_RegServiceDiscover"
|
||||||
const SubServiceDiscover = OriginDiscoveryClientName + ".RPC_SubServiceDiscover"
|
const SubServiceDiscover = OriginDiscoveryClientName + ".RPC_SubServiceDiscover"
|
||||||
const AddSubServiceDiscover = OriginDiscoveryMasterName + ".RPC_AddSubServiceDiscover"
|
|
||||||
const NodeRetireRpcMethod = OriginDiscoveryMasterName + ".RPC_NodeRetire"
|
const NodeRetireRpcMethod = OriginDiscoveryMasterName + ".RPC_NodeRetire"
|
||||||
const RpcPingMethod = OriginDiscoveryMasterName + ".RPC_Ping"
|
const RpcPingMethod = OriginDiscoveryMasterName + ".RPC_Ping"
|
||||||
const UnRegServiceDiscover = OriginDiscoveryMasterName + ".RPC_UnRegServiceDiscover"
|
const UnRegServiceDiscover = OriginDiscoveryMasterName + ".RPC_UnRegServiceDiscover"
|
||||||
@@ -147,16 +146,16 @@ func (ds *OriginDiscoveryMaster) OnStart() {
|
|||||||
ds.checkTTL()
|
ds.checkTTL()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *OriginDiscoveryMaster) OnNatsConnected(){
|
func (ds *OriginDiscoveryMaster) OnNatsConnected() {
|
||||||
//向所有的节点同步服务发现信息
|
//向所有的节点同步服务发现信息
|
||||||
var notifyDiscover rpc.SubscribeDiscoverNotify
|
var notifyDiscover rpc.SubscribeDiscoverNotify
|
||||||
notifyDiscover.IsFull = true
|
notifyDiscover.IsFull = true
|
||||||
notifyDiscover.NodeInfo = dc.nodeInfo
|
notifyDiscover.NodeInfo = ds.nodeInfo
|
||||||
notifyDiscover.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
|
notifyDiscover.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
|
||||||
dc.RpcCastGo(SubServiceDiscover, ¬ifyDiscover)
|
ds.RpcCastGo(SubServiceDiscover, ¬ifyDiscover)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *OriginDiscoveryMaster) OnNatsDisconnect(){
|
func (ds *OriginDiscoveryMaster) OnNatsDisconnect() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *OriginDiscoveryMaster) OnNodeConnected(nodeId string) {
|
func (ds *OriginDiscoveryMaster) OnNodeConnected(nodeId string) {
|
||||||
@@ -188,7 +187,7 @@ func (ds *OriginDiscoveryMaster) OnNodeDisconnect(nodeId string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ds *OriginDiscoveryMaster) RpcCastGo(serviceMethod string, args interface{}) {
|
func (ds *OriginDiscoveryMaster) RpcCastGo(serviceMethod string, args interface{}) {
|
||||||
for nodeId, _ := range ds.mapNodeInfo {
|
for nodeId := range ds.mapNodeInfo {
|
||||||
if nodeId == cluster.GetLocalNodeInfo().NodeId {
|
if nodeId == cluster.GetLocalNodeInfo().NodeId {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -208,7 +207,7 @@ func (ds *OriginDiscoveryMaster) RPC_Ping(req *rpc.Ping, res *rpc.Pong) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *OriginDiscoveryMaster) RPC_NodeRetire(req *rpc.NodeRetireReq, res *rpc.Empty) error {
|
func (ds *OriginDiscoveryMaster) RPC_NodeRetire(req *rpc.NodeRetireReq, _ *rpc.Empty) error {
|
||||||
log.Info("node is retire", log.String("nodeId", req.NodeInfo.NodeId), log.Bool("retire", req.NodeInfo.Retire))
|
log.Info("node is retire", log.String("nodeId", req.NodeInfo.NodeId), log.Bool("retire", req.NodeInfo.Retire))
|
||||||
|
|
||||||
ds.updateNodeInfo(req.NodeInfo)
|
ds.updateNodeInfo(req.NodeInfo)
|
||||||
@@ -259,14 +258,13 @@ func (ds *OriginDiscoveryMaster) RPC_RegServiceDiscover(req *rpc.RegServiceDisco
|
|||||||
//加入到本地Cluster模块中,将连接该结点
|
//加入到本地Cluster模块中,将连接该结点
|
||||||
cluster.serviceDiscoverySetNodeInfo(&nodeInfo)
|
cluster.serviceDiscoverySetNodeInfo(&nodeInfo)
|
||||||
|
|
||||||
|
|
||||||
res.IsFull = true
|
res.IsFull = true
|
||||||
res.NodeInfo = ds.nodeInfo
|
res.NodeInfo = ds.nodeInfo
|
||||||
res.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
|
res.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *OriginDiscoveryMaster) RPC_UnRegServiceDiscover(req *rpc.UnRegServiceDiscoverReq, res *rpc.Empty) error {
|
func (ds *OriginDiscoveryMaster) RPC_UnRegServiceDiscover(req *rpc.UnRegServiceDiscoverReq, _ *rpc.Empty) error {
|
||||||
log.Debug("RPC_UnRegServiceDiscover", log.String("nodeId", req.NodeId))
|
log.Debug("RPC_UnRegServiceDiscover", log.String("nodeId", req.NodeId))
|
||||||
ds.OnNodeDisconnect(req.NodeId)
|
ds.OnNodeDisconnect(req.NodeId)
|
||||||
return nil
|
return nil
|
||||||
@@ -350,7 +348,6 @@ func (dc *OriginDiscoveryClient) ping(){
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (dc *OriginDiscoveryClient) OnStart() {
|
func (dc *OriginDiscoveryClient) OnStart() {
|
||||||
//2.添加并连接发现主结点
|
//2.添加并连接发现主结点
|
||||||
dc.addDiscoveryMaster()
|
dc.addDiscoveryMaster()
|
||||||
@@ -381,8 +378,8 @@ func (dc *OriginDiscoveryClient) fullCompareDiffNode(masterNodeId string, mapNod
|
|||||||
}
|
}
|
||||||
|
|
||||||
//本地任何Master都不存在的,放到diffNodeIdSlice
|
//本地任何Master都不存在的,放到diffNodeIdSlice
|
||||||
for nodeId, _ := range mapNodeId {
|
for nodeId := range mapNodeId {
|
||||||
_, ok := mapNodeInfo[nodeId]
|
_, ok = mapNodeInfo[nodeId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
diffNodeIdSlice = append(diffNodeIdSlice, nodeId)
|
diffNodeIdSlice = append(diffNodeIdSlice, nodeId)
|
||||||
}
|
}
|
||||||
@@ -391,7 +388,7 @@ func (dc *OriginDiscoveryClient) fullCompareDiffNode(masterNodeId string, mapNod
|
|||||||
return diffNodeIdSlice
|
return diffNodeIdSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
//订阅发现的服务通知
|
// RPC_SubServiceDiscover 订阅发现的服务通知
|
||||||
func (dc *OriginDiscoveryClient) RPC_SubServiceDiscover(req *rpc.SubscribeDiscoverNotify) error {
|
func (dc *OriginDiscoveryClient) RPC_SubServiceDiscover(req *rpc.SubscribeDiscoverNotify) error {
|
||||||
mapNodeInfo := map[string]*rpc.NodeInfo{}
|
mapNodeInfo := map[string]*rpc.NodeInfo{}
|
||||||
for _, nodeInfo := range req.NodeInfo {
|
for _, nodeInfo := range req.NodeInfo {
|
||||||
@@ -474,7 +471,7 @@ func (dc *OriginDiscoveryClient) OnRelease(){
|
|||||||
|
|
||||||
err := dc.CallNodeWithTimeout(3*time.Second, masterNodeList.MasterNodeList[i].NodeId, UnRegServiceDiscover, &nodeRetireReq, &rpc.Empty{})
|
err := dc.CallNodeWithTimeout(3*time.Second, masterNodeList.MasterNodeList[i].NodeId, UnRegServiceDiscover, &nodeRetireReq, &rpc.Empty{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("call "+UnRegServiceDiscover+" is fail",log.ErrorAttr("err",err))
|
log.Error("call "+UnRegServiceDiscover+" is fail", log.ErrorField("err", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -496,7 +493,7 @@ func (dc *OriginDiscoveryClient) OnRetire(){
|
|||||||
|
|
||||||
err := dc.GoNode(masterNodeList.MasterNodeList[i].NodeId, NodeRetireRpcMethod, &nodeRetireReq)
|
err := dc.GoNode(masterNodeList.MasterNodeList[i].NodeId, NodeRetireRpcMethod, &nodeRetireReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("call "+NodeRetireRpcMethod+" is fail",log.ErrorAttr("err",err))
|
log.Error("call "+NodeRetireRpcMethod+" is fail", log.ErrorField("err", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -616,7 +613,6 @@ func (cls *Cluster) AddDiscoveryService(serviceName string, bPublicService bool)
|
|||||||
cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId] = struct{}{}
|
cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (cls *Cluster) IsOriginMasterDiscoveryNode(nodeId string) bool {
|
func (cls *Cluster) IsOriginMasterDiscoveryNode(nodeId string) bool {
|
||||||
return cls.getOriginMasterDiscoveryNodeInfo(nodeId) != nil
|
return cls.getOriginMasterDiscoveryNodeInfo(nodeId) != nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,30 @@
|
|||||||
package cluster
|
package cluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/v2/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
|
||||||
|
|
||||||
type EtcdList struct {
|
type EtcdList struct {
|
||||||
NetworkName []string
|
NetworkName []string
|
||||||
Endpoints []string
|
Endpoints []string
|
||||||
|
UserName string
|
||||||
|
Password string
|
||||||
|
Cert string
|
||||||
|
CertKey string
|
||||||
|
Ca string
|
||||||
}
|
}
|
||||||
|
|
||||||
type EtcdDiscovery struct {
|
type EtcdDiscovery struct {
|
||||||
@@ -44,7 +52,7 @@ const MinTTL = 3
|
|||||||
type DiscoveryInfo struct {
|
type DiscoveryInfo struct {
|
||||||
discoveryType DiscoveryType
|
discoveryType DiscoveryType
|
||||||
Etcd *EtcdDiscovery //etcd
|
Etcd *EtcdDiscovery //etcd
|
||||||
Origin *OriginDiscovery //orign
|
Origin *OriginDiscovery //origin
|
||||||
}
|
}
|
||||||
|
|
||||||
type NatsConfig struct {
|
type NatsConfig struct {
|
||||||
@@ -55,7 +63,6 @@ type NatsConfig struct {
|
|||||||
type RpcMode struct {
|
type RpcMode struct {
|
||||||
Typ string `json:"Type"`
|
Typ string `json:"Type"`
|
||||||
Nats NatsConfig
|
Nats NatsConfig
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeInfoList struct {
|
type NodeInfoList struct {
|
||||||
@@ -64,6 +71,38 @@ type NodeInfoList struct {
|
|||||||
NodeList []NodeInfo
|
NodeList []NodeInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validConfigFile(f string) bool {
|
||||||
|
return strings.HasSuffix(f, ".json")|| strings.HasSuffix(f, ".yml") || strings.HasSuffix(f, ".yaml")
|
||||||
|
}
|
||||||
|
|
||||||
|
func yamlToJson(data []byte, v interface{}) ([]byte, error) {
|
||||||
|
mapKeyData := map[string]interface{}{}
|
||||||
|
err := yaml.Unmarshal(data, &mapKeyData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err = json.Marshal(mapKeyData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalConfig(data []byte, v interface{}) error {
|
||||||
|
envData := []byte(os.ExpandEnv(string(data)))
|
||||||
|
if !json.Valid(envData) {
|
||||||
|
var err error
|
||||||
|
envData, err = yamlToJson(envData, v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Unmarshal(envData, v)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *DiscoveryInfo) getDiscoveryType() DiscoveryType {
|
func (d *DiscoveryInfo) getDiscoveryType() DiscoveryType {
|
||||||
return d.discoveryType
|
return d.discoveryType
|
||||||
}
|
}
|
||||||
@@ -89,7 +128,7 @@ func (d *DiscoveryInfo) setEtcd(etcd *EtcdDiscovery) error{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if d.discoveryType != InvalidType {
|
if d.discoveryType != InvalidType {
|
||||||
return fmt.Errorf("Repeat configuration of Discovery")
|
return fmt.Errorf("repeat configuration of Discovery")
|
||||||
}
|
}
|
||||||
|
|
||||||
//Endpoints不允许重复
|
//Endpoints不允许重复
|
||||||
@@ -130,7 +169,7 @@ func (d *DiscoveryInfo) setOrigin(originDiscovery *OriginDiscovery) error{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if d.discoveryType != InvalidType {
|
if d.discoveryType != InvalidType {
|
||||||
return fmt.Errorf("Repeat configuration of Discovery")
|
return fmt.Errorf("repeat configuration of Discovery")
|
||||||
}
|
}
|
||||||
|
|
||||||
mapListenAddr := make(map[string]struct{})
|
mapListenAddr := make(map[string]struct{})
|
||||||
@@ -161,7 +200,7 @@ func (cls *Cluster) ReadClusterConfig(filepath string) (*NodeInfoList, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(d, c)
|
err = unmarshalConfig(d, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -176,7 +215,7 @@ func (cls *Cluster) readServiceConfig(filepath string) (interface{}, map[string]
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(d, &c)
|
err = unmarshalConfig(d, &c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -235,30 +274,33 @@ func (cls *Cluster) readLocalClusterConfig(nodeId string) (DiscoveryInfo, []Node
|
|||||||
var discoveryInfo DiscoveryInfo
|
var discoveryInfo DiscoveryInfo
|
||||||
var rpcMode RpcMode
|
var rpcMode RpcMode
|
||||||
|
|
||||||
clusterCfgPath := strings.TrimRight(configDir, "/") + "/cluster"
|
//读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件
|
||||||
fileInfoList, err := os.ReadDir(clusterCfgPath)
|
err := filepath.Walk(configDir, func(path string, info fs.FileInfo, err error)error {
|
||||||
if err != nil {
|
if info.IsDir() {
|
||||||
return discoveryInfo, nil,rpcMode, fmt.Errorf("Read dir %s is fail :%+v", clusterCfgPath, err)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件
|
if err != nil {
|
||||||
for _, f := range fileInfoList {
|
return err
|
||||||
if f.IsDir() == false {
|
}
|
||||||
filePath := strings.TrimRight(strings.TrimRight(clusterCfgPath, "/"), "\\") + "/" + f.Name()
|
|
||||||
fileNodeInfoList, rerr := cls.ReadClusterConfig(filePath)
|
|
||||||
|
|
||||||
if rerr != nil {
|
if !validConfigFile(info.Name()) {
|
||||||
return discoveryInfo, nil,rpcMode, fmt.Errorf("read file path %s is error:%+v", filePath, rerr)
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fileNodeInfoList, rErr := cls.ReadClusterConfig(path)
|
||||||
|
if rErr != nil {
|
||||||
|
return fmt.Errorf("read file path %s is error:%+v", path, rErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cls.SetRpcMode(&fileNodeInfoList.RpcMode, &rpcMode)
|
err = cls.SetRpcMode(&fileNodeInfoList.RpcMode, &rpcMode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return discoveryInfo, nil,rpcMode, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = discoveryInfo.setDiscovery(&fileNodeInfoList.Discovery)
|
err = discoveryInfo.setDiscovery(&fileNodeInfoList.Discovery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return discoveryInfo,nil,rpcMode,err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, nodeInfo := range fileNodeInfoList.NodeList {
|
for _, nodeInfo := range fileNodeInfoList.NodeList {
|
||||||
@@ -266,14 +308,19 @@ func (cls *Cluster) readLocalClusterConfig(nodeId string) (DiscoveryInfo, []Node
|
|||||||
nodeInfoList = append(nodeInfoList, nodeInfo)
|
nodeInfoList = append(nodeInfoList, nodeInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return discoveryInfo, nil, rpcMode, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if nodeId != rpc.NodeIdNull && (len(nodeInfoList) != 1) {
|
if nodeId != rpc.NodeIdNull && (len(nodeInfoList) != 1) {
|
||||||
return discoveryInfo, nil, rpcMode, fmt.Errorf("nodeid %s configuration error in NodeList", nodeId)
|
return discoveryInfo, nil, rpcMode, fmt.Errorf("nodeid %s configuration error in NodeList", nodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, _ := range nodeInfoList {
|
for i := range nodeInfoList {
|
||||||
for j, s := range nodeInfoList[i].ServiceList {
|
for j, s := range nodeInfoList[i].ServiceList {
|
||||||
//私有结点不加入到Public服务列表中
|
//私有结点不加入到Public服务列表中
|
||||||
if strings.HasPrefix(s, "_") == false && nodeInfoList[i].Private == false {
|
if strings.HasPrefix(s, "_") == false && nodeInfoList[i].Private == false {
|
||||||
@@ -288,36 +335,32 @@ func (cls *Cluster) readLocalClusterConfig(nodeId string) (DiscoveryInfo, []Node
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) readLocalService(localNodeId string) error {
|
func (cls *Cluster) readLocalService(localNodeId string) error {
|
||||||
clusterCfgPath := strings.TrimRight(configDir, "/") + "/cluster"
|
|
||||||
fileInfoList, err := os.ReadDir(clusterCfgPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Read dir %s is fail :%+v", clusterCfgPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var globalCfg interface{}
|
var globalCfg interface{}
|
||||||
publicService := map[string]interface{}{}
|
publicService := map[string]interface{}{}
|
||||||
nodeService := map[string]interface{}{}
|
nodeService := map[string]interface{}{}
|
||||||
|
|
||||||
//读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件
|
//读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件
|
||||||
for _, f := range fileInfoList {
|
err := filepath.Walk(configDir, func(path string, info fs.FileInfo, err error)error{
|
||||||
if f.IsDir() == true {
|
if info.IsDir() {
|
||||||
continue
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if filepath.Ext(f.Name())!= ".json" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
filePath := strings.TrimRight(strings.TrimRight(clusterCfgPath, "/"), "\\") + "/" + f.Name()
|
|
||||||
currGlobalCfg, serviceConfig, mapNodeService, err := cls.readServiceConfig(filePath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !validConfigFile(info.Name()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
currGlobalCfg, serviceConfig, mapNodeService, err := cls.readServiceConfig(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if currGlobalCfg != nil {
|
if currGlobalCfg != nil {
|
||||||
//不允许重复的配置global配置
|
//不允许重复的配置global配置
|
||||||
if globalCfg != nil {
|
if globalCfg != nil {
|
||||||
return fmt.Errorf("[Global] does not allow repeated configuration in %s.",f.Name())
|
return fmt.Errorf("[Global] does not allow repeated configuration in %s", info.Name())
|
||||||
}
|
}
|
||||||
globalCfg = currGlobalCfg
|
globalCfg = currGlobalCfg
|
||||||
}
|
}
|
||||||
@@ -333,7 +376,7 @@ func (cls *Cluster) readLocalService(localNodeId string) error {
|
|||||||
pubCfg, ok := serviceConfig[s]
|
pubCfg, ok := serviceConfig[s]
|
||||||
if ok == true {
|
if ok == true {
|
||||||
if _, publicOk := publicService[s]; publicOk == true {
|
if _, publicOk := publicService[s]; publicOk == true {
|
||||||
return fmt.Errorf("public service [%s] does not allow repeated configuration in %s.",s,f.Name())
|
return fmt.Errorf("public service [%s] does not allow repeated configuration in %s", s, info.Name())
|
||||||
}
|
}
|
||||||
publicService[s] = pubCfg
|
publicService[s] = pubCfg
|
||||||
}
|
}
|
||||||
@@ -349,12 +392,17 @@ func (cls *Cluster) readLocalService(localNodeId string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, nodeOK := nodeService[s]; nodeOK == true {
|
if _, nodeOK := nodeService[s]; nodeOK == true {
|
||||||
return fmt.Errorf("NodeService NodeId[%d] Service[%s] does not allow repeated configuration in %s.",cls.localNodeInfo.NodeId,s,f.Name())
|
return fmt.Errorf("NodeService NodeId[%s] Service[%s] does not allow repeated configuration in %s", cls.localNodeInfo.NodeId, s, info.Name())
|
||||||
}
|
}
|
||||||
nodeService[s] = nodeCfg
|
nodeService[s] = nodeCfg
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//组合所有的配置
|
//组合所有的配置
|
||||||
@@ -384,13 +432,12 @@ func (cls *Cluster) readLocalService(localNodeId string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) parseLocalCfg() {
|
func (cls *Cluster) parseLocalCfg() error{
|
||||||
rpcInfo := NodeRpcInfo{}
|
rpcInfo := NodeRpcInfo{}
|
||||||
rpcInfo.nodeInfo = cls.localNodeInfo
|
rpcInfo.nodeInfo = cls.localNodeInfo
|
||||||
rpcInfo.client = rpc.NewLClient(rpcInfo.nodeInfo.NodeId, &cls.callSet)
|
rpcInfo.client = rpc.NewLClient(rpcInfo.nodeInfo.NodeId, &cls.callSet)
|
||||||
|
|
||||||
cls.mapRpc[cls.localNodeInfo.NodeId] = &rpcInfo
|
cls.mapRpc[cls.localNodeInfo.NodeId] = &rpcInfo
|
||||||
|
|
||||||
for _, serviceName := range cls.localNodeInfo.ServiceList {
|
for _, serviceName := range cls.localNodeInfo.ServiceList {
|
||||||
splitServiceName := strings.Split(serviceName, ":")
|
splitServiceName := strings.Split(serviceName, ":")
|
||||||
if len(splitServiceName) == 2 {
|
if len(splitServiceName) == 2 {
|
||||||
@@ -403,13 +450,17 @@ func (cls *Cluster) parseLocalCfg() {
|
|||||||
cls.mapTemplateServiceNode[templateServiceName][serviceName] = struct{}{}
|
cls.mapTemplateServiceNode[templateServiceName][serviceName] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if _, ok := cls.mapServiceNode[serviceName]; ok == false {
|
if _, ok := cls.mapServiceNode[serviceName]; ok == false {
|
||||||
cls.mapServiceNode[serviceName] = make(map[string]struct{})
|
cls.mapServiceNode[serviceName] = make(map[string]struct{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _,ok:=cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId];ok {
|
||||||
|
return fmt.Errorf("duplicate service %s is configured in node %s", serviceName, cls.localNodeInfo.NodeId)
|
||||||
|
}
|
||||||
cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId] = struct{}{}
|
cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) IsNatsMode() bool {
|
func (cls *Cluster) IsNatsMode() bool {
|
||||||
@@ -442,8 +493,7 @@ func (cls *Cluster) InitCfg(localNodeId string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//本地配置服务加到全局map信息中
|
//本地配置服务加到全局map信息中
|
||||||
cls.parseLocalCfg()
|
return cls.parseLocalCfg()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cls *Cluster) IsConfigService(serviceName string) bool {
|
func (cls *Cluster) IsConfigService(serviceName string) bool {
|
||||||
@@ -466,7 +516,7 @@ func (cls *Cluster) GetNodeIdByTemplateService(templateServiceName string, rpcCl
|
|||||||
for serviceName := range mapServiceName {
|
for serviceName := range mapServiceName {
|
||||||
mapNodeId, ok := cls.mapServiceNode[serviceName]
|
mapNodeId, ok := cls.mapServiceNode[serviceName]
|
||||||
if ok == true {
|
if ok == true {
|
||||||
for nodeId, _ := range mapNodeId {
|
for nodeId := range mapNodeId {
|
||||||
pClient, retire := GetCluster().getRpcClient(nodeId)
|
pClient, retire := GetCluster().getRpcClient(nodeId)
|
||||||
if pClient == nil || pClient.IsConnected() == false {
|
if pClient == nil || pClient.IsConnected() == false {
|
||||||
continue
|
continue
|
||||||
@@ -490,7 +540,7 @@ func (cls *Cluster) GetNodeIdByService(serviceName string, rpcClientList []*rpc.
|
|||||||
defer cls.locker.RUnlock()
|
defer cls.locker.RUnlock()
|
||||||
mapNodeId, ok := cls.mapServiceNode[serviceName]
|
mapNodeId, ok := cls.mapServiceNode[serviceName]
|
||||||
if ok == true {
|
if ok == true {
|
||||||
for nodeId, _ := range mapNodeId {
|
for nodeId := range mapNodeId {
|
||||||
pClient, retire := GetCluster().getRpcClient(nodeId)
|
pClient, retire := GetCluster().getRpcClient(nodeId)
|
||||||
if pClient == nil || pClient.IsConnected() == false {
|
if pClient == nil || pClient.IsConnected() == false {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ type Concurrent struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
OpenConcurrentByNumCPU 函数使用说明
|
||||||
|
|
||||||
cpuMul 表示cpu的倍数
|
cpuMul 表示cpu的倍数
|
||||||
建议:(1)cpu密集型 使用1 (2)i/o密集型使用2或者更高
|
建议:(1)cpu密集型 使用1 (2)i/o密集型使用2或者更高
|
||||||
*/
|
*/
|
||||||
@@ -56,7 +58,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.Stack("fn and cb is nil")
|
log.StackError("fn and cb is nil")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,15 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
|
|
||||||
|
|
||||||
|
"context"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/v2/util/queue"
|
"github.com/duanhf2012/origin/v2/util/queue"
|
||||||
"context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var idleTimeout = int64(2 * time.Second)
|
var idleTimeout = int64(2 * time.Second)
|
||||||
|
|
||||||
const maxTaskQueueSessionId = 10000
|
const maxTaskQueueSessionId = 10000
|
||||||
|
|
||||||
type dispatch struct {
|
type dispatch struct {
|
||||||
@@ -56,7 +57,7 @@ func (d *dispatch) run() {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case queueId := <-d.queueIdChannel:
|
case queueId := <-d.queueIdChannel:
|
||||||
d.processqueueEvent(queueId)
|
d.processQueueEvent(queueId)
|
||||||
default:
|
default:
|
||||||
select {
|
select {
|
||||||
case t, ok := <-d.tasks:
|
case t, ok := <-d.tasks:
|
||||||
@@ -65,7 +66,7 @@ func (d *dispatch) run() {
|
|||||||
}
|
}
|
||||||
d.processTask(&t)
|
d.processTask(&t)
|
||||||
case queueId := <-d.queueIdChannel:
|
case queueId := <-d.queueIdChannel:
|
||||||
d.processqueueEvent(queueId)
|
d.processQueueEvent(queueId)
|
||||||
case <-timeout.C:
|
case <-timeout.C:
|
||||||
d.processTimer()
|
d.processTimer()
|
||||||
case <-d.cancelContext.Done():
|
case <-d.cancelContext.Done():
|
||||||
@@ -93,7 +94,7 @@ func (d *dispatch) processTimer() {
|
|||||||
d.idle = true
|
d.idle = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dispatch) processqueueEvent(queueId int64) {
|
func (d *dispatch) processQueueEvent(queueId int64) {
|
||||||
d.idle = false
|
d.idle = false
|
||||||
|
|
||||||
queueSession := d.mapTaskQueueSession[queueId]
|
queueSession := d.mapTaskQueueSession[queueId]
|
||||||
@@ -161,20 +162,19 @@ func (d *dispatch) pushQueueTaskFinishEvent(queueId int64) {
|
|||||||
d.queueIdChannel <- queueId
|
d.queueIdChannel <- queueId
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dispatch) pushAsyncDoCallbackEvent(cb func(err error)) {
|
func (d *dispatch) pushAsyncDoCallbackEvent(cb func(err error)) {
|
||||||
if cb == nil {
|
if cb == nil {
|
||||||
//不需要回调的情况
|
//不需要回调的情况
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.cbChannel <- cb
|
d.cbChannel <- cb
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dispatch) close() {
|
func (d *dispatch) close() {
|
||||||
atomic.StoreInt32(&d.minConcurrentNum, -1)
|
atomic.StoreInt32(&d.minConcurrentNum, -1)
|
||||||
d.cancel()
|
d.cancel()
|
||||||
|
|
||||||
|
|
||||||
breakFor:
|
breakFor:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@@ -192,10 +192,7 @@ breakFor:
|
|||||||
func (d *dispatch) DoCallback(cb func(err error)) {
|
func (d *dispatch) DoCallback(cb func(err error)) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.Dump(string(buf[:l]),log.String("error",errString))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
)
|
)
|
||||||
@@ -51,15 +51,13 @@ func (w *worker) run(waitGroup *sync.WaitGroup, t task) {
|
|||||||
func (w *worker) exec(t *task) {
|
func (w *worker) exec(t *task) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
errString := fmt.Sprint(r)
|
||||||
|
|
||||||
cb := t.cb
|
cb := t.cb
|
||||||
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))
|
log.StackError(errString)
|
||||||
w.endCallFun(true, t)
|
w.endCallFun(true, t)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -67,8 +65,8 @@ func (w *worker) exec(t *task) {
|
|||||||
w.endCallFun(t.fn(), t)
|
w.endCallFun(t.fn(), t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) endCallFun(isDocallBack bool,t *task) {
|
func (w *worker) endCallFun(isDoCallBack bool, t *task) {
|
||||||
if isDocallBack {
|
if isDoCallBack {
|
||||||
w.pushAsyncDoCallbackEvent(t.cb)
|
w.pushAsyncDoCallbackEvent(t.cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ import (
|
|||||||
|
|
||||||
type valueType int
|
type valueType int
|
||||||
type CommandFunctionCB func(args interface{}) error
|
type CommandFunctionCB func(args interface{}) error
|
||||||
|
|
||||||
var commandList []*command
|
var commandList []*command
|
||||||
var programName string
|
var programName string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
boolType valueType = 0
|
boolType valueType = 0
|
||||||
stringType valueType = 1
|
stringType valueType = 1
|
||||||
@@ -33,11 +35,9 @@ func (cmd *command) execute() error{
|
|||||||
return cmd.fn(cmd.strValue)
|
return cmd.fn(cmd.strValue)
|
||||||
} else if cmd.valType == intType {
|
} else if cmd.valType == intType {
|
||||||
return cmd.fn(cmd.intValue)
|
return cmd.fn(cmd.intValue)
|
||||||
}else{
|
|
||||||
return fmt.Errorf("Unknow command type.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return fmt.Errorf("unknow command type")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run(args []string) error {
|
func Run(args []string) error {
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ package event
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"runtime"
|
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
//事件接受器
|
// EventCallBack 事件接受器
|
||||||
type EventCallBack func(event IEvent)
|
type EventCallBack func(event IEvent)
|
||||||
|
|
||||||
type IEvent interface {
|
type IEvent interface {
|
||||||
@@ -17,10 +16,14 @@ type IEvent interface {
|
|||||||
type Event struct {
|
type Event struct {
|
||||||
Type EventType
|
Type EventType
|
||||||
Data interface{}
|
Data interface{}
|
||||||
|
IntExt [2]int64
|
||||||
|
StringExt [2]string
|
||||||
|
AnyExt [2]any
|
||||||
ref bool
|
ref bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var emptyEvent Event
|
var emptyEvent Event
|
||||||
|
|
||||||
func (e *Event) Reset() {
|
func (e *Event) Reset() {
|
||||||
*e = emptyEvent
|
*e = emptyEvent
|
||||||
}
|
}
|
||||||
@@ -134,7 +137,6 @@ func (handler *EventHandler) Init(processor IEventProcessor){
|
|||||||
handler.mapRegEvent = map[EventType]map[IEventProcessor]interface{}{}
|
handler.mapRegEvent = map[EventType]map[IEventProcessor]interface{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (processor *EventProcessor) Init(eventChannel IEventChannel) {
|
func (processor *EventProcessor) Init(eventChannel IEventChannel) {
|
||||||
processor.IEventChannel = eventChannel
|
processor.IEventChannel = eventChannel
|
||||||
}
|
}
|
||||||
@@ -212,10 +214,7 @@ func (handler *EventHandler) Destroy(){
|
|||||||
func (processor *EventProcessor) EventHandler(ev IEvent) {
|
func (processor *EventProcessor) EventHandler(ev IEvent) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.Dump(string(buf[:l]),log.String("error",errString))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -243,4 +242,3 @@ func (processor *EventProcessor) castEvent(event IEvent){
|
|||||||
proc.PushEvent(event)
|
proc.PushEvent(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,16 +10,14 @@ const (
|
|||||||
Sys_Event_Tcp EventType = -3
|
Sys_Event_Tcp EventType = -3
|
||||||
Sys_Event_Http_Event EventType = -4
|
Sys_Event_Http_Event EventType = -4
|
||||||
Sys_Event_WebSocket EventType = -5
|
Sys_Event_WebSocket EventType = -5
|
||||||
Sys_Event_Node_Conn_Event EventType = -6
|
Sys_Event_Kcp EventType = -6
|
||||||
Sys_Event_Nats_Conn_Event EventType = -7
|
Sys_Event_Node_Conn_Event EventType = -7
|
||||||
Sys_Event_DiscoverService EventType = -8
|
Sys_Event_Nats_Conn_Event EventType = -8
|
||||||
Sys_Event_DiscardGoroutine EventType = -9
|
Sys_Event_DiscoverService EventType = -9
|
||||||
Sys_Event_QueueTaskFinish EventType = -10
|
Sys_Event_Retire EventType = -10
|
||||||
Sys_Event_Retire EventType = -11
|
Sys_Event_EtcdDiscovery EventType = -11
|
||||||
Sys_Event_EtcdDiscovery EventType = -12
|
Sys_Event_Gin_Event EventType = -12
|
||||||
Sys_Event_Gin_Event EventType = -13
|
Sys_Event_FrameTick EventType = -13
|
||||||
Sys_Event_FrameTick EventType = -14
|
|
||||||
|
|
||||||
Sys_Event_User_Define EventType = 1
|
Sys_Event_User_Define EventType = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
65
go.mod
65
go.mod
@@ -1,40 +1,80 @@
|
|||||||
module github.com/duanhf2012/origin/v2
|
module github.com/duanhf2012/origin/v2
|
||||||
|
|
||||||
go 1.21
|
go 1.22
|
||||||
|
|
||||||
|
toolchain go1.22.7
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/IBM/sarama v1.43.3
|
||||||
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/go-sql-driver/mysql v1.6.0
|
github.com/go-sql-driver/mysql v1.6.0
|
||||||
github.com/gomodule/redigo v1.8.8
|
github.com/gomodule/redigo v1.8.8
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/nats-io/nats.go v1.34.1
|
github.com/nats-io/nats.go v1.34.1
|
||||||
github.com/pierrec/lz4/v4 v4.1.18
|
github.com/pierrec/lz4/v4 v4.1.21
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||||
|
github.com/xtaci/kcp-go/v5 v5.6.18
|
||||||
go.etcd.io/etcd/api/v3 v3.5.13
|
go.etcd.io/etcd/api/v3 v3.5.13
|
||||||
go.etcd.io/etcd/client/v3 v3.5.13
|
go.etcd.io/etcd/client/v3 v3.5.13
|
||||||
go.mongodb.org/mongo-driver v1.9.1
|
go.mongodb.org/mongo-driver v1.9.1
|
||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
google.golang.org/protobuf v1.33.0
|
google.golang.org/protobuf v1.34.1
|
||||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/bytedance/sonic v1.11.6 // indirect
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||||
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
github.com/coreos/go-semver v0.3.0 // indirect
|
github.com/coreos/go-semver v0.3.0 // indirect
|
||||||
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/eapache/go-resiliency v1.7.0 // indirect
|
||||||
|
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect
|
||||||
|
github.com/eapache/queue v1.1.0 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||||
github.com/go-stack/stack v1.8.0 // indirect
|
github.com/go-stack/stack v1.8.0 // indirect
|
||||||
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/golang/snappy v0.0.1 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/klauspost/compress v1.17.2 // indirect
|
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
|
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||||
|
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
|
||||||
|
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
|
||||||
|
github.com/jcmturner/gofork v1.7.6 // indirect
|
||||||
|
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
|
||||||
|
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||||
|
github.com/klauspost/reedsolomon v1.12.0 // indirect
|
||||||
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/nats-io/nkeys v0.4.7 // indirect
|
github.com/nats-io/nkeys v0.4.7 // indirect
|
||||||
github.com/nats-io/nuid v1.0.1 // indirect
|
github.com/nats-io/nuid v1.0.1 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||||
|
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||||
|
github.com/templexxx/cpu v0.1.1 // indirect
|
||||||
|
github.com/templexxx/xorsimd v0.4.3 // indirect
|
||||||
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.13 // indirect
|
github.com/tklauser/go-sysconf v0.3.13 // indirect
|
||||||
github.com/tklauser/numcpus v0.7.0 // indirect
|
github.com/tklauser/numcpus v0.7.0 // indirect
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
github.com/xdg-go/scram v1.0.2 // indirect
|
github.com/xdg-go/scram v1.0.2 // indirect
|
||||||
github.com/xdg-go/stringprep v1.0.2 // indirect
|
github.com/xdg-go/stringprep v1.0.2 // indirect
|
||||||
@@ -42,11 +82,12 @@ require (
|
|||||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.13 // indirect
|
go.etcd.io/etcd/client/pkg/v3 v3.5.13 // indirect
|
||||||
go.uber.org/multierr v1.10.0 // indirect
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
golang.org/x/crypto v0.18.0 // indirect
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
golang.org/x/net v0.17.0 // indirect
|
golang.org/x/crypto v0.26.0 // indirect
|
||||||
golang.org/x/sync v0.3.0 // indirect
|
golang.org/x/net v0.28.0 // indirect
|
||||||
golang.org/x/sys v0.16.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/sys v0.23.0 // indirect
|
||||||
|
golang.org/x/text v0.17.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
|
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||||
|
|||||||
228
go.sum
228
go.sum
@@ -1,3 +1,18 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/IBM/sarama v1.43.3 h1:Yj6L2IaNvb2mRBop39N7mmJAHBVY3dTPncr3qGVkxPA=
|
||||||
|
github.com/IBM/sarama v1.43.3/go.mod h1:FVIRaLrhK3Cla/9FfRF5X9Zua2KpS3SYIXxhac1H+FQ=
|
||||||
|
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||||
|
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||||
|
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||||
|
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||||
|
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
||||||
@@ -5,44 +20,120 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/eapache/go-resiliency v1.7.0 h1:n3NRTnBn5N0Cbi/IeOHuQn9s2UwVUH7Ga0ZWcP+9JTA=
|
||||||
|
github.com/eapache/go-resiliency v1.7.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho=
|
||||||
|
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws=
|
||||||
|
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0=
|
||||||
|
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||||
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||||
|
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||||
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
|
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||||
|
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
|
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||||
|
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/gomodule/redigo v1.8.8 h1:f6cXq6RRfiyrOJEV7p3JhLDlmawGBVBBP1MggY8Mo4E=
|
github.com/gomodule/redigo v1.8.8 h1:f6cXq6RRfiyrOJEV7p3JhLDlmawGBVBBP1MggY8Mo4E=
|
||||||
github.com/gomodule/redigo v1.8.8/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
|
github.com/gomodule/redigo v1.8.8/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
|
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
||||||
|
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
||||||
|
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
|
||||||
|
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
|
||||||
|
github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
|
||||||
|
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
|
||||||
|
github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
|
||||||
|
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
|
||||||
|
github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=
|
||||||
|
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
|
||||||
|
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||||
|
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
|
github.com/klauspost/reedsolomon v1.12.0 h1:I5FEp3xSwVCcEh3F5A7dofEfhXdF/bWhQWPH+XwBFno=
|
||||||
|
github.com/klauspost/reedsolomon v1.12.0/go.mod h1:EPLZJeh4l27pUGC3aXOjheaoh1I9yut7xTURiW3LQ9Y=
|
||||||
|
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||||
@@ -52,36 +143,66 @@ github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
|
|||||||
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
||||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
|
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||||
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||||
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
|
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||||
|
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/templexxx/cpu v0.1.1 h1:isxHaxBXpYFWnk2DReuKkigaZyrjs2+9ypIdGP4h+HI=
|
||||||
|
github.com/templexxx/cpu v0.1.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
||||||
|
github.com/templexxx/xorsimd v0.4.3 h1:9AQTFHd7Bhk3dIT7Al2XeBX5DWOvsUPZCuhyAtNbHjU=
|
||||||
|
github.com/templexxx/xorsimd v0.4.3/go.mod h1:oZQcD6RFDisW2Am58dSAGwwL6rHjbzrlu25VDqfWkQg=
|
||||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
|
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||||
|
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||||
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
|
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
|
||||||
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
|
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
|
||||||
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
|
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
|
||||||
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
|
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
|
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||||
|
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
|
github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
|
||||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||||
github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc=
|
github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc=
|
||||||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
||||||
|
github.com/xtaci/kcp-go/v5 v5.6.18 h1:7oV4mc272pcnn39/13BB11Bx7hJM4ogMIEokJYVWn4g=
|
||||||
|
github.com/xtaci/kcp-go/v5 v5.6.18/go.mod h1:75S1AKYYzNUSXIv30h+jPKJYZUwqpfvLshu63nCNSOM=
|
||||||
|
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
|
||||||
|
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.13 h1:8WXU2/NBge6AUF1K1gOexB6e07NgsN1hXK0rSTtgSp4=
|
go.etcd.io/etcd/api/v3 v3.5.13 h1:8WXU2/NBge6AUF1K1gOexB6e07NgsN1hXK0rSTtgSp4=
|
||||||
@@ -98,65 +219,126 @@ go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
|||||||
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
|
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||||
|
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
|
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||||
|
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||||
|
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||||
|
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||||
|
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY=
|
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY=
|
||||||
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
|
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q=
|
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
|
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
|
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||||
|
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||||
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
package log // import "go.uber.org/zap/buffer"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
const _size = 9216
|
|
||||||
|
|
||||||
type Buffer struct {
|
|
||||||
bs []byte
|
|
||||||
//mu sync.Mutex // ensures atomic writes; protects the following fields
|
|
||||||
}
|
|
||||||
|
|
||||||
func (buff *Buffer) Init(){
|
|
||||||
buff.bs = make([]byte,_size)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// AppendByte writes a single byte to the Buffer.
|
|
||||||
func (b *Buffer) AppendByte(v byte) {
|
|
||||||
b.bs = append(b.bs, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Buffer) AppendBytes(v []byte) {
|
|
||||||
b.bs = append(b.bs, v...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendString writes a string to the Buffer.
|
|
||||||
func (b *Buffer) AppendString(s string) {
|
|
||||||
b.bs = append(b.bs, s...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendInt appends an integer to the underlying buffer (assuming base 10).
|
|
||||||
func (b *Buffer) AppendInt(i int64) {
|
|
||||||
b.bs = strconv.AppendInt(b.bs, i, 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendUint appends an unsigned integer to the underlying buffer (assuming
|
|
||||||
// base 10).
|
|
||||||
func (b *Buffer) AppendUint(i uint64) {
|
|
||||||
b.bs = strconv.AppendUint(b.bs, i, 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendBool appends a bool to the underlying buffer.
|
|
||||||
func (b *Buffer) AppendBool(v bool) {
|
|
||||||
b.bs = strconv.AppendBool(b.bs, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendFloat appends a float to the underlying buffer. It doesn't quote NaN
|
|
||||||
// or +/- Inf.
|
|
||||||
func (b *Buffer) AppendFloat(f float64, bitSize int) {
|
|
||||||
b.bs = strconv.AppendFloat(b.bs, f, 'f', -1, bitSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the length of the underlying byte slice.
|
|
||||||
func (b *Buffer) Len() int {
|
|
||||||
return len(b.bs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cap returns the capacity of the underlying byte slice.
|
|
||||||
func (b *Buffer) Cap() int {
|
|
||||||
return cap(b.bs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bytes returns a mutable reference to the underlying byte slice.
|
|
||||||
func (b *Buffer) Bytes() []byte {
|
|
||||||
return b.bs
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a string copy of the underlying byte slice.
|
|
||||||
func (b *Buffer) String() string {
|
|
||||||
return string(b.bs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset resets the underlying byte slice. Subsequent writes re-use the slice's
|
|
||||||
// backing array.
|
|
||||||
func (b *Buffer) Reset() {
|
|
||||||
b.bs = b.bs[:0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write implements io.Writer.
|
|
||||||
func (b *Buffer) Write(bs []byte) (int, error) {
|
|
||||||
b.bs = append(b.bs, bs...)
|
|
||||||
return len(bs), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TrimNewline trims any final "\n" byte from the end of the buffer.
|
|
||||||
func (b *Buffer) TrimNewline() {
|
|
||||||
if i := len(b.bs) - 1; i >= 0 {
|
|
||||||
if b.bs[i] == '\n' {
|
|
||||||
b.bs = b.bs[:i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
161
log/handler.go
161
log/handler.go
@@ -1,161 +0,0 @@
|
|||||||
package log
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"log/slog"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"runtime/debug"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const defaultSkip = 7
|
|
||||||
type IOriginHandler interface {
|
|
||||||
slog.Handler
|
|
||||||
Lock()
|
|
||||||
UnLock()
|
|
||||||
SetSkip(skip int)
|
|
||||||
GetSkip() int
|
|
||||||
}
|
|
||||||
|
|
||||||
type BaseHandler struct {
|
|
||||||
addSource bool
|
|
||||||
w io.Writer
|
|
||||||
locker sync.Mutex
|
|
||||||
skip int
|
|
||||||
}
|
|
||||||
|
|
||||||
type OriginTextHandler struct {
|
|
||||||
BaseHandler
|
|
||||||
*slog.TextHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
type OriginJsonHandler struct {
|
|
||||||
BaseHandler
|
|
||||||
*slog.JSONHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bh *BaseHandler) SetSkip(skip int){
|
|
||||||
bh.skip = skip
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bh *BaseHandler) GetSkip() int{
|
|
||||||
return bh.skip
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
})
|
|
||||||
|
|
||||||
textHandler.skip = defaultSkip
|
|
||||||
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,
|
|
||||||
})
|
|
||||||
|
|
||||||
jsonHandler.skip = defaultSkip
|
|
||||||
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(b.skip, pcs[:])
|
|
||||||
record.PC = pcs[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
722
log/log.go
722
log/log.go
@@ -1,523 +1,337 @@
|
|||||||
package log
|
package log
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"go.uber.org/zap"
|
||||||
"fmt"
|
"go.uber.org/zap/zapcore"
|
||||||
"github.com/duanhf2012/origin/v2/util/bytespool"
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
"io"
|
|
||||||
"log/slog"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
|
||||||
var OpenConsole bool
|
|
||||||
var LogSize int64
|
|
||||||
var LogChannelCap int
|
|
||||||
var LogPath string
|
|
||||||
var LogLevel slog.Level = LevelTrace
|
|
||||||
|
|
||||||
|
|
||||||
var gLogger, _ = NewTextLogger(LevelDebug, "", "",true,LogChannelCap)
|
|
||||||
var isSetLogger bool
|
var isSetLogger bool
|
||||||
var memPool = bytespool.NewMemAreaPool()
|
var gLogger = NewDefaultLogger()
|
||||||
|
|
||||||
// levels
|
|
||||||
const (
|
|
||||||
LevelTrace = slog.Level(-8)
|
|
||||||
LevelDebug = slog.LevelDebug
|
|
||||||
LevelInfo = slog.LevelInfo
|
|
||||||
LevelWarning = slog.LevelWarn
|
|
||||||
LevelError = slog.LevelError
|
|
||||||
LevelStack = slog.Level(12)
|
|
||||||
LevelDump = slog.Level(16)
|
|
||||||
LevelFatal = slog.Level(20)
|
|
||||||
)
|
|
||||||
|
|
||||||
type ILogger interface {
|
|
||||||
Trace(msg string, args ...any)
|
|
||||||
Debug(msg string, args ...any)
|
|
||||||
Info(msg string, args ...any)
|
|
||||||
Warning(msg string, args ...any)
|
|
||||||
Error(msg string, args ...any)
|
|
||||||
Stack(msg string, args ...any)
|
|
||||||
Dump(msg string, args ...any)
|
|
||||||
Fatal(msg string, args ...any)
|
|
||||||
|
|
||||||
DoSPrintf(level slog.Level,a []interface{})
|
|
||||||
FormatHeader(buf *Buffer,level slog.Level,calldepth int)
|
|
||||||
Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
Slogger *slog.Logger
|
*zap.Logger
|
||||||
|
stack bool
|
||||||
|
|
||||||
ioWriter IoWriter
|
OpenConsole *bool
|
||||||
|
LogPath string
|
||||||
sBuff Buffer
|
FileName string
|
||||||
|
Skip int
|
||||||
|
LogLevel zapcore.Level
|
||||||
|
Encoder zapcore.Encoder
|
||||||
|
LogConfig *lumberjack.Logger
|
||||||
|
SugaredLogger *zap.SugaredLogger
|
||||||
|
CoreList []zapcore.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
type IoWriter struct {
|
func SetLogger(logger *Logger) {
|
||||||
outFile io.Writer // destination for output
|
if logger != nil {
|
||||||
writeBytes int64
|
|
||||||
logChannel chan []byte
|
|
||||||
wg sync.WaitGroup
|
|
||||||
closeSig chan struct{}
|
|
||||||
|
|
||||||
lockWrite sync.Mutex
|
|
||||||
|
|
||||||
filePath string
|
|
||||||
fileprefix string
|
|
||||||
fileDay int
|
|
||||||
fileCreateTime int64 //second
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IoWriter) Close() error {
|
|
||||||
iw.lockWrite.Lock()
|
|
||||||
defer iw.lockWrite.Unlock()
|
|
||||||
|
|
||||||
iw.close()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IoWriter) close() error {
|
|
||||||
if iw.closeSig != nil {
|
|
||||||
close(iw.closeSig)
|
|
||||||
iw.closeSig = nil
|
|
||||||
}
|
|
||||||
iw.wg.Wait()
|
|
||||||
|
|
||||||
if iw.outFile!= nil {
|
|
||||||
err := iw.outFile.(io.Closer).Close()
|
|
||||||
iw.outFile = nil
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IoWriter) writeFile(p []byte) (n int, err error){
|
|
||||||
//swich log file
|
|
||||||
iw.swichFile()
|
|
||||||
|
|
||||||
if iw.outFile != nil {
|
|
||||||
n,err = iw.outFile.Write(p)
|
|
||||||
if n > 0 {
|
|
||||||
atomic.AddInt64(&iw.writeBytes,int64(n))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0,nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IoWriter) Write(p []byte) (n int, err error){
|
|
||||||
iw.lockWrite.Lock()
|
|
||||||
defer iw.lockWrite.Unlock()
|
|
||||||
|
|
||||||
if iw.logChannel == nil {
|
|
||||||
return iw.writeIo(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
copyBuff := memPool.MakeBytes(len(p))
|
|
||||||
if copyBuff == nil {
|
|
||||||
return 0,fmt.Errorf("MakeByteSlice failed")
|
|
||||||
}
|
|
||||||
copy(copyBuff,p)
|
|
||||||
|
|
||||||
iw.logChannel <- copyBuff
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IoWriter) writeIo(p []byte) (n int, err error){
|
|
||||||
n,err = iw.writeFile(p)
|
|
||||||
|
|
||||||
if OpenConsole {
|
|
||||||
n,err = os.Stdout.Write(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IoWriter) setLogChannel(logChannelNum int) (err error){
|
|
||||||
iw.lockWrite.Lock()
|
|
||||||
defer iw.lockWrite.Unlock()
|
|
||||||
iw.close()
|
|
||||||
|
|
||||||
if logChannelNum == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//copy iw.logChannel
|
|
||||||
var logInfo []byte
|
|
||||||
logChannel := make(chan []byte,logChannelNum)
|
|
||||||
for i := 0; i < logChannelNum&&i<len(iw.logChannel); i++{
|
|
||||||
logInfo = <- iw.logChannel
|
|
||||||
logChannel <- logInfo
|
|
||||||
}
|
|
||||||
iw.logChannel = logChannel
|
|
||||||
|
|
||||||
iw.closeSig = make(chan struct{})
|
|
||||||
iw.wg.Add(1)
|
|
||||||
go iw.run()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IoWriter) run(){
|
|
||||||
defer iw.wg.Done()
|
|
||||||
|
|
||||||
Loop:
|
|
||||||
for{
|
|
||||||
select {
|
|
||||||
case <- iw.closeSig:
|
|
||||||
break Loop
|
|
||||||
case logs := <-iw.logChannel:
|
|
||||||
iw.writeIo(logs)
|
|
||||||
memPool.ReleaseBytes(logs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for len(iw.logChannel) > 0 {
|
|
||||||
logs := <-iw.logChannel
|
|
||||||
iw.writeIo(logs)
|
|
||||||
memPool.ReleaseBytes(logs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IoWriter) isFull() bool {
|
|
||||||
if LogSize == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return atomic.LoadInt64(&iw.writeBytes) >= LogSize
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) setLogChannel(logChannel int) (err error){
|
|
||||||
return logger.ioWriter.setLogChannel(logChannel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IoWriter) swichFile() error{
|
|
||||||
now := time.Now()
|
|
||||||
if iw.fileCreateTime == now.Unix() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if iw.fileDay == now.Day() && iw.isFull() == false {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if iw.filePath != "" {
|
|
||||||
var err error
|
|
||||||
fileName := fmt.Sprintf("%s%d%02d%02d_%02d_%02d_%02d.log",
|
|
||||||
iw.fileprefix,
|
|
||||||
now.Year(),
|
|
||||||
now.Month(),
|
|
||||||
now.Day(),
|
|
||||||
now.Hour(),
|
|
||||||
now.Minute(),
|
|
||||||
now.Second())
|
|
||||||
|
|
||||||
filePath := path.Join(iw.filePath, fileName)
|
|
||||||
|
|
||||||
iw.outFile,err = os.Create(filePath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
iw.fileDay = now.Day()
|
|
||||||
iw.fileCreateTime = now.Unix()
|
|
||||||
atomic.StoreInt64(&iw.writeBytes,0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDefaultHandler() IOriginHandler{
|
|
||||||
return gLogger.(*Logger).Slogger.Handler().(IOriginHandler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTextLogger(level slog.Level,pathName string,filePrefix string,addSource bool,logChannelCap int) (ILogger,error){
|
|
||||||
var logger Logger
|
|
||||||
logger.ioWriter.filePath = pathName
|
|
||||||
logger.ioWriter.fileprefix = filePrefix
|
|
||||||
|
|
||||||
logger.Slogger = slog.New(NewOriginTextHandler(level,&logger.ioWriter,addSource,defaultReplaceAttr))
|
|
||||||
logger.setLogChannel(logChannelCap)
|
|
||||||
err := logger.ioWriter.swichFile()
|
|
||||||
if err != nil {
|
|
||||||
return nil,err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &logger,nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewJsonLogger(level slog.Level,pathName string,filePrefix string,addSource bool,logChannelCap int) (ILogger,error){
|
|
||||||
var logger Logger
|
|
||||||
logger.ioWriter.filePath = pathName
|
|
||||||
logger.ioWriter.fileprefix = filePrefix
|
|
||||||
|
|
||||||
logger.Slogger = slog.New(NewOriginJsonHandler(level,&logger.ioWriter,true,defaultReplaceAttr))
|
|
||||||
logger.setLogChannel(logChannelCap)
|
|
||||||
err := logger.ioWriter.swichFile()
|
|
||||||
if err != nil {
|
|
||||||
return nil,err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &logger,nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// It's dangerous to call the method on logging
|
|
||||||
func (logger *Logger) Close() {
|
|
||||||
logger.ioWriter.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Trace(msg string, args ...any) {
|
|
||||||
logger.Slogger.Log(context.Background(),LevelTrace,msg,args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Debug(msg string, args ...any) {
|
|
||||||
|
|
||||||
logger.Slogger.Log(context.Background(),LevelDebug,msg,args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Info(msg string, args ...any) {
|
|
||||||
logger.Slogger.Log(context.Background(),LevelInfo,msg,args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warning(msg string, args ...any) {
|
|
||||||
logger.Slogger.Log(context.Background(),LevelWarning,msg,args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Error(msg string, args ...any) {
|
|
||||||
logger.Slogger.Log(context.Background(),LevelError,msg,args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Stack(msg string, args ...any) {
|
|
||||||
logger.Slogger.Log(context.Background(),LevelStack,msg,args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Dump(msg string, args ...any) {
|
|
||||||
logger.Slogger.Log(context.Background(),LevelDump,msg,args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Fatal(msg string, args ...any) {
|
|
||||||
logger.Slogger.Log(context.Background(),LevelFatal,msg,args...)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// It's non-thread-safe
|
|
||||||
func SetLogger(logger ILogger) {
|
|
||||||
if logger != nil && isSetLogger == false {
|
|
||||||
gLogger = logger
|
gLogger = logger
|
||||||
isSetLogger = true
|
isSetLogger = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLogger() ILogger{
|
func GetLogger() *Logger {
|
||||||
return gLogger
|
return gLogger
|
||||||
}
|
}
|
||||||
|
|
||||||
func Trace(msg string, args ...any){
|
func (logger *Logger) SetEncoder(encoder zapcore.Encoder) {
|
||||||
gLogger.Trace(msg, args...)
|
logger.Encoder = encoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func Debug(msg string, args ...any){
|
func (logger *Logger) SetSkip(skip int) {
|
||||||
gLogger.Debug(msg,args...)
|
logger.Skip = skip
|
||||||
}
|
}
|
||||||
|
|
||||||
func Info(msg string, args ...any){
|
func GetJsonEncoder() zapcore.Encoder {
|
||||||
gLogger.Info(msg,args...)
|
encoderConfig := zap.NewProductionEncoderConfig()
|
||||||
|
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
|
||||||
|
encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
|
||||||
|
encoderConfig.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
||||||
|
enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Warning(msg string, args ...any){
|
return zapcore.NewJSONEncoder(encoderConfig)
|
||||||
gLogger.Warning(msg,args...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Error(msg string, args ...any){
|
func GetTxtEncoder() zapcore.Encoder {
|
||||||
gLogger.Error(msg,args...)
|
encoderConfig := zap.NewProductionEncoderConfig()
|
||||||
|
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
|
||||||
|
encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
|
||||||
|
encoderConfig.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
||||||
|
enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Stack(msg string, args ...any){
|
return zapcore.NewConsoleEncoder(encoderConfig)
|
||||||
gLogger.Stack(msg,args...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Dump(dump string, args ...any){
|
func getLogConfig() *lumberjack.Logger {
|
||||||
gLogger.Dump(dump,args...)
|
return &lumberjack.Logger{
|
||||||
|
Filename: "",
|
||||||
|
MaxSize: 2048,
|
||||||
|
MaxBackups: 0,
|
||||||
|
MaxAge: 0,
|
||||||
|
Compress: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fatal(msg string, args ...any){
|
func NewDefaultLogger() *Logger {
|
||||||
gLogger.Fatal(msg,args...)
|
logger := Logger{}
|
||||||
|
logger.Encoder = GetJsonEncoder()
|
||||||
|
logger.LogConfig = getLogConfig()
|
||||||
|
logger.LogConfig.LocalTime = true
|
||||||
|
|
||||||
|
logger.Init()
|
||||||
|
return &logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func Close() {
|
func (logger *Logger) SetLogLevel(level zapcore.Level) {
|
||||||
gLogger.Close()
|
logger.LogLevel = level
|
||||||
}
|
}
|
||||||
|
|
||||||
func ErrorAttr(key string,value error) slog.Attr{
|
func (logger *Logger) Enabled(zapcore.Level) bool {
|
||||||
if value== nil {
|
return logger.stack
|
||||||
return slog.Attr{key, slog.StringValue("nil")}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return slog.Attr{key, slog.StringValue(value.Error())}
|
func (logger *Logger) Init() {
|
||||||
}
|
if isSetLogger {
|
||||||
|
|
||||||
func String(key, value string) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.StringValue(value)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Int(key string, value int) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.Int64Value(int64(value))}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Int64(key string, value int64) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.Int64Value(value)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Int32(key string, value int32) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.Int64Value(int64(value))}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Int16(key string, value int16) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.Int64Value(int64(value))}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Int8(key string, value int8) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.Int64Value(int64(value))}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uint(key string, value uint) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.Uint64Value(uint64(value))}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uint64(key string, v uint64) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.Uint64Value(v)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uint32(key string, value uint32) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.Uint64Value(uint64(value))}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uint16(key string, value uint16) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.Uint64Value(uint64(value))}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uint8(key string, value uint8) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.Uint64Value(uint64(value))}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Float64(key string, v float64) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.Float64Value(v)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Bool(key string, v bool) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.BoolValue(v)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Time(key string, v time.Time) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.TimeValue(v)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Duration(key string, v time.Duration) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.DurationValue(v)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Any(key string, value any) slog.Attr {
|
|
||||||
return slog.Attr{key, slog.AnyValue(value)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Group(key string, args ...any) slog.Attr {
|
|
||||||
return slog.Group(key, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) DoSPrintf(level slog.Level,a []interface{}) {
|
|
||||||
if logger.Slogger.Enabled(context.Background(),level) == false{
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Slogger.Handler().(IOriginHandler).Lock()
|
var coreList []zapcore.Core
|
||||||
defer logger.Slogger.Handler().(IOriginHandler).UnLock()
|
if logger.OpenConsole == nil || *logger.OpenConsole {
|
||||||
|
core := zapcore.NewCore(logger.Encoder, zapcore.AddSync(os.Stdout), logger.LogLevel)
|
||||||
logger.sBuff.Reset()
|
coreList = append(coreList, core)
|
||||||
|
|
||||||
logger.FormatHeader(&logger.sBuff,level,3)
|
|
||||||
|
|
||||||
for _,s := range a {
|
|
||||||
logger.sBuff.AppendString(slog.AnyValue(s).String())
|
|
||||||
}
|
|
||||||
logger.sBuff.AppendString("\"\n")
|
|
||||||
logger.ioWriter.Write([]byte(logger.sBuff.Bytes()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) STrace(a ...interface{}) {
|
if logger.CoreList != nil {
|
||||||
logger.DoSPrintf(LevelTrace,a)
|
coreList = append(coreList, logger.CoreList...)
|
||||||
|
}else if logger.LogPath != "" {
|
||||||
|
WriteSyncer := zapcore.AddSync(logger.LogConfig)
|
||||||
|
core := zapcore.NewCore(logger.Encoder, WriteSyncer, logger.LogLevel)
|
||||||
|
coreList = append(coreList, core)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) SDebug(a ...interface{}) {
|
core := zapcore.NewTee(coreList...)
|
||||||
logger.DoSPrintf(LevelDebug,a)
|
logger.Logger = zap.New(core, zap.AddCaller(), zap.AddStacktrace(logger), zap.AddCallerSkip(1+logger.Skip))
|
||||||
|
logger.SugaredLogger = logger.Logger.Sugar()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) SInfo(a ...interface{}) {
|
func (logger *Logger) Debug(msg string, fields ...zap.Field) {
|
||||||
logger.DoSPrintf(LevelInfo,a)
|
logger.Logger.Debug(msg, fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) SWarning(a ...interface{}) {
|
func (logger *Logger) Info(msg string, fields ...zap.Field) {
|
||||||
logger.DoSPrintf(LevelWarning,a)
|
logger.Logger.Info(msg, fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) SError(a ...interface{}) {
|
func (logger *Logger) Warn(msg string, fields ...zap.Field) {
|
||||||
logger.DoSPrintf(LevelError,a)
|
logger.Logger.Warn(msg, fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func STrace(a ...interface{}) {
|
func (logger *Logger) Error(msg string, fields ...zap.Field) {
|
||||||
gLogger.DoSPrintf(LevelTrace,a)
|
logger.Logger.Error(msg, fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SDebug(a ...interface{}) {
|
func (logger *Logger) StackError(msg string, args ...zap.Field) {
|
||||||
gLogger.DoSPrintf(LevelDebug,a)
|
logger.stack = true
|
||||||
|
logger.Logger.Log(zapcore.ErrorLevel, msg, args...)
|
||||||
|
logger.stack = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func SInfo(a ...interface{}) {
|
func (logger *Logger) Fatal(msg string, fields ...zap.Field) {
|
||||||
gLogger.DoSPrintf(LevelInfo,a)
|
gLogger.stack = true
|
||||||
|
logger.Logger.Fatal(msg, fields...)
|
||||||
|
gLogger.stack = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func SWarning(a ...interface{}) {
|
func Debug(msg string, fields ...zap.Field) {
|
||||||
gLogger.DoSPrintf(LevelWarning,a)
|
gLogger.Logger.Debug(msg, fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SError(a ...interface{}) {
|
func Info(msg string, fields ...zap.Field) {
|
||||||
gLogger.DoSPrintf(LevelError,a)
|
gLogger.Logger.Info(msg, fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (logger *Logger) FormatHeader(buf *Buffer,level slog.Level,calldepth int) {
|
func Warn(msg string, fields ...zap.Field) {
|
||||||
t := time.Now()
|
gLogger.Logger.Warn(msg, fields...)
|
||||||
var file string
|
|
||||||
var line int
|
|
||||||
|
|
||||||
// Release lock while getting caller info - it's expensive.
|
|
||||||
var ok bool
|
|
||||||
_, file, line, ok = runtime.Caller(calldepth)
|
|
||||||
if !ok {
|
|
||||||
file = "???"
|
|
||||||
line = 0
|
|
||||||
}
|
}
|
||||||
file = filepath.Base(file)
|
|
||||||
|
|
||||||
buf.AppendString("time=\"")
|
func Error(msg string, fields ...zap.Field) {
|
||||||
buf.AppendString(t.Format("2006/01/02 15:04:05"))
|
gLogger.Logger.Error(msg, fields...)
|
||||||
buf.AppendString("\"")
|
}
|
||||||
logger.sBuff.AppendString(" level=")
|
|
||||||
logger.sBuff.AppendString(getStrLevel(level))
|
func StackError(msg string, fields ...zap.Field) {
|
||||||
logger.sBuff.AppendString(" source=")
|
gLogger.stack = true
|
||||||
|
gLogger.Logger.Error(msg, fields...)
|
||||||
buf.AppendString(file)
|
gLogger.stack = false
|
||||||
buf.AppendByte(':')
|
}
|
||||||
buf.AppendInt(int64(line))
|
|
||||||
buf.AppendString(" msg=\"")
|
func Fatal(msg string, fields ...zap.Field) {
|
||||||
|
gLogger.stack = true
|
||||||
|
gLogger.Logger.Fatal(msg, fields...)
|
||||||
|
gLogger.stack = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func Debugf(template string, args ...any) {
|
||||||
|
gLogger.SugaredLogger.Debugf(template, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Infof(template string, args ...any) {
|
||||||
|
gLogger.SugaredLogger.Infof(template, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Warnf(template string, args ...any) {
|
||||||
|
gLogger.SugaredLogger.Warnf(template, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Errorf(template string, args ...any) {
|
||||||
|
gLogger.SugaredLogger.Errorf(template, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StackErrorf(template string, args ...any) {
|
||||||
|
gLogger.stack = true
|
||||||
|
gLogger.SugaredLogger.Errorf(template, args...)
|
||||||
|
gLogger.stack = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fatalf(template string, args ...any) {
|
||||||
|
gLogger.SugaredLogger.Fatalf(template, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logger *Logger) SDebug(args ...interface{}) {
|
||||||
|
logger.SugaredLogger.Debugln(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logger *Logger) SInfo(args ...interface{}) {
|
||||||
|
logger.SugaredLogger.Infoln(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logger *Logger) SWarn(args ...interface{}) {
|
||||||
|
logger.SugaredLogger.Warnln(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logger *Logger) SError(args ...interface{}) {
|
||||||
|
logger.SugaredLogger.Errorln(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logger *Logger) SStackError(args ...interface{}) {
|
||||||
|
gLogger.stack = true
|
||||||
|
logger.SugaredLogger.Errorln(args...)
|
||||||
|
gLogger.stack = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logger *Logger) SFatal(args ...interface{}) {
|
||||||
|
gLogger.stack = true
|
||||||
|
logger.SugaredLogger.Fatalln(args...)
|
||||||
|
gLogger.stack = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func SDebug(args ...interface{}) {
|
||||||
|
gLogger.SugaredLogger.Debugln(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SInfo(args ...interface{}) {
|
||||||
|
gLogger.SugaredLogger.Infoln(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SWarn(args ...interface{}) {
|
||||||
|
gLogger.SugaredLogger.Warnln(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SError(args ...interface{}) {
|
||||||
|
gLogger.SugaredLogger.Errorln(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SStackError(args ...interface{}) {
|
||||||
|
gLogger.stack = true
|
||||||
|
gLogger.SugaredLogger.Errorln(args...)
|
||||||
|
gLogger.stack = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func SFatal(args ...interface{}) {
|
||||||
|
gLogger.stack = true
|
||||||
|
gLogger.SugaredLogger.Fatalln(args...)
|
||||||
|
gLogger.stack = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ErrorField(key string, value error) zap.Field {
|
||||||
|
if value == nil {
|
||||||
|
return zap.String(key, "nil")
|
||||||
|
}
|
||||||
|
return zap.String(key, value.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func String(key, value string) zap.Field {
|
||||||
|
return zap.String(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int(key string, value int) zap.Field {
|
||||||
|
return zap.Int(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int64(key string, value int64) zap.Field {
|
||||||
|
return zap.Int64(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int32(key string, value int32) zap.Field {
|
||||||
|
return zap.Int32(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int16(key string, value int16) zap.Field {
|
||||||
|
return zap.Int16(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int8(key string, value int8) zap.Field {
|
||||||
|
return zap.Int8(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uint(key string, value uint) zap.Field {
|
||||||
|
return zap.Uint(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uint64(key string, v uint64) zap.Field {
|
||||||
|
return zap.Uint64(key, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uint32(key string, value uint32) zap.Field {
|
||||||
|
return zap.Uint32(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uint16(key string, value uint16) zap.Field {
|
||||||
|
return zap.Uint16(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uint8(key string, value uint8) zap.Field {
|
||||||
|
return zap.Uint8(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Float64(key string, v float64) zap.Field {
|
||||||
|
return zap.Float64(key, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Bool(key string, v bool) zap.Field {
|
||||||
|
return zap.Bool(key, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Bools(key string, v []bool) zap.Field {
|
||||||
|
return zap.Bools(key, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Time(key string, v time.Time) zap.Field {
|
||||||
|
return zap.Time(key, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Duration(key string, v time.Duration) zap.Field {
|
||||||
|
return zap.Duration(key, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Durations(key string, v []time.Duration) zap.Field {
|
||||||
|
return zap.Durations(key, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Any(key string, value any) zap.Field {
|
||||||
|
return zap.Any(key, value)
|
||||||
}
|
}
|
||||||
160
network/conn.go
160
network/conn.go
@@ -1,7 +1,12 @@
|
|||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"net"
|
"net"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Conn interface {
|
type Conn interface {
|
||||||
@@ -13,3 +18,158 @@ type Conn interface {
|
|||||||
Destroy()
|
Destroy()
|
||||||
ReleaseReadMsg(byteBuff []byte)
|
ReleaseReadMsg(byteBuff []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ConnSet map[net.Conn]struct{}
|
||||||
|
|
||||||
|
type NetConn struct {
|
||||||
|
sync.Mutex
|
||||||
|
conn net.Conn
|
||||||
|
writeChan chan []byte
|
||||||
|
closeFlag int32
|
||||||
|
msgParser *MsgParser
|
||||||
|
}
|
||||||
|
|
||||||
|
func freeChannel(conn *NetConn) {
|
||||||
|
for len(conn.writeChan) > 0 {
|
||||||
|
byteBuff := <-conn.writeChan
|
||||||
|
if byteBuff != nil {
|
||||||
|
conn.ReleaseReadMsg(byteBuff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newNetConn(conn net.Conn, pendingWriteNum int, msgParser *MsgParser, writeDeadline time.Duration) *NetConn {
|
||||||
|
netConn := new(NetConn)
|
||||||
|
netConn.conn = conn
|
||||||
|
netConn.writeChan = make(chan []byte, pendingWriteNum)
|
||||||
|
netConn.msgParser = msgParser
|
||||||
|
go func() {
|
||||||
|
for b := range netConn.writeChan {
|
||||||
|
if b == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.SetWriteDeadline(time.Now().Add(writeDeadline))
|
||||||
|
_, err := conn.Write(b)
|
||||||
|
netConn.msgParser.ReleaseBytes(b)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conn.Close()
|
||||||
|
netConn.Lock()
|
||||||
|
freeChannel(netConn)
|
||||||
|
atomic.StoreInt32(&netConn.closeFlag, 1)
|
||||||
|
netConn.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return netConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) doDestroy() {
|
||||||
|
netConn.conn.Close()
|
||||||
|
|
||||||
|
if atomic.LoadInt32(&netConn.closeFlag) == 0 {
|
||||||
|
close(netConn.writeChan)
|
||||||
|
atomic.StoreInt32(&netConn.closeFlag, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) Destroy() {
|
||||||
|
netConn.Lock()
|
||||||
|
defer netConn.Unlock()
|
||||||
|
|
||||||
|
netConn.doDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) Close() {
|
||||||
|
netConn.Lock()
|
||||||
|
defer netConn.Unlock()
|
||||||
|
if atomic.LoadInt32(&netConn.closeFlag) == 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
netConn.doWrite(nil)
|
||||||
|
atomic.StoreInt32(&netConn.closeFlag, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) GetRemoteIp() string {
|
||||||
|
return netConn.conn.RemoteAddr().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) doWrite(b []byte) error {
|
||||||
|
if len(netConn.writeChan) == cap(netConn.writeChan) {
|
||||||
|
netConn.ReleaseReadMsg(b)
|
||||||
|
log.Error("close conn: channel full")
|
||||||
|
netConn.doDestroy()
|
||||||
|
return errors.New("close conn: channel full")
|
||||||
|
}
|
||||||
|
|
||||||
|
netConn.writeChan <- b
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// b must not be modified by the others goroutines
|
||||||
|
func (netConn *NetConn) Write(b []byte) (int,error) {
|
||||||
|
netConn.Lock()
|
||||||
|
defer netConn.Unlock()
|
||||||
|
if atomic.LoadInt32(&netConn.closeFlag) == 1 || b == nil {
|
||||||
|
netConn.ReleaseReadMsg(b)
|
||||||
|
return 0,errors.New("conn is close")
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(b),netConn.doWrite(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) Read(b []byte) (int, error) {
|
||||||
|
return netConn.conn.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) LocalAddr() net.Addr {
|
||||||
|
return netConn.conn.LocalAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) RemoteAddr() net.Addr {
|
||||||
|
return netConn.conn.RemoteAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) ReadMsg() ([]byte, error) {
|
||||||
|
return netConn.msgParser.Read(netConn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) GetRecyclerReaderBytes() func(data []byte) {
|
||||||
|
return netConn.msgParser.GetRecyclerReaderBytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) ReleaseReadMsg(byteBuff []byte) {
|
||||||
|
netConn.msgParser.ReleaseBytes(byteBuff)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) WriteMsg(args ...[]byte) error {
|
||||||
|
if atomic.LoadInt32(&netConn.closeFlag) == 1 {
|
||||||
|
return errors.New("conn is close")
|
||||||
|
}
|
||||||
|
return netConn.msgParser.Write(netConn, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) WriteRawMsg(args []byte) error {
|
||||||
|
if atomic.LoadInt32(&netConn.closeFlag) == 1 {
|
||||||
|
return errors.New("conn is close")
|
||||||
|
}
|
||||||
|
|
||||||
|
_,err:= netConn.Write(args)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) IsConnected() bool {
|
||||||
|
return atomic.LoadInt32(&netConn.closeFlag) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) SetReadDeadline(d time.Duration) {
|
||||||
|
netConn.conn.SetReadDeadline(time.Now().Add(d))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netConn *NetConn) SetWriteDeadline(d time.Duration) {
|
||||||
|
netConn.conn.SetWriteDeadline(time.Now().Add(d))
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var DefaultMaxHeaderBytes int = 1<<20
|
var DefaultMaxHeaderBytes = 1 << 20
|
||||||
|
|
||||||
type CAFile struct {
|
type CAFile struct {
|
||||||
CertFile string
|
CertFile string
|
||||||
@@ -39,7 +39,7 @@ func (slf *HttpServer) Start() {
|
|||||||
|
|
||||||
func (slf *HttpServer) startListen() error {
|
func (slf *HttpServer) startListen() error {
|
||||||
if slf.httpServer != nil {
|
if slf.httpServer != nil {
|
||||||
return errors.New("Duplicate start not allowed")
|
return errors.New("duplicate start not allowed")
|
||||||
}
|
}
|
||||||
|
|
||||||
var tlsCaList []tls.Certificate
|
var tlsCaList []tls.Certificate
|
||||||
@@ -81,7 +81,6 @@ func (slf *HttpServer) startListen() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (slf *HttpServer) SetCAFile(caFile []CAFile) {
|
func (slf *HttpServer) SetCAFile(caFile []CAFile) {
|
||||||
slf.caFileList = caFile
|
slf.caFileList = caFile
|
||||||
}
|
}
|
||||||
|
|||||||
161
network/kcp_client.go
Normal file
161
network/kcp_client.go
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/xtaci/kcp-go/v5"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type KCPClient struct {
|
||||||
|
sync.Mutex
|
||||||
|
Addr string
|
||||||
|
ConnNum int
|
||||||
|
ConnectInterval time.Duration
|
||||||
|
PendingWriteNum int
|
||||||
|
ReadDeadline time.Duration
|
||||||
|
WriteDeadline time.Duration
|
||||||
|
AutoReconnect bool
|
||||||
|
NewAgent func(conn *NetConn) Agent
|
||||||
|
cons ConnSet
|
||||||
|
wg sync.WaitGroup
|
||||||
|
closeFlag bool
|
||||||
|
|
||||||
|
// msg parser
|
||||||
|
MsgParser
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *KCPClient) Start() {
|
||||||
|
client.init()
|
||||||
|
|
||||||
|
for i := 0; i < client.ConnNum; i++ {
|
||||||
|
client.wg.Add(1)
|
||||||
|
go client.connect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *KCPClient) init() {
|
||||||
|
client.Lock()
|
||||||
|
defer client.Unlock()
|
||||||
|
|
||||||
|
if client.ConnNum <= 0 {
|
||||||
|
client.ConnNum = 1
|
||||||
|
log.Info("invalid ConnNum", log.Int("reset", client.ConnNum))
|
||||||
|
}
|
||||||
|
if client.ConnectInterval <= 0 {
|
||||||
|
client.ConnectInterval = 3 * time.Second
|
||||||
|
log.Info("invalid ConnectInterval", log.Duration("reset", client.ConnectInterval))
|
||||||
|
}
|
||||||
|
if client.PendingWriteNum <= 0 {
|
||||||
|
client.PendingWriteNum = 1000
|
||||||
|
log.Info("invalid PendingWriteNum", log.Int("reset", client.PendingWriteNum))
|
||||||
|
}
|
||||||
|
if client.ReadDeadline == 0 {
|
||||||
|
client.ReadDeadline = 15 * time.Second
|
||||||
|
log.Info("invalid ReadDeadline", log.Int64("reset", int64(client.ReadDeadline.Seconds())))
|
||||||
|
}
|
||||||
|
if client.WriteDeadline == 0 {
|
||||||
|
client.WriteDeadline = 15 * time.Second
|
||||||
|
log.Info("invalid WriteDeadline", log.Int64("reset", int64(client.WriteDeadline.Seconds())))
|
||||||
|
}
|
||||||
|
if client.NewAgent == nil {
|
||||||
|
log.Fatal("NewAgent must not be nil")
|
||||||
|
}
|
||||||
|
if client.cons != nil {
|
||||||
|
log.Fatal("client is running")
|
||||||
|
}
|
||||||
|
|
||||||
|
if client.MinMsgLen == 0 {
|
||||||
|
client.MinMsgLen = Default_MinMsgLen
|
||||||
|
}
|
||||||
|
if client.MaxMsgLen == 0 {
|
||||||
|
client.MaxMsgLen = Default_MaxMsgLen
|
||||||
|
}
|
||||||
|
if client.LenMsgLen == 0 {
|
||||||
|
client.LenMsgLen = Default_LenMsgLen
|
||||||
|
}
|
||||||
|
maxMsgLen := client.MsgParser.getMaxMsgLen()
|
||||||
|
if client.MaxMsgLen > maxMsgLen {
|
||||||
|
client.MaxMsgLen = maxMsgLen
|
||||||
|
log.Info("invalid MaxMsgLen", log.Uint32("reset", maxMsgLen))
|
||||||
|
}
|
||||||
|
|
||||||
|
client.cons = make(ConnSet)
|
||||||
|
client.closeFlag = false
|
||||||
|
client.MsgParser.Init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *KCPClient) GetCloseFlag() bool {
|
||||||
|
client.Lock()
|
||||||
|
defer client.Unlock()
|
||||||
|
|
||||||
|
return client.closeFlag
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *KCPClient) dial() net.Conn {
|
||||||
|
for {
|
||||||
|
conn, err := kcp.DialWithOptions(client.Addr, nil, 10, 3)
|
||||||
|
if client.closeFlag {
|
||||||
|
return conn
|
||||||
|
} else if err == nil && conn != nil {
|
||||||
|
conn.SetNoDelay(1, 10, 2, 1)
|
||||||
|
conn.SetDSCP(46)
|
||||||
|
conn.SetStreamMode(true)
|
||||||
|
conn.SetWindowSize(1024, 1024)
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Warn("connect error ", log.String("error", err.Error()), log.String("Addr", client.Addr))
|
||||||
|
time.Sleep(client.ConnectInterval)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *KCPClient) connect() {
|
||||||
|
defer client.wg.Done()
|
||||||
|
reconnect:
|
||||||
|
conn := client.dial()
|
||||||
|
if conn == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Lock()
|
||||||
|
if client.closeFlag {
|
||||||
|
client.Unlock()
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
client.cons[conn] = struct{}{}
|
||||||
|
client.Unlock()
|
||||||
|
|
||||||
|
netConn := newNetConn(conn, client.PendingWriteNum, &client.MsgParser, client.WriteDeadline)
|
||||||
|
agent := client.NewAgent(netConn)
|
||||||
|
agent.Run()
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
netConn.Close()
|
||||||
|
client.Lock()
|
||||||
|
delete(client.cons, conn)
|
||||||
|
client.Unlock()
|
||||||
|
agent.OnClose()
|
||||||
|
|
||||||
|
if client.AutoReconnect {
|
||||||
|
time.Sleep(client.ConnectInterval)
|
||||||
|
goto reconnect
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *KCPClient) Close(waitDone bool) {
|
||||||
|
client.Lock()
|
||||||
|
client.closeFlag = true
|
||||||
|
for conn := range client.cons {
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
client.cons = nil
|
||||||
|
client.Unlock()
|
||||||
|
|
||||||
|
if waitDone == true {
|
||||||
|
client.wg.Wait()
|
||||||
|
}
|
||||||
|
}
|
||||||
257
network/kcp_server.go
Normal file
257
network/kcp_server.go
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/network/processor"
|
||||||
|
"github.com/xtaci/kcp-go/v5"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type KCPServer struct {
|
||||||
|
NewAgent func(Conn) Agent
|
||||||
|
|
||||||
|
kcpCfg *KcpCfg
|
||||||
|
blockCrypt kcp.BlockCrypt
|
||||||
|
|
||||||
|
process processor.IRawProcessor
|
||||||
|
msgParser MsgParser
|
||||||
|
conns ConnSet
|
||||||
|
mutexConns sync.Mutex
|
||||||
|
wgLn sync.WaitGroup
|
||||||
|
wgConns sync.WaitGroup
|
||||||
|
|
||||||
|
listener *kcp.Listener
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
NoDelayCfg
|
||||||
|
|
||||||
|
普通模式: ikcp_nodelay(kcp, 0, 40, 0, 0);
|
||||||
|
极速模式: ikcp_nodelay(kcp, 1, 10, 2, 1);
|
||||||
|
*/
|
||||||
|
type NoDelayCfg struct {
|
||||||
|
NoDelay int // 是否启用 nodelay模式,0不启用;1启用
|
||||||
|
IntervalMill int // 协议内部工作的 interval,单位毫秒,比如 10ms或者 20ms
|
||||||
|
Resend int // 快速重传模式,默认0关闭,可以设置2(2次ACK跨越将会直接重传)
|
||||||
|
CongestionControl int // 是否关闭流控,默认是0代表不关闭,1代表关闭
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultNoDelay = 1
|
||||||
|
DefaultIntervalMill = 10
|
||||||
|
DefaultResend = 2
|
||||||
|
DefaultCongestionControl = 1
|
||||||
|
|
||||||
|
DefaultMtu = 1400
|
||||||
|
DefaultSndWndSize = 4096
|
||||||
|
DefaultRcvWndSize = 4096
|
||||||
|
DefaultStreamMode = true
|
||||||
|
DefaultDSCP = 46
|
||||||
|
DefaultDataShards = 10
|
||||||
|
DefaultParityShards = 0
|
||||||
|
|
||||||
|
DefaultReadDeadlineMill = 15 * time.Second
|
||||||
|
DefaultWriteDeadlineMill = 15 * time.Second
|
||||||
|
|
||||||
|
DefaultMaxConnNum = 20000
|
||||||
|
)
|
||||||
|
|
||||||
|
type KcpCfg struct {
|
||||||
|
ListenAddr string // 监听地址
|
||||||
|
MaxConnNum int //最大连接数
|
||||||
|
NoDelay *NoDelayCfg
|
||||||
|
|
||||||
|
Mtu *int // mtu大小
|
||||||
|
SndWndSize *int // 发送窗口大小,默认1024
|
||||||
|
RcvWndSize *int // 接收窗口大小,默认1024
|
||||||
|
ReadDeadlineMill *time.Duration // 读超时毫秒
|
||||||
|
WriteDeadlineMill *time.Duration // 写超时毫秒
|
||||||
|
StreamMode *bool // 是否打开流模式,默认true
|
||||||
|
DSCP *int // 差分服务代码点,默认46
|
||||||
|
ReadBuffSize *int // 读Buff大小,默认
|
||||||
|
WriteBuffSize *int // 写Buff大小
|
||||||
|
|
||||||
|
// 用于 FEC(前向纠错)的数据分片和校验分片数量,,默认10,0
|
||||||
|
DataShards *int
|
||||||
|
ParityShards *int
|
||||||
|
|
||||||
|
// 包体内容
|
||||||
|
|
||||||
|
LittleEndian bool //是否小端序
|
||||||
|
LenMsgLen int //消息头占用byte数量,只能是1byte,2byte,4byte。如果是4byte,意味着消息最大可以是math.MaxUint32(4GB)
|
||||||
|
MinMsgLen uint32 //最小消息长度
|
||||||
|
MaxMsgLen uint32 //最大消息长度,超过判定不合法,断开连接
|
||||||
|
PendingWriteNum int //写channel最大消息数量
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kp *KCPServer) Init(kcpCfg *KcpCfg) {
|
||||||
|
kp.kcpCfg = kcpCfg
|
||||||
|
kp.msgParser.Init()
|
||||||
|
kp.msgParser.LenMsgLen = kp.kcpCfg.LenMsgLen
|
||||||
|
kp.msgParser.MaxMsgLen = kp.kcpCfg.MaxMsgLen
|
||||||
|
kp.msgParser.MinMsgLen = kp.kcpCfg.MinMsgLen
|
||||||
|
kp.msgParser.LittleEndian = kp.kcpCfg.LittleEndian
|
||||||
|
|
||||||
|
// setting default noDelay
|
||||||
|
if kp.kcpCfg.NoDelay == nil {
|
||||||
|
var noDelay NoDelayCfg
|
||||||
|
noDelay.NoDelay = DefaultNoDelay
|
||||||
|
noDelay.IntervalMill = DefaultIntervalMill
|
||||||
|
noDelay.Resend = DefaultResend
|
||||||
|
noDelay.CongestionControl = DefaultCongestionControl
|
||||||
|
kp.kcpCfg.NoDelay = &noDelay
|
||||||
|
}
|
||||||
|
|
||||||
|
if kp.kcpCfg.Mtu == nil {
|
||||||
|
mtu := DefaultMtu
|
||||||
|
kp.kcpCfg.Mtu = &mtu
|
||||||
|
}
|
||||||
|
|
||||||
|
if kp.kcpCfg.SndWndSize == nil {
|
||||||
|
sndWndSize := DefaultSndWndSize
|
||||||
|
kp.kcpCfg.SndWndSize = &sndWndSize
|
||||||
|
}
|
||||||
|
if kp.kcpCfg.RcvWndSize == nil {
|
||||||
|
rcvWndSize := DefaultRcvWndSize
|
||||||
|
kp.kcpCfg.RcvWndSize = &rcvWndSize
|
||||||
|
}
|
||||||
|
if kp.kcpCfg.ReadDeadlineMill == nil {
|
||||||
|
readDeadlineMill := DefaultReadDeadlineMill
|
||||||
|
kp.kcpCfg.ReadDeadlineMill = &readDeadlineMill
|
||||||
|
} else {
|
||||||
|
*kp.kcpCfg.ReadDeadlineMill *= time.Millisecond
|
||||||
|
}
|
||||||
|
if kp.kcpCfg.WriteDeadlineMill == nil {
|
||||||
|
writeDeadlineMill := DefaultWriteDeadlineMill
|
||||||
|
kp.kcpCfg.WriteDeadlineMill = &writeDeadlineMill
|
||||||
|
} else {
|
||||||
|
*kp.kcpCfg.WriteDeadlineMill *= time.Millisecond
|
||||||
|
}
|
||||||
|
if kp.kcpCfg.StreamMode == nil {
|
||||||
|
streamMode := DefaultStreamMode
|
||||||
|
kp.kcpCfg.StreamMode = &streamMode
|
||||||
|
}
|
||||||
|
if kp.kcpCfg.DataShards == nil {
|
||||||
|
dataShards := DefaultDataShards
|
||||||
|
kp.kcpCfg.DataShards = &dataShards
|
||||||
|
}
|
||||||
|
if kp.kcpCfg.ParityShards == nil {
|
||||||
|
parityShards := DefaultParityShards
|
||||||
|
kp.kcpCfg.ParityShards = &parityShards
|
||||||
|
}
|
||||||
|
if kp.kcpCfg.DSCP == nil {
|
||||||
|
dss := DefaultDSCP
|
||||||
|
kp.kcpCfg.DSCP = &dss
|
||||||
|
}
|
||||||
|
|
||||||
|
if kp.kcpCfg.MaxConnNum == 0 {
|
||||||
|
kp.kcpCfg.MaxConnNum = DefaultMaxConnNum
|
||||||
|
}
|
||||||
|
|
||||||
|
kp.conns = make(ConnSet, 2048)
|
||||||
|
kp.msgParser.Init()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kp *KCPServer) Start() error {
|
||||||
|
listener, err := kcp.ListenWithOptions(kp.kcpCfg.ListenAddr, kp.blockCrypt, *kp.kcpCfg.DataShards, *kp.kcpCfg.ParityShards)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if kp.kcpCfg.ReadBuffSize != nil {
|
||||||
|
err = listener.SetReadBuffer(*kp.kcpCfg.ReadBuffSize)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if kp.kcpCfg.WriteBuffSize != nil {
|
||||||
|
err = listener.SetWriteBuffer(*kp.kcpCfg.WriteBuffSize)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = listener.SetDSCP(*kp.kcpCfg.DSCP)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
kp.listener = listener
|
||||||
|
|
||||||
|
kp.wgLn.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer kp.wgLn.Done()
|
||||||
|
for kp.run(listener) {
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kp *KCPServer) initSession(session *kcp.UDPSession) {
|
||||||
|
session.SetStreamMode(*kp.kcpCfg.StreamMode)
|
||||||
|
session.SetWindowSize(*kp.kcpCfg.SndWndSize, *kp.kcpCfg.RcvWndSize)
|
||||||
|
session.SetNoDelay(kp.kcpCfg.NoDelay.NoDelay, kp.kcpCfg.NoDelay.IntervalMill, kp.kcpCfg.NoDelay.Resend, kp.kcpCfg.NoDelay.CongestionControl)
|
||||||
|
session.SetDSCP(*kp.kcpCfg.DSCP)
|
||||||
|
session.SetMtu(*kp.kcpCfg.Mtu)
|
||||||
|
session.SetACKNoDelay(false)
|
||||||
|
|
||||||
|
//session.SetWriteDeadline(time.Now().Add(*kp.kcpCfg.WriteDeadlineMill))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kp *KCPServer) run(listener *kcp.Listener) bool {
|
||||||
|
conn, err := listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("accept error", log.String("ListenAddr", kp.kcpCfg.ListenAddr), log.ErrorField("err", err))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
kp.mutexConns.Lock()
|
||||||
|
if len(kp.conns) >= kp.kcpCfg.MaxConnNum {
|
||||||
|
kp.mutexConns.Unlock()
|
||||||
|
conn.Close()
|
||||||
|
log.Warn("too many connections")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
kp.conns[conn] = struct{}{}
|
||||||
|
kp.mutexConns.Unlock()
|
||||||
|
|
||||||
|
if kp.kcpCfg.ReadBuffSize != nil {
|
||||||
|
conn.(*kcp.UDPSession).SetReadBuffer(*kp.kcpCfg.ReadBuffSize)
|
||||||
|
}
|
||||||
|
if kp.kcpCfg.WriteBuffSize != nil {
|
||||||
|
conn.(*kcp.UDPSession).SetWriteBuffer(*kp.kcpCfg.WriteBuffSize)
|
||||||
|
}
|
||||||
|
kp.initSession(conn.(*kcp.UDPSession))
|
||||||
|
|
||||||
|
netConn := newNetConn(conn, kp.kcpCfg.PendingWriteNum, &kp.msgParser, *kp.kcpCfg.WriteDeadlineMill)
|
||||||
|
agent := kp.NewAgent(netConn)
|
||||||
|
kp.wgConns.Add(1)
|
||||||
|
go func() {
|
||||||
|
agent.Run()
|
||||||
|
// cleanup
|
||||||
|
conn.Close()
|
||||||
|
kp.mutexConns.Lock()
|
||||||
|
delete(kp.conns, conn)
|
||||||
|
kp.mutexConns.Unlock()
|
||||||
|
agent.OnClose()
|
||||||
|
|
||||||
|
kp.wgConns.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kp *KCPServer) Close() {
|
||||||
|
kp.listener.Close()
|
||||||
|
kp.wgLn.Wait()
|
||||||
|
|
||||||
|
kp.mutexConns.Lock()
|
||||||
|
for conn := range kp.conns {
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
kp.conns = nil
|
||||||
|
kp.mutexConns.Unlock()
|
||||||
|
kp.wgConns.Wait()
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@ type JsonProcessor struct {
|
|||||||
unknownMessageHandler UnknownMessageJsonHandler
|
unknownMessageHandler UnknownMessageJsonHandler
|
||||||
connectHandler ConnectJsonHandler
|
connectHandler ConnectJsonHandler
|
||||||
disconnectHandler ConnectJsonHandler
|
disconnectHandler ConnectJsonHandler
|
||||||
bytespool.IBytesMempool
|
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.IBytesMempool = bytespool.NewMemAreaPool()
|
processor.IBytesMemPool = bytespool.NewMemAreaPool()
|
||||||
|
|
||||||
return processor
|
return processor
|
||||||
}
|
}
|
||||||
@@ -44,14 +44,14 @@ func (jsonProcessor *JsonProcessor) SetByteOrder(littleEndian bool) {
|
|||||||
jsonProcessor.LittleEndian = littleEndian
|
jsonProcessor.LittleEndian = littleEndian
|
||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// MsgRoute must goroutine safe
|
||||||
func (jsonProcessor *JsonProcessor) MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error {
|
func (jsonProcessor *JsonProcessor) MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error {
|
||||||
pPackInfo := msg.(*JsonPackInfo)
|
pPackInfo := msg.(*JsonPackInfo)
|
||||||
defer recyclerReaderBytes(pPackInfo.rawMsg)
|
defer recyclerReaderBytes(pPackInfo.rawMsg)
|
||||||
|
|
||||||
v, ok := jsonProcessor.mapMsg[pPackInfo.typ]
|
v, ok := jsonProcessor.mapMsg[pPackInfo.typ]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return fmt.Errorf("cannot find msgtype %d is register!",pPackInfo.typ)
|
return fmt.Errorf("cannot find msgtype %d is register", pPackInfo.typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.msgHandler(clientId, pPackInfo.msg)
|
v.msgHandler(clientId, pPackInfo.msg)
|
||||||
@@ -59,7 +59,9 @@ func (jsonProcessor *JsonProcessor ) MsgRoute(clientId string,msg interface{},re
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (jsonProcessor *JsonProcessor) Unmarshal(clientId string, data []byte) (interface{}, error) {
|
func (jsonProcessor *JsonProcessor) Unmarshal(clientId string, data []byte) (interface{}, error) {
|
||||||
typeStruct := struct {Type int `json:"typ"`}{}
|
typeStruct := struct {
|
||||||
|
Type int `json:"typ"`
|
||||||
|
}{}
|
||||||
err := json.Unmarshal(data, &typeStruct)
|
err := json.Unmarshal(data, &typeStruct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -68,7 +70,7 @@ func (jsonProcessor *JsonProcessor) Unmarshal(clientId string,data []byte) (inte
|
|||||||
msgType := uint16(typeStruct.Type)
|
msgType := uint16(typeStruct.Type)
|
||||||
info, ok := jsonProcessor.mapMsg[msgType]
|
info, ok := jsonProcessor.mapMsg[msgType]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return nil,fmt.Errorf("Cannot find register %d msgType!",msgType)
|
return nil, fmt.Errorf("cannot find register %d msgType", msgType)
|
||||||
}
|
}
|
||||||
|
|
||||||
msgData := reflect.New(info.msgType.Elem()).Interface()
|
msgData := reflect.New(info.msgType.Elem()).Interface()
|
||||||
@@ -89,12 +91,12 @@ func (jsonProcessor *JsonProcessor) Marshal(clientId string,msg interface{}) ([]
|
|||||||
return rawMsg, nil
|
return rawMsg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jsonProcessor *JsonProcessor) Register(msgtype uint16,msg interface{},handle MessageJsonHandler) {
|
func (jsonProcessor *JsonProcessor) Register(msgType uint16, msg interface{}, handle MessageJsonHandler) {
|
||||||
var info MessageJsonInfo
|
var info MessageJsonInfo
|
||||||
|
|
||||||
info.msgType = reflect.TypeOf(msg)
|
info.msgType = reflect.TypeOf(msg)
|
||||||
info.msgHandler = handle
|
info.msgHandler = handle
|
||||||
jsonProcessor.mapMsg[msgtype] = info
|
jsonProcessor.mapMsg[msgType] = info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jsonProcessor *JsonProcessor) MakeMsg(msgType uint16, msg interface{}) *JsonPackInfo {
|
func (jsonProcessor *JsonProcessor) MakeMsg(msgType uint16, msg interface{}) *JsonPackInfo {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type PBProcessor struct {
|
|||||||
unknownMessageHandler UnknownMessageHandler
|
unknownMessageHandler UnknownMessageHandler
|
||||||
connectHandler ConnectHandler
|
connectHandler ConnectHandler
|
||||||
disconnectHandler ConnectHandler
|
disconnectHandler ConnectHandler
|
||||||
bytespool.IBytesMempool
|
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.IBytesMempool = bytespool.NewMemAreaPool()
|
processor.IBytesMemPool = bytespool.NewMemAreaPool()
|
||||||
return processor
|
return processor
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,26 +53,26 @@ func (slf *PBPackInfo) GetMsg() proto.Message {
|
|||||||
return slf.msg
|
return slf.msg
|
||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// MsgRoute must goroutine safe
|
||||||
func (pbProcessor *PBProcessor) MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error {
|
func (pbProcessor *PBProcessor) MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error {
|
||||||
pPackInfo := msg.(*PBPackInfo)
|
pPackInfo := msg.(*PBPackInfo)
|
||||||
defer recyclerReaderBytes(pPackInfo.rawMsg)
|
defer recyclerReaderBytes(pPackInfo.rawMsg)
|
||||||
|
|
||||||
v, ok := pbProcessor.mapMsg[pPackInfo.typ]
|
v, ok := pbProcessor.mapMsg[pPackInfo.typ]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return fmt.Errorf("Cannot find msgtype %d is register!", pPackInfo.typ)
|
return fmt.Errorf("cannot find msgtype %d is register", pPackInfo.typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.msgHandler(clientId, pPackInfo.msg)
|
v.msgHandler(clientId, pPackInfo.msg)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// Unmarshal must goroutine safe
|
||||||
func (pbProcessor *PBProcessor) Unmarshal(clientId string, data []byte) (interface{}, error) {
|
func (pbProcessor *PBProcessor) Unmarshal(clientId string, data []byte) (interface{}, error) {
|
||||||
return pbProcessor.UnmarshalWithOutRelease(clientId, data)
|
return pbProcessor.UnmarshalWithOutRelease(clientId, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// unmarshal but not release data
|
// UnmarshalWithOutRelease not release data
|
||||||
func (pbProcessor *PBProcessor) UnmarshalWithOutRelease(clientId string, data []byte) (interface{}, error) {
|
func (pbProcessor *PBProcessor) UnmarshalWithOutRelease(clientId string, data []byte) (interface{}, error) {
|
||||||
var msgType uint16
|
var msgType uint16
|
||||||
if pbProcessor.LittleEndian == true {
|
if pbProcessor.LittleEndian == true {
|
||||||
@@ -83,7 +83,7 @@ func (pbProcessor *PBProcessor) UnmarshalWithOutRelease(clientId string, data []
|
|||||||
|
|
||||||
info, ok := pbProcessor.mapMsg[msgType]
|
info, ok := pbProcessor.mapMsg[msgType]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return nil, fmt.Errorf("cannot find register %d msgtype!", msgType)
|
return nil, fmt.Errorf("cannot find register %d msgtype", msgType)
|
||||||
}
|
}
|
||||||
msg := reflect.New(info.msgType.Elem()).Interface()
|
msg := reflect.New(info.msgType.Elem()).Interface()
|
||||||
protoMsg := msg.(proto.Message)
|
protoMsg := msg.(proto.Message)
|
||||||
@@ -95,7 +95,7 @@ func (pbProcessor *PBProcessor) UnmarshalWithOutRelease(clientId string, data []
|
|||||||
return &PBPackInfo{typ: msgType, msg: protoMsg, rawMsg: data}, nil
|
return &PBPackInfo{typ: msgType, msg: protoMsg, rawMsg: data}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// Marshal must goroutine safe
|
||||||
func (pbProcessor *PBProcessor) Marshal(clientId string, msg interface{}) ([]byte, error) {
|
func (pbProcessor *PBProcessor) Marshal(clientId string, msg interface{}) ([]byte, error) {
|
||||||
pMsg := msg.(*PBPackInfo)
|
pMsg := msg.(*PBPackInfo)
|
||||||
|
|
||||||
@@ -118,12 +118,12 @@ func (pbProcessor *PBProcessor) Marshal(clientId string, msg interface{}) ([]byt
|
|||||||
return buff, nil
|
return buff, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pbProcessor *PBProcessor) Register(msgtype uint16, msg proto.Message, handle MessageHandler) {
|
func (pbProcessor *PBProcessor) Register(msgType uint16, msg proto.Message, handle MessageHandler) {
|
||||||
var info MessageInfo
|
var info MessageInfo
|
||||||
|
|
||||||
info.msgType = reflect.TypeOf(msg.(proto.Message))
|
info.msgType = reflect.TypeOf(msg.(proto.Message))
|
||||||
info.msgHandler = handle
|
info.msgHandler = handle
|
||||||
pbProcessor.mapMsg[msgtype] = info
|
pbProcessor.mapMsg[msgType] = info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pbProcessor *PBProcessor) MakeMsg(msgType uint16, protoMsg proto.Message) *PBPackInfo {
|
func (pbProcessor *PBProcessor) MakeMsg(msgType uint16, protoMsg proto.Message) *PBPackInfo {
|
||||||
@@ -139,7 +139,6 @@ func (pbProcessor *PBProcessor) UnknownMsgRoute(clientId string, msg interface{}
|
|||||||
recyclerReaderBytes(msg.([]byte))
|
recyclerReaderBytes(msg.([]byte))
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect event
|
|
||||||
func (pbProcessor *PBProcessor) ConnectedRoute(clientId string) {
|
func (pbProcessor *PBProcessor) ConnectedRoute(clientId string) {
|
||||||
pbProcessor.connectHandler(clientId)
|
pbProcessor.connectHandler(clientId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ type RawConnectHandler func(clientId string)
|
|||||||
type UnknownRawMessageHandler func(clientId string, msg []byte)
|
type UnknownRawMessageHandler func(clientId string, msg []byte)
|
||||||
|
|
||||||
const RawMsgTypeSize = 2
|
const RawMsgTypeSize = 2
|
||||||
|
|
||||||
type PBRawProcessor struct {
|
type PBRawProcessor struct {
|
||||||
msgHandler RawMessageHandler
|
msgHandler RawMessageHandler
|
||||||
LittleEndian bool
|
LittleEndian bool
|
||||||
@@ -37,7 +38,7 @@ func (pbRawProcessor *PBRawProcessor) SetByteOrder(littleEndian bool) {
|
|||||||
pbRawProcessor.LittleEndian = littleEndian
|
pbRawProcessor.LittleEndian = littleEndian
|
||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// MsgRoute must goroutine safe
|
||||||
func (pbRawProcessor *PBRawProcessor) MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error {
|
func (pbRawProcessor *PBRawProcessor) MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error {
|
||||||
pPackInfo := msg.(*PBRawPackInfo)
|
pPackInfo := msg.(*PBRawPackInfo)
|
||||||
pbRawProcessor.msgHandler(clientId, pPackInfo.typ, pPackInfo.rawMsg)
|
pbRawProcessor.msgHandler(clientId, pPackInfo.typ, pPackInfo.rawMsg)
|
||||||
@@ -46,7 +47,7 @@ func (pbRawProcessor *PBRawProcessor ) MsgRoute(clientId string, msg interface{}
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// Unmarshal must goroutine safe
|
||||||
func (pbRawProcessor *PBRawProcessor) Unmarshal(clientId string, data []byte) (interface{}, error) {
|
func (pbRawProcessor *PBRawProcessor) Unmarshal(clientId string, data []byte) (interface{}, error) {
|
||||||
var msgType uint16
|
var msgType uint16
|
||||||
if pbRawProcessor.LittleEndian == true {
|
if pbRawProcessor.LittleEndian == true {
|
||||||
@@ -58,7 +59,7 @@ func (pbRawProcessor *PBRawProcessor ) Unmarshal(clientId string,data []byte) (i
|
|||||||
return &PBRawPackInfo{typ: msgType, rawMsg: data}, nil
|
return &PBRawPackInfo{typ: msgType, rawMsg: data}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// must goroutine safe
|
// Marshal must goroutine safe
|
||||||
func (pbRawProcessor *PBRawProcessor) Marshal(clientId string, msg interface{}) ([]byte, error) {
|
func (pbRawProcessor *PBRawProcessor) Marshal(clientId string, msg interface{}) ([]byte, error) {
|
||||||
pMsg := msg.(*PBRawPackInfo)
|
pMsg := msg.(*PBRawPackInfo)
|
||||||
|
|
||||||
@@ -90,7 +91,6 @@ func (pbRawProcessor *PBRawProcessor) UnknownMsgRoute(clientId string,msg interf
|
|||||||
pbRawProcessor.unknownMessageHandler(clientId, msg.([]byte))
|
pbRawProcessor.unknownMessageHandler(clientId, msg.([]byte))
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect event
|
|
||||||
func (pbRawProcessor *PBRawProcessor) ConnectedRoute(clientId string) {
|
func (pbRawProcessor *PBRawProcessor) ConnectedRoute(clientId string) {
|
||||||
pbRawProcessor.connectHandler(clientId)
|
pbRawProcessor.connectHandler(clientId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
package processor
|
package processor
|
||||||
|
|
||||||
|
|
||||||
type IProcessor interface {
|
type IProcessor interface {
|
||||||
// must goroutine safe
|
// MsgRoute must goroutine safe
|
||||||
MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error
|
MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error
|
||||||
//must goroutine safe
|
// UnknownMsgRoute must goroutine safe
|
||||||
UnknownMsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte))
|
UnknownMsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte))
|
||||||
// connect event
|
// ConnectedRoute connect event
|
||||||
ConnectedRoute(clientId string)
|
ConnectedRoute(clientId string)
|
||||||
DisConnectedRoute(clientId string)
|
DisConnectedRoute(clientId string)
|
||||||
|
|
||||||
// must goroutine safe
|
// Unmarshal must goroutine safe
|
||||||
Unmarshal(clientId string, data []byte) (interface{}, error)
|
Unmarshal(clientId string, data []byte) (interface{}, error)
|
||||||
// must goroutine safe
|
// Marshal must goroutine safe
|
||||||
Marshal(clientId string, msg interface{}) ([]byte, error)
|
Marshal(clientId string, msg interface{}) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,4 +25,3 @@ type IRawProcessor interface {
|
|||||||
SetConnectedHandler(connectHandler RawConnectHandler)
|
SetConnectedHandler(connectHandler RawConnectHandler)
|
||||||
SetDisConnectedHandler(disconnectHandler RawConnectHandler)
|
SetDisConnectedHandler(disconnectHandler RawConnectHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type TCPClient struct {
|
|||||||
ReadDeadline time.Duration
|
ReadDeadline time.Duration
|
||||||
WriteDeadline time.Duration
|
WriteDeadline time.Duration
|
||||||
AutoReconnect bool
|
AutoReconnect bool
|
||||||
NewAgent func(*TCPConn) Agent
|
NewAgent func(conn *NetConn) Agent
|
||||||
cons ConnSet
|
cons ConnSet
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
closeFlag bool
|
closeFlag bool
|
||||||
@@ -74,7 +74,7 @@ func (client *TCPClient) init() {
|
|||||||
if client.LenMsgLen == 0 {
|
if client.LenMsgLen == 0 {
|
||||||
client.LenMsgLen = Default_LenMsgLen
|
client.LenMsgLen = Default_LenMsgLen
|
||||||
}
|
}
|
||||||
maxMsgLen := client.MsgParser.getMaxMsgLen(client.LenMsgLen)
|
maxMsgLen := client.MsgParser.getMaxMsgLen()
|
||||||
if client.MaxMsgLen > maxMsgLen {
|
if client.MaxMsgLen > maxMsgLen {
|
||||||
client.MaxMsgLen = maxMsgLen
|
client.MaxMsgLen = maxMsgLen
|
||||||
log.Info("invalid MaxMsgLen", log.Uint32("reset", maxMsgLen))
|
log.Info("invalid MaxMsgLen", log.Uint32("reset", maxMsgLen))
|
||||||
@@ -82,7 +82,7 @@ func (client *TCPClient) init() {
|
|||||||
|
|
||||||
client.cons = make(ConnSet)
|
client.cons = make(ConnSet)
|
||||||
client.closeFlag = false
|
client.closeFlag = false
|
||||||
client.MsgParser.init()
|
client.MsgParser.Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *TCPClient) GetCloseFlag() bool {
|
func (client *TCPClient) GetCloseFlag() bool {
|
||||||
@@ -102,7 +102,7 @@ func (client *TCPClient) dial() net.Conn {
|
|||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Warning("connect error ",log.String("error",err.Error()), log.String("Addr",client.Addr))
|
log.Warn("connect error ", log.String("error", err.Error()), log.String("Addr", client.Addr))
|
||||||
time.Sleep(client.ConnectInterval)
|
time.Sleep(client.ConnectInterval)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ reconnect:
|
|||||||
client.cons[conn] = struct{}{}
|
client.cons[conn] = struct{}{}
|
||||||
client.Unlock()
|
client.Unlock()
|
||||||
|
|
||||||
tcpConn := newTCPConn(conn, client.PendingWriteNum, &client.MsgParser,client.WriteDeadline)
|
tcpConn := newNetConn(conn, client.PendingWriteNum, &client.MsgParser, client.WriteDeadline)
|
||||||
agent := client.NewAgent(tcpConn)
|
agent := client.NewAgent(tcpConn)
|
||||||
agent.Run()
|
agent.Run()
|
||||||
|
|
||||||
@@ -156,4 +156,3 @@ func (client *TCPClient) Close(waitDone bool) {
|
|||||||
client.wg.Wait()
|
client.wg.Wait()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,169 +0,0 @@
|
|||||||
package network
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
|
||||||
"net"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ConnSet map[net.Conn]struct{}
|
|
||||||
|
|
||||||
type TCPConn struct {
|
|
||||||
sync.Mutex
|
|
||||||
conn net.Conn
|
|
||||||
writeChan chan []byte
|
|
||||||
closeFlag int32
|
|
||||||
msgParser *MsgParser
|
|
||||||
}
|
|
||||||
|
|
||||||
func freeChannel(conn *TCPConn){
|
|
||||||
for;len(conn.writeChan)>0;{
|
|
||||||
byteBuff := <- conn.writeChan
|
|
||||||
if byteBuff != nil {
|
|
||||||
conn.ReleaseReadMsg(byteBuff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTCPConn(conn net.Conn, pendingWriteNum int, msgParser *MsgParser,writeDeadline time.Duration) *TCPConn {
|
|
||||||
tcpConn := new(TCPConn)
|
|
||||||
tcpConn.conn = conn
|
|
||||||
tcpConn.writeChan = make(chan []byte, pendingWriteNum)
|
|
||||||
tcpConn.msgParser = msgParser
|
|
||||||
go func() {
|
|
||||||
for b := range tcpConn.writeChan {
|
|
||||||
if b == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.SetWriteDeadline(time.Now().Add(writeDeadline))
|
|
||||||
_, err := conn.Write(b)
|
|
||||||
tcpConn.msgParser.ReleaseBytes(b)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conn.Close()
|
|
||||||
tcpConn.Lock()
|
|
||||||
freeChannel(tcpConn)
|
|
||||||
atomic.StoreInt32(&tcpConn.closeFlag,1)
|
|
||||||
tcpConn.Unlock()
|
|
||||||
}()
|
|
||||||
|
|
||||||
return tcpConn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) doDestroy() {
|
|
||||||
tcpConn.conn.(*net.TCPConn).SetLinger(0)
|
|
||||||
tcpConn.conn.Close()
|
|
||||||
|
|
||||||
if atomic.LoadInt32(&tcpConn.closeFlag)==0 {
|
|
||||||
close(tcpConn.writeChan)
|
|
||||||
atomic.StoreInt32(&tcpConn.closeFlag,1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) Destroy() {
|
|
||||||
tcpConn.Lock()
|
|
||||||
defer tcpConn.Unlock()
|
|
||||||
|
|
||||||
tcpConn.doDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) Close() {
|
|
||||||
tcpConn.Lock()
|
|
||||||
defer tcpConn.Unlock()
|
|
||||||
if atomic.LoadInt32(&tcpConn.closeFlag)==1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tcpConn.doWrite(nil)
|
|
||||||
atomic.StoreInt32(&tcpConn.closeFlag,1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) GetRemoteIp() string {
|
|
||||||
return tcpConn.conn.RemoteAddr().String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) doWrite(b []byte) error{
|
|
||||||
if len(tcpConn.writeChan) == cap(tcpConn.writeChan) {
|
|
||||||
tcpConn.ReleaseReadMsg(b)
|
|
||||||
log.Error("close conn: channel full")
|
|
||||||
tcpConn.doDestroy()
|
|
||||||
return errors.New("close conn: channel full")
|
|
||||||
}
|
|
||||||
|
|
||||||
tcpConn.writeChan <- b
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// b must not be modified by the others goroutines
|
|
||||||
func (tcpConn *TCPConn) Write(b []byte) error{
|
|
||||||
tcpConn.Lock()
|
|
||||||
defer tcpConn.Unlock()
|
|
||||||
if atomic.LoadInt32(&tcpConn.closeFlag)==1 || b == nil {
|
|
||||||
tcpConn.ReleaseReadMsg(b)
|
|
||||||
return errors.New("conn is close")
|
|
||||||
}
|
|
||||||
|
|
||||||
return tcpConn.doWrite(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) Read(b []byte) (int, error) {
|
|
||||||
return tcpConn.conn.Read(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) LocalAddr() net.Addr {
|
|
||||||
return tcpConn.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) RemoteAddr() net.Addr {
|
|
||||||
return tcpConn.conn.RemoteAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) ReadMsg() ([]byte, error) {
|
|
||||||
return tcpConn.msgParser.Read(tcpConn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) GetRecyclerReaderBytes() func (data []byte) {
|
|
||||||
bytePool := tcpConn.msgParser.IBytesMempool
|
|
||||||
return func(data []byte) {
|
|
||||||
bytePool.ReleaseBytes(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) ReleaseReadMsg(byteBuff []byte){
|
|
||||||
tcpConn.msgParser.ReleaseBytes(byteBuff)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) WriteMsg(args ...[]byte) error {
|
|
||||||
if atomic.LoadInt32(&tcpConn.closeFlag) == 1 {
|
|
||||||
return errors.New("conn is close")
|
|
||||||
}
|
|
||||||
return tcpConn.msgParser.Write(tcpConn, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) WriteRawMsg(args []byte) error {
|
|
||||||
if atomic.LoadInt32(&tcpConn.closeFlag) == 1 {
|
|
||||||
return errors.New("conn is close")
|
|
||||||
}
|
|
||||||
|
|
||||||
return tcpConn.Write(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) IsConnected() bool {
|
|
||||||
return atomic.LoadInt32(&tcpConn.closeFlag) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) SetReadDeadline(d time.Duration) {
|
|
||||||
tcpConn.conn.SetReadDeadline(time.Now().Add(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tcpConn *TCPConn) SetWriteDeadline(d time.Duration) {
|
|
||||||
tcpConn.conn.SetWriteDeadline(time.Now().Add(d))
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
// --------------
|
// MsgParser --------------
|
||||||
// | len | data |
|
// | len | data |
|
||||||
// --------------
|
// --------------
|
||||||
type MsgParser struct {
|
type MsgParser struct {
|
||||||
@@ -17,11 +17,10 @@ type MsgParser struct {
|
|||||||
MaxMsgLen uint32
|
MaxMsgLen uint32
|
||||||
LittleEndian bool
|
LittleEndian bool
|
||||||
|
|
||||||
bytespool.IBytesMempool
|
bytespool.IBytesMemPool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *MsgParser) getMaxMsgLen() uint32 {
|
||||||
func (p *MsgParser) getMaxMsgLen(lenMsgLen int) uint32 {
|
|
||||||
switch p.LenMsgLen {
|
switch p.LenMsgLen {
|
||||||
case 1:
|
case 1:
|
||||||
return math.MaxUint8
|
return math.MaxUint8
|
||||||
@@ -34,17 +33,17 @@ func (p *MsgParser) getMaxMsgLen(lenMsgLen int) uint32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *MsgParser) init(){
|
func (p *MsgParser) Init() {
|
||||||
p.IBytesMempool = bytespool.NewMemAreaPool()
|
p.IBytesMemPool = bytespool.NewMemAreaPool()
|
||||||
}
|
}
|
||||||
|
|
||||||
// goroutine safe
|
// goroutine safe
|
||||||
func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) {
|
func (p *MsgParser) Read(r io.Reader) ([]byte, error) {
|
||||||
var b [4]byte
|
var b [4]byte
|
||||||
bufMsgLen := b[:p.LenMsgLen]
|
bufMsgLen := b[:p.LenMsgLen]
|
||||||
|
|
||||||
// read len
|
// read len
|
||||||
if _, err := io.ReadFull(conn, bufMsgLen); err != nil {
|
if _, err := io.ReadFull(r, bufMsgLen); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +75,7 @@ func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) {
|
|||||||
|
|
||||||
// data
|
// data
|
||||||
msgData := p.MakeBytes(int(msgLen))
|
msgData := p.MakeBytes(int(msgLen))
|
||||||
if _, err := io.ReadFull(conn, msgData[:msgLen]); err != nil {
|
if _, err := io.ReadFull(r, msgData[:msgLen]); err != nil {
|
||||||
p.ReleaseBytes(msgData)
|
p.ReleaseBytes(msgData)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -85,7 +84,7 @@ func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// goroutine safe
|
// goroutine safe
|
||||||
func (p *MsgParser) Write(conn *TCPConn, args ...[]byte) error {
|
func (p *MsgParser) Write(conn io.Writer, args ...[]byte) error {
|
||||||
// get len
|
// get len
|
||||||
var msgLen uint32
|
var msgLen uint32
|
||||||
for i := 0; i < len(args); i++ {
|
for i := 0; i < len(args); i++ {
|
||||||
@@ -130,3 +129,9 @@ func (p *MsgParser) Write(conn *TCPConn, args ...[]byte) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *MsgParser) GetRecyclerReaderBytes() func(data []byte) {
|
||||||
|
return func(data []byte) {
|
||||||
|
p.IBytesMemPool.ReleaseBytes(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/v2/util/bytespool"
|
"github.com/duanhf2012/origin/v2/util/bytespool"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
"fmt"
|
|
||||||
"errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -15,7 +15,6 @@ const(
|
|||||||
Default_WriteDeadline = time.Second * 30 //默认写超时30s
|
Default_WriteDeadline = time.Second * 30 //默认写超时30s
|
||||||
Default_MaxConnNum = 1000000 //默认最大连接数
|
Default_MaxConnNum = 1000000 //默认最大连接数
|
||||||
Default_PendingWriteNum = 100000 //单连接写消息Channel容量
|
Default_PendingWriteNum = 100000 //单连接写消息Channel容量
|
||||||
Default_LittleEndian = false //默认大小端
|
|
||||||
Default_MinMsgLen = 2 //最小消息长度2byte
|
Default_MinMsgLen = 2 //最小消息长度2byte
|
||||||
Default_LenMsgLen = 2 //包头字段长度占用2byte
|
Default_LenMsgLen = 2 //包头字段长度占用2byte
|
||||||
Default_MaxMsgLen = 65535 //最大消息长度
|
Default_MaxMsgLen = 65535 //最大消息长度
|
||||||
@@ -28,7 +27,7 @@ type TCPServer struct {
|
|||||||
ReadDeadline time.Duration
|
ReadDeadline time.Duration
|
||||||
WriteDeadline time.Duration
|
WriteDeadline time.Duration
|
||||||
|
|
||||||
NewAgent func(*TCPConn) Agent
|
NewAgent func(conn Conn) Agent
|
||||||
ln net.Listener
|
ln net.Listener
|
||||||
conns ConnSet
|
conns ConnSet
|
||||||
mutexConns sync.Mutex
|
mutexConns sync.Mutex
|
||||||
@@ -43,6 +42,8 @@ func (server *TCPServer) Start() error{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server.wgLn.Add(1)
|
||||||
go server.run()
|
go server.run()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -51,7 +52,7 @@ func (server *TCPServer) Start() error{
|
|||||||
func (server *TCPServer) init() error {
|
func (server *TCPServer) init() error {
|
||||||
ln, err := net.Listen("tcp", server.Addr)
|
ln, err := net.Listen("tcp", server.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Listen tcp fail,error:%s",err.Error())
|
return fmt.Errorf("listen tcp fail,error:%s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.MaxConnNum <= 0 {
|
if server.MaxConnNum <= 0 {
|
||||||
@@ -74,7 +75,7 @@ func (server *TCPServer) init() error{
|
|||||||
log.Info("invalid MaxMsgLen", log.Uint32("reset to", server.MaxMsgLen))
|
log.Info("invalid MaxMsgLen", log.Uint32("reset to", server.MaxMsgLen))
|
||||||
}
|
}
|
||||||
|
|
||||||
maxMsgLen := server.MsgParser.getMaxMsgLen(server.LenMsgLen)
|
maxMsgLen := server.MsgParser.getMaxMsgLen()
|
||||||
if server.MaxMsgLen > maxMsgLen {
|
if server.MaxMsgLen > maxMsgLen {
|
||||||
server.MaxMsgLen = maxMsgLen
|
server.MaxMsgLen = maxMsgLen
|
||||||
log.Info("invalid MaxMsgLen", log.Uint32("reset", maxMsgLen))
|
log.Info("invalid MaxMsgLen", log.Uint32("reset", maxMsgLen))
|
||||||
@@ -100,44 +101,44 @@ func (server *TCPServer) init() error{
|
|||||||
}
|
}
|
||||||
|
|
||||||
server.ln = ln
|
server.ln = ln
|
||||||
server.conns = make(ConnSet)
|
server.conns = make(ConnSet, 2048)
|
||||||
server.MsgParser.init()
|
server.MsgParser.Init()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TCPServer) SetNetMempool(mempool bytespool.IBytesMempool){
|
func (server *TCPServer) SetNetMemPool(memPool bytespool.IBytesMemPool) {
|
||||||
server.IBytesMempool = mempool
|
server.IBytesMemPool = memPool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TCPServer) GetNetMempool() bytespool.IBytesMempool {
|
func (server *TCPServer) GetNetMemPool() bytespool.IBytesMemPool {
|
||||||
return server.IBytesMempool
|
return server.IBytesMemPool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TCPServer) run() {
|
func (server *TCPServer) run() {
|
||||||
server.wgLn.Add(1)
|
|
||||||
defer server.wgLn.Done()
|
defer server.wgLn.Done()
|
||||||
|
|
||||||
var tempDelay time.Duration
|
var tempDelay time.Duration
|
||||||
for {
|
for {
|
||||||
conn, err := server.ln.Accept()
|
conn, err := server.ln.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ne, ok := err.(net.Error); ok && ne.Temporary() {
|
var ne net.Error
|
||||||
|
if errors.As(err, &ne) && ne.Timeout() {
|
||||||
if tempDelay == 0 {
|
if tempDelay == 0 {
|
||||||
tempDelay = 5 * time.Millisecond
|
tempDelay = 5 * time.Millisecond
|
||||||
} else {
|
} else {
|
||||||
tempDelay *= 2
|
tempDelay *= 2
|
||||||
}
|
}
|
||||||
if max := 1 * time.Second; tempDelay > max {
|
|
||||||
tempDelay = max
|
|
||||||
}
|
|
||||||
log.Info("accept fail", log.String("error", err.Error()), log.Duration("sleep time", tempDelay))
|
log.Info("accept fail", log.String("error", err.Error()), log.Duration("sleep time", tempDelay))
|
||||||
|
tempDelay = min(1*time.Second, tempDelay)
|
||||||
time.Sleep(tempDelay)
|
time.Sleep(tempDelay)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conn.(*net.TCPConn).SetLinger(0)
|
||||||
conn.(*net.TCPConn).SetNoDelay(true)
|
conn.(*net.TCPConn).SetNoDelay(true)
|
||||||
tempDelay = 0
|
tempDelay = 0
|
||||||
|
|
||||||
@@ -145,7 +146,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.Warning("too many connections")
|
log.Warn("too many connections")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +154,7 @@ func (server *TCPServer) run() {
|
|||||||
server.mutexConns.Unlock()
|
server.mutexConns.Unlock()
|
||||||
server.wgConns.Add(1)
|
server.wgConns.Add(1)
|
||||||
|
|
||||||
tcpConn := newTCPConn(conn, server.PendingWriteNum, &server.MsgParser,server.WriteDeadline)
|
tcpConn := newNetConn(conn, server.PendingWriteNum, &server.MsgParser, server.WriteDeadline)
|
||||||
agent := server.NewAgent(tcpConn)
|
agent := server.NewAgent(tcpConn)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ reconnect:
|
|||||||
client.cons[conn] = struct{}{}
|
client.cons[conn] = struct{}{}
|
||||||
client.Unlock()
|
client.Unlock()
|
||||||
|
|
||||||
wsConn := newWSConn(conn, client.PendingWriteNum, client.MaxMsgLen,client.MessageType)
|
wsConn := newWSConn(conn,nil, client.PendingWriteNum, client.MaxMsgLen,client.MessageType)
|
||||||
agent := client.NewAgent(wsConn)
|
agent := client.NewAgent(wsConn)
|
||||||
agent.Run()
|
agent.Run()
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,13 +17,15 @@ type WSConn struct {
|
|||||||
writeChan chan []byte
|
writeChan chan []byte
|
||||||
maxMsgLen uint32
|
maxMsgLen uint32
|
||||||
closeFlag bool
|
closeFlag bool
|
||||||
|
header http.Header
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWSConn(conn *websocket.Conn, pendingWriteNum int, maxMsgLen uint32,messageType int) *WSConn {
|
func newWSConn(conn *websocket.Conn, header http.Header, pendingWriteNum int, maxMsgLen uint32, messageType int) *WSConn {
|
||||||
wsConn := new(WSConn)
|
wsConn := new(WSConn)
|
||||||
wsConn.conn = conn
|
wsConn.conn = conn
|
||||||
wsConn.writeChan = make(chan []byte, pendingWriteNum)
|
wsConn.writeChan = make(chan []byte, pendingWriteNum)
|
||||||
wsConn.maxMsgLen = maxMsgLen
|
wsConn.maxMsgLen = maxMsgLen
|
||||||
|
wsConn.header = header
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for b := range wsConn.writeChan {
|
for b := range wsConn.writeChan {
|
||||||
@@ -46,7 +49,6 @@ func newWSConn(conn *websocket.Conn, pendingWriteNum int, maxMsgLen uint32,messa
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (wsConn *WSConn) doDestroy() {
|
func (wsConn *WSConn) doDestroy() {
|
||||||
wsConn.conn.UnderlyingConn().(*net.TCPConn).SetLinger(0)
|
|
||||||
wsConn.conn.Close()
|
wsConn.conn.Close()
|
||||||
|
|
||||||
if !wsConn.closeFlag {
|
if !wsConn.closeFlag {
|
||||||
@@ -83,6 +85,10 @@ func (wsConn *WSConn) doWrite(b []byte) {
|
|||||||
wsConn.writeChan <- b
|
wsConn.writeChan <- b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (wsConn *WSConn) GetHeader() http.Header {
|
||||||
|
return wsConn.header
|
||||||
|
}
|
||||||
|
|
||||||
func (wsConn *WSConn) LocalAddr() net.Addr {
|
func (wsConn *WSConn) LocalAddr() net.Addr {
|
||||||
return wsConn.conn.LocalAddr()
|
return wsConn.conn.LocalAddr()
|
||||||
}
|
}
|
||||||
@@ -91,13 +97,13 @@ func (wsConn *WSConn) RemoteAddr() net.Addr {
|
|||||||
return wsConn.conn.RemoteAddr()
|
return wsConn.conn.RemoteAddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
// goroutine not safe
|
// ReadMsg goroutine not safe
|
||||||
func (wsConn *WSConn) ReadMsg() ([]byte, error) {
|
func (wsConn *WSConn) ReadMsg() ([]byte, error) {
|
||||||
_, b, err := wsConn.conn.ReadMessage()
|
_, b, err := wsConn.conn.ReadMessage()
|
||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// args must not be modified by the others goroutines
|
// WriteMsg args must not be modified by the others goroutines
|
||||||
func (wsConn *WSConn) WriteMsg(args ...[]byte) error {
|
func (wsConn *WSConn) WriteMsg(args ...[]byte) error {
|
||||||
wsConn.Lock()
|
wsConn.Lock()
|
||||||
defer wsConn.Unlock()
|
defer wsConn.Unlock()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package network
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"net"
|
"net"
|
||||||
@@ -67,13 +68,15 @@ 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.Warning("too many connections")
|
log.Warn("too many connections")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handler.conns[conn] = struct{}{}
|
handler.conns[conn] = struct{}{}
|
||||||
handler.mutexConns.Unlock()
|
handler.mutexConns.Unlock()
|
||||||
|
|
||||||
wsConn := newWSConn(conn, handler.pendingWriteNum, handler.maxMsgLen, handler.messageType)
|
conn.UnderlyingConn().(*net.TCPConn).SetLinger(0)
|
||||||
|
conn.UnderlyingConn().(*net.TCPConn).SetNoDelay(true)
|
||||||
|
wsConn := newWSConn(conn, r.Header, handler.pendingWriteNum, handler.maxMsgLen, handler.messageType)
|
||||||
agent := handler.newAgent(wsConn)
|
agent := handler.newAgent(wsConn)
|
||||||
agent.Run()
|
agent.Run()
|
||||||
|
|
||||||
@@ -92,10 +95,11 @@ func (server *WSServer) SetMessageType(messageType int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *WSServer) Start() {
|
func (server *WSServer) Start() error {
|
||||||
ln, err := net.Listen("tcp", server.Addr)
|
ln, err := net.Listen("tcp", server.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("WSServer Listen fail",log.String("error", err.Error()))
|
log.Error("WSServer Listen fail", log.String("error", err.Error()))
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.MaxConnNum <= 0 {
|
if server.MaxConnNum <= 0 {
|
||||||
@@ -115,18 +119,19 @@ func (server *WSServer) Start() {
|
|||||||
log.Info("invalid HTTPTimeout", log.Duration("reset", server.HTTPTimeout))
|
log.Info("invalid HTTPTimeout", log.Duration("reset", server.HTTPTimeout))
|
||||||
}
|
}
|
||||||
if server.NewAgent == nil {
|
if server.NewAgent == nil {
|
||||||
log.Fatal("NewAgent must not be nil")
|
log.Error("NewAgent must not be nil")
|
||||||
|
return errors.New("NewAgent must not be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.CertFile != "" || server.KeyFile != "" {
|
if server.CertFile != "" || server.KeyFile != "" {
|
||||||
config := &tls.Config{}
|
config := &tls.Config{}
|
||||||
config.NextProtos = []string{"http/1.1"}
|
config.NextProtos = []string{"http/1.1"}
|
||||||
|
|
||||||
var err error
|
|
||||||
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.Fatal("LoadX509KeyPair fail",log.String("error", err.Error()))
|
log.Error("LoadX509KeyPair fail", log.String("error", err.Error()))
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ln = tls.NewListener(ln, config)
|
ln = tls.NewListener(ln, config)
|
||||||
@@ -155,6 +160,7 @@ func (server *WSServer) Start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
go httpServer.Serve(ln)
|
go httpServer.Serve(ln)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *WSServer) Close() {
|
func (server *WSServer) Close() {
|
||||||
|
|||||||
134
node/node.go
134
node/node.go
@@ -9,17 +9,19 @@ import (
|
|||||||
"github.com/duanhf2012/origin/v2/profiler"
|
"github.com/duanhf2012/origin/v2/profiler"
|
||||||
"github.com/duanhf2012/origin/v2/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/duanhf2012/origin/v2/util/buildtime"
|
"github.com/duanhf2012/origin/v2/util/buildtime"
|
||||||
|
"github.com/duanhf2012/origin/v2/util/sysprocess"
|
||||||
"github.com/duanhf2012/origin/v2/util/timer"
|
"github.com/duanhf2012/origin/v2/util/timer"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"github.com/duanhf2012/origin/v2/util/sysprocess"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var sig chan os.Signal
|
var sig chan os.Signal
|
||||||
@@ -27,7 +29,6 @@ var nodeId string
|
|||||||
var preSetupService []service.IService //预安装
|
var preSetupService []service.IService //预安装
|
||||||
var preSetupTemplateService []func() service.IService
|
var preSetupTemplateService []func() service.IService
|
||||||
var profilerInterval time.Duration
|
var profilerInterval time.Duration
|
||||||
var bValid bool
|
|
||||||
var configDir = "./config/"
|
var configDir = "./config/"
|
||||||
var NodeIsRun = false
|
var NodeIsRun = false
|
||||||
|
|
||||||
@@ -55,14 +56,12 @@ func init() {
|
|||||||
console.RegisterCommandString("retire", "", "<-retire nodeid=nodeid> retire originserver process.", retireNode)
|
console.RegisterCommandString("retire", "", "<-retire nodeid=nodeid> retire originserver process.", retireNode)
|
||||||
console.RegisterCommandString("config", "", "<-config path> Configuration file path.", setConfigPath)
|
console.RegisterCommandString("config", "", "<-config path> Configuration file path.", setConfigPath)
|
||||||
console.RegisterCommandString("console", "", "<-console true|false> Turn on or off screen log output.", openConsole)
|
console.RegisterCommandString("console", "", "<-console true|false> Turn on or off screen log output.", openConsole)
|
||||||
console.RegisterCommandString("loglevel", "debug", "<-loglevel debug|release|warning|error|fatal> Set loglevel.", setLevel)
|
console.RegisterCommandString("loglevel", "debug", "<-loglevel debug|info|warn|error|stackerror|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("logsize", 0, "<-logsize size> Set log size(MB).", setLogSize)
|
||||||
console.RegisterCommandInt("logchannelcap", -1, "<-logchannelcap num> Set log channel cap.", setLogChannelCapNum)
|
|
||||||
console.RegisterCommandString("pprof", "", "<-pprof ip:port> Open performance analysis.", setPprof)
|
console.RegisterCommandString("pprof", "", "<-pprof ip:port> Open performance analysis.", setPprof)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func notifyAllServiceRetire() {
|
func notifyAllServiceRetire() {
|
||||||
service.NotifyAllServiceRetire()
|
service.NotifyAllServiceRetire()
|
||||||
}
|
}
|
||||||
@@ -83,7 +82,7 @@ func usage(val interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setName(val interface{}) error {
|
func setName(_ interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +109,7 @@ func setConfigPath(val interface{}) error {
|
|||||||
}
|
}
|
||||||
_, err := os.Stat(configPath)
|
_, err := os.Stat(configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Cannot find file path %s", configPath)
|
return fmt.Errorf("cannot find file path %s", configPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster.SetConfigDir(configPath)
|
cluster.SetConfigDir(configPath)
|
||||||
@@ -158,12 +157,14 @@ func initNode(id string) {
|
|||||||
nodeId = id
|
nodeId = id
|
||||||
err := cluster.GetCluster().Init(GetNodeId(), Setup)
|
err := cluster.GetCluster().Init(GetNodeId(), Setup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Init cluster fail",log.ErrorAttr("error",err))
|
log.Error("Init cluster fail", log.ErrorField("error", err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = initLog()
|
err = initLog()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("Init log fail", log.ErrorField("error", err))
|
||||||
|
os.Exit(1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,22 +214,25 @@ func initNode(id string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//3.service初始化
|
//3.service初始化
|
||||||
|
log.Info("Start running server.")
|
||||||
service.Init()
|
service.Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
func initLog() error {
|
func initLog() error {
|
||||||
if log.LogPath == "" {
|
logger := log.GetLogger()
|
||||||
setLogPath("./log")
|
if logger.LogPath == "" {
|
||||||
}
|
err := setLogPath("./log")
|
||||||
|
|
||||||
localnodeinfo := cluster.GetCluster().GetLocalNodeInfo()
|
|
||||||
filepre := fmt.Sprintf("%s_", localnodeinfo.NodeId)
|
|
||||||
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")
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.SetLogger(logger)
|
}
|
||||||
|
|
||||||
|
localNodeInfo := cluster.GetCluster().GetLocalNodeInfo()
|
||||||
|
fileName := fmt.Sprintf("%s.log", localNodeInfo.NodeId)
|
||||||
|
logger.FileName = fileName
|
||||||
|
logger.LogConfig.Filename = filepath.Join(logger.LogPath, logger.FileName)
|
||||||
|
|
||||||
|
logger.Init()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +244,6 @@ func Start() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func retireNode(args interface{}) error {
|
func retireNode(args interface{}) error {
|
||||||
//1.解析参数
|
//1.解析参数
|
||||||
param := args.(string)
|
param := args.(string)
|
||||||
@@ -265,12 +268,10 @@ func retireNode(args interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RetireProcess(processId)
|
RetireProcess(processId)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func stopNode(args interface{}) error {
|
func stopNode(args interface{}) error {
|
||||||
//1.解析参数
|
//1.解析参数
|
||||||
param := args.(string)
|
param := args.(string)
|
||||||
@@ -328,34 +329,37 @@ func startNode(args interface{}) error {
|
|||||||
myName, mErr := sysprocess.GetMyProcessName()
|
myName, mErr := sysprocess.GetMyProcessName()
|
||||||
//当前进程名获取失败,不应该发生
|
//当前进程名获取失败,不应该发生
|
||||||
if mErr != nil {
|
if mErr != nil {
|
||||||
log.Info("get my process's name is error",log.ErrorAttr("err", mErr))
|
log.Error("get my process's name is error", log.ErrorField("err", mErr))
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
//进程id存在,而且进程名也相同,被认为是当前进程重复运行
|
//进程id存在,而且进程名也相同,被认为是当前进程重复运行
|
||||||
if cErr == nil && name == myName {
|
if cErr == nil && name == myName {
|
||||||
log.Info("repeat runs are not allowed",log.String("nodeId",strNodeId),log.Int("processId",processId))
|
log.Error("repeat runs are not allowed", log.String("nodeId", strNodeId), log.Int("processId", processId))
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
//2.记录进程id号
|
//2.记录进程id号
|
||||||
log.Info("Start running server.")
|
|
||||||
writeProcessPid(strNodeId)
|
writeProcessPid(strNodeId)
|
||||||
timer.StartTimer(10*time.Millisecond, 1000000)
|
timer.StartTimer(10*time.Millisecond, 1000000)
|
||||||
|
|
||||||
//3.初始化node
|
//3.初始化node
|
||||||
|
defer log.GetLogger().Logger.Sync()
|
||||||
initNode(strNodeId)
|
initNode(strNodeId)
|
||||||
|
|
||||||
//4.运行service
|
//4.运行service
|
||||||
service.Start()
|
service.Start()
|
||||||
|
|
||||||
//5.运行集群
|
//5.运行集群
|
||||||
cluster.GetCluster().Start()
|
err := cluster.GetCluster().Start()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
|
||||||
//6.监听程序退出信号&性能报告
|
//6.监听程序退出信号&性能报告
|
||||||
|
|
||||||
var pProfilerTicker *time.Ticker = &time.Ticker{}
|
var pProfilerTicker *time.Ticker = &time.Ticker{}
|
||||||
if profilerInterval > 0 {
|
if profilerInterval > 0 {
|
||||||
pProfilerTicker = time.NewTicker(profilerInterval)
|
pProfilerTicker = time.NewTicker(profilerInterval)
|
||||||
@@ -378,16 +382,20 @@ func startNode(args interface{}) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//7.退出
|
//7.退出
|
||||||
service.StopAllService()
|
service.StopAllService()
|
||||||
cluster.GetCluster().Stop()
|
cluster.GetCluster().Stop()
|
||||||
|
|
||||||
log.Info("Server is stop.")
|
log.Info("Server is stop.")
|
||||||
log.Close()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type templateServicePoint[T any] interface {
|
||||||
|
*T
|
||||||
|
service.IService
|
||||||
|
}
|
||||||
|
|
||||||
func Setup(s ...service.IService) {
|
func Setup(s ...service.IService) {
|
||||||
for _, sv := range s {
|
for _, sv := range s {
|
||||||
sv.OnSetup(sv)
|
sv.OnSetup(sv)
|
||||||
@@ -395,12 +403,19 @@ func Setup(s ...service.IService) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetupTemplate(fs ...func()service.IService){
|
func SetupTemplateFunc(fs ...func() service.IService) {
|
||||||
for _, f := range fs {
|
for _, f := range fs {
|
||||||
preSetupTemplateService = append(preSetupTemplateService, f)
|
preSetupTemplateService = append(preSetupTemplateService, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetupTemplate[T any, P templateServicePoint[T]]() {
|
||||||
|
SetupTemplateFunc(func() service.IService {
|
||||||
|
var t T
|
||||||
|
return P(&t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func GetService(serviceName string) service.IService {
|
func GetService(serviceName string) service.IService {
|
||||||
return service.GetService(serviceName)
|
return service.GetService(serviceName)
|
||||||
}
|
}
|
||||||
@@ -424,11 +439,13 @@ func openConsole(args interface{}) error {
|
|||||||
}
|
}
|
||||||
strOpen := strings.ToLower(strings.TrimSpace(args.(string)))
|
strOpen := strings.ToLower(strings.TrimSpace(args.(string)))
|
||||||
if strOpen == "false" {
|
if strOpen == "false" {
|
||||||
log.OpenConsole = false
|
bOpenConsole := false
|
||||||
|
log.GetLogger().OpenConsole = &bOpenConsole
|
||||||
} else if strOpen == "true" {
|
} else if strOpen == "true" {
|
||||||
log.OpenConsole = true
|
bOpenConsole := true
|
||||||
|
log.GetLogger().OpenConsole = &bOpenConsole
|
||||||
} else {
|
} else {
|
||||||
return errors.New("Parameter console error!")
|
return errors.New("parameter console error")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -440,20 +457,18 @@ func setLevel(args interface{}) error {
|
|||||||
|
|
||||||
strlogLevel := strings.TrimSpace(args.(string))
|
strlogLevel := strings.TrimSpace(args.(string))
|
||||||
switch strlogLevel {
|
switch strlogLevel {
|
||||||
case "trace":
|
|
||||||
log.LogLevel = log.LevelTrace
|
|
||||||
case "debug":
|
case "debug":
|
||||||
log.LogLevel = log.LevelDebug
|
log.GetLogger().LogLevel = zapcore.DebugLevel
|
||||||
case "info":
|
case "info":
|
||||||
log.LogLevel = log.LevelInfo
|
log.GetLogger().LogLevel = zapcore.InfoLevel
|
||||||
case "warning":
|
case "warn":
|
||||||
log.LogLevel = log.LevelWarning
|
log.GetLogger().LogLevel = zapcore.WarnLevel
|
||||||
case "error":
|
case "error":
|
||||||
log.LogLevel = log.LevelError
|
log.GetLogger().LogLevel = zapcore.ErrorLevel
|
||||||
case "stack":
|
case "stackerror":
|
||||||
log.LogLevel = log.LevelStack
|
log.GetLogger().LogLevel = zapcore.ErrorLevel
|
||||||
case "fatal":
|
case "fatal":
|
||||||
log.LogLevel = log.LevelFatal
|
log.GetLogger().LogLevel = zapcore.FatalLevel
|
||||||
default:
|
default:
|
||||||
return errors.New("unknown level: " + strlogLevel)
|
return errors.New("unknown level: " + strlogLevel)
|
||||||
}
|
}
|
||||||
@@ -464,52 +479,33 @@ func setLogPath(args interface{}) error {
|
|||||||
if args == "" {
|
if args == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
logPath := strings.TrimSpace(args.(string))
|
||||||
log.LogPath = strings.TrimSpace(args.(string))
|
dir, err := os.Stat(logPath)
|
||||||
dir, err := os.Stat(log.LogPath) //这个文件夹不存在
|
|
||||||
if err == nil && dir.IsDir() == false {
|
if err == nil && dir.IsDir() == false {
|
||||||
return errors.New("Not found dir " + log.LogPath)
|
return errors.New("Not found dir " + logPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = os.Mkdir(log.LogPath, os.ModePerm)
|
err = os.MkdirAll(logPath, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Cannot create dir " + log.LogPath)
|
return errors.New("Cannot create dir " + logPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.GetLogger().LogPath = logPath
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setLogSize(args interface{}) error {
|
func setLogSize(args interface{}) error {
|
||||||
if args == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
logSize, ok := args.(int)
|
logSize, ok := args.(int)
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return errors.New("param logsize is error")
|
return errors.New("param logsize is error")
|
||||||
}
|
}
|
||||||
|
if logSize == 0 {
|
||||||
log.LogSize = int64(logSize)*1024*1024
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setLogChannelCapNum(args interface{}) error {
|
log.GetLogger().LogConfig.MaxSize = logSize
|
||||||
if args == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
logChannelCap,ok := args.(int)
|
|
||||||
if ok == false{
|
|
||||||
return errors.New("param logsize is error")
|
|
||||||
}
|
|
||||||
|
|
||||||
if logChannelCap == -1 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
log.LogChannelCap = logChannelCap
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,21 @@ package profiler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
"fmt"
|
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//最大超长时间,一般可以认为是死锁或者死循环,或者极差的性能问题
|
// DefaultMaxOvertime 最大超长时间,一般可以认为是死锁或者死循环,或者极差的性能问题
|
||||||
var DefaultMaxOvertime time.Duration = 5*time.Second
|
var DefaultMaxOvertime = 5 * time.Second
|
||||||
//超过该时间将会监控报告
|
|
||||||
var DefaultOvertime time.Duration = 10*time.Millisecond
|
// DefaultOvertime 超过该时间将会监控报告
|
||||||
var DefaultMaxRecordNum int = 100 //最大记录条数
|
var DefaultOvertime = 10 * time.Millisecond
|
||||||
|
var DefaultMaxRecordNum = 100 //最大记录条数
|
||||||
var mapProfiler map[string]*Profiler
|
var mapProfiler map[string]*Profiler
|
||||||
|
|
||||||
type ReportFunType func(name string, callNum int, costTime time.Duration, record *list.List)
|
type ReportFunType func(name string, callNum int, costTime time.Duration, record *list.List)
|
||||||
|
|
||||||
var reportFunc ReportFunType = DefaultReportFunction
|
var reportFunc ReportFunType = DefaultReportFunction
|
||||||
|
|
||||||
type Element struct {
|
type Element struct {
|
||||||
@@ -23,6 +25,7 @@ type Element struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RecordType int
|
type RecordType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaxOvertimeType = 1
|
MaxOvertimeType = 1
|
||||||
OvertimeType = 2
|
OvertimeType = 2
|
||||||
@@ -196,4 +199,3 @@ func Report() {
|
|||||||
DefaultReportFunction(name, callNum, totalCostTime, record)
|
DefaultReportFunction(name, callNum, totalCostTime, record)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package rpc
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type CallSet struct {
|
type CallSet struct {
|
||||||
@@ -20,8 +20,6 @@ type CallSet struct {
|
|||||||
callTimerHeap CallTimerHeap
|
callTimerHeap CallTimerHeap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (cs *CallSet) Init() {
|
func (cs *CallSet) Init() {
|
||||||
cs.pendingLock.Lock()
|
cs.pendingLock.Lock()
|
||||||
cs.callTimerHeap.Init()
|
cs.callTimerHeap.Init()
|
||||||
@@ -34,7 +32,7 @@ func (cs *CallSet) Init(){
|
|||||||
cs.pendingLock.Unlock()
|
cs.pendingLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *CallSet) makeCallFail(call *Call) {
|
func (cs *CallSet) makeCallFail(call *Call) {
|
||||||
if call.callback != nil && call.callback.IsValid() {
|
if call.callback != nil && call.callback.IsValid() {
|
||||||
call.rpcHandler.PushRpcResponse(call)
|
call.rpcHandler.PushRpcResponse(call)
|
||||||
} else {
|
} else {
|
||||||
@@ -42,105 +40,105 @@ func (bc *CallSet) makeCallFail(call *Call) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *CallSet) checkRpcCallTimeout() {
|
func (cs *CallSet) checkRpcCallTimeout() {
|
||||||
for {
|
for {
|
||||||
time.Sleep(DefaultCheckRpcCallTimeoutInterval)
|
time.Sleep(DefaultCheckRpcCallTimeoutInterval)
|
||||||
for i := 0; i < bc.maxCheckCallRpcCount; i++ {
|
for i := 0; i < cs.maxCheckCallRpcCount; i++ {
|
||||||
bc.pendingLock.Lock()
|
cs.pendingLock.Lock()
|
||||||
|
|
||||||
callSeq := bc.callTimerHeap.PopTimeout()
|
callSeq := cs.callTimerHeap.PopTimeout()
|
||||||
if callSeq == 0 {
|
if callSeq == 0 {
|
||||||
bc.pendingLock.Unlock()
|
cs.pendingLock.Unlock()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
pCall := bc.pending[callSeq]
|
pCall := cs.pending[callSeq]
|
||||||
if pCall == nil {
|
if pCall == nil {
|
||||||
bc.pendingLock.Unlock()
|
cs.pendingLock.Unlock()
|
||||||
log.Error("call seq is not find", log.Uint64("seq", callSeq))
|
log.Error("call seq is not find", log.Uint64("seq", callSeq))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(bc.pending,callSeq)
|
delete(cs.pending, callSeq)
|
||||||
strTimeout := strconv.FormatInt(int64(pCall.TimeOut.Seconds()), 10)
|
strTimeout := strconv.FormatInt(int64(pCall.TimeOut.Seconds()), 10)
|
||||||
pCall.Err = errors.New("RPC call takes more than " + strTimeout + " seconds,method is " + pCall.ServiceMethod)
|
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()))
|
log.Error("call timeout", log.String("error", pCall.Err.Error()))
|
||||||
bc.makeCallFail(pCall)
|
cs.makeCallFail(pCall)
|
||||||
bc.pendingLock.Unlock()
|
cs.pendingLock.Unlock()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *CallSet) AddPending(call *Call) {
|
func (cs *CallSet) AddPending(call *Call) {
|
||||||
bc.pendingLock.Lock()
|
cs.pendingLock.Lock()
|
||||||
|
|
||||||
if call.Seq == 0 {
|
if call.Seq == 0 {
|
||||||
bc.pendingLock.Unlock()
|
cs.pendingLock.Unlock()
|
||||||
log.Stack("call is error.")
|
log.StackError("call is error.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bc.pending[call.Seq] = call
|
cs.pending[call.Seq] = call
|
||||||
bc.callTimerHeap.AddTimer(call.Seq,call.TimeOut)
|
cs.callTimerHeap.AddTimer(call.Seq, call.TimeOut)
|
||||||
|
|
||||||
bc.pendingLock.Unlock()
|
cs.pendingLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *CallSet) RemovePending(seq uint64) *Call {
|
func (cs *CallSet) RemovePending(seq uint64) *Call {
|
||||||
if seq == 0 {
|
if seq == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
bc.pendingLock.Lock()
|
cs.pendingLock.Lock()
|
||||||
call := bc.removePending(seq)
|
call := cs.removePending(seq)
|
||||||
bc.pendingLock.Unlock()
|
cs.pendingLock.Unlock()
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *CallSet) removePending(seq uint64) *Call {
|
func (cs *CallSet) removePending(seq uint64) *Call {
|
||||||
v, ok := bc.pending[seq]
|
v, ok := cs.pending[seq]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
bc.callTimerHeap.Cancel(seq)
|
cs.callTimerHeap.Cancel(seq)
|
||||||
delete(bc.pending, seq)
|
delete(cs.pending, seq)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *CallSet) FindPending(seq uint64) (pCall *Call) {
|
func (cs *CallSet) FindPending(seq uint64) (pCall *Call) {
|
||||||
if seq == 0 {
|
if seq == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
bc.pendingLock.Lock()
|
cs.pendingLock.Lock()
|
||||||
pCall = bc.pending[seq]
|
pCall = cs.pending[seq]
|
||||||
bc.pendingLock.Unlock()
|
cs.pendingLock.Unlock()
|
||||||
|
|
||||||
return pCall
|
return pCall
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *CallSet) cleanPending(){
|
func (cs *CallSet) cleanPending() {
|
||||||
bc.pendingLock.Lock()
|
cs.pendingLock.Lock()
|
||||||
for {
|
for {
|
||||||
callSeq := bc.callTimerHeap.PopFirst()
|
callSeq := cs.callTimerHeap.PopFirst()
|
||||||
if callSeq == 0 {
|
if callSeq == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
pCall := bc.pending[callSeq]
|
pCall := cs.pending[callSeq]
|
||||||
if pCall == nil {
|
if pCall == nil {
|
||||||
log.Error("call Seq is not find", log.Uint64("seq", callSeq))
|
log.Error("call Seq is not find", log.Uint64("seq", callSeq))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(bc.pending,callSeq)
|
delete(cs.pending, callSeq)
|
||||||
pCall.Err = errors.New("nodeid is disconnect ")
|
pCall.Err = errors.New("node is disconnect ")
|
||||||
bc.makeCallFail(pCall)
|
cs.makeCallFail(pCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
bc.pendingLock.Unlock()
|
cs.pendingLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *CallSet) generateSeq() uint64 {
|
func (cs *CallSet) generateSeq() uint64 {
|
||||||
return atomic.AddUint64(&bc.startSeq, 1)
|
return atomic.AddUint64(&cs.startSeq, 1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package rpc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/v2/network"
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
|
||||||
"fmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -29,10 +29,10 @@ type IWriter interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type IRealClient interface {
|
type IRealClient interface {
|
||||||
SetConn(conn *network.TCPConn)
|
SetConn(conn *network.NetConn)
|
||||||
Close(waitDone bool)
|
Close(waitDone bool)
|
||||||
|
|
||||||
AsyncCall(NodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error)
|
AsyncCall(NodeId string, timeout time.Duration, rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) (CancelRpc, error)
|
||||||
Go(NodeId string, timeout time.Duration, rpcHandler IRpcHandler, noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call
|
Go(NodeId string, timeout time.Duration, rpcHandler IRpcHandler, noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call
|
||||||
RawGo(NodeId string, timeout time.Duration, rpcHandler IRpcHandler, processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call
|
RawGo(NodeId string, timeout time.Duration, rpcHandler IRpcHandler, processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call
|
||||||
IsConnected() bool
|
IsConnected() bool
|
||||||
@@ -43,8 +43,6 @@ type IRealClient interface {
|
|||||||
Bind(server IServer)
|
Bind(server IServer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
clientId uint32
|
clientId uint32
|
||||||
targetNodeId string
|
targetNodeId string
|
||||||
@@ -54,7 +52,7 @@ type Client struct {
|
|||||||
IRealClient
|
IRealClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) NewClientAgent(conn *network.TCPConn) network.Agent {
|
func (client *Client) NewClientAgent(conn *network.NetConn) network.Agent {
|
||||||
client.SetConn(conn)
|
client.SetConn(conn)
|
||||||
|
|
||||||
return client
|
return client
|
||||||
@@ -68,7 +66,6 @@ func (client *Client) GetClientId() uint32 {
|
|||||||
return client.clientId
|
return client.clientId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (client *Client) processRpcResponse(responseData []byte) error {
|
func (client *Client) processRpcResponse(responseData []byte) error {
|
||||||
bCompress := (responseData[0] >> 7) > 0
|
bCompress := (responseData[0] >> 7) > 0
|
||||||
processor := GetProcessor(responseData[0] & 0x7f)
|
processor := GetProcessor(responseData[0] & 0x7f)
|
||||||
@@ -107,7 +104,7 @@ func (client *Client) processRpcResponse(responseData []byte) error{
|
|||||||
//rc.conn.ReleaseReadMsg(bytes)
|
//rc.conn.ReleaseReadMsg(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
processor.ReleaseRpcResponse(response.RpcResponseData)
|
processor.ReleaseRpcResponse(response.RpcResponseData)
|
||||||
log.Error("rpcClient Unmarshal head error",log.ErrorAttr("error",err))
|
log.Error("rpcClient Unmarshal head error", log.ErrorField("error", err))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +116,7 @@ func (client *Client) processRpcResponse(responseData []byte) error{
|
|||||||
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.Error("rpcClient Unmarshal body failed",log.ErrorAttr("error",err))
|
log.Error("rpcClient Unmarshal body failed", log.ErrorField("error", err))
|
||||||
v.Err = err
|
v.Err = err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,7 +137,6 @@ func (client *Client) processRpcResponse(responseData []byte) error{
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//func (rc *Client) Go(timeout time.Duration,rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
|
//func (rc *Client) 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)
|
||||||
@@ -154,11 +150,11 @@ func (client *Client) processRpcResponse(responseData []byte) error{
|
|||||||
// return rc.RawGo(timeout,rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply)
|
// return rc.RawGo(timeout,rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply)
|
||||||
//}
|
//}
|
||||||
|
|
||||||
func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call {
|
func (client *Client) rawGo(nodeId string, w IWriter, timeout time.Duration, rpcHandler IRpcHandler, processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call {
|
||||||
call := MakeCall()
|
call := MakeCall()
|
||||||
call.ServiceMethod = serviceMethod
|
call.ServiceMethod = serviceMethod
|
||||||
call.Reply = reply
|
call.Reply = reply
|
||||||
call.Seq = rc.generateSeq()
|
call.Seq = client.generateSeq()
|
||||||
call.TimeOut = timeout
|
call.TimeOut = timeout
|
||||||
|
|
||||||
request := MakeRpcRequest(processor, call.Seq, rpcMethodId, serviceMethod, noReply, rawArgs)
|
request := MakeRpcRequest(processor, call.Seq, rpcMethodId, serviceMethod, noReply, rawArgs)
|
||||||
@@ -182,7 +178,7 @@ func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler
|
|||||||
|
|
||||||
var compressBuff []byte
|
var compressBuff []byte
|
||||||
bCompress := uint8(0)
|
bCompress := uint8(0)
|
||||||
if rc.compressBytesLen > 0 && len(bytes) >= rc.compressBytesLen {
|
if client.compressBytesLen > 0 && len(bytes) >= client.compressBytesLen {
|
||||||
var cErr error
|
var cErr error
|
||||||
compressBuff, cErr = compressor.CompressBlock(bytes)
|
compressBuff, cErr = compressor.CompressBlock(bytes)
|
||||||
if cErr != nil {
|
if cErr != nil {
|
||||||
@@ -198,7 +194,7 @@ func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
if noReply == false {
|
if noReply == false {
|
||||||
rc.AddPending(call)
|
client.AddPending(call)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = w.WriteMsg(nodeId, []byte{uint8(processor.GetProcessorType()) | bCompress}, bytes)
|
err = w.WriteMsg(nodeId, []byte{uint8(processor.GetProcessorType()) | bCompress}, bytes)
|
||||||
@@ -206,8 +202,8 @@ func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler
|
|||||||
compressor.CompressBufferCollection(compressBuff)
|
compressor.CompressBufferCollection(compressBuff)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rc.RemovePending(call.Seq)
|
client.RemovePending(call.Seq)
|
||||||
log.Error("WiteMsg is fail",log.ErrorAttr("error",err))
|
log.Error("WriteMsg is fail", log.ErrorField("error", err))
|
||||||
call.Seq = 0
|
call.Seq = 0
|
||||||
call.DoError(err)
|
call.DoError(err)
|
||||||
}
|
}
|
||||||
@@ -215,14 +211,14 @@ func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler
|
|||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *Client) asyncCall(nodeId string,w IWriter,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) {
|
func (client *Client) asyncCall(nodeId string, w IWriter, timeout time.Duration, rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) (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 emptyCancelRpc, herr
|
return emptyCancelRpc, herr
|
||||||
}
|
}
|
||||||
|
|
||||||
seq := rc.generateSeq()
|
seq := client.generateSeq()
|
||||||
request := MakeRpcRequest(processor, seq, 0, serviceMethod, false, InParam)
|
request := MakeRpcRequest(processor, seq, 0, serviceMethod, false, InParam)
|
||||||
bytes, err := processor.Marshal(request.RpcRequestData)
|
bytes, err := processor.Marshal(request.RpcRequestData)
|
||||||
ReleaseRpcRequest(request)
|
ReleaseRpcRequest(request)
|
||||||
@@ -236,7 +232,7 @@ func (rc *Client) asyncCall(nodeId string,w IWriter,timeout time.Duration,rpcHan
|
|||||||
|
|
||||||
var compressBuff []byte
|
var compressBuff []byte
|
||||||
bCompress := uint8(0)
|
bCompress := uint8(0)
|
||||||
if rc.compressBytesLen>0 &&len(bytes) >= rc.compressBytesLen {
|
if client.compressBytesLen > 0 && len(bytes) >= client.compressBytesLen {
|
||||||
var cErr error
|
var cErr error
|
||||||
compressBuff, cErr = compressor.CompressBlock(bytes)
|
compressBuff, cErr = compressor.CompressBlock(bytes)
|
||||||
if cErr != nil {
|
if cErr != nil {
|
||||||
@@ -256,22 +252,19 @@ func (rc *Client) asyncCall(nodeId string,w IWriter,timeout time.Duration,rpcHan
|
|||||||
call.ServiceMethod = serviceMethod
|
call.ServiceMethod = serviceMethod
|
||||||
call.Seq = seq
|
call.Seq = seq
|
||||||
call.TimeOut = timeout
|
call.TimeOut = timeout
|
||||||
rc.AddPending(call)
|
client.AddPending(call)
|
||||||
|
|
||||||
err = w.WriteMsg(nodeId, []byte{uint8(processorType) | bCompress}, bytes)
|
err = w.WriteMsg(nodeId, []byte{uint8(processorType) | bCompress}, bytes)
|
||||||
if cap(compressBuff) > 0 {
|
if cap(compressBuff) > 0 {
|
||||||
compressor.CompressBufferCollection(compressBuff)
|
compressor.CompressBufferCollection(compressBuff)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rc.RemovePending(call.Seq)
|
client.RemovePending(call.Seq)
|
||||||
ReleaseCall(call)
|
ReleaseCall(call)
|
||||||
return emptyCancelRpc, err
|
return emptyCancelRpc, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cancelable {
|
|
||||||
rpcCancel := RpcCancel{CallSeq:seq,Cli: rc}
|
rpcCancel := RpcCancel{CallSeq: seq, Cli: client}
|
||||||
return rpcCancel.CancelRpc, nil
|
return rpcCancel.CancelRpc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return emptyCancelRpc,nil
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
var memPool bytespool.IBytesMempool = bytespool.NewMemAreaPool()
|
var memPool bytespool.IBytesMemPool = bytespool.NewMemAreaPool()
|
||||||
|
|
||||||
type ICompressor interface {
|
type ICompressor interface {
|
||||||
CompressBlock(src []byte) ([]byte, error) //dst如果有预申请使用dst内存,传入nil时内部申请
|
CompressBlock(src []byte) ([]byte, error) //dst如果有预申请使用dst内存,传入nil时内部申请
|
||||||
@@ -19,6 +19,7 @@ type ICompressor interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var compressor ICompressor
|
var compressor ICompressor
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
SetCompressor(&Lz4Compressor{})
|
SetCompressor(&Lz4Compressor{})
|
||||||
}
|
}
|
||||||
@@ -56,7 +57,7 @@ func (lc *Lz4Compressor) CompressBlock(src []byte) (dest []byte, err error) {
|
|||||||
|
|
||||||
if ratio > 255 {
|
if ratio > 255 {
|
||||||
memPool.ReleaseBytes(dest)
|
memPool.ReleaseBytes(dest)
|
||||||
return nil,fmt.Errorf("Impermissible errors")
|
return nil, fmt.Errorf("impermissible errors")
|
||||||
}
|
}
|
||||||
|
|
||||||
dest[0] = uint8(ratio)
|
dest[0] = uint8(ratio)
|
||||||
@@ -76,7 +77,7 @@ func (lc *Lz4Compressor) UncompressBlock(src []byte) (dest []byte, err error) {
|
|||||||
|
|
||||||
radio := uint8(src[0])
|
radio := uint8(src[0])
|
||||||
if radio == 0 {
|
if radio == 0 {
|
||||||
return nil,fmt.Errorf("Impermissible errors")
|
return nil, fmt.Errorf("impermissible errors")
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = memPool.MakeBytes(len(src) * int(radio))
|
dest = memPool.MakeBytes(len(src) * int(radio))
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//本结点的Client
|
// LClient 本结点的Client
|
||||||
type LClient struct {
|
type LClient struct {
|
||||||
selfClient *Client
|
selfClient *Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *LClient) Lock(){
|
func (lc *LClient) Lock() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *LClient) Unlock(){
|
func (lc *LClient) Unlock() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LClient) Run() {
|
func (lc *LClient) Run() {
|
||||||
@@ -31,7 +31,7 @@ func (lc *LClient) IsConnected() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LClient) SetConn(conn *network.TCPConn){
|
func (lc *LClient) SetConn(conn *network.NetConn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LClient) Close(waitDone bool) {
|
func (lc *LClient) Close(waitDone bool) {
|
||||||
@@ -69,8 +69,7 @@ func (lc *LClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler
|
|||||||
return pLocalRpcServer.selfNodeRpcHandlerGo(timeout, 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 (lc *LClient) RawGo(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceName string, rawArgs []byte, reply interface{}) *Call {
|
||||||
func (rc *LClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceName string, rawArgs []byte, reply interface{}) *Call {
|
|
||||||
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
||||||
|
|
||||||
//服务自我调用
|
//服务自我调用
|
||||||
@@ -80,7 +79,7 @@ func (rc *LClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHand
|
|||||||
call.Reply = reply
|
call.Reply = reply
|
||||||
call.TimeOut = timeout
|
call.TimeOut = timeout
|
||||||
|
|
||||||
err := pLocalRpcServer.myselfRpcHandlerGo(rc.selfClient,serviceName, serviceName, rawArgs, requestHandlerNull,nil)
|
err := pLocalRpcServer.myselfRpcHandlerGo(lc.selfClient, serviceName, serviceName, rawArgs, requestHandlerNull, nil)
|
||||||
call.Err = err
|
call.Err = err
|
||||||
call.done <- call
|
call.done <- call
|
||||||
|
|
||||||
@@ -88,11 +87,10 @@ func (rc *LClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHand
|
|||||||
}
|
}
|
||||||
|
|
||||||
//其他的rpcHandler的处理器
|
//其他的rpcHandler的处理器
|
||||||
return pLocalRpcServer.selfNodeRpcHandlerGo(timeout,processor,rc.selfClient, true, serviceName, rpcMethodId, serviceName, nil, nil, rawArgs)
|
return pLocalRpcServer.selfNodeRpcHandlerGo(timeout, processor, lc.selfClient, true, serviceName, rpcMethodId, serviceName, nil, nil, rawArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (lc *LClient) AsyncCall(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, reply interface{}) (CancelRpc, error) {
|
||||||
func (lc *LClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, reply interface{},cancelable bool) (CancelRpc,error) {
|
|
||||||
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
pLocalRpcServer := rpcHandler.GetRpcServer()()
|
||||||
|
|
||||||
//判断是否是同一服务
|
//判断是否是同一服务
|
||||||
@@ -111,21 +109,18 @@ func (lc *LClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpc
|
|||||||
}
|
}
|
||||||
|
|
||||||
//其他的rpcHandler的处理器
|
//其他的rpcHandler的处理器
|
||||||
calcelRpc,err := pLocalRpcServer.selfNodeRpcHandlerAsyncGo(timeout,lc.selfClient, rpcHandler, false, serviceName, serviceMethod, args, reply, callback,cancelable)
|
cancelRpc, err := pLocalRpcServer.selfNodeRpcHandlerAsyncGo(timeout, lc.selfClient, rpcHandler, false, serviceName, serviceMethod, args, reply, callback)
|
||||||
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 calcelRpc,nil
|
return cancelRpc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLClient(localNodeId string, callSet *CallSet) *Client {
|
func NewLClient(localNodeId string, callSet *CallSet) *Client {
|
||||||
client := &Client{}
|
client := &Client{}
|
||||||
client.clientId = atomic.AddUint32(&clientSeq, 1)
|
client.clientId = atomic.AddUint32(&clientSeq, 1)
|
||||||
client.targetNodeId = localNodeId
|
client.targetNodeId = localNodeId
|
||||||
//client.maxCheckCallRpcCount = DefaultMaxCheckCallRpcCount
|
|
||||||
//client.callRpcTimeout = DefaultRpcTimeout
|
|
||||||
|
|
||||||
lClient := &LClient{}
|
lClient := &LClient{}
|
||||||
lClient.selfClient = client
|
lClient.selfClient = client
|
||||||
client.IRealClient = lClient
|
client.IRealClient = lClient
|
||||||
@@ -133,5 +128,5 @@ func NewLClient(localNodeId string,callSet *CallSet) *Client{
|
|||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *LClient) Bind(server IServer){
|
func (lc *LClient) Bind(_ IServer) {
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
|
||||||
"strings"
|
"strings"
|
||||||
"fmt"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type BaseServer struct {
|
type BaseServer struct {
|
||||||
localNodeId string
|
localNodeId string
|
||||||
compressBytesLen int
|
compressBytesLen int
|
||||||
@@ -17,13 +17,13 @@ type BaseServer struct {
|
|||||||
iServer IServer
|
iServer IServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ls *BaseServer) initBaseServer(compressBytesLen int,rpcHandleFinder RpcHandleFinder){
|
func (server *BaseServer) initBaseServer(compressBytesLen int, rpcHandleFinder RpcHandleFinder) {
|
||||||
ls.compressBytesLen = compressBytesLen
|
server.compressBytesLen = compressBytesLen
|
||||||
ls.rpcHandleFinder = rpcHandleFinder
|
server.rpcHandleFinder = rpcHandleFinder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ls *BaseServer) myselfRpcHandlerGo(client *Client,handlerName string, serviceMethod string, args interface{},callBack reflect.Value, reply interface{}) error {
|
func (server *BaseServer) myselfRpcHandlerGo(client *Client, handlerName string, serviceMethod string, args interface{}, callBack reflect.Value, reply interface{}) error {
|
||||||
rpcHandler := ls.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.Error("service method not config", log.String("serviceMethod", serviceMethod))
|
log.Error("service method not config", log.String("serviceMethod", serviceMethod))
|
||||||
@@ -33,16 +33,16 @@ func (ls *BaseServer) myselfRpcHandlerGo(client *Client,handlerName string, serv
|
|||||||
return rpcHandler.CallMethod(client, serviceMethod, args, callBack, reply)
|
return rpcHandler.CallMethod(client, serviceMethod, args, callBack, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ls *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call {
|
func (server *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration, processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call {
|
||||||
pCall := MakeCall()
|
pCall := MakeCall()
|
||||||
pCall.Seq = client.generateSeq()
|
pCall.Seq = client.generateSeq()
|
||||||
pCall.TimeOut = timeout
|
pCall.TimeOut = timeout
|
||||||
pCall.ServiceMethod = serviceMethod
|
pCall.ServiceMethod = serviceMethod
|
||||||
|
|
||||||
rpcHandler := ls.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.Error("service method not config",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err))
|
log.Error("service method not config", log.String("serviceMethod", serviceMethod), log.ErrorField("error", err))
|
||||||
pCall.Seq = 0
|
pCall.Seq = 0
|
||||||
pCall.DoError(err)
|
pCall.DoError(err)
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ func (ls *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcP
|
|||||||
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.Error("unmarshalInParam is failed",log.String("serviceMethod",serviceMethod),log.Uint32("rpcMethodId",rpcMethodId),log.ErrorAttr("error",err))
|
log.Error("unmarshalInParam is failed", log.String("serviceMethod", serviceMethod), log.Uint32("rpcMethodId", rpcMethodId), log.ErrorField("error", err))
|
||||||
pCall.Seq = 0
|
pCall.Seq = 0
|
||||||
pCall.DoError(err)
|
pCall.DoError(err)
|
||||||
ReleaseRpcRequest(req)
|
ReleaseRpcRequest(req)
|
||||||
@@ -90,12 +90,12 @@ func (ls *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcP
|
|||||||
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.Error("returns data cannot be marshal",log.Uint64("seq",callSeq),log.ErrorAttr("error",err))
|
log.Error("returns data cannot be marshal", log.Uint64("seq", callSeq), log.ErrorField("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.Error("returns data cannot be Unmarshal",log.Uint64("seq",callSeq),log.ErrorAttr("error",err))
|
log.Error("returns data cannot be Unmarshal", log.Uint64("seq", callSeq), log.ErrorField("error", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ func (ls *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcP
|
|||||||
return pCall
|
return pCall
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *BaseServer) selfNodeRpcHandlerAsyncGo(timeout time.Duration,client *Client, callerRpcHandler IRpcHandler, noReply bool, handlerName string, serviceMethod string, args interface{}, reply interface{}, callback reflect.Value,cancelable bool) (CancelRpc,error) {
|
func (server *BaseServer) selfNodeRpcHandlerAsyncGo(timeout time.Duration, client *Client, callerRpcHandler IRpcHandler, noReply bool, handlerName string, serviceMethod string, args interface{}, reply interface{}, callback reflect.Value) (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!")
|
||||||
@@ -194,7 +194,7 @@ func (server *BaseServer) selfNodeRpcHandlerAsyncGo(timeout time.Duration,client
|
|||||||
return cancelRpc, nil
|
return cancelRpc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse writeResponse) error{
|
func (server *BaseServer) processRpcRequest(data []byte, connTag string, wrResponse writeResponse) error {
|
||||||
bCompress := (data[0] >> 7) > 0
|
bCompress := (data[0] >> 7) > 0
|
||||||
processor := GetProcessor(data[0] & 0x7f)
|
processor := GetProcessor(data[0] & 0x7f)
|
||||||
if processor == nil {
|
if processor == nil {
|
||||||
@@ -209,7 +209,7 @@ func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse wr
|
|||||||
|
|
||||||
compressBuff, unCompressErr = compressor.UncompressBlock(byteData)
|
compressBuff, unCompressErr = compressor.UncompressBlock(byteData)
|
||||||
if unCompressErr != nil {
|
if unCompressErr != nil {
|
||||||
return errors.New("UncompressBlock failed")
|
return errors.New("uncompressBlock failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
byteData = compressBuff
|
byteData = compressBuff
|
||||||
@@ -245,7 +245,7 @@ func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse wr
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rpcHandler := bs.rpcHandleFinder.FindRpcHandler(serviceMethod[0])
|
rpcHandler := server.rpcHandleFinder.FindRpcHandler(serviceMethod[0])
|
||||||
if rpcHandler == nil {
|
if rpcHandler == nil {
|
||||||
rpcError := RpcError(fmt.Sprintf("service method %s not config!", req.RpcRequestData.GetServiceMethod()))
|
rpcError := RpcError(fmt.Sprintf("service method %s not config!", req.RpcRequestData.GetServiceMethod()))
|
||||||
if req.RpcRequestData.IsNoReply() == false {
|
if req.RpcRequestData.IsNoReply() == false {
|
||||||
@@ -266,7 +266,7 @@ func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse wr
|
|||||||
req.inParam, err = rpcHandler.UnmarshalInParam(req.rpcProcessor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetRpcMethodId(), req.RpcRequestData.GetInParam())
|
req.inParam, err = rpcHandler.UnmarshalInParam(req.rpcProcessor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetRpcMethodId(), req.RpcRequestData.GetInParam())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rErr := "Call Rpc " + req.RpcRequestData.GetServiceMethod() + " Param error " + err.Error()
|
rErr := "Call Rpc " + req.RpcRequestData.GetServiceMethod() + " Param error " + err.Error()
|
||||||
log.Error("call rpc param error",log.String("serviceMethod",req.RpcRequestData.GetServiceMethod()),log.ErrorAttr("error",err))
|
log.Error("call rpc param error", log.String("serviceMethod", req.RpcRequestData.GetServiceMethod()), log.ErrorField("error", err))
|
||||||
if req.requestHandle != nil {
|
if req.requestHandle != nil {
|
||||||
req.requestHandle(nil, RpcError(rErr))
|
req.requestHandle(nil, RpcError(rErr))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/v2/network"
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
|
"github.com/nats-io/nats.go"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
"github.com/nats-io/nats.go"
|
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//跨结点连接的Client
|
// NatsClient 跨结点连接的Client
|
||||||
type NatsClient struct {
|
type NatsClient struct {
|
||||||
localNodeId string
|
localNodeId string
|
||||||
notifyEventFun NotifyEventFun
|
notifyEventFun NotifyEventFun
|
||||||
@@ -28,7 +29,7 @@ func (nc *NatsClient) onSubscribe(msg *nats.Msg){
|
|||||||
nc.client.processRpcResponse(msg.Data)
|
nc.client.processRpcResponse(msg.Data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nc *NatsClient) SetConn(conn *network.TCPConn){
|
func (nc *NatsClient) SetConn(conn *network.NetConn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nc *NatsClient) Close(waitDone bool) {
|
func (nc *NatsClient) Close(waitDone bool) {
|
||||||
@@ -40,30 +41,30 @@ func (nc *NatsClient) Run(){
|
|||||||
func (nc *NatsClient) OnClose() {
|
func (nc *NatsClient) OnClose() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *NatsClient) Bind(server IServer){
|
func (nc *NatsClient) Bind(server IServer) {
|
||||||
s := server.(*NatsServer)
|
s := server.(*NatsServer)
|
||||||
rc.natsConn = s.natsConn
|
nc.natsConn = s.natsConn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *NatsClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
|
func (nc *NatsClient) Go(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
|
||||||
_, processor := GetProcessorType(args)
|
_, processor := GetProcessorType(args)
|
||||||
InParam, err := processor.Marshal(args)
|
InParam, err := processor.Marshal(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Marshal is fail",log.ErrorAttr("error",err))
|
log.Error("Marshal is fail", log.ErrorField("error", err))
|
||||||
call := MakeCall()
|
call := MakeCall()
|
||||||
call.DoError(err)
|
call.DoError(err)
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc.client.rawGo(nodeId,rc,timeout,rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply)
|
return nc.client.rawGo(nodeId, nc, timeout, rpcHandler, processor, noReply, 0, serviceMethod, InParam, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *NatsClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call {
|
func (nc *NatsClient) RawGo(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call {
|
||||||
return rc.client.rawGo(nodeId,rc,timeout,rpcHandler,processor, noReply, rpcMethodId, serviceMethod, rawArgs, reply)
|
return nc.client.rawGo(nodeId, nc, timeout, rpcHandler, processor, noReply, rpcMethodId, serviceMethod, rawArgs, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *NatsClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) {
|
func (nc *NatsClient) AsyncCall(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) (CancelRpc, error) {
|
||||||
cancelRpc,err := rc.client.asyncCall(nodeId,rc,timeout,rpcHandler, serviceMethod, callback, args, replyParam,cancelable)
|
cancelRpc, err := nc.client.asyncCall(nodeId, nc, timeout, rpcHandler, serviceMethod, callback, args, replyParam)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
callback.Call([]reflect.Value{reflect.ValueOf(replyParam), reflect.ValueOf(err)})
|
callback.Call([]reflect.Value{reflect.ValueOf(replyParam), reflect.ValueOf(err)})
|
||||||
}
|
}
|
||||||
@@ -71,7 +72,7 @@ func (rc *NatsClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler I
|
|||||||
return cancelRpc, nil
|
return cancelRpc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *NatsClient) WriteMsg (nodeId string,args ...[]byte) error{
|
func (nc *NatsClient) WriteMsg(nodeId string, args ...[]byte) error {
|
||||||
buff := make([]byte, 0, 4096)
|
buff := make([]byte, 0, 4096)
|
||||||
for _, ar := range args {
|
for _, ar := range args {
|
||||||
buff = append(buff, ar...)
|
buff = append(buff, ar...)
|
||||||
@@ -81,10 +82,10 @@ func (rc *NatsClient) WriteMsg (nodeId string,args ...[]byte) error{
|
|||||||
msg.Subject = "os." + nodeId
|
msg.Subject = "os." + nodeId
|
||||||
msg.Data = buff
|
msg.Data = buff
|
||||||
msg.Header = nats.Header{}
|
msg.Header = nats.Header{}
|
||||||
msg.Header.Set("fnode",rc.localNodeId)
|
msg.Header.Set("fnode", nc.localNodeId)
|
||||||
return rc.natsConn.PublishMsg(&msg)
|
return nc.natsConn.PublishMsg(&msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *NatsClient) IsConnected() bool{
|
func (nc *NatsClient) IsConnected() bool {
|
||||||
return rc.natsConn!=nil && rc.natsConn.Status() == nats.CONNECTED
|
return nc.natsConn != nil && nc.natsConn.Status() == nats.CONNECTED
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nats-io/nats.go"
|
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/nats-io/nats.go"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,6 +19,7 @@ type NatsServer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const reconnectWait = 3 * time.Second
|
const reconnectWait = 3 * time.Second
|
||||||
|
|
||||||
func (ns *NatsServer) Start() error {
|
func (ns *NatsServer) Start() error {
|
||||||
var err error
|
var err error
|
||||||
var options []nats.Option
|
var options []nats.Option
|
||||||
@@ -31,7 +32,6 @@ func (ns *NatsServer) Start() error{
|
|||||||
options = append(options, nats.ConnectHandler(func(nc *nats.Conn) {
|
options = append(options, nats.ConnectHandler(func(nc *nats.Conn) {
|
||||||
log.Info("nats is connected", log.String("connUrl", nc.ConnectedUrl()))
|
log.Info("nats is connected", log.String("connUrl", nc.ConnectedUrl()))
|
||||||
ns.notifyEventFun(&NatsConnEvent{IsConnect: true})
|
ns.notifyEventFun(&NatsConnEvent{IsConnect: true})
|
||||||
//log.Error("nats is connect",log.String("connUrl",nc.ConnectedUrl()))
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
options = append(options, nats.ReconnectHandler(func(nc *nats.Conn) {
|
options = append(options, nats.ReconnectHandler(func(nc *nats.Conn) {
|
||||||
@@ -48,7 +48,7 @@ func (ns *NatsServer) Start() error{
|
|||||||
|
|
||||||
ns.natsConn, err = nats.Connect(ns.natsUrl, options...)
|
ns.natsConn, err = nats.Connect(ns.natsUrl, options...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Connect to nats fail",log.String("natsUrl",ns.natsUrl),log.ErrorAttr("err",err))
|
log.Error("Connect to nats fail", log.String("natsUrl", ns.natsUrl), log.ErrorField("err", err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ func (ns *NatsServer) WriteResponse(processor IRpcProcessor, nodeId string,servi
|
|||||||
defer processor.ReleaseRpcResponse(rpcResponse.RpcResponseData)
|
defer processor.ReleaseRpcResponse(rpcResponse.RpcResponseData)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("mashal RpcResponseData failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err))
|
log.Error("marshal RpcResponseData failed", log.String("serviceMethod", serviceMethod), log.ErrorField("error", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ func (ns *NatsServer) WriteResponse(processor IRpcProcessor, nodeId string,servi
|
|||||||
if ns.compressBytesLen > 0 && len(bytes) >= ns.compressBytesLen {
|
if ns.compressBytesLen > 0 && len(bytes) >= ns.compressBytesLen {
|
||||||
compressBuff, err = compressor.CompressBlock(bytes)
|
compressBuff, err = compressor.CompressBlock(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("CompressBlock failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err))
|
log.Error("CompressBlock failed", log.String("serviceMethod", serviceMethod), log.ErrorField("error", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(compressBuff) < len(bytes) {
|
if len(compressBuff) < len(bytes) {
|
||||||
@@ -106,7 +106,7 @@ func (ns *NatsServer) WriteResponse(processor IRpcProcessor, nodeId string,servi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("WriteMsg error,Rpc return is fail",log.String("nodeId",nodeId),log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err))
|
log.Error("WriteMsg error,Rpc return is fail", log.String("nodeId", nodeId), log.String("serviceMethod", serviceMethod), log.ErrorField("error", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/duanhf2012/origin/v2/util/sync"
|
"github.com/duanhf2012/origin/v2/util/sync"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
"fmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type PBProcessor struct {
|
type PBProcessor struct {
|
||||||
@@ -27,8 +27,7 @@ func (slf *PBRpcRequestData) MakeRequest(seq uint64,rpcMethodId uint32,serviceMe
|
|||||||
return slf
|
return slf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (slf *PBRpcResponseData) MakeResponse(seq uint64, err RpcError, reply []byte) *PBRpcResponseData {
|
||||||
func (slf *PBRpcResponseData) MakeRespone(seq uint64,err RpcError,reply []byte) *PBRpcResponseData{
|
|
||||||
slf.Seq = seq
|
slf.Seq = seq
|
||||||
slf.Error = err.Error()
|
slf.Error = err.Error()
|
||||||
slf.Reply = reply
|
slf.Reply = reply
|
||||||
@@ -56,7 +55,7 @@ func (slf *PBProcessor) MakeRpcRequest(seq uint64,rpcMethodId uint32,serviceMeth
|
|||||||
|
|
||||||
func (slf *PBProcessor) MakeRpcResponse(seq uint64, err RpcError, reply []byte) IRpcResponseData {
|
func (slf *PBProcessor) MakeRpcResponse(seq uint64, err RpcError, reply []byte) IRpcResponseData {
|
||||||
pPBRpcResponseData := rpcPbResponseDataPool.Get().(*PBRpcResponseData)
|
pPBRpcResponseData := rpcPbResponseDataPool.Get().(*PBRpcResponseData)
|
||||||
pPBRpcResponseData.MakeRespone(seq,err,reply)
|
pPBRpcResponseData.MakeResponse(seq, err, reply)
|
||||||
return pPBRpcResponseData
|
return pPBRpcResponseData
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,9 +97,3 @@ func (slf *PBRpcResponseData) GetErr() *RpcError {
|
|||||||
err := RpcError(slf.GetError())
|
err := RpcError(slf.GetError())
|
||||||
return &err
|
return &err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,16 +6,16 @@ import (
|
|||||||
"github.com/duanhf2012/origin/v2/network"
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//跨结点连接的Client
|
// RClient 跨结点连接的Client
|
||||||
type RClient struct {
|
type RClient struct {
|
||||||
selfClient *Client
|
selfClient *Client
|
||||||
network.TCPClient
|
network.TCPClient
|
||||||
conn *network.TCPConn
|
conn *network.NetConn
|
||||||
|
|
||||||
notifyEventFun NotifyEventFun
|
notifyEventFun NotifyEventFun
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ func (rc *RClient) IsConnected() bool {
|
|||||||
return rc.conn != nil && rc.conn.IsConnected() == true
|
return rc.conn != nil && rc.conn.IsConnected() == true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RClient) GetConn() *network.TCPConn{
|
func (rc *RClient) GetConn() *network.NetConn {
|
||||||
rc.Lock()
|
rc.Lock()
|
||||||
conn := rc.conn
|
conn := rc.conn
|
||||||
rc.Unlock()
|
rc.Unlock()
|
||||||
@@ -35,7 +35,7 @@ func (rc *RClient) GetConn() *network.TCPConn{
|
|||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RClient) SetConn(conn *network.TCPConn){
|
func (rc *RClient) SetConn(conn *network.NetConn) {
|
||||||
rc.Lock()
|
rc.Lock()
|
||||||
rc.conn = conn
|
rc.conn = conn
|
||||||
rc.Unlock()
|
rc.Unlock()
|
||||||
@@ -49,7 +49,7 @@ func (rc *RClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler
|
|||||||
_, processor := GetProcessorType(args)
|
_, processor := GetProcessorType(args)
|
||||||
InParam, err := processor.Marshal(args)
|
InParam, err := processor.Marshal(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Marshal is fail",log.ErrorAttr("error",err))
|
log.Error("Marshal is fail", log.ErrorField("error", err))
|
||||||
call := MakeCall()
|
call := MakeCall()
|
||||||
call.DoError(err)
|
call.DoError(err)
|
||||||
return call
|
return call
|
||||||
@@ -62,8 +62,8 @@ func (rc *RClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHand
|
|||||||
return rc.selfClient.rawGo(nodeId, rc, timeout, rpcHandler, processor, noReply, rpcMethodId, serviceMethod, rawArgs, reply)
|
return rc.selfClient.rawGo(nodeId, rc, timeout, rpcHandler, processor, noReply, rpcMethodId, serviceMethod, rawArgs, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) {
|
func (rc *RClient) AsyncCall(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) (CancelRpc, error) {
|
||||||
cancelRpc,err := rc.selfClient.asyncCall(nodeId,rc,timeout,rpcHandler, serviceMethod, callback, args, replyParam,cancelable)
|
cancelRpc, err := rc.selfClient.asyncCall(nodeId, rc, timeout, rpcHandler, serviceMethod, callback, args, replyParam)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
callback.Call([]reflect.Value{reflect.ValueOf(replyParam), reflect.ValueOf(err)})
|
callback.Call([]reflect.Value{reflect.ValueOf(replyParam), reflect.ValueOf(err)})
|
||||||
}
|
}
|
||||||
@@ -74,10 +74,7 @@ func (rc *RClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpc
|
|||||||
func (rc *RClient) Run() {
|
func (rc *RClient) Run() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.Dump(string(buf[:l]),log.String("error",errString))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -89,7 +86,7 @@ func (rc *RClient) Run() {
|
|||||||
for {
|
for {
|
||||||
bytes, err := rc.conn.ReadMsg()
|
bytes, err := rc.conn.ReadMsg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("rclient read msg is failed",log.ErrorAttr("error",err))
|
log.Error("RClient read msg is failed", log.ErrorField("error", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,13 +137,11 @@ func NewRClient(targetNodeId string, addr string, maxRpcParamLen uint32,compress
|
|||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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.cleanPending()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (rc *RClient) Bind(server IServer) {
|
func (rc *RClient) Bind(server IServer) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,20 +3,21 @@ package rpc
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
"github.com/duanhf2012/origin/v2/event"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxClusterNode int = 32
|
const maxClusterNode int = 32
|
||||||
|
|
||||||
type FuncRpcClient func(nodeId string, serviceMethod string, filterRetire bool, client []*Client) (error, []*Client)
|
type FuncRpcClient func(nodeId string, serviceMethod string, filterRetire bool, client []*Client) (error, []*Client)
|
||||||
type FuncRpcServer func() IServer
|
type FuncRpcServer func() IServer
|
||||||
|
|
||||||
const NodeIdNull = ""
|
const NodeIdNull = ""
|
||||||
|
|
||||||
var nilError = reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())
|
var nilError = reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())
|
||||||
@@ -66,7 +67,7 @@ type RpcHandler struct {
|
|||||||
//pClientList []*Client
|
//pClientList []*Client
|
||||||
}
|
}
|
||||||
|
|
||||||
//type TriggerRpcConnEvent func(bConnect bool, clientSeq uint32, nodeId string)
|
// NotifyEventToAllService type TriggerRpcConnEvent func(bConnect bool, clientSeq uint32, nodeId string)
|
||||||
type NotifyEventToAllService func(event event.IEvent)
|
type NotifyEventToAllService func(event event.IEvent)
|
||||||
|
|
||||||
type INodeConnListener interface {
|
type INodeConnListener interface {
|
||||||
@@ -85,6 +86,7 @@ type IDiscoveryServiceListener interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CancelRpc func()
|
type CancelRpc func()
|
||||||
|
|
||||||
func emptyCancelRpc() {}
|
func emptyCancelRpc() {}
|
||||||
|
|
||||||
type IRpcHandler interface {
|
type IRpcHandler interface {
|
||||||
@@ -162,13 +164,6 @@ func (handler *RpcHandler) suitableMethods(method reflect.Method) error {
|
|||||||
//取出输入参数类型
|
//取出输入参数类型
|
||||||
var rpcMethodInfo RpcMethodInfo
|
var rpcMethodInfo RpcMethodInfo
|
||||||
typ := method.Type
|
typ := method.Type
|
||||||
if typ.NumOut() != 1 {
|
|
||||||
return fmt.Errorf("%s The number of returned arguments must be 1", method.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if typ.Out(0).String() != "error" {
|
|
||||||
return fmt.Errorf("%s The return parameter must be of type error", method.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if typ.NumIn() < 2 || typ.NumIn() > 4 {
|
if typ.NumIn() < 2 || typ.NumIn() > 4 {
|
||||||
return fmt.Errorf("%s Unsupported parameter format", method.Name)
|
return fmt.Errorf("%s Unsupported parameter format", method.Name)
|
||||||
@@ -181,6 +176,18 @@ func (handler *RpcHandler) suitableMethods(method reflect.Method) error {
|
|||||||
rpcMethodInfo.hasResponder = true
|
rpcMethodInfo.hasResponder = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rpcMethodInfo.hasResponder && typ.NumOut() > 0 {
|
||||||
|
return fmt.Errorf("%s should not have return parameters", method.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !rpcMethodInfo.hasResponder && typ.NumOut() != 1 {
|
||||||
|
return fmt.Errorf("%s The number of returned arguments must be 1", method.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !rpcMethodInfo.hasResponder && typ.Out(0).String() != "error" {
|
||||||
|
return fmt.Errorf("%s The return parameter must be of type error", method.Name)
|
||||||
|
}
|
||||||
|
|
||||||
for i := parIdx; i < typ.NumIn(); i++ {
|
for i := parIdx; i < typ.NumIn(); i++ {
|
||||||
if handler.isExportedOrBuiltinType(typ.In(i)) == false {
|
if handler.isExportedOrBuiltinType(typ.In(i)) == false {
|
||||||
return fmt.Errorf("%s Unsupported parameter types", method.Name)
|
return fmt.Errorf("%s Unsupported parameter types", method.Name)
|
||||||
@@ -218,10 +225,7 @@ func (handler *RpcHandler) RegisterRpc(rpcHandler IRpcHandler) error {
|
|||||||
func (handler *RpcHandler) HandlerRpcResponseCB(call *Call) {
|
func (handler *RpcHandler) HandlerRpcResponseCB(call *Call) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.Dump(string(buf[:l]),log.String("error",errString))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -240,10 +244,7 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
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)
|
||||||
@@ -309,15 +310,17 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
requestHanle := request.requestHandle
|
requestHandle := request.requestHandle
|
||||||
returnValues := v.method.Func.Call(paramList)
|
returnValues := v.method.Func.Call(paramList)
|
||||||
|
if len(returnValues) > 0 {
|
||||||
errInter := returnValues[0].Interface()
|
errInter := returnValues[0].Interface()
|
||||||
if errInter != nil {
|
if errInter != nil {
|
||||||
err = errInter.(error)
|
err = errInter.(error)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if v.hasResponder == false && requestHanle != nil {
|
if v.hasResponder == false && requestHandle != nil {
|
||||||
requestHanle(oParam.Interface(), ConvertError(err))
|
requestHandle(oParam.Interface(), ConvertError(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,7 +350,7 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
|
|||||||
//有返回值时
|
//有返回值时
|
||||||
if reply != nil {
|
if reply != nil {
|
||||||
//如果是Call同步调用
|
//如果是Call同步调用
|
||||||
hander :=func(Returns interface{}, Err RpcError) {
|
hd := func(Returns interface{}, Err RpcError) {
|
||||||
rpcCall := client.RemovePending(callSeq)
|
rpcCall := client.RemovePending(callSeq)
|
||||||
if rpcCall == nil {
|
if rpcCall == nil {
|
||||||
log.Error("cannot find call seq", log.Uint64("seq", callSeq))
|
log.Error("cannot find call seq", log.Uint64("seq", callSeq))
|
||||||
@@ -370,7 +373,7 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
|
|||||||
rpcCall.Reply = reply
|
rpcCall.Reply = reply
|
||||||
rpcCall.done <- rpcCall
|
rpcCall.done <- rpcCall
|
||||||
}
|
}
|
||||||
paramList = append(paramList, reflect.ValueOf(hander))
|
paramList = append(paramList, reflect.ValueOf(hd))
|
||||||
} else { //无返回值时,是一个requestHandlerNull空回调
|
} else { //无返回值时,是一个requestHandlerNull空回调
|
||||||
paramList = append(paramList, callBack)
|
paramList = append(paramList, callBack)
|
||||||
}
|
}
|
||||||
@@ -437,7 +440,7 @@ func (handler *RpcHandler) goRpc(processor IRpcProcessor, bCast bool, nodeId str
|
|||||||
err, pClientList := handler.funcRpcClient(nodeId, serviceMethod, false, pClientList)
|
err, pClientList := handler.funcRpcClient(nodeId, serviceMethod, false, pClientList)
|
||||||
if len(pClientList) == 0 {
|
if len(pClientList) == 0 {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("call serviceMethod is failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err))
|
log.Error("call serviceMethod is failed", log.String("serviceMethod", serviceMethod), log.ErrorField("error", err))
|
||||||
} else {
|
} else {
|
||||||
log.Error("cannot find serviceMethod", log.String("serviceMethod", serviceMethod))
|
log.Error("cannot find serviceMethod", log.String("serviceMethod", serviceMethod))
|
||||||
}
|
}
|
||||||
@@ -466,7 +469,7 @@ func (handler *RpcHandler) callRpc(timeout time.Duration,nodeId string, serviceM
|
|||||||
pClientList := make([]*Client, 0, maxClusterNode)
|
pClientList := make([]*Client, 0, maxClusterNode)
|
||||||
err, pClientList := handler.funcRpcClient(nodeId, serviceMethod, false, pClientList)
|
err, pClientList := handler.funcRpcClient(nodeId, serviceMethod, false, pClientList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Call serviceMethod is failed",log.ErrorAttr("error",err))
|
log.Error("Call serviceMethod is failed", log.ErrorField("error", err))
|
||||||
return err
|
return err
|
||||||
} else if len(pClientList) <= 0 {
|
} else if len(pClientList) <= 0 {
|
||||||
err = errors.New("Call serviceMethod is error:cannot find " + serviceMethod)
|
err = errors.New("Call serviceMethod is error:cannot find " + serviceMethod)
|
||||||
@@ -512,9 +515,9 @@ func (handler *RpcHandler) asyncCallRpc(timeout time.Duration,nodeId string, ser
|
|||||||
if len(pClientList) == 0 || err != nil {
|
if len(pClientList) == 0 || err != nil {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if nodeId != NodeIdNull {
|
if nodeId != NodeIdNull {
|
||||||
err = fmt.Errorf("cannot find %s from nodeId %d",serviceMethod,nodeId)
|
err = fmt.Errorf("cannot find %s from nodeId %s", serviceMethod, nodeId)
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("No %s service found in the origin network",serviceMethod)
|
err = fmt.Errorf("no %s service found in the origin network", serviceMethod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fVal.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
|
fVal.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
|
||||||
@@ -530,8 +533,7 @@ func (handler *RpcHandler) asyncCallRpc(timeout time.Duration,nodeId string, ser
|
|||||||
}
|
}
|
||||||
|
|
||||||
//2.rpcClient调用
|
//2.rpcClient调用
|
||||||
//如果调用本结点服务
|
return pClientList[0].AsyncCall(pClientList[0].GetTargetNodeId(), timeout, handler.rpcHandler, serviceMethod, fVal, args, reply, )
|
||||||
return pClientList[0].AsyncCall(pClientList[0].GetTargetNodeId(),timeout,handler.rpcHandler, serviceMethod, fVal, args, reply,false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *RpcHandler) GetName() string {
|
func (handler *RpcHandler) GetName() string {
|
||||||
@@ -590,7 +592,7 @@ func (handler *RpcHandler) RawGoNode(rpcProcessorType RpcProcessorType, nodeId s
|
|||||||
pClientList := make([]*Client, 0, 1)
|
pClientList := make([]*Client, 0, 1)
|
||||||
err, pClientList := handler.funcRpcClient(nodeId, serviceName, false, pClientList)
|
err, pClientList := handler.funcRpcClient(nodeId, serviceName, false, pClientList)
|
||||||
if len(pClientList) == 0 || err != nil {
|
if len(pClientList) == 0 || err != nil {
|
||||||
log.Error("call serviceMethod is failed",log.ErrorAttr("error",err))
|
log.Error("call serviceMethod is failed", log.ErrorField("error", err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(pClientList) > 1 {
|
if len(pClientList) > 1 {
|
||||||
@@ -635,7 +637,6 @@ func (handler *RpcHandler) UnmarshalInParam(rpcProcessor IRpcProcessor, serviceM
|
|||||||
return param, err
|
return param, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (handler *RpcHandler) GetRpcServer() FuncRpcServer {
|
func (handler *RpcHandler) GetRpcServer() FuncRpcServer {
|
||||||
return handler.funcRpcServer
|
return handler.funcRpcServer
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,6 @@ func (rn *RpcNats) NewNatsClient(targetNodeId string,localNodeId string,callSet
|
|||||||
|
|
||||||
client.clientId = atomic.AddUint32(&clientSeq, 1)
|
client.clientId = atomic.AddUint32(&clientSeq, 1)
|
||||||
client.targetNodeId = targetNodeId
|
client.targetNodeId = targetNodeId
|
||||||
//client.maxCheckCallRpcCount = DefaultMaxCheckCallRpcCount
|
|
||||||
//client.callRpcTimeout = DefaultRpcTimeout
|
|
||||||
|
|
||||||
natsClient := &rn.NatsClient
|
natsClient := &rn.NatsClient
|
||||||
natsClient.localNodeId = localNodeId
|
natsClient.localNodeId = localNodeId
|
||||||
natsClient.client = &client
|
natsClient.client = &client
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Default_ReadWriteDeadline = 15 * time.Second
|
const Default_ReadWriteDeadline = 15 * time.Second
|
||||||
|
|
||||||
type RpcProcessorType uint8
|
type RpcProcessorType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -30,7 +31,7 @@ type IServer interface {
|
|||||||
|
|
||||||
selfNodeRpcHandlerGo(timeout time.Duration, processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call
|
selfNodeRpcHandlerGo(timeout time.Duration, processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call
|
||||||
myselfRpcHandlerGo(client *Client, handlerName string, serviceMethod string, args interface{}, callBack reflect.Value, reply interface{}) error
|
myselfRpcHandlerGo(client *Client, handlerName string, serviceMethod string, args interface{}, callBack reflect.Value, reply interface{}) error
|
||||||
selfNodeRpcHandlerAsyncGo(timeout time.Duration,client *Client, callerRpcHandler IRpcHandler, noReply bool, handlerName string, serviceMethod string, args interface{}, reply interface{}, callback reflect.Value,cancelable bool) (CancelRpc,error)
|
selfNodeRpcHandlerAsyncGo(timeout time.Duration, client *Client, callerRpcHandler IRpcHandler, noReply bool, handlerName string, serviceMethod string, args interface{}, reply interface{}, callback reflect.Value) (CancelRpc, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type writeResponse func(processor IRpcProcessor, connTag string, serviceMethod string, seq uint64, reply interface{}, rpcError RpcError)
|
type writeResponse func(processor IRpcProcessor, connTag string, serviceMethod string, seq uint64, reply interface{}, rpcError RpcError)
|
||||||
@@ -89,7 +90,6 @@ func (server *Server) Start() error{
|
|||||||
|
|
||||||
server.rpcServer.Addr = ":" + splitAddr[1]
|
server.rpcServer.Addr = ":" + splitAddr[1]
|
||||||
server.rpcServer.MinMsgLen = 2
|
server.rpcServer.MinMsgLen = 2
|
||||||
server.compressBytesLen = server.compressBytesLen
|
|
||||||
if server.maxRpcParamLen > 0 {
|
if server.maxRpcParamLen > 0 {
|
||||||
server.rpcServer.MaxMsgLen = server.maxRpcParamLen
|
server.rpcServer.MaxMsgLen = server.maxRpcParamLen
|
||||||
} else {
|
} else {
|
||||||
@@ -130,7 +130,7 @@ func (agent *RpcAgent) WriteResponse(processor IRpcProcessor, connTag string, se
|
|||||||
defer processor.ReleaseRpcResponse(rpcResponse.RpcResponseData)
|
defer processor.ReleaseRpcResponse(rpcResponse.RpcResponseData)
|
||||||
|
|
||||||
if errM != nil {
|
if errM != nil {
|
||||||
log.Error("mashal RpcResponseData failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",errM))
|
log.Error("marshal RpcResponseData failed", log.String("serviceMethod", serviceMethod), log.ErrorField("error", errM))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ func (agent *RpcAgent) WriteResponse(processor IRpcProcessor, connTag string, se
|
|||||||
|
|
||||||
compressBuff, cErr = compressor.CompressBlock(bytes)
|
compressBuff, cErr = compressor.CompressBlock(bytes)
|
||||||
if cErr != nil {
|
if cErr != nil {
|
||||||
log.Error("CompressBlock failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",cErr))
|
log.Error("CompressBlock failed", log.String("serviceMethod", serviceMethod), log.ErrorField("error", cErr))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(compressBuff) < len(bytes) {
|
if len(compressBuff) < len(bytes) {
|
||||||
@@ -155,35 +155,34 @@ func (agent *RpcAgent) WriteResponse(processor IRpcProcessor, connTag string, se
|
|||||||
compressor.CompressBufferCollection(compressBuff)
|
compressor.CompressBufferCollection(compressBuff)
|
||||||
}
|
}
|
||||||
if errM != nil {
|
if errM != nil {
|
||||||
log.Error("WriteMsg error,Rpc return is fail",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",errM))
|
log.Error("WriteMsg error,Rpc return is fail", log.String("serviceMethod", serviceMethod), log.ErrorField("error", errM))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (agent *RpcAgent) Run() {
|
func (agent *RpcAgent) Run() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.Dump(string(buf[:l]),log.String("error",errString))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
data, err := agent.conn.ReadMsg()
|
data, err := agent.conn.ReadMsg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("read message is error",log.String("remoteAddress",agent.conn.RemoteAddr().String()),log.ErrorAttr("error",err))
|
//will close conn
|
||||||
//will close tcpconn
|
log.Error("read message is error", log.String("remoteAddress", agent.conn.RemoteAddr().String()), log.ErrorField("error", err))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
defer agent.conn.ReleaseReadMsg(data)
|
|
||||||
err = agent.rpcServer.processRpcRequest(data, "", agent.WriteResponse)
|
err = agent.rpcServer.processRpcRequest(data, "", agent.WriteResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("processRpcRequest is error",log.String("remoteAddress",agent.conn.RemoteAddr().String()),log.ErrorAttr("error",err))
|
//will close conn
|
||||||
//will close tcpconn
|
agent.conn.ReleaseReadMsg(data)
|
||||||
|
log.Error("processRpcRequest is error", log.String("remoteAddress", agent.conn.RemoteAddr().String()), log.ErrorField("error", err))
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
agent.conn.ReleaseReadMsg(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,9 +208,8 @@ func (agent *RpcAgent) Destroy() {
|
|||||||
agent.conn.Destroy()
|
agent.conn.Destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) NewAgent(c *network.TCPConn) network.Agent {
|
func (server *Server) NewAgent(c network.Conn) network.Agent {
|
||||||
agent := &RpcAgent{conn: c, rpcServer: server}
|
agent := &RpcAgent{conn: c, rpcServer: server}
|
||||||
|
|
||||||
return agent
|
return agent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,12 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/duanhf2012/origin/v2/concurrent"
|
||||||
"github.com/duanhf2012/origin/v2/event"
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
rpcHandle "github.com/duanhf2012/origin/v2/rpc"
|
rpcHandle "github.com/duanhf2012/origin/v2/rpc"
|
||||||
"github.com/duanhf2012/origin/v2/util/timer"
|
"github.com/duanhf2012/origin/v2/util/timer"
|
||||||
"github.com/duanhf2012/origin/v2/concurrent"
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
const InitModuleId = 1e9
|
const InitModuleId = 1e9
|
||||||
@@ -35,9 +36,9 @@ type IModule interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type IModuleTimer interface {
|
type IModuleTimer interface {
|
||||||
AfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer
|
SafeAfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer
|
||||||
CronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer.Cron
|
SafeCronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer.Cron
|
||||||
NewTicker(d time.Duration, cb func(*timer.Ticker)) *timer.Ticker
|
SafeNewTicker(d time.Duration, cb func(*timer.Ticker)) *timer.Ticker
|
||||||
}
|
}
|
||||||
|
|
||||||
type Module struct {
|
type Module struct {
|
||||||
@@ -46,7 +47,7 @@ type Module struct {
|
|||||||
moduleName string //模块名称
|
moduleName string //模块名称
|
||||||
parent IModule //父亲
|
parent IModule //父亲
|
||||||
self IModule //自己
|
self IModule //自己
|
||||||
child map[uint32]IModule //孩子们
|
child []IModule //孩子们
|
||||||
mapActiveTimer map[timer.ITimer]struct{}
|
mapActiveTimer map[timer.ITimer]struct{}
|
||||||
mapActiveIdTimer map[uint64]timer.ITimer
|
mapActiveIdTimer map[uint64]timer.ITimer
|
||||||
dispatcher *timer.Dispatcher //timer
|
dispatcher *timer.Dispatcher //timer
|
||||||
@@ -93,10 +94,7 @@ func (m *Module) AddModule(module IModule) (uint32, error) {
|
|||||||
pAddModule.moduleId = m.NewModuleId()
|
pAddModule.moduleId = m.NewModuleId()
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.child == nil {
|
_,ok := m.ancestor.getBaseModule().(*Module).descendants[module.GetModuleId()]
|
||||||
m.child = map[uint32]IModule{}
|
|
||||||
}
|
|
||||||
_, ok := m.child[module.GetModuleId()]
|
|
||||||
if ok == true {
|
if ok == true {
|
||||||
return 0, fmt.Errorf("exists module id %d", module.GetModuleId())
|
return 0, fmt.Errorf("exists module id %d", module.GetModuleId())
|
||||||
}
|
}
|
||||||
@@ -109,29 +107,33 @@ func (m *Module) AddModule(module IModule) (uint32, error) {
|
|||||||
pAddModule.eventHandler = event.NewEventHandler()
|
pAddModule.eventHandler = event.NewEventHandler()
|
||||||
pAddModule.eventHandler.Init(m.eventHandler.GetEventProcessor())
|
pAddModule.eventHandler.Init(m.eventHandler.GetEventProcessor())
|
||||||
pAddModule.IConcurrent = m.IConcurrent
|
pAddModule.IConcurrent = m.IConcurrent
|
||||||
|
|
||||||
|
m.child = append(m.child,module)
|
||||||
|
m.ancestor.getBaseModule().(*Module).descendants[module.GetModuleId()] = module
|
||||||
|
|
||||||
err := module.OnInit()
|
err := module.OnInit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
delete(m.ancestor.getBaseModule().(*Module).descendants, module.GetModuleId())
|
||||||
|
m.child = m.child[:len(m.child)-1]
|
||||||
|
log.Error("module OnInit error",log.String("ModuleName",module.GetModuleName()),log.ErrorField("err",err))
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
m.child[module.GetModuleId()] = module
|
|
||||||
m.ancestor.getBaseModule().(*Module).descendants[module.GetModuleId()] = module
|
|
||||||
|
|
||||||
log.Debug("Add module " + module.GetModuleName() + " completed")
|
log.Debug("Add module " + module.GetModuleName() + " completed")
|
||||||
return module.GetModuleId(), nil
|
return module.GetModuleId(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) ReleaseModule(moduleId uint32) {
|
func (m *Module) ReleaseModule(moduleId uint32) {
|
||||||
pModule := m.GetModule(moduleId).getBaseModule().(*Module)
|
pModule := m.GetModule(moduleId).getBaseModule().(*Module)
|
||||||
|
pModule.self.OnRelease()
|
||||||
|
log.Debug("Release module " + pModule.GetModuleName())
|
||||||
|
|
||||||
//释放子孙
|
for i:=len(pModule.child)-1; i>=0; i-- {
|
||||||
for id := range pModule.child {
|
m.ReleaseModule(pModule.child[i].GetModuleId())
|
||||||
m.ReleaseModule(id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pModule.self.OnRelease()
|
|
||||||
pModule.GetEventHandler().Destroy()
|
pModule.GetEventHandler().Destroy()
|
||||||
log.Debug("Release module "+ pModule.GetModuleName())
|
|
||||||
for pTimer := range pModule.mapActiveTimer {
|
for pTimer := range pModule.mapActiveTimer {
|
||||||
pTimer.Cancel()
|
pTimer.Cancel()
|
||||||
}
|
}
|
||||||
@@ -140,7 +142,10 @@ func (m *Module) ReleaseModule(moduleId uint32) {
|
|||||||
t.Cancel()
|
t.Cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(m.child, moduleId)
|
m.child = slices.DeleteFunc(m.child, func(module IModule) bool {
|
||||||
|
return module.GetModuleId() == moduleId
|
||||||
|
})
|
||||||
|
|
||||||
delete(m.ancestor.getBaseModule().(*Module).descendants, moduleId)
|
delete(m.ancestor.getBaseModule().(*Module).descendants, moduleId)
|
||||||
|
|
||||||
//清理被删除的Module
|
//清理被删除的Module
|
||||||
@@ -208,6 +213,7 @@ func (m *Module) OnAddTimer(t timer.ITimer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: this function simply calls SafeAfterFunc
|
||||||
func (m *Module) AfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer {
|
func (m *Module) AfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer {
|
||||||
if m.mapActiveTimer == nil {
|
if m.mapActiveTimer == nil {
|
||||||
m.mapActiveTimer = map[timer.ITimer]struct{}{}
|
m.mapActiveTimer = map[timer.ITimer]struct{}{}
|
||||||
@@ -216,6 +222,7 @@ func (m *Module) AfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer
|
|||||||
return m.dispatcher.AfterFunc(d, nil, cb, m.OnCloseTimer, m.OnAddTimer)
|
return m.dispatcher.AfterFunc(d, nil, cb, m.OnCloseTimer, m.OnAddTimer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: this function simply calls SafeCronFunc
|
||||||
func (m *Module) CronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer.Cron {
|
func (m *Module) CronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer.Cron {
|
||||||
if m.mapActiveTimer == nil {
|
if m.mapActiveTimer == nil {
|
||||||
m.mapActiveTimer = map[timer.ITimer]struct{}{}
|
m.mapActiveTimer = map[timer.ITimer]struct{}{}
|
||||||
@@ -224,6 +231,7 @@ func (m *Module) CronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer
|
|||||||
return m.dispatcher.CronFunc(cronExpr, nil, cb, m.OnCloseTimer, m.OnAddTimer)
|
return m.dispatcher.CronFunc(cronExpr, nil, cb, m.OnCloseTimer, m.OnAddTimer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: this function simply calls SafeNewTicker
|
||||||
func (m *Module) NewTicker(d time.Duration, cb func(*timer.Ticker)) *timer.Ticker {
|
func (m *Module) NewTicker(d time.Duration, cb func(*timer.Ticker)) *timer.Ticker {
|
||||||
if m.mapActiveTimer == nil {
|
if m.mapActiveTimer == nil {
|
||||||
m.mapActiveTimer = map[timer.ITimer]struct{}{}
|
m.mapActiveTimer = map[timer.ITimer]struct{}{}
|
||||||
@@ -278,7 +286,7 @@ 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.Warning("timerId is invalid")
|
log.Warn("timerId is invalid")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +297,7 @@ func (m *Module) CancelTimerId(timerId *uint64) bool {
|
|||||||
|
|
||||||
t, ok := m.mapActiveIdTimer[*timerId]
|
t, ok := m.mapActiveIdTimer[*timerId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
log.Stack("cannot find timer id ", log.Uint64("timerId",*timerId))
|
log.StackError("cannot find timer id ", log.Uint64("timerId", *timerId))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,24 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/concurrent"
|
||||||
"github.com/duanhf2012/origin/v2/event"
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/v2/profiler"
|
"github.com/duanhf2012/origin/v2/profiler"
|
||||||
"github.com/duanhf2012/origin/v2/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
"github.com/duanhf2012/origin/v2/util/timer"
|
"github.com/duanhf2012/origin/v2/util/timer"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"github.com/duanhf2012/origin/v2/concurrent"
|
|
||||||
"encoding/json"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var timerDispatcherLen = 100000
|
var timerDispatcherLen = 100000
|
||||||
var maxServiceEventChannelNum = 2000000
|
var maxServiceEventChannelNum = 2000000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type IService interface {
|
type IService interface {
|
||||||
concurrent.IConcurrent
|
concurrent.IConcurrent
|
||||||
Init(iService IService, getClientFun rpc.FuncRpcClient, getServerFun rpc.FuncRpcServer, serviceCfg interface{})
|
Init(iService IService, getClientFun rpc.FuncRpcClient, getServerFun rpc.FuncRpcServer, serviceCfg interface{})
|
||||||
@@ -69,8 +66,6 @@ type Service struct {
|
|||||||
closeSig chan struct{}
|
closeSig chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// DiscoveryServiceEvent 发现服务结点
|
// DiscoveryServiceEvent 发现服务结点
|
||||||
type DiscoveryServiceEvent struct {
|
type DiscoveryServiceEvent struct {
|
||||||
IsDiscovery bool
|
IsDiscovery bool
|
||||||
@@ -86,7 +81,6 @@ type EtcdServiceRecordEvent struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Empty struct {
|
type Empty struct {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetMaxServiceChannel(maxEventChannel int) {
|
func SetMaxServiceChannel(maxEventChannel int) {
|
||||||
@@ -97,7 +91,6 @@ func (rpcEventData *DiscoveryServiceEvent) GetEventType() event.EventType{
|
|||||||
return event.Sys_Event_DiscoverService
|
return event.Sys_Event_DiscoverService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (s *Service) OnSetup(iService IService) {
|
func (s *Service) OnSetup(iService IService) {
|
||||||
if iService.GetName() == "" {
|
if iService.GetName() == "" {
|
||||||
s.name = reflect.Indirect(reflect.ValueOf(iService)).Type().Name()
|
s.name = reflect.Indirect(reflect.ValueOf(iService)).Type().Name()
|
||||||
@@ -107,7 +100,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.Fatal("rofiler.RegProfiler "+s.GetName()+" fail.")
|
log.Fatal("profiler.RegProfiler " + s.GetName() + " fail.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +144,7 @@ func (s *Service) Start() {
|
|||||||
s.startStatus = true
|
s.startStatus = true
|
||||||
atomic.StoreInt32(&s.isRelease, 0)
|
atomic.StoreInt32(&s.isRelease, 0)
|
||||||
var waitRun sync.WaitGroup
|
var waitRun sync.WaitGroup
|
||||||
log.Info(s.GetName()+" service is running",)
|
log.Info(s.GetName() + " service is running")
|
||||||
s.self.(IService).OnStart()
|
s.self.(IService).OnStart()
|
||||||
|
|
||||||
for i := int32(0); i < s.goroutineNum; i++ {
|
for i := int32(0); i < s.goroutineNum; i++ {
|
||||||
@@ -170,8 +163,8 @@ func (s *Service) run() {
|
|||||||
defer s.wg.Done()
|
defer s.wg.Done()
|
||||||
var bStop = false
|
var bStop = false
|
||||||
|
|
||||||
concurrent := s.IConcurrent.(*concurrent.Concurrent)
|
cr := s.IConcurrent.(*concurrent.Concurrent)
|
||||||
concurrentCBChannel := concurrent.GetCallBackChannel()
|
concurrentCBChannel := cr.GetCallBackChannel()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var analyzer *profiler.Analyzer
|
var analyzer *profiler.Analyzer
|
||||||
@@ -179,13 +172,13 @@ func (s *Service) run() {
|
|||||||
case <-s.closeSig:
|
case <-s.closeSig:
|
||||||
bStop = true
|
bStop = true
|
||||||
s.Release()
|
s.Release()
|
||||||
concurrent.Close()
|
cr.Close()
|
||||||
case cb := <-concurrentCBChannel:
|
case cb := <-concurrentCBChannel:
|
||||||
concurrent.DoCallback(cb)
|
cr.DoCallback(cb)
|
||||||
case ev := <-s.chanEvent:
|
case ev := <-s.chanEvent:
|
||||||
switch ev.GetEventType() {
|
switch ev.GetEventType() {
|
||||||
case event.Sys_Event_Retire:
|
case event.Sys_Event_Retire:
|
||||||
log.Info("service OnRetire",log.String("servceName",s.GetName()))
|
log.Info("service OnRetire", log.String("serviceName", s.GetName()))
|
||||||
s.self.(IService).OnRetire()
|
s.self.(IService).OnRetire()
|
||||||
case event.ServiceRpcRequestEvent:
|
case event.ServiceRpcRequestEvent:
|
||||||
cEvent, ok := ev.(*event.Event)
|
cEvent, ok := ev.(*event.Event)
|
||||||
@@ -267,17 +260,16 @@ func (s *Service) SetName(serviceName string) {
|
|||||||
func (s *Service) Release() {
|
func (s *Service) Release() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.Dump(string(buf[:l]),log.String("error",errString))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if atomic.AddInt32(&s.isRelease, -1) == -1 {
|
if atomic.AddInt32(&s.isRelease, -1) == -1 {
|
||||||
s.self.OnRelease()
|
s.self.OnRelease()
|
||||||
|
for i:=len(s.child)-1; i>=0; i-- {
|
||||||
|
s.ReleaseModule(s.child[i].GetModuleId())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) OnRelease() {
|
func (s *Service) OnRelease() {
|
||||||
@@ -336,11 +328,11 @@ func (s *Service) OnStart(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) OnNodeConnEvent(ev event.IEvent) {
|
func (s *Service) OnNodeConnEvent(ev event.IEvent) {
|
||||||
event := ev.(*rpc.RpcConnEvent)
|
re := ev.(*rpc.RpcConnEvent)
|
||||||
if event.IsConnect {
|
if re.IsConnect {
|
||||||
s.nodeConnLister.OnNodeConnected(event.NodeId)
|
s.nodeConnLister.OnNodeConnected(re.NodeId)
|
||||||
} else {
|
} else {
|
||||||
s.nodeConnLister.OnNodeDisconnect(event.NodeId)
|
s.nodeConnLister.OnNodeDisconnect(re.NodeId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,11 +346,11 @@ func (s *Service) OnNatsConnEvent(ev event.IEvent){
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) OnDiscoverServiceEvent(ev event.IEvent) {
|
func (s *Service) OnDiscoverServiceEvent(ev event.IEvent) {
|
||||||
event := ev.(*DiscoveryServiceEvent)
|
de := ev.(*DiscoveryServiceEvent)
|
||||||
if event.IsDiscovery {
|
if de.IsDiscovery {
|
||||||
s.discoveryServiceLister.OnDiscoveryService(event.NodeId,event.ServiceName)
|
s.discoveryServiceLister.OnDiscoveryService(de.NodeId, de.ServiceName)
|
||||||
} else {
|
} else {
|
||||||
s.discoveryServiceLister.OnUnDiscoveryService(event.NodeId,event.ServiceName)
|
s.discoveryServiceLister.OnUnDiscoveryService(de.NodeId, de.ServiceName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,7 +409,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.Error(err.Error())
|
log.Error(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -442,6 +434,7 @@ func (s *Service) SetEventChannelNum(num int){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: replace it with the OpenConcurrent function
|
||||||
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 {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func Init() {
|
|||||||
for _,s := range setupServiceList {
|
for _,s := range setupServiceList {
|
||||||
err := s.OnInit()
|
err := s.OnInit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to initialize "+s.GetName()+" service",log.ErrorAttr("err",err))
|
log.Error("Failed to initialize "+s.GetName()+" service",log.ErrorField("err",err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func (ft *FrameTimer) addTimerData(timerID FrameTimerID, frameNum FrameNumber, t
|
|||||||
td.cb = cb
|
td.cb = cb
|
||||||
td.idx = -1
|
td.idx = -1
|
||||||
td.tickerFrameNum = tickerFrameNum
|
td.tickerFrameNum = tickerFrameNum
|
||||||
|
td.ctx = ctx
|
||||||
ft.mapTimer[timerID] = td
|
ft.mapTimer[timerID] = td
|
||||||
return td
|
return td
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func (slf *SyncHttpResponse) Get(timeoutMs int) HttpResponse {
|
|||||||
return rsp
|
return rsp
|
||||||
}
|
}
|
||||||
return HttpResponse{
|
return HttpResponse{
|
||||||
Err: fmt.Errorf("Getting the return result timeout [%d]ms", timeoutMs),
|
Err: fmt.Errorf("getting the return result timeout [%d]ms", timeoutMs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ func (m *HttpClientModule) InitHttpClient(transport http.RoundTripper,timeout ti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *HttpClientModule) Init(proxyUrl string, maxpool int, dialTimeout time.Duration,dialKeepAlive time.Duration,idleConnTimeout time.Duration,timeout time.Duration) {
|
func (m *HttpClientModule) Init(proxyUrl string, maxPool int, dialTimeout time.Duration, dialKeepAlive time.Duration, idleConnTimeout time.Duration, timeout time.Duration) {
|
||||||
type ProxyFun func(_ *http.Request) (*url.URL, error)
|
type ProxyFun func(_ *http.Request) (*url.URL, error)
|
||||||
var proxyFun ProxyFun
|
var proxyFun ProxyFun
|
||||||
if proxyUrl != "" {
|
if proxyUrl != "" {
|
||||||
@@ -66,8 +66,8 @@ func (m *HttpClientModule) Init(proxyUrl string, maxpool int, dialTimeout time.D
|
|||||||
Timeout: dialTimeout,
|
Timeout: dialTimeout,
|
||||||
KeepAlive: dialKeepAlive,
|
KeepAlive: dialKeepAlive,
|
||||||
}).DialContext,
|
}).DialContext,
|
||||||
MaxIdleConns: maxpool,
|
MaxIdleConns: maxPool,
|
||||||
MaxIdleConnsPerHost: maxpool,
|
MaxIdleConnsPerHost: maxPool,
|
||||||
IdleConnTimeout: idleConnTimeout,
|
IdleConnTimeout: idleConnTimeout,
|
||||||
Proxy: proxyFun,
|
Proxy: proxyFun,
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
|||||||
@@ -75,12 +75,12 @@ func (s *Session) NextSeq(db string, collection string, id interface{}) (int, er
|
|||||||
return res.Seq, err
|
return res.Seq, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexKeys[索引][每个索引key字段]
|
// EnsureIndex indexKeys[索引][每个索引key字段]
|
||||||
func (s *Session) EnsureIndex(db string, collection string, indexKeys [][]string, bBackground bool, sparse bool, asc bool) error {
|
func (s *Session) EnsureIndex(db string, collection string, indexKeys [][]string, bBackground bool, sparse bool, asc bool) error {
|
||||||
return s.ensureIndex(db, collection, indexKeys, bBackground, false, sparse, asc)
|
return s.ensureIndex(db, collection, indexKeys, bBackground, false, sparse, asc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexKeys[索引][每个索引key字段]
|
// EnsureUniqueIndex indexKeys[索引][每个索引key字段]
|
||||||
func (s *Session) EnsureUniqueIndex(db string, collection string, indexKeys [][]string, bBackground bool, sparse bool, asc bool) error {
|
func (s *Session) EnsureUniqueIndex(db string, collection string, indexKeys [][]string, bBackground bool, sparse bool, asc bool) error {
|
||||||
return s.ensureIndex(db, collection, indexKeys, bBackground, true, sparse, asc)
|
return s.ensureIndex(db, collection, indexKeys, bBackground, true, sparse, asc)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ type PingExecute struct {
|
|||||||
pintExit chan bool
|
pintExit chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// DBModule ...
|
|
||||||
type MySQLModule struct {
|
type MySQLModule struct {
|
||||||
service.Module
|
service.Module
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
@@ -53,7 +52,7 @@ type DBResult struct {
|
|||||||
RowsAffected int64
|
RowsAffected int64
|
||||||
|
|
||||||
rowNum int
|
rowNum int
|
||||||
RowInfo map[string][]interface{} //map[fieldname][row]sql.NullString
|
RowInfo map[string][]interface{} //map[fieldName][row]sql.NullString
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataSetList struct {
|
type DataSetList struct {
|
||||||
@@ -63,13 +62,11 @@ type DataSetList struct {
|
|||||||
blur bool
|
blur bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type dbControl interface {
|
type dbControl interface {
|
||||||
Exec(query string, args ...interface{}) (sql.Result, error)
|
Exec(query string, args ...interface{}) (sql.Result, error)
|
||||||
Query(query string, args ...interface{}) (*sql.Rows, error)
|
Query(query string, args ...interface{}) (*sql.Rows, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (m *MySQLModule) Init(url string, userName string, password string, dbname string, maxConn int) error {
|
func (m *MySQLModule) Init(url string, userName string, password string, dbname string, maxConn int) error {
|
||||||
m.url = url
|
m.url = url
|
||||||
m.username = userName
|
m.username = userName
|
||||||
@@ -116,7 +113,7 @@ func (slf *Tx) Commit() error {
|
|||||||
return slf.tx.Commit()
|
return slf.tx.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryEx executes a query that return rows.
|
// Query executes a query that return rows.
|
||||||
func (slf *Tx) Query(strQuery string, args ...interface{}) (*DataSetList, error) {
|
func (slf *Tx) Query(strQuery string, args ...interface{}) (*DataSetList, error) {
|
||||||
return query(slf.slowDuration, slf.tx, strQuery, args...)
|
return query(slf.slowDuration, slf.tx, strQuery, args...)
|
||||||
}
|
}
|
||||||
@@ -225,12 +222,12 @@ func query(slowDuration time.Duration,db dbControl,strQuery string, args ...inte
|
|||||||
|
|
||||||
if checkArgs(args) != nil {
|
if checkArgs(args) != nil {
|
||||||
log.Error("CheckArgs is error :%s", strQuery)
|
log.Error("CheckArgs is error :%s", strQuery)
|
||||||
return &datasetList, fmt.Errorf("CheckArgs is error!")
|
return &datasetList, fmt.Errorf("checkArgs is error")
|
||||||
}
|
}
|
||||||
|
|
||||||
if db == nil {
|
if db == nil {
|
||||||
log.Error("cannot connect database:%s", strQuery)
|
log.Error("cannot connect database:%s", strQuery)
|
||||||
return &datasetList, fmt.Errorf("cannot connect database!")
|
return &datasetList, fmt.Errorf("cannot connect database")
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeFuncStart := time.Now()
|
TimeFuncStart := time.Now()
|
||||||
@@ -256,7 +253,7 @@ func query(slowDuration time.Duration,db dbControl,strQuery string, args ...inte
|
|||||||
if dbResult.RowInfo == nil {
|
if dbResult.RowInfo == nil {
|
||||||
dbResult.RowInfo = make(map[string][]interface{})
|
dbResult.RowInfo = make(map[string][]interface{})
|
||||||
}
|
}
|
||||||
//RowInfo map[string][][]sql.NullString //map[fieldname][row][column]sql.NullString
|
|
||||||
colField, err := rows.Columns()
|
colField, err := rows.Columns()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &datasetList, err
|
return &datasetList, err
|
||||||
@@ -268,10 +265,10 @@ func query(slowDuration time.Duration,db dbControl,strQuery string, args ...inte
|
|||||||
}
|
}
|
||||||
rows.Scan(valuePtrs...)
|
rows.Scan(valuePtrs...)
|
||||||
|
|
||||||
for idx, fieldname := range colField {
|
for idx, fieldName := range colField {
|
||||||
fieldRowData := dbResult.RowInfo[strings.ToLower(fieldname)]
|
fieldRowData := dbResult.RowInfo[strings.ToLower(fieldName)]
|
||||||
fieldRowData = append(fieldRowData, valuePtrs[idx])
|
fieldRowData = append(fieldRowData, valuePtrs[idx])
|
||||||
dbResult.RowInfo[strings.ToLower(fieldname)] = fieldRowData
|
dbResult.RowInfo[strings.ToLower(fieldName)] = fieldRowData
|
||||||
}
|
}
|
||||||
dbResult.rowNum += 1
|
dbResult.rowNum += 1
|
||||||
}
|
}
|
||||||
@@ -295,12 +292,12 @@ func exec(slowDuration time.Duration,db dbControl,strSql string, args ...interfa
|
|||||||
ret := &DBResult{}
|
ret := &DBResult{}
|
||||||
if db == nil {
|
if db == nil {
|
||||||
log.Error("cannot connect database:%s", strSql)
|
log.Error("cannot connect database:%s", strSql)
|
||||||
return ret, fmt.Errorf("cannot connect database!")
|
return ret, fmt.Errorf("cannot connect database")
|
||||||
}
|
}
|
||||||
|
|
||||||
if checkArgs(args) != nil {
|
if checkArgs(args) != nil {
|
||||||
log.Error("CheckArgs is error :%s", strSql)
|
log.Error("CheckArgs is error :%s", strSql)
|
||||||
return ret, fmt.Errorf("CheckArgs is error!")
|
return ret, fmt.Errorf("checkArgs is error")
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeFuncStart := time.Now()
|
TimeFuncStart := time.Now()
|
||||||
@@ -361,21 +358,21 @@ func (ds *DataSetList) slice2interface(in interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v := reflect.ValueOf(in).Elem()
|
v := reflect.ValueOf(in).Elem()
|
||||||
newv := reflect.MakeSlice(v.Type(), 0, length)
|
newV := reflect.MakeSlice(v.Type(), 0, length)
|
||||||
v.Set(newv)
|
v.Set(newV)
|
||||||
v.SetLen(length)
|
v.SetLen(length)
|
||||||
|
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
idxv := v.Index(i)
|
idxV := v.Index(i)
|
||||||
if idxv.Kind() == reflect.Ptr {
|
if idxV.Kind() == reflect.Ptr {
|
||||||
newObj := reflect.New(idxv.Type().Elem())
|
newObj := reflect.New(idxV.Type().Elem())
|
||||||
v.Index(i).Set(newObj)
|
v.Index(i).Set(newObj)
|
||||||
idxv = newObj
|
idxV = newObj
|
||||||
} else {
|
} else {
|
||||||
idxv = idxv.Addr()
|
idxV = idxV.Addr()
|
||||||
}
|
}
|
||||||
|
|
||||||
err := ds.rowData2interface(i, ds.dataSetList[ds.currentDataSetIdx].RowInfo, idxv)
|
err := ds.rowData2interface(i, ds.dataSetList[ds.currentDataSetIdx].RowInfo, idxV)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -390,7 +387,7 @@ func (ds *DataSetList) rowData2interface(rowIdx int, m map[string][]interface{},
|
|||||||
typ := t.Elem()
|
typ := t.Elem()
|
||||||
|
|
||||||
if !val.IsValid() {
|
if !val.IsValid() {
|
||||||
return errors.New("Incorrect data type!")
|
return errors.New("incorrect data type")
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < val.NumField(); i++ {
|
for i := 0; i < val.NumField(); i++ {
|
||||||
@@ -402,11 +399,11 @@ func (ds *DataSetList) rowData2interface(rowIdx int, m map[string][]interface{},
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tag != "" && tag != "-" {
|
if tag != "" && tag != "-" {
|
||||||
vtag := strings.ToLower(tag)
|
vTag := strings.ToLower(tag)
|
||||||
columnData, ok := m[vtag]
|
columnData, ok := m[vTag]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
if !ds.blur {
|
if !ds.blur {
|
||||||
return fmt.Errorf("Cannot find filed name %s!", vtag)
|
return fmt.Errorf("cannot find filed name %s", vTag)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -416,12 +413,12 @@ func (ds *DataSetList) rowData2interface(rowIdx int, m map[string][]interface{},
|
|||||||
meta := columnData[rowIdx].(*sql.NullString)
|
meta := columnData[rowIdx].(*sql.NullString)
|
||||||
if !ok {
|
if !ok {
|
||||||
if !ds.blur {
|
if !ds.blur {
|
||||||
return fmt.Errorf("No corresponding field was found in the result set %s!", tag)
|
return fmt.Errorf("no corresponding field was found in the result set %s", tag)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !value.CanSet() {
|
if !value.CanSet() {
|
||||||
return errors.New("Struct fields do not have read or write permissions!")
|
return errors.New("struct fields do not have read or write permissions")
|
||||||
}
|
}
|
||||||
|
|
||||||
if meta.Valid == false {
|
if meta.Valid == false {
|
||||||
@@ -460,7 +457,7 @@ func (ds *DataSetList) rowData2interface(rowIdx int, m map[string][]interface{},
|
|||||||
}
|
}
|
||||||
value.SetBool(b)
|
value.SetBool(b)
|
||||||
default:
|
default:
|
||||||
return errors.New("The database map has unrecognized data types!")
|
return errors.New("the database map has unrecognized data types")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,10 @@ import (
|
|||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/v2/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"log/slog"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type IGinProcessor interface {
|
type IGinProcessor interface {
|
||||||
@@ -69,28 +68,28 @@ func (gm *GinModule) eventHandler(ev event.IEvent) {
|
|||||||
|
|
||||||
func (gm *GinModule) Start() {
|
func (gm *GinModule) Start() {
|
||||||
gm.srv.Addr = gm.listenAddr
|
gm.srv.Addr = gm.listenAddr
|
||||||
log.Info("http start listen", slog.Any("addr", gm.listenAddr))
|
log.Info("http start listen", log.Any("addr", gm.listenAddr))
|
||||||
go func() {
|
go func() {
|
||||||
err := gm.srv.ListenAndServe()
|
err := gm.srv.ListenAndServe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("ListenAndServe error", slog.Any("error", err.Error()))
|
log.Error("ListenAndServe error", log.Any("error", err.Error()))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gm *GinModule) StartTLS(certFile, keyFile string) {
|
func (gm *GinModule) StartTLS(certFile, keyFile string) {
|
||||||
log.Info("http start listen", slog.Any("addr", gm.listenAddr))
|
log.Info("http start listen", log.Any("addr", gm.listenAddr))
|
||||||
go func() {
|
go func() {
|
||||||
err := gm.srv.ListenAndServeTLS(certFile, keyFile)
|
err := gm.srv.ListenAndServeTLS(certFile, keyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("ListenAndServeTLS error", slog.Any("error", err.Error()))
|
log.Fatal("ListenAndServeTLS error", log.Any("error", err.Error()))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gm *GinModule) Stop(ctx context.Context) {
|
func (gm *GinModule) Stop(ctx context.Context) {
|
||||||
if err := gm.srv.Shutdown(ctx); err != nil {
|
if err := gm.srv.Shutdown(ctx); err != nil {
|
||||||
log.Error("Server Shutdown", slog.Any("error", err))
|
log.Error("Server Shutdown", log.Any("error", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +209,7 @@ func (gm *GinModule) handleMethod(httpMethod, relativePath string, handlers ...S
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
log.Error("GinModule process timeout", slog.Any("path", c.Request.URL.Path))
|
log.Error("GinModule process timeout", log.Any("path", c.Request.URL.Path))
|
||||||
c.AbortWithStatus(http.StatusRequestTimeout)
|
c.AbortWithStatus(http.StatusRequestTimeout)
|
||||||
case <-chanWait:
|
case <-chanWait:
|
||||||
}
|
}
|
||||||
210
sysmodule/netmodule/kcpmodule/KcpModule.go
Normal file
210
sysmodule/netmodule/kcpmodule/KcpModule.go
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
package kcpmodule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
|
"github.com/duanhf2012/origin/v2/network/processor"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
"github.com/xtaci/kcp-go/v5"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type KcpModule struct {
|
||||||
|
service.Module
|
||||||
|
blockCrypt kcp.BlockCrypt
|
||||||
|
|
||||||
|
mapClientLocker sync.RWMutex
|
||||||
|
mapClient map[string]*Client
|
||||||
|
process processor.IRawProcessor
|
||||||
|
|
||||||
|
kcpServer network.KCPServer
|
||||||
|
kcpCfg *network.KcpCfg
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
id string
|
||||||
|
kcpConn *network.NetConn
|
||||||
|
kcpModule *KcpModule
|
||||||
|
}
|
||||||
|
|
||||||
|
type KcpPackType int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
KPTConnected KcpPackType = 0
|
||||||
|
KPTDisConnected KcpPackType = 1
|
||||||
|
KPTPack KcpPackType = 2
|
||||||
|
KPTUnknownPack KcpPackType = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type KcpPack struct {
|
||||||
|
Type KcpPackType //0表示连接 1表示断开 2表示数据
|
||||||
|
ClientId string
|
||||||
|
Data interface{}
|
||||||
|
RecyclerReaderBytes func(data []byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) OnInit() error {
|
||||||
|
if km.kcpCfg == nil || km.process == nil {
|
||||||
|
return fmt.Errorf("please call the Init function correctly")
|
||||||
|
}
|
||||||
|
|
||||||
|
km.mapClient = make(map[string]*Client, km.kcpCfg.MaxConnNum)
|
||||||
|
km.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_Kcp, km.GetEventHandler(), km.kcpEventHandler)
|
||||||
|
km.process.SetByteOrder(km.kcpCfg.LittleEndian)
|
||||||
|
km.kcpServer.Init(km.kcpCfg)
|
||||||
|
km.kcpServer.NewAgent = km.NewAgent
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) Init(kcpCfg *network.KcpCfg, process processor.IRawProcessor) {
|
||||||
|
km.kcpCfg = kcpCfg
|
||||||
|
km.process = process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) Start() error {
|
||||||
|
return km.kcpServer.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) kcpEventHandler(ev event.IEvent) {
|
||||||
|
e := ev.(*event.Event)
|
||||||
|
switch KcpPackType(e.IntExt[0]) {
|
||||||
|
case KPTConnected:
|
||||||
|
km.process.ConnectedRoute(e.StringExt[0])
|
||||||
|
case KPTDisConnected:
|
||||||
|
km.process.DisConnectedRoute(e.StringExt[0])
|
||||||
|
case KPTUnknownPack:
|
||||||
|
km.process.UnknownMsgRoute(e.StringExt[0], e.Data, e.AnyExt[0].(func(data []byte)))
|
||||||
|
case KPTPack:
|
||||||
|
km.process.MsgRoute(e.StringExt[0], e.Data, e.AnyExt[0].(func(data []byte)))
|
||||||
|
}
|
||||||
|
|
||||||
|
event.DeleteEvent(ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) SetBlob(blockCrypt kcp.BlockCrypt) {
|
||||||
|
km.blockCrypt = blockCrypt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) OnConnected(c *Client) {
|
||||||
|
ev := event.NewEvent()
|
||||||
|
ev.Type = event.Sys_Event_Kcp
|
||||||
|
ev.IntExt[0] = int64(KPTConnected)
|
||||||
|
ev.StringExt[0] = c.id
|
||||||
|
|
||||||
|
km.NotifyEvent(ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) OnClose(c *Client) {
|
||||||
|
ev := event.NewEvent()
|
||||||
|
ev.Type = event.Sys_Event_Kcp
|
||||||
|
ev.IntExt[0] = int64(KPTDisConnected)
|
||||||
|
ev.StringExt[0] = c.id
|
||||||
|
|
||||||
|
km.NotifyEvent(ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) newClient(conn network.Conn) *Client {
|
||||||
|
km.mapClientLocker.Lock()
|
||||||
|
defer km.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
pClient := &Client{kcpConn: conn.(*network.NetConn), id: primitive.NewObjectID().Hex()}
|
||||||
|
pClient.kcpModule = km
|
||||||
|
km.mapClient[pClient.id] = pClient
|
||||||
|
|
||||||
|
return pClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) GetProcessor() processor.IRawProcessor {
|
||||||
|
return km.process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) SendRawMsg(clientId string, data []byte) error {
|
||||||
|
km.mapClientLocker.Lock()
|
||||||
|
client, ok := km.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
km.mapClientLocker.Unlock()
|
||||||
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
|
}
|
||||||
|
km.mapClientLocker.Unlock()
|
||||||
|
return client.kcpConn.WriteMsg(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) Close(clientId string) {
|
||||||
|
km.mapClientLocker.Lock()
|
||||||
|
client, ok := km.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
km.mapClientLocker.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
km.mapClientLocker.Unlock()
|
||||||
|
client.kcpConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) GetClientIp(clientId string) string {
|
||||||
|
km.mapClientLocker.Lock()
|
||||||
|
defer km.mapClientLocker.Unlock()
|
||||||
|
client, ok := km.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
removeAddr := client.kcpConn.RemoteAddr()
|
||||||
|
if removeAddr != nil {
|
||||||
|
return removeAddr.String()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) NewAgent(conn network.Conn) network.Agent {
|
||||||
|
c := km.newClient(conn)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) Run() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
log.StackError(fmt.Sprint(r))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
c.kcpModule.OnConnected(c)
|
||||||
|
for c.kcpConn != nil {
|
||||||
|
c.kcpConn.SetReadDeadline(*c.kcpModule.kcpCfg.ReadDeadlineMill)
|
||||||
|
msgBuff, err := c.kcpConn.ReadMsg()
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("read client failed", log.ErrorField("error", err), log.String("clientId", c.id))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := c.kcpModule.process.Unmarshal(c.id, msgBuff)
|
||||||
|
if err != nil {
|
||||||
|
ev := event.NewEvent()
|
||||||
|
ev.Type = event.Sys_Event_Kcp
|
||||||
|
ev.IntExt[0] = int64(KPTUnknownPack)
|
||||||
|
ev.StringExt[0] = c.id
|
||||||
|
ev.Data = msgBuff
|
||||||
|
ev.AnyExt[0] = c.kcpConn.GetRecyclerReaderBytes()
|
||||||
|
c.kcpModule.NotifyEvent(ev)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ev := event.NewEvent()
|
||||||
|
ev.Type = event.Sys_Event_Kcp
|
||||||
|
ev.IntExt[0] = int64(KPTPack)
|
||||||
|
ev.StringExt[0] = c.id
|
||||||
|
ev.Data = data
|
||||||
|
ev.AnyExt[0] = c.kcpConn.GetRecyclerReaderBytes()
|
||||||
|
c.kcpModule.NotifyEvent(ev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) OnClose() {
|
||||||
|
c.kcpModule.OnClose(c)
|
||||||
|
|
||||||
|
c.kcpModule.mapClientLocker.Lock()
|
||||||
|
delete(c.kcpModule.mapClient, c.id)
|
||||||
|
c.kcpModule.mapClientLocker.Unlock()
|
||||||
|
}
|
||||||
219
sysmodule/netmodule/tcpmodule/TcpModule.go
Normal file
219
sysmodule/netmodule/tcpmodule/TcpModule.go
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
package tcpmodule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
|
"github.com/duanhf2012/origin/v2/network/processor"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TcpModule struct {
|
||||||
|
tcpServer network.TCPServer
|
||||||
|
service.Module
|
||||||
|
|
||||||
|
mapClientLocker sync.RWMutex
|
||||||
|
mapClient map[string]*Client
|
||||||
|
process processor.IRawProcessor
|
||||||
|
tcpCfg *TcpCfg
|
||||||
|
}
|
||||||
|
|
||||||
|
type TcpPackType int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
TPTConnected TcpPackType = 0
|
||||||
|
TPTDisConnected TcpPackType = 1
|
||||||
|
TPTPack TcpPackType = 2
|
||||||
|
TPTUnknownPack TcpPackType = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type TcpPack struct {
|
||||||
|
Type TcpPackType //0表示连接 1表示断开 2表示数据
|
||||||
|
ClientId string
|
||||||
|
Data interface{}
|
||||||
|
RecyclerReaderBytes func(data []byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
id string
|
||||||
|
tcpConn *network.NetConn
|
||||||
|
tcpModule *TcpModule
|
||||||
|
}
|
||||||
|
|
||||||
|
type TcpCfg struct {
|
||||||
|
ListenAddr string //监听地址
|
||||||
|
MaxConnNum int //最大连接数
|
||||||
|
PendingWriteNum int //写channel最大消息数量
|
||||||
|
LittleEndian bool //是否小端序
|
||||||
|
LenMsgLen int //消息头占用byte数量,只能是1byte,2byte,4byte。如果是4byte,意味着消息最大可以是math.MaxUint32(4GB)
|
||||||
|
MinMsgLen uint32 //最小消息长度
|
||||||
|
MaxMsgLen uint32 //最大消息长度,超过判定不合法,断开连接
|
||||||
|
ReadDeadlineSecond time.Duration //读超时
|
||||||
|
WriteDeadlineSecond time.Duration //写超时
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) OnInit() error {
|
||||||
|
if tm.tcpCfg == nil || tm.process == nil {
|
||||||
|
return fmt.Errorf("please call the Init function correctly")
|
||||||
|
}
|
||||||
|
|
||||||
|
//2.初始化网络模块
|
||||||
|
tm.tcpServer.Addr = tm.tcpCfg.ListenAddr
|
||||||
|
tm.tcpServer.MaxConnNum = tm.tcpCfg.MaxConnNum
|
||||||
|
tm.tcpServer.PendingWriteNum = tm.tcpCfg.PendingWriteNum
|
||||||
|
tm.tcpServer.LittleEndian = tm.tcpCfg.LittleEndian
|
||||||
|
tm.tcpServer.LenMsgLen = tm.tcpCfg.LenMsgLen
|
||||||
|
tm.tcpServer.MinMsgLen = tm.tcpCfg.MinMsgLen
|
||||||
|
tm.tcpServer.MaxMsgLen = tm.tcpCfg.MaxMsgLen
|
||||||
|
tm.tcpServer.ReadDeadline = tm.tcpCfg.ReadDeadlineSecond * time.Second
|
||||||
|
tm.tcpServer.WriteDeadline = tm.tcpCfg.WriteDeadlineSecond * time.Second
|
||||||
|
tm.mapClient = make(map[string]*Client, tm.tcpServer.MaxConnNum)
|
||||||
|
tm.tcpServer.NewAgent = tm.NewClient
|
||||||
|
|
||||||
|
//3.设置解析处理器
|
||||||
|
tm.process.SetByteOrder(tm.tcpCfg.LittleEndian)
|
||||||
|
|
||||||
|
//4.设置网络事件处理
|
||||||
|
tm.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_Tcp, tm.GetEventHandler(), tm.tcpEventHandler)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) Init(tcpCfg *TcpCfg, process processor.IRawProcessor) {
|
||||||
|
tm.tcpCfg = tcpCfg
|
||||||
|
tm.process = process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) Start() error {
|
||||||
|
return tm.tcpServer.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) tcpEventHandler(ev event.IEvent) {
|
||||||
|
pack := ev.(*event.Event).Data.(TcpPack)
|
||||||
|
switch pack.Type {
|
||||||
|
case TPTConnected:
|
||||||
|
tm.process.ConnectedRoute(pack.ClientId)
|
||||||
|
case TPTDisConnected:
|
||||||
|
tm.process.DisConnectedRoute(pack.ClientId)
|
||||||
|
case TPTUnknownPack:
|
||||||
|
tm.process.UnknownMsgRoute(pack.ClientId, pack.Data, pack.RecyclerReaderBytes)
|
||||||
|
case TPTPack:
|
||||||
|
tm.process.MsgRoute(pack.ClientId, pack.Data, pack.RecyclerReaderBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) NewClient(conn network.Conn) network.Agent {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
defer tm.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
clientId := primitive.NewObjectID().Hex()
|
||||||
|
pClient := &Client{tcpConn: conn.(*network.NetConn), id: clientId}
|
||||||
|
pClient.tcpModule = tm
|
||||||
|
tm.mapClient[clientId] = pClient
|
||||||
|
|
||||||
|
return pClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Client) GetId() string {
|
||||||
|
return slf.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Client) Run() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
log.StackError(fmt.Sprint(r))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTConnected}})
|
||||||
|
for slf.tcpConn != nil {
|
||||||
|
slf.tcpConn.SetReadDeadline(slf.tcpModule.tcpServer.ReadDeadline)
|
||||||
|
bytes, err := slf.tcpConn.ReadMsg()
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("read client failed", log.ErrorField("error", err), log.String("clientId", slf.id))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
data, err := slf.tcpModule.process.Unmarshal(slf.id, bytes)
|
||||||
|
if err != nil {
|
||||||
|
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTUnknownPack, Data: bytes, RecyclerReaderBytes: slf.tcpConn.GetRecyclerReaderBytes()}})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTPack, Data: data, RecyclerReaderBytes: slf.tcpConn.GetRecyclerReaderBytes()}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Client) OnClose() {
|
||||||
|
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTDisConnected}})
|
||||||
|
slf.tcpModule.mapClientLocker.Lock()
|
||||||
|
defer slf.tcpModule.mapClientLocker.Unlock()
|
||||||
|
delete(slf.tcpModule.mapClient, slf.GetId())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) SendMsg(clientId string, msg interface{}) error {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
client, ok := tm.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
tm.mapClientLocker.Unlock()
|
||||||
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
|
}
|
||||||
|
|
||||||
|
tm.mapClientLocker.Unlock()
|
||||||
|
bytes, err := tm.process.Marshal(clientId, msg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return client.tcpConn.WriteMsg(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) Close(clientId string) {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
defer tm.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
client, ok := tm.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if client.tcpConn != nil {
|
||||||
|
client.tcpConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
log.SWarn("close client:", clientId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) GetClientIp(clientId string) string {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
defer tm.mapClientLocker.Unlock()
|
||||||
|
pClient, ok := tm.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return pClient.tcpConn.GetRemoteIp()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) SendRawMsg(clientId string, msg []byte) error {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
client, ok := tm.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
tm.mapClientLocker.Unlock()
|
||||||
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
|
}
|
||||||
|
tm.mapClientLocker.Unlock()
|
||||||
|
return client.tcpConn.WriteMsg(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) GetConnNum() int {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
connNum := len(tm.mapClient)
|
||||||
|
tm.mapClientLocker.Unlock()
|
||||||
|
return connNum
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) GetProcessor() processor.IRawProcessor {
|
||||||
|
return tm.process
|
||||||
|
}
|
||||||
203
sysmodule/netmodule/wsmodule/WSModule.go
Normal file
203
sysmodule/netmodule/wsmodule/WSModule.go
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
package wsmodule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
|
"github.com/duanhf2012/origin/v2/network/processor"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WSModule struct {
|
||||||
|
service.Module
|
||||||
|
|
||||||
|
WSServer network.WSServer
|
||||||
|
|
||||||
|
mapClientLocker sync.RWMutex
|
||||||
|
mapClient map[string]*WSClient
|
||||||
|
process processor.IRawProcessor
|
||||||
|
wsCfg *WSCfg
|
||||||
|
}
|
||||||
|
|
||||||
|
type WSClient struct {
|
||||||
|
id string
|
||||||
|
wsConn *network.WSConn
|
||||||
|
wsModule *WSModule
|
||||||
|
}
|
||||||
|
|
||||||
|
type WSCfg struct {
|
||||||
|
ListenAddr string
|
||||||
|
MaxConnNum int
|
||||||
|
PendingWriteNum int
|
||||||
|
MaxMsgLen uint32
|
||||||
|
LittleEndian bool //是否小端序
|
||||||
|
}
|
||||||
|
|
||||||
|
type WSPackType int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
WPTConnected WSPackType = 0
|
||||||
|
WPTDisConnected WSPackType = 1
|
||||||
|
WPTPack WSPackType = 2
|
||||||
|
WPTUnknownPack WSPackType = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type WSPack struct {
|
||||||
|
Type WSPackType //0表示连接 1表示断开 2表示数据
|
||||||
|
MsgProcessor processor.IRawProcessor
|
||||||
|
ClientId string
|
||||||
|
Data any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) OnInit() error {
|
||||||
|
if ws.wsCfg == nil || ws.process == nil {
|
||||||
|
return fmt.Errorf("please call the Init function correctly")
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.WSServer.MaxConnNum = ws.wsCfg.MaxConnNum
|
||||||
|
ws.WSServer.PendingWriteNum = ws.wsCfg.PendingWriteNum
|
||||||
|
ws.WSServer.MaxMsgLen = ws.wsCfg.MaxMsgLen
|
||||||
|
ws.WSServer.Addr = ws.wsCfg.ListenAddr
|
||||||
|
|
||||||
|
//3.设置解析处理器
|
||||||
|
ws.process.SetByteOrder(ws.wsCfg.LittleEndian)
|
||||||
|
|
||||||
|
ws.mapClient = make(map[string]*WSClient, ws.WSServer.MaxConnNum)
|
||||||
|
ws.WSServer.NewAgent = ws.NewWSClient
|
||||||
|
|
||||||
|
//4.设置网络事件处理
|
||||||
|
ws.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_WebSocket, ws.GetEventHandler(), ws.wsEventHandler)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) Init(wsCfg *WSCfg, process processor.IRawProcessor) {
|
||||||
|
ws.wsCfg = wsCfg
|
||||||
|
ws.process = process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) Start() error {
|
||||||
|
return ws.WSServer.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) wsEventHandler(ev event.IEvent) {
|
||||||
|
pack := ev.(*event.Event).Data.(*WSPack)
|
||||||
|
switch pack.Type {
|
||||||
|
case WPTConnected:
|
||||||
|
ws.process.ConnectedRoute(pack.ClientId)
|
||||||
|
case WPTDisConnected:
|
||||||
|
ws.process.DisConnectedRoute(pack.ClientId)
|
||||||
|
case WPTUnknownPack:
|
||||||
|
ws.process.UnknownMsgRoute(pack.ClientId, pack.Data, ws.recyclerReaderBytes)
|
||||||
|
case WPTPack:
|
||||||
|
ws.process.MsgRoute(pack.ClientId, pack.Data, ws.recyclerReaderBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) recyclerReaderBytes([]byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) NewWSClient(conn *network.WSConn) network.Agent {
|
||||||
|
ws.mapClientLocker.Lock()
|
||||||
|
defer ws.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
pClient := &WSClient{wsConn: conn, id: primitive.NewObjectID().Hex()}
|
||||||
|
pClient.wsModule = ws
|
||||||
|
ws.mapClient[pClient.id] = pClient
|
||||||
|
|
||||||
|
return pClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *WSClient) GetId() string {
|
||||||
|
return wc.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *WSClient) Run() {
|
||||||
|
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTConnected}})
|
||||||
|
for {
|
||||||
|
bytes, err := wc.wsConn.ReadMsg()
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("read client is error", log.String("clientId", wc.id), log.ErrorField("err", err))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
data, err := wc.wsModule.process.Unmarshal(wc.id, bytes)
|
||||||
|
if err != nil {
|
||||||
|
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTUnknownPack, Data: bytes}})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTPack, Data: data}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *WSClient) OnClose() {
|
||||||
|
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTDisConnected}})
|
||||||
|
wc.wsModule.mapClientLocker.Lock()
|
||||||
|
defer wc.wsModule.mapClientLocker.Unlock()
|
||||||
|
delete(wc.wsModule.mapClient, wc.GetId())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) GetProcessor() processor.IRawProcessor {
|
||||||
|
return ws.process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) GetClientIp(clientId string) string {
|
||||||
|
ws.mapClientLocker.Lock()
|
||||||
|
defer ws.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
pClient, ok := ws.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return pClient.wsConn.RemoteAddr().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) Close(clientId string) {
|
||||||
|
ws.mapClientLocker.Lock()
|
||||||
|
defer ws.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
client, ok := ws.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if client.wsConn != nil {
|
||||||
|
client.wsConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) SendMsg(clientId string, msg interface{}) error {
|
||||||
|
ws.mapClientLocker.Lock()
|
||||||
|
client, ok := ws.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
ws.mapClientLocker.Unlock()
|
||||||
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.mapClientLocker.Unlock()
|
||||||
|
bytes, err := ws.process.Marshal(clientId, msg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return client.wsConn.WriteMsg(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) SendRawMsg(clientId string, msg []byte) error {
|
||||||
|
ws.mapClientLocker.Lock()
|
||||||
|
client, ok := ws.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
ws.mapClientLocker.Unlock()
|
||||||
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
|
}
|
||||||
|
ws.mapClientLocker.Unlock()
|
||||||
|
return client.wsConn.WriteMsg(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) SetMessageType(messageType int) {
|
||||||
|
ws.WSServer.SetMessageType(messageType)
|
||||||
|
}
|
||||||
@@ -66,7 +66,7 @@ func (m *RedisModule) Init(redisCfg *ConfigRedis) {
|
|||||||
}
|
}
|
||||||
c, err := redis.Dial("tcp", redisServer, opt...)
|
c, err := redis.Dial("tcp", redisServer, opt...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Connect redis fail reason:%v", err)
|
log.Error("Connect redis fail", log.ErrorField("err",err))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ func (m *RedisModule) Init(redisCfg *ConfigRedis) {
|
|||||||
}
|
}
|
||||||
_, err := c.Do("PING")
|
_, err := c.Do("PING")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Do PING fail reason:%v", err)
|
log.Error("Do PING fail reason", log.ErrorField("err",err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@@ -90,18 +90,18 @@ func (m *RedisModule) Init(redisCfg *ConfigRedis) {
|
|||||||
func (m *RedisModule) getConn() (redis.Conn, error) {
|
func (m *RedisModule) getConn() (redis.Conn, error) {
|
||||||
if m.redisPool == nil {
|
if m.redisPool == nil {
|
||||||
log.Error("Not Init RedisModule")
|
log.Error("Not Init RedisModule")
|
||||||
return nil, fmt.Errorf("Not Init RedisModule")
|
return nil, fmt.Errorf("not Init RedisModule")
|
||||||
}
|
}
|
||||||
conn := m.redisPool.Get()
|
conn := m.redisPool.Get()
|
||||||
if conn == nil {
|
if conn == nil {
|
||||||
log.Error("Cannot get connection")
|
log.Error("Cannot get connection")
|
||||||
return nil, fmt.Errorf("Cannot get connection")
|
return nil, fmt.Errorf("cannot get connection")
|
||||||
}
|
}
|
||||||
|
|
||||||
if conn.Err() != nil {
|
if conn.Err() != nil {
|
||||||
err := conn.Err()
|
err := conn.Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Get Conn have error,reason:%v", err)
|
log.Error("get Conn have error", log.ErrorField("err",err))
|
||||||
}
|
}
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -118,7 +118,7 @@ func (m *RedisModule) TestPingRedis() error {
|
|||||||
|
|
||||||
err = m.redisPool.TestOnBorrow(conn, time.Now())
|
err = m.redisPool.TestOnBorrow(conn, time.Now())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("TestOnBorrow fail,reason:%v", err)
|
log.Error("TestOnBorrow fail", log.ErrorField("err",err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ func (m *RedisModule) SetStringJSONExpire(key interface{}, val interface{}, expi
|
|||||||
|
|
||||||
func (m *RedisModule) setStringByExpire(key, value, expire interface{}) error {
|
func (m *RedisModule) setStringByExpire(key, value, expire interface{}) error {
|
||||||
if key == "" {
|
if key == "" {
|
||||||
return errors.New("Key Is Empty")
|
return errors.New("key is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
@@ -171,7 +171,7 @@ func (m *RedisModule) setStringByExpire(key, value, expire interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
log.Error("setStringByExpire fail,reason:%v", retErr)
|
log.Error("setStringByExpire fail", log.ErrorField("err",retErr))
|
||||||
return retErr
|
return retErr
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ func (m *RedisModule) setMuchStringByExpire(mapInfo map[interface{}]interface{},
|
|||||||
}
|
}
|
||||||
|
|
||||||
if serr != nil {
|
if serr != nil {
|
||||||
log.Error("setMuchStringByExpire fail,reason:%v", serr)
|
log.Error("setMuchStringByExpire fail",log.ErrorField("err",serr))
|
||||||
conn.Do("DISCARD")
|
conn.Do("DISCARD")
|
||||||
return serr
|
return serr
|
||||||
} else {
|
} else {
|
||||||
@@ -262,7 +262,7 @@ func (m *RedisModule) setMuchStringByExpire(mapInfo map[interface{}]interface{},
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("setMuchStringByExpire fail,reason:%v", err)
|
log.Error("setMuchStringByExpire fail", log.ErrorField("err",err))
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
@@ -277,7 +277,7 @@ func (m *RedisModule) GetString(key interface{}) (string, error) {
|
|||||||
|
|
||||||
ret, err := conn.Do("GET", key)
|
ret, err := conn.Do("GET", key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetString fail,reason:%v", err)
|
log.Error("GetString fail", log.ErrorField("err",err))
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +298,7 @@ func (m *RedisModule) GetStringJSON(key string, st interface{}) error {
|
|||||||
|
|
||||||
ret, err := conn.Do("GET", key)
|
ret, err := conn.Do("GET", key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetStringJSON fail,reason:%v", err)
|
log.Error("GetStringJSON fail", log.ErrorField("err",err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +315,7 @@ func (m *RedisModule) GetStringJSON(key string, st interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = json.Unmarshal(str, st); err != nil {
|
if err = json.Unmarshal(str, st); err != nil {
|
||||||
log.Error("GetStringJSON fail json.Unmarshal is error:%s,%s,reason:%v", key, string(str), err)
|
log.Errorf("GetStringJSON fail json.Unmarshal is error:%s,%s,reason:%v", key, string(str), err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,13 +336,13 @@ func (m *RedisModule) GetStringMap(keys []string) (retMap map[string]string, err
|
|||||||
// 开始Send数据
|
// 开始Send数据
|
||||||
err = conn.Send("MULTI")
|
err = conn.Send("MULTI")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetMuchString fail %v", err)
|
log.Errorf("GetMuchString fail %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, val := range keys {
|
for _, val := range keys {
|
||||||
err = conn.Send("GET", val)
|
err = conn.Send("GET", val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetMuchString fail,reason:%v", err)
|
log.Errorf("GetMuchString fail,reason:%v", err)
|
||||||
conn.Do("DISCARD")
|
conn.Do("DISCARD")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -351,7 +351,7 @@ func (m *RedisModule) GetStringMap(keys []string) (retMap map[string]string, err
|
|||||||
// 执行命令
|
// 执行命令
|
||||||
ret, err := conn.Do("EXEC")
|
ret, err := conn.Do("EXEC")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetMuchString fail %v", err)
|
log.Errorf("GetMuchString fail %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +383,7 @@ func (m *RedisModule) ExistsKey(key interface{}) (bool, error) {
|
|||||||
|
|
||||||
ret, err := conn.Do("EXISTS", key)
|
ret, err := conn.Do("EXISTS", key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("ExistsKey fail, reason:%v", err)
|
log.Errorf("ExistsKey fail, reason:%v", err)
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
retValue, ok := ret.(int64)
|
retValue, ok := ret.(int64)
|
||||||
@@ -404,7 +404,7 @@ func (m *RedisModule) DelString(key interface{}) error {
|
|||||||
|
|
||||||
ret, err := conn.Do("DEL", key)
|
ret, err := conn.Do("DEL", key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("DelString fail, reason:%v", err)
|
log.Errorf("DelString fail, reason:%v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,7 +439,7 @@ func (m *RedisModule) DelStringKeyList(keys []interface{}) (map[interface{}]bool
|
|||||||
for _, val := range keys {
|
for _, val := range keys {
|
||||||
err = conn.Send("DEL", val)
|
err = conn.Send("DEL", val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("DelMuchString fail,reason:%v", err)
|
log.Errorf("DelMuchString fail,reason:%v", err)
|
||||||
conn.Do("DISCARD")
|
conn.Do("DISCARD")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -448,7 +448,7 @@ func (m *RedisModule) DelStringKeyList(keys []interface{}) (map[interface{}]bool
|
|||||||
ret, err := conn.Do("EXEC")
|
ret, err := conn.Do("EXEC")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("DelMuchString fail,reason:%v", err)
|
log.Errorf("DelMuchString fail,reason:%v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,7 +474,7 @@ func (m *RedisModule) DelStringKeyList(keys []interface{}) (map[interface{}]bool
|
|||||||
|
|
||||||
func (m *RedisModule) SetHash(redisKey, hashKey, value interface{}) error {
|
func (m *RedisModule) SetHash(redisKey, hashKey, value interface{}) error {
|
||||||
if redisKey == "" || hashKey == "" {
|
if redisKey == "" || hashKey == "" {
|
||||||
return errors.New("Key Is Empty")
|
return errors.New("key is empty")
|
||||||
}
|
}
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -484,16 +484,15 @@ func (m *RedisModule) SetHash(redisKey, hashKey, value interface{}) error {
|
|||||||
|
|
||||||
_, retErr := conn.Do("HSET", redisKey, hashKey, value)
|
_, retErr := conn.Do("HSET", redisKey, hashKey, value)
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
log.Error("SetHash fail,reason:%v", retErr)
|
log.Errorf("SetHash fail,reason:%v", retErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return retErr
|
return retErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRedisAllHashJSON ...
|
|
||||||
func (m *RedisModule) GetAllHashJSON(redisKey string) (map[string]string, error) {
|
func (m *RedisModule) GetAllHashJSON(redisKey string) (map[string]string, error) {
|
||||||
if redisKey == "" {
|
if redisKey == "" {
|
||||||
return nil, errors.New("Key Is Empty")
|
return nil, errors.New("key is empty")
|
||||||
}
|
}
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -503,7 +502,7 @@ func (m *RedisModule) GetAllHashJSON(redisKey string) (map[string]string, error)
|
|||||||
|
|
||||||
value, err := conn.Do("HGETALL", redisKey)
|
value, err := conn.Do("HGETALL", redisKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetAllHashJSON fail,reason:%v", err)
|
log.Errorf("GetAllHashJSON fail,reason:%v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,7 +512,7 @@ func (m *RedisModule) GetAllHashJSON(redisKey string) (map[string]string, error)
|
|||||||
func (m *RedisModule) GetHash(redisKey interface{}, fieldKey interface{}) (string, error) {
|
func (m *RedisModule) GetHash(redisKey interface{}, fieldKey interface{}) (string, error) {
|
||||||
if redisKey == "" || fieldKey == "" {
|
if redisKey == "" || fieldKey == "" {
|
||||||
log.Error("GetHashValueByKey key is empty!")
|
log.Error("GetHashValueByKey key is empty!")
|
||||||
return "", errors.New("Key Is Empty")
|
return "", errors.New("key is empty")
|
||||||
}
|
}
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -523,11 +522,11 @@ func (m *RedisModule) GetHash(redisKey interface{}, fieldKey interface{}) (strin
|
|||||||
|
|
||||||
value, err := conn.Do("HGET", redisKey, fieldKey)
|
value, err := conn.Do("HGET", redisKey, fieldKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetHashValueByKey fail,reason:%v", err)
|
log.Errorf("GetHashValueByKey fail,reason:%v", err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return "", errors.New("Reids Get Hash nil")
|
return "", errors.New("redis get hash nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return redis.String(value, nil)
|
return redis.String(value, nil)
|
||||||
@@ -536,7 +535,7 @@ func (m *RedisModule) GetHash(redisKey interface{}, fieldKey interface{}) (strin
|
|||||||
func (m *RedisModule) GetMuchHash(args ...interface{}) ([]string, error) {
|
func (m *RedisModule) GetMuchHash(args ...interface{}) ([]string, error) {
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
log.Error("GetHashValueByHashKeyList key len less than two!")
|
log.Error("GetHashValueByHashKeyList key len less than two!")
|
||||||
return nil, errors.New("Key Is Empty")
|
return nil, errors.New("key is empty")
|
||||||
}
|
}
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -546,15 +545,15 @@ func (m *RedisModule) GetMuchHash(args ...interface{}) ([]string, error) {
|
|||||||
|
|
||||||
value, err := conn.Do("HMGET", args...)
|
value, err := conn.Do("HMGET", args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetHashValueByKey fail,reason:%v", err)
|
log.Errorf("GetHashValueByKey fail,reason:%v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return nil, errors.New("Reids Get Hash nil")
|
return nil, errors.New("redis get hash nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
valueList := value.([]interface{})
|
valueList := value.([]interface{})
|
||||||
retList := []string{}
|
var retList []string
|
||||||
for _, valueItem := range valueList {
|
for _, valueItem := range valueList {
|
||||||
valueByte, ok := valueItem.([]byte)
|
valueByte, ok := valueItem.([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -572,7 +571,7 @@ func (m *RedisModule) ScanMatchKeys(cursorValue int, redisKey string, count int)
|
|||||||
nextCursorValue := 0
|
nextCursorValue := 0
|
||||||
if redisKey == "" {
|
if redisKey == "" {
|
||||||
log.Error("ScanMatchKeys key is empty!")
|
log.Error("ScanMatchKeys key is empty!")
|
||||||
return nextCursorValue, nil, errors.New("Key Is Empty")
|
return nextCursorValue, nil, errors.New("key is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
@@ -583,11 +582,11 @@ func (m *RedisModule) ScanMatchKeys(cursorValue int, redisKey string, count int)
|
|||||||
|
|
||||||
value, err := conn.Do("SCAN", cursorValue, "match", redisKey, "count", count)
|
value, err := conn.Do("SCAN", cursorValue, "match", redisKey, "count", count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetHashValueByKey fail,reason:%v", err)
|
log.Errorf("GetHashValueByKey fail,reason:%v", err)
|
||||||
return nextCursorValue, nil, err
|
return nextCursorValue, nil, err
|
||||||
}
|
}
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return nextCursorValue, nil, errors.New("Reids Get Hash nil")
|
return nextCursorValue, nil, errors.New("redis get hash nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
valueList := value.([]interface{})
|
valueList := value.([]interface{})
|
||||||
@@ -619,7 +618,7 @@ func (m *RedisModule) SetHashMapJSON(redisKey string, mapFieldValue map[interfac
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
_, err = conn.Do("HSET", redisKey, symbol, temp)
|
_, err = conn.Do("HSET", redisKey, symbol, temp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("SetMuchHashJSON fail,reason:%v", err)
|
log.Errorf("SetMuchHashJSON fail,reason:%v", err)
|
||||||
conn.Send("DISCARD")
|
conn.Send("DISCARD")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -628,7 +627,7 @@ func (m *RedisModule) SetHashMapJSON(redisKey string, mapFieldValue map[interfac
|
|||||||
// 执行命令
|
// 执行命令
|
||||||
_, err = conn.Do("EXEC")
|
_, err = conn.Do("EXEC")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("SetMuchHashJSON fail,reason:%v", err)
|
log.Errorf("SetMuchHashJSON fail,reason:%v", err)
|
||||||
conn.Send("DISCARD")
|
conn.Send("DISCARD")
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@@ -643,7 +642,7 @@ func (m *RedisModule) DelHash(args ...interface{}) error {
|
|||||||
|
|
||||||
_, retErr := conn.Do("HDEL", args...)
|
_, retErr := conn.Do("HDEL", args...)
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
log.Error("DelMuchHash fail,reason:%v", retErr)
|
log.Errorf("DelMuchHash fail,reason:%v", retErr)
|
||||||
}
|
}
|
||||||
return retErr
|
return retErr
|
||||||
}
|
}
|
||||||
@@ -669,7 +668,7 @@ func (m *RedisModule) RPushListJSON(key interface{}, value ...interface{}) error
|
|||||||
// LPUSH和RPUSH
|
// LPUSH和RPUSH
|
||||||
func (m *RedisModule) setListPush(setType string, args ...interface{}) error {
|
func (m *RedisModule) setListPush(setType string, args ...interface{}) error {
|
||||||
if setType != "LPUSH" && setType != "RPUSH" {
|
if setType != "LPUSH" && setType != "RPUSH" {
|
||||||
return errors.New("Redis List Push Type Error,Must Be LPUSH or RPUSH")
|
return errors.New("redis list push type error,must be LPUSH or RPUSH")
|
||||||
}
|
}
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -679,7 +678,7 @@ func (m *RedisModule) setListPush(setType string, args ...interface{}) error {
|
|||||||
|
|
||||||
_, retErr := conn.Do(setType, args...)
|
_, retErr := conn.Do(setType, args...)
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
log.Error("setList fail,reason:%v", retErr)
|
log.Errorf("setList fail,reason:%v", retErr)
|
||||||
}
|
}
|
||||||
return retErr
|
return retErr
|
||||||
}
|
}
|
||||||
@@ -697,7 +696,6 @@ func (m *RedisModule) setListJSONPush(setType string, key interface{}, value ...
|
|||||||
return m.setListPush(setType, args...)
|
return m.setListPush(setType, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lrange ...
|
|
||||||
func (m *RedisModule) LRangeList(key string, start, end int) ([]string, error) {
|
func (m *RedisModule) LRangeList(key string, start, end int) ([]string, error) {
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -707,14 +705,14 @@ func (m *RedisModule) LRangeList(key string, start, end int) ([]string, error) {
|
|||||||
|
|
||||||
reply, err := conn.Do("lrange", key, start, end)
|
reply, err := conn.Do("lrange", key, start, end)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("SetListJSONRpush fail,reason:%v", err)
|
log.Errorf("SetListJSONRpush fail,reason:%v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return redis.Strings(reply, err)
|
return redis.Strings(reply, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取List的长度
|
// GetListLen 获取List的长度
|
||||||
func (m *RedisModule) GetListLen(key string) (int, error) {
|
func (m *RedisModule) GetListLen(key string) (int, error) {
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -724,13 +722,13 @@ func (m *RedisModule) GetListLen(key string) (int, error) {
|
|||||||
|
|
||||||
reply, err := conn.Do("LLEN", key)
|
reply, err := conn.Do("LLEN", key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetListLen fail,reason:%v", err)
|
log.Errorf("GetListLen fail,reason:%v", err)
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
return redis.Int(reply, err)
|
return redis.Int(reply, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 弹出List最后条记录
|
// RPOPListValue 弹出List最后条记录
|
||||||
func (m *RedisModule) RPOPListValue(key string) (string, error) {
|
func (m *RedisModule) RPOPListValue(key string) (string, error) {
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -750,7 +748,7 @@ func (m *RedisModule) LTrimList(key string, start, end int) error {
|
|||||||
|
|
||||||
_, err = conn.Do("LTRIM", key, start, end)
|
_, err = conn.Do("LTRIM", key, start, end)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("LtrimListValue fail,reason:%v", err)
|
log.Errorf("LtrimListValue fail,reason:%v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -782,7 +780,7 @@ func (m *RedisModule) LRange(key string, start, stop int) ([]byte, error) {
|
|||||||
return makeListJson(reply.([]interface{}), false), nil
|
return makeListJson(reply.([]interface{}), false), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 弹出list(消息队列)数据,数据放入out fromLeft表示是否从左侧弹出 block表示是否阻塞 timeout表示阻塞超时
|
// ListPopJson 弹出list(消息队列)数据,数据放入out fromLeft表示是否从左侧弹出 block表示是否阻塞 timeout表示阻塞超时
|
||||||
func (m *RedisModule) ListPopJson(key string, fromLeft, block bool, timeout int, out interface{}) error {
|
func (m *RedisModule) ListPopJson(key string, fromLeft, block bool, timeout int, out interface{}) error {
|
||||||
b, err := m.ListPop(key, fromLeft, block, timeout)
|
b, err := m.ListPop(key, fromLeft, block, timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -795,7 +793,7 @@ func (m *RedisModule) ListPopJson(key string, fromLeft, block bool, timeout int,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 弹出list(消息队列)数据 fromLeft表示是否从左侧弹出 block表示是否阻塞 timeout表示阻塞超时
|
// ListPop 弹出list(消息队列)数据 fromLeft表示是否从左侧弹出 block表示是否阻塞 timeout表示阻塞超时
|
||||||
func (m *RedisModule) ListPop(key string, fromLeft, block bool, timeout int) ([]byte, error) {
|
func (m *RedisModule) ListPop(key string, fromLeft, block bool, timeout int) ([]byte, error) {
|
||||||
cmd := ""
|
cmd := ""
|
||||||
if fromLeft {
|
if fromLeft {
|
||||||
@@ -837,7 +835,7 @@ func (m *RedisModule) ListPop(key string, fromLeft, block bool, timeout int) ([]
|
|||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 有序集合插入Json
|
// ZADDInsertJson 有序集合插入Json
|
||||||
func (m *RedisModule) ZADDInsertJson(key string, score float64, value interface{}) error {
|
func (m *RedisModule) ZADDInsertJson(key string, score float64, value interface{}) error {
|
||||||
|
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
@@ -851,13 +849,13 @@ func (m *RedisModule) ZADDInsertJson(key string, score float64, value interface{
|
|||||||
}
|
}
|
||||||
_, err = conn.Do("ZADD", key, score, JsonValue)
|
_, err = conn.Do("ZADD", key, score, JsonValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("ZADDInsertJson fail,reason:%v", err)
|
log.Errorf("ZADDInsertJson fail,reason:%v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 有序集合插入
|
// ZADDInsert 有序集合插入
|
||||||
func (m *RedisModule) ZADDInsert(key string, score float64, Data interface{}) error {
|
func (m *RedisModule) ZADDInsert(key string, score float64, Data interface{}) error {
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -867,7 +865,7 @@ func (m *RedisModule) ZADDInsert(key string, score float64, Data interface{}) er
|
|||||||
|
|
||||||
_, err = conn.Do("ZADD", key, score, Data)
|
_, err = conn.Do("ZADD", key, score, Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("ZADDInsert fail,reason:%v", err)
|
log.Errorf("ZADDInsert fail,reason:%v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -897,7 +895,7 @@ func (m *RedisModule) ZRangeJSON(key string, start, stop int, ascend bool, withS
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取有序set指定排名 ascend=true表示按升序遍历 否则按降序遍历
|
// ZRange 取有序set指定排名 ascend=true表示按升序遍历 否则按降序遍历
|
||||||
func (m *RedisModule) ZRange(key string, start, stop int, ascend bool, withScores bool) ([]byte, error) {
|
func (m *RedisModule) ZRange(key string, start, stop int, ascend bool, withScores bool) ([]byte, error) {
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -921,7 +919,7 @@ func (m *RedisModule) ZRange(key string, start, stop int, ascend bool, withScore
|
|||||||
return makeListJson(reply.([]interface{}), withScores), nil
|
return makeListJson(reply.([]interface{}), withScores), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取有序集合长度
|
// Zcard 获取有序集合长度
|
||||||
func (m *RedisModule) Zcard(key string) (int, error) {
|
func (m *RedisModule) Zcard(key string) (int, error) {
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1005,7 +1003,7 @@ func (m *RedisModule) ZRangeByScore(key string, start, stop float64, ascend bool
|
|||||||
return makeListJson(reply.([]interface{}), withScores), nil
|
return makeListJson(reply.([]interface{}), withScores), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取指定member的排名
|
// ZScore 获取指定member的排名
|
||||||
func (m *RedisModule) ZScore(key string, member interface{}) (float64, error) {
|
func (m *RedisModule) ZScore(key string, member interface{}) (float64, error) {
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1021,7 +1019,7 @@ func (m *RedisModule) ZScore(key string, member interface{}) (float64, error) {
|
|||||||
return redis.Float64(reply, err)
|
return redis.Float64(reply, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取指定member的排名
|
// ZRank 获取指定member的排名
|
||||||
func (m *RedisModule) ZRank(key string, member interface{}, ascend bool) (int, error) {
|
func (m *RedisModule) ZRank(key string, member interface{}, ascend bool) (int, error) {
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1080,7 +1078,7 @@ func (m *RedisModule) ZREMMulti(key string, member ...interface{}) (int, error)
|
|||||||
|
|
||||||
func (m *RedisModule) HincrbyHashInt(redisKey, hashKey string, value int) error {
|
func (m *RedisModule) HincrbyHashInt(redisKey, hashKey string, value int) error {
|
||||||
if redisKey == "" || hashKey == "" {
|
if redisKey == "" || hashKey == "" {
|
||||||
return errors.New("Key Is Empty")
|
return errors.New("key is empty")
|
||||||
}
|
}
|
||||||
conn, err := m.getConn()
|
conn, err := m.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1090,7 +1088,7 @@ func (m *RedisModule) HincrbyHashInt(redisKey, hashKey string, value int) error
|
|||||||
|
|
||||||
_, retErr := conn.Do("HINCRBY", redisKey, hashKey, value)
|
_, retErr := conn.Do("HINCRBY", redisKey, hashKey, value)
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
log.Error("HincrbyHashInt fail,reason:%v", retErr)
|
log.Errorf("HincrbyHashInt fail,reason:%v", retErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return retErr
|
return retErr
|
||||||
@@ -1105,7 +1103,7 @@ func (m *RedisModule) EXPlREInsert(key string, TTl int) error {
|
|||||||
|
|
||||||
_, err = conn.Do("expire", key, TTl)
|
_, err = conn.Do("expire", key, TTl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("expire fail,reason:%v", err)
|
log.Errorf("expire fail,reason:%v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -1131,7 +1129,7 @@ func (m *RedisModule) Keys(key string) ([]string, error) {
|
|||||||
|
|
||||||
ret, err := conn.Do("KEYS", key)
|
ret, err := conn.Do("KEYS", key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("KEYS fail, reason:%v", err)
|
log.Errorf("KEYS fail, reason:%v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
retList, ok := ret.([]interface{})
|
retList, ok := ret.([]interface{})
|
||||||
@@ -1140,7 +1138,7 @@ func (m *RedisModule) Keys(key string) ([]string, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
strs := []string{}
|
var strs []string
|
||||||
for _, val := range retList {
|
for _, val := range retList {
|
||||||
strVal, ok := val.([]byte)
|
strVal, ok := val.([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ var DefaultReadTimeout time.Duration = time.Second * 10
|
|||||||
var DefaultWriteTimeout time.Duration = time.Second * 10
|
var DefaultWriteTimeout time.Duration = time.Second * 10
|
||||||
var DefaultProcessTimeout time.Duration = time.Second * 10
|
var DefaultProcessTimeout time.Duration = time.Second * 10
|
||||||
|
|
||||||
//http redirect
|
|
||||||
type HttpRedirectData struct {
|
type HttpRedirectData struct {
|
||||||
Url string
|
Url string
|
||||||
CookieList []*http.Cookie
|
CookieList []*http.Cookie
|
||||||
@@ -53,7 +52,7 @@ type IHttpRouter interface {
|
|||||||
POST(url string, handle HttpHandle) bool
|
POST(url string, handle HttpHandle) bool
|
||||||
Router(session *HttpSession)
|
Router(session *HttpSession)
|
||||||
|
|
||||||
SetServeFile(method HTTP_METHOD, urlpath string, dirname string) error
|
SetServeFile(method HTTP_METHOD, urlPath string, dirname string) error
|
||||||
SetFormFileKey(formFileKey string)
|
SetFormFileKey(formFileKey string)
|
||||||
GetFormFileKey() string
|
GetFormFileKey() string
|
||||||
AddHttpFiltrate(FiltrateFun HttpFiltrate) bool
|
AddHttpFiltrate(FiltrateFun HttpFiltrate) bool
|
||||||
@@ -215,7 +214,7 @@ func (slf *HttpRouter) analysisRouterUrl(url string) (string, error) {
|
|||||||
//替换所有空格
|
//替换所有空格
|
||||||
url = strings.ReplaceAll(url, " ", "")
|
url = strings.ReplaceAll(url, " ", "")
|
||||||
if len(url) <= 1 || url[0] != '/' {
|
if len(url) <= 1 || url[0] != '/' {
|
||||||
return "", fmt.Errorf("url %s format is error!", url)
|
return "", fmt.Errorf("url %s format is error", url)
|
||||||
}
|
}
|
||||||
|
|
||||||
//去掉尾部的/
|
//去掉尾部的/
|
||||||
@@ -300,12 +299,12 @@ func (httpService *HttpService) SetHttpRouter(httpRouter IHttpRouter, eventHandl
|
|||||||
httpService.RegEventReceiverFunc(event.Sys_Event_Http_Event, eventHandler, httpService.HttpEventHandler)
|
httpService.RegEventReceiverFunc(event.Sys_Event_Http_Event, eventHandler, httpService.HttpEventHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *HttpRouter) SetServeFile(method HTTP_METHOD, urlpath string, dirname string) error {
|
func (slf *HttpRouter) SetServeFile(method HTTP_METHOD, urlPath string, dirname string) error {
|
||||||
_, err := os.Stat(dirname)
|
_, err := os.Stat(dirname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
matchURL, aErr := slf.analysisRouterUrl(urlpath)
|
matchURL, aErr := slf.analysisRouterUrl(urlPath)
|
||||||
if aErr != nil {
|
if aErr != nil {
|
||||||
return aErr
|
return aErr
|
||||||
}
|
}
|
||||||
@@ -350,15 +349,15 @@ func (slf *HttpSession) redirects() {
|
|||||||
func (httpService *HttpService) OnInit() error {
|
func (httpService *HttpService) OnInit() error {
|
||||||
iConfig := httpService.GetServiceCfg()
|
iConfig := httpService.GetServiceCfg()
|
||||||
if iConfig == nil {
|
if iConfig == nil {
|
||||||
return fmt.Errorf("%s service config is error!", httpService.GetName())
|
return fmt.Errorf("%s service config is error", httpService.GetName())
|
||||||
}
|
}
|
||||||
httpCfg := iConfig.(map[string]interface{})
|
httpCfg := iConfig.(map[string]interface{})
|
||||||
addr, ok := httpCfg["ListenAddr"]
|
addr, ok := httpCfg["ListenAddr"]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return fmt.Errorf("%s service config is error!", httpService.GetName())
|
return fmt.Errorf("%s service config is error", httpService.GetName())
|
||||||
}
|
}
|
||||||
var readTimeout time.Duration = DefaultReadTimeout
|
var readTimeout = DefaultReadTimeout
|
||||||
var writeTimeout time.Duration = DefaultWriteTimeout
|
var writeTimeout = DefaultWriteTimeout
|
||||||
|
|
||||||
if cfgRead, ok := httpCfg["ReadTimeout"]; ok == true {
|
if cfgRead, ok := httpCfg["ReadTimeout"]; ok == true {
|
||||||
readTimeout = time.Duration(cfgRead.(float64)) * time.Millisecond
|
readTimeout = time.Duration(cfgRead.(float64)) * time.Millisecond
|
||||||
|
|||||||
@@ -62,13 +62,13 @@ func (cs *CustomerSubscriber) trySetSubscriberBaseInfo(rpcHandler rpc.IRpcHandle
|
|||||||
cs.serviceName = strRpcMethod[0]
|
cs.serviceName = strRpcMethod[0]
|
||||||
|
|
||||||
if cluster.HasService(fromNodeId, cs.serviceName) == false {
|
if cluster.HasService(fromNodeId, cs.serviceName) == false {
|
||||||
err := fmt.Errorf("nodeId %d cannot found %s", fromNodeId, cs.serviceName)
|
err := fmt.Errorf("nodeId %s cannot found %s", fromNodeId, cs.serviceName)
|
||||||
log.SError(err.Error())
|
log.SError(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cluster.GetCluster().IsNodeConnected(fromNodeId) == false {
|
if cluster.GetCluster().IsNodeConnected(fromNodeId) == false {
|
||||||
err := fmt.Errorf("nodeId %d is disconnect", fromNodeId)
|
err := fmt.Errorf("nodeId %s is disconnect", fromNodeId)
|
||||||
log.SError(err.Error())
|
log.SError(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ func (cs *CustomerSubscriber) trySetSubscriberBaseInfo(rpcHandler rpc.IRpcHandle
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始订阅
|
// Subscribe 开始订阅
|
||||||
func (cs *CustomerSubscriber) Subscribe(rpcHandler rpc.IRpcHandler, ss *Subscriber, topic string, subscribeMethod SubscribeMethod, customerId string, fromNodeId string, callBackRpcMethod string, startIndex uint64, oneBatchQuantity int32) error {
|
func (cs *CustomerSubscriber) Subscribe(rpcHandler rpc.IRpcHandler, ss *Subscriber, topic string, subscribeMethod SubscribeMethod, customerId string, fromNodeId string, callBackRpcMethod string, startIndex uint64, oneBatchQuantity int32) error {
|
||||||
err := cs.trySetSubscriberBaseInfo(rpcHandler, ss, topic, subscribeMethod, customerId, fromNodeId, callBackRpcMethod, startIndex, oneBatchQuantity)
|
err := cs.trySetSubscriberBaseInfo(rpcHandler, ss, topic, subscribeMethod, customerId, fromNodeId, callBackRpcMethod, startIndex, oneBatchQuantity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -96,7 +96,7 @@ func (cs *CustomerSubscriber) Subscribe(rpcHandler rpc.IRpcHandler, ss *Subscrib
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取消订阅
|
// UnSubscribe 取消订阅
|
||||||
func (cs *CustomerSubscriber) UnSubscribe() {
|
func (cs *CustomerSubscriber) UnSubscribe() {
|
||||||
atomic.StoreInt32(&cs.isStop, 1)
|
atomic.StoreInt32(&cs.isStop, 1)
|
||||||
}
|
}
|
||||||
@@ -170,7 +170,7 @@ func (cs *CustomerSubscriber) subscribe() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CustomerSubscriber) checkCustomerIsValid() bool {
|
func (cs *CustomerSubscriber) checkCustomerIsValid() bool {
|
||||||
//1.检查nodeid是否在线,不在线,直接取消订阅
|
//1.检查nodeId是否在线,不在线,直接取消订阅
|
||||||
if cluster.GetCluster().IsNodeConnected(cs.fromNodeId) == false {
|
if cluster.GetCluster().IsNodeConnected(cs.fromNodeId) == false {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func (mq *MemoryQueue) Init(cap int32) {
|
|||||||
mq.topicQueue = make([]TopicData, cap+1)
|
mq.topicQueue = make([]TopicData, cap+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从队尾Push数据
|
// Push 从队尾Push数据
|
||||||
func (mq *MemoryQueue) Push(topicData *TopicData) bool {
|
func (mq *MemoryQueue) Push(topicData *TopicData) bool {
|
||||||
mq.locker.Lock()
|
mq.locker.Lock()
|
||||||
defer mq.locker.Unlock()
|
defer mq.locker.Unlock()
|
||||||
|
|||||||
@@ -201,14 +201,13 @@ func (mp *MongoPersist) PersistTopicData(topic string, topicData []TopicData, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
//如果成功
|
//如果成功
|
||||||
return topicData[findPos:len(topicData)], topicData[0:findPos], true
|
return topicData[findPos:], topicData[0:findPos], true
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindTopicData 查找数据
|
// FindTopicData 查找数据
|
||||||
func (mp *MongoPersist) findTopicData(topic string, startIndex uint64, limit int64, topicBuff []TopicData) ([]TopicData, bool) {
|
func (mp *MongoPersist) findTopicData(topic string, startIndex uint64, limit int64, topicBuff []TopicData) ([]TopicData, bool) {
|
||||||
s := mp.mongo.TakeSession()
|
s := mp.mongo.TakeSession()
|
||||||
|
|
||||||
|
|
||||||
condition := bson.D{{Key: "_id", Value: bson.D{{Key: "$gt", Value: startIndex}}}}
|
condition := bson.D{{Key: "_id", Value: bson.D{{Key: "$gt", Value: startIndex}}}}
|
||||||
|
|
||||||
var findOption options.FindOptions
|
var findOption options.FindOptions
|
||||||
@@ -238,11 +237,7 @@ func (mp *MongoPersist) findTopicData(topic string, startIndex uint64, limit int
|
|||||||
defer cancelAll()
|
defer cancelAll()
|
||||||
err = cursor.All(ctxAll, &res)
|
err = cursor.All(ctxAll, &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != nil {
|
log.Error("find collect name ", topic, " is error", log.ErrorAttr("err", err))
|
||||||
log.SError("find collect name ", topic, " is error:", err.Error())
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +246,7 @@ func (mp *MongoPersist) findTopicData(topic string, startIndex uint64, limit int
|
|||||||
rawData, errM := bson.Marshal(res[i])
|
rawData, errM := bson.Marshal(res[i])
|
||||||
if errM != nil {
|
if errM != nil {
|
||||||
if errM != nil {
|
if errM != nil {
|
||||||
log.SError("collect name ", topic, " Marshal is error:", err.Error())
|
log.Error("collect name ", topic, " Marshal is error", log.ErrorAttr("err", err))
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@@ -305,9 +300,9 @@ func (mp *MongoPersist) FindTopicData(topic string, startIndex uint64, limit int
|
|||||||
}
|
}
|
||||||
|
|
||||||
//从startIndex开始一直往后查
|
//从startIndex开始一直往后查
|
||||||
topicData, isSucc := mp.findTopicData(topic, startIndex, limit,topicBuff)
|
topicData, ok := mp.findTopicData(topic, startIndex, limit, topicBuff)
|
||||||
//有数据或者数据库出错时返回,返回后,会进行下一轮的查询遍历
|
//有数据或者数据库出错时返回,返回后,会进行下一轮的查询遍历
|
||||||
if len(topicData) > 0 || isSucc == false {
|
if len(topicData) > 0 || ok == false {
|
||||||
return topicData
|
return topicData
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,14 +406,14 @@ func (mp *MongoPersist) PersistIndex(topic string, customerId string, index uint
|
|||||||
|
|
||||||
condition := bson.D{{Key: "Customer", Value: customerId}, {Key: "Topic", Value: topic}}
|
condition := bson.D{{Key: "Customer", Value: customerId}, {Key: "Topic", Value: topic}}
|
||||||
upsert := bson.M{"Customer": customerId, "Topic": topic, "Index": index}
|
upsert := bson.M{"Customer": customerId, "Topic": topic, "Index": index}
|
||||||
updata := bson.M{"$set": upsert}
|
update := bson.M{"$set": upsert}
|
||||||
|
|
||||||
var UpdateOptionsOpts []*options.UpdateOptions
|
var UpdateOptionsOpts []*options.UpdateOptions
|
||||||
UpdateOptionsOpts = append(UpdateOptionsOpts, options.Update().SetUpsert(true))
|
UpdateOptionsOpts = append(UpdateOptionsOpts, options.Update().SetUpsert(true))
|
||||||
|
|
||||||
ctx, cancel := s.GetDefaultContext()
|
ctx, cancel := s.GetDefaultContext()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err := s.Collection(mp.dbName, CustomerCollectName).UpdateOne(ctx, condition, updata, UpdateOptionsOpts...)
|
_, err := s.Collection(mp.dbName, CustomerCollectName).UpdateOne(ctx, condition, update, UpdateOptionsOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.SError("PersistIndex fail :", err.Error())
|
log.SError("PersistIndex fail :", err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 订阅器
|
// Subscriber 订阅器
|
||||||
type Subscriber struct {
|
type Subscriber struct {
|
||||||
customerLocker sync.RWMutex
|
customerLocker sync.RWMutex
|
||||||
mapCustomer map[string]*CustomerSubscriber
|
mapCustomer map[string]*CustomerSubscriber
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ type TopicRoom struct {
|
|||||||
isStop int32
|
isStop int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// maxProcessTopicBacklogNum:主题最大积压数量
|
// Init maxProcessTopicBacklogNum:主题最大积压数量
|
||||||
func (tr *TopicRoom) Init(maxTopicBacklogNum int32, memoryQueueLen int32, topic string, queueWait *sync.WaitGroup, dataPersist QueueDataPersist) {
|
func (tr *TopicRoom) Init(maxTopicBacklogNum int32, memoryQueueLen int32, topic string, queueWait *sync.WaitGroup, dataPersist QueueDataPersist) {
|
||||||
if maxTopicBacklogNum == 0 {
|
if maxTopicBacklogNum == 0 {
|
||||||
maxTopicBacklogNum = DefaultMaxTopicBacklogNum
|
maxTopicBacklogNum = DefaultMaxTopicBacklogNum
|
||||||
@@ -124,7 +124,7 @@ func (tr *TopicRoom) topicRoomRun() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. 如果存档成功,并且有后续批次,则继续存档
|
// 2. 如果存档成功,并且有后续批次,则继续存档
|
||||||
if ret == true && len(stagingBuff) > 0 {
|
if len(stagingBuff) > 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ func (mp *MongoPersist) ReadCfg() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//启服从数据库加载
|
// OnStart 启服从数据库加载
|
||||||
func (mp *MongoPersist) OnStart() {
|
func (mp *MongoPersist) OnStart() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ func (mp *MongoPersist) loadFromDB(rankId uint64,rankCollectName string) error{
|
|||||||
|
|
||||||
rankSkip := mp.mapRankSkip[rankId]
|
rankSkip := mp.mapRankSkip[rankId]
|
||||||
if rankSkip == nil {
|
if rankSkip == nil {
|
||||||
err = fmt.Errorf("rank ", rankCollectName, " is not setup:")
|
err = fmt.Errorf("rank %s is not setup", rankCollectName)
|
||||||
log.SError(err.Error())
|
log.SError(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -222,7 +222,6 @@ func (mp *MongoPersist) OnEnterRank(rankSkip IRankSkip, enterData *RankData){
|
|||||||
mp.mapUpsertRankData[rankSkip.GetRankID()][enterData.Key] = *enterData
|
mp.mapUpsertRankData[rankSkip.GetRankID()][enterData.Key] = *enterData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (mp *MongoPersist) OnLeaveRank(rankSkip IRankSkip, leaveData *RankData) {
|
func (mp *MongoPersist) OnLeaveRank(rankSkip IRankSkip, leaveData *RankData) {
|
||||||
mp.Lock()
|
mp.Lock()
|
||||||
defer mp.Unlock()
|
defer mp.Unlock()
|
||||||
@@ -245,13 +244,13 @@ func (mp *MongoPersist) OnChangeRankData(rankSkip IRankSkip, changeData *RankDat
|
|||||||
mp.mapUpsertRankData[rankSkip.GetRankID()][changeData.Key] = *changeData
|
mp.mapUpsertRankData[rankSkip.GetRankID()][changeData.Key] = *changeData
|
||||||
}
|
}
|
||||||
|
|
||||||
//停存持久化到DB
|
// OnStop 停存持久化到DB
|
||||||
func (mp *MongoPersist) OnStop(mapRankSkip map[uint64]*RankSkip) {
|
func (mp *MongoPersist) OnStop(mapRankSkip map[uint64]*RankSkip) {
|
||||||
atomic.StoreInt32(&mp.stop, 1)
|
atomic.StoreInt32(&mp.stop, 1)
|
||||||
mp.waitGroup.Wait()
|
mp.waitGroup.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mp *MongoPersist) JugeTimeoutSave() bool{
|
func (mp *MongoPersist) JudgeTimeoutSave() bool {
|
||||||
timeout := time.Now()
|
timeout := time.Now()
|
||||||
isTimeOut := timeout.Sub(mp.lastSaveTime) >= mp.SaveInterval
|
isTimeOut := timeout.Sub(mp.lastSaveTime) >= mp.SaveInterval
|
||||||
if isTimeOut == true {
|
if isTimeOut == true {
|
||||||
@@ -272,7 +271,7 @@ func (mp *MongoPersist) persistCoroutine(){
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if mp.JugeTimeoutSave() == false{
|
if mp.JudgeTimeoutSave() == false {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,7 +419,6 @@ func (mp *MongoPersist) removeRankDataToDB(mapRemoveRankData map[uint64]map[uint
|
|||||||
|
|
||||||
mp.removeRankData(rankId, keyList)
|
mp.removeRankData(rankId, keyList)
|
||||||
|
|
||||||
//如果删完,删掉rankid下所有
|
|
||||||
if len(mapRemoveKey) == 0 {
|
if len(mapRemoveKey) == 0 {
|
||||||
delete(mapRemoveRankData, rankId)
|
delete(mapRemoveRankData, rankId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package rankservice
|
package rankservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/v2/service"
|
|
||||||
"github.com/duanhf2012/origin/v2/rpc"
|
"github.com/duanhf2012/origin/v2/rpc"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RankDataChangeType int8
|
type RankDataChangeType int8
|
||||||
@@ -17,7 +17,6 @@ type IRankSkip interface {
|
|||||||
type IRankModule interface {
|
type IRankModule interface {
|
||||||
service.IModule
|
service.IModule
|
||||||
|
|
||||||
|
|
||||||
OnSetupRank(manual bool, rankSkip *RankSkip) error //当完成安装排行榜对象时
|
OnSetupRank(manual bool, rankSkip *RankSkip) error //当完成安装排行榜对象时
|
||||||
OnStart() //服务开启时回调
|
OnStart() //服务开启时回调
|
||||||
OnEnterRank(rankSkip IRankSkip, enterData *RankData) //进入排行
|
OnEnterRank(rankSkip IRankSkip, enterData *RankData) //进入排行
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func (rs *RankService) OnRelease() {
|
|||||||
rs.rankModule.OnStop(rs.mapRankSkip)
|
rs.rankModule.OnStop(rs.mapRankSkip)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 安装排行模块
|
// SetupRankModule 安装排行模块
|
||||||
func (rs *RankService) SetupRankModule(rankModule IRankModule) {
|
func (rs *RankService) SetupRankModule(rankModule IRankModule) {
|
||||||
rs.rankModule = rankModule
|
rs.rankModule = rankModule
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ func (rs *RankSkip) GetRankNodeData(findKey uint64) (*RankData, uint64) {
|
|||||||
return rankNode, index + 1
|
return rankNode, index + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRankNodeDataByPos 获取,返回排名节点与名次
|
// GetRankNodeDataByRank 获取,返回排名节点与名次
|
||||||
func (rs *RankSkip) GetRankNodeDataByRank(rank uint64) (*RankData, uint64) {
|
func (rs *RankSkip) GetRankNodeDataByRank(rank uint64) (*RankData, uint64) {
|
||||||
rs.pickExpireKey()
|
rs.pickExpireKey()
|
||||||
rankNode := rs.skipList.ByPosition(rank - 1)
|
rankNode := rs.skipList.ByPosition(rank - 1)
|
||||||
@@ -382,7 +382,7 @@ func (rs *RankSkip) GetRankKeyPrevToLimit(findKey, count uint64, result *rpc.Ran
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRankKeyPrevToLimit 获取key前count名的数据
|
// GetRankKeyNextToLimit 获取key前count名的数据
|
||||||
func (rs *RankSkip) GetRankKeyNextToLimit(findKey, count uint64, result *rpc.RankDataList) error {
|
func (rs *RankSkip) GetRankKeyNextToLimit(findKey, count uint64, result *rpc.RankDataList) error {
|
||||||
if rs.GetRankLen() <= 0 {
|
if rs.GetRankLen() <= 0 {
|
||||||
return fmt.Errorf("rank[%d] no data", rs.rankId)
|
return fmt.Errorf("rank[%d] no data", rs.rankId)
|
||||||
@@ -411,7 +411,7 @@ func (rs *RankSkip) GetRankKeyNextToLimit(findKey, count uint64, result *rpc.Ran
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRankList 获取排行榜数据,startPos开始的count个数据
|
// GetRankDataFromToLimit 获取排行榜数据,startPos开始的count个数据
|
||||||
func (rs *RankSkip) GetRankDataFromToLimit(startPos, count uint64, result *rpc.RankDataList) error {
|
func (rs *RankSkip) GetRankDataFromToLimit(startPos, count uint64, result *rpc.RankDataList) error {
|
||||||
if rs.GetRankLen() <= 0 {
|
if rs.GetRankLen() <= 0 {
|
||||||
//初始排行榜可能没有数据
|
//初始排行榜可能没有数据
|
||||||
|
|||||||
@@ -8,11 +8,10 @@ import (
|
|||||||
"github.com/duanhf2012/origin/v2/network/processor"
|
"github.com/duanhf2012/origin/v2/network/processor"
|
||||||
"github.com/duanhf2012/origin/v2/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"github.com/duanhf2012/origin/v2/util/bytespool"
|
"github.com/duanhf2012/origin/v2/util/bytespool"
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"time"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TcpService struct {
|
type TcpService struct {
|
||||||
@@ -25,6 +24,7 @@ type TcpService struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TcpPackType int8
|
type TcpPackType int8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TPT_Connected TcpPackType = 0
|
TPT_Connected TcpPackType = 0
|
||||||
TPT_DisConnected TcpPackType = 1
|
TPT_DisConnected TcpPackType = 1
|
||||||
@@ -40,19 +40,19 @@ type TcpPack struct {
|
|||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
id string
|
id string
|
||||||
tcpConn *network.TCPConn
|
tcpConn *network.NetConn
|
||||||
tcpService *TcpService
|
tcpService *TcpService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpService *TcpService) OnInit() error {
|
func (tcpService *TcpService) OnInit() error {
|
||||||
iConfig := tcpService.GetServiceCfg()
|
iConfig := tcpService.GetServiceCfg()
|
||||||
if iConfig == nil {
|
if iConfig == nil {
|
||||||
return fmt.Errorf("%s service config is error!", tcpService.GetName())
|
return fmt.Errorf("%s service config is error", tcpService.GetName())
|
||||||
}
|
}
|
||||||
tcpCfg := iConfig.(map[string]interface{})
|
tcpCfg := iConfig.(map[string]interface{})
|
||||||
addr, ok := tcpCfg["ListenAddr"]
|
addr, ok := tcpCfg["ListenAddr"]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return fmt.Errorf("%s service config is error!", tcpService.GetName())
|
return fmt.Errorf("%s service config is error", tcpService.GetName())
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpService.tcpServer.Addr = addr.(string)
|
tcpService.tcpServer.Addr = addr.(string)
|
||||||
@@ -94,9 +94,7 @@ func (tcpService *TcpService) OnInit() error{
|
|||||||
|
|
||||||
tcpService.mapClient = make(map[string]*Client, tcpService.tcpServer.MaxConnNum)
|
tcpService.mapClient = make(map[string]*Client, tcpService.tcpServer.MaxConnNum)
|
||||||
tcpService.tcpServer.NewAgent = tcpService.NewClient
|
tcpService.tcpServer.NewAgent = tcpService.NewClient
|
||||||
tcpService.tcpServer.Start()
|
return tcpService.tcpServer.Start()
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpService *TcpService) TcpEventHandler(ev event.IEvent) {
|
func (tcpService *TcpService) TcpEventHandler(ev event.IEvent) {
|
||||||
@@ -116,19 +114,18 @@ func (tcpService *TcpService) TcpEventHandler(ev event.IEvent) {
|
|||||||
func (tcpService *TcpService) recyclerReaderBytes(data []byte) {
|
func (tcpService *TcpService) recyclerReaderBytes(data []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (tcpService *TcpService) SetProcessor(process processor.IProcessor, handler event.IEventHandler) {
|
func (tcpService *TcpService) SetProcessor(process processor.IProcessor, handler event.IEventHandler) {
|
||||||
tcpService.process = process
|
tcpService.process = process
|
||||||
tcpService.RegEventReceiverFunc(event.Sys_Event_Tcp, handler, tcpService.TcpEventHandler)
|
tcpService.RegEventReceiverFunc(event.Sys_Event_Tcp, handler, tcpService.TcpEventHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpService *TcpService) NewClient(conn *network.TCPConn) network.Agent {
|
func (tcpService *TcpService) NewClient(conn network.Conn) network.Agent {
|
||||||
tcpService.mapClientLocker.Lock()
|
tcpService.mapClientLocker.Lock()
|
||||||
defer tcpService.mapClientLocker.Unlock()
|
defer tcpService.mapClientLocker.Unlock()
|
||||||
|
|
||||||
uuId, _ := uuid.NewUUID()
|
uuId, _ := uuid.NewUUID()
|
||||||
clientId := strings.ReplaceAll(uuId.String(), "-", "")
|
clientId := strings.ReplaceAll(uuId.String(), "-", "")
|
||||||
pClient := &Client{tcpConn: conn, id: clientId}
|
pClient := &Client{tcpConn: conn.(*network.NetConn), id: clientId}
|
||||||
pClient.tcpService = tcpService
|
pClient.tcpService = tcpService
|
||||||
tcpService.mapClient[clientId] = pClient
|
tcpService.mapClient[clientId] = pClient
|
||||||
|
|
||||||
@@ -142,10 +139,7 @@ func (slf *Client) GetId() string {
|
|||||||
func (slf *Client) Run() {
|
func (slf *Client) Run() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.Dump(string(buf[:l]),log.String("error",errString))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -158,7 +152,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.Debug("read client failed",log.ErrorAttr("error",err),log.String("clientId",slf.id))
|
log.Debug("read client failed", log.ErrorField("error", err), log.String("clientId", slf.id))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
data, err := slf.tcpService.process.Unmarshal(slf.id, bytes)
|
data, err := slf.tcpService.process.Unmarshal(slf.id, bytes)
|
||||||
@@ -183,7 +177,7 @@ func (tcpService *TcpService) SendMsg(clientId string,msg interface{}) error{
|
|||||||
client, ok := tcpService.mapClient[clientId]
|
client, ok := tcpService.mapClient[clientId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
tcpService.mapClientLocker.Unlock()
|
tcpService.mapClientLocker.Unlock()
|
||||||
return fmt.Errorf("client %d is disconnect!",clientId)
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpService.mapClientLocker.Unlock()
|
tcpService.mapClientLocker.Unlock()
|
||||||
@@ -210,10 +204,10 @@ func (tcpService *TcpService) Close(clientId string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcpService *TcpService) GetClientIp(clientid string) string{
|
func (tcpService *TcpService) GetClientIp(clientId string) string {
|
||||||
tcpService.mapClientLocker.Lock()
|
tcpService.mapClientLocker.Lock()
|
||||||
defer tcpService.mapClientLocker.Unlock()
|
defer tcpService.mapClientLocker.Unlock()
|
||||||
pClient,ok := tcpService.mapClient[clientid]
|
pClient, ok := tcpService.mapClient[clientId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -221,13 +215,12 @@ func (tcpService *TcpService) GetClientIp(clientid string) string{
|
|||||||
return pClient.tcpConn.GetRemoteIp()
|
return pClient.tcpConn.GetRemoteIp()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (tcpService *TcpService) SendRawMsg(clientId string, msg []byte) error {
|
func (tcpService *TcpService) SendRawMsg(clientId string, msg []byte) error {
|
||||||
tcpService.mapClientLocker.Lock()
|
tcpService.mapClientLocker.Lock()
|
||||||
client, ok := tcpService.mapClient[clientId]
|
client, ok := tcpService.mapClient[clientId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
tcpService.mapClientLocker.Unlock()
|
tcpService.mapClientLocker.Unlock()
|
||||||
return fmt.Errorf("client %d is disconnect!",clientId)
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
}
|
}
|
||||||
tcpService.mapClientLocker.Unlock()
|
tcpService.mapClientLocker.Unlock()
|
||||||
return client.tcpConn.WriteMsg(msg)
|
return client.tcpConn.WriteMsg(msg)
|
||||||
@@ -238,13 +231,12 @@ func (tcpService *TcpService) SendRawData(clientId string,data []byte) error{
|
|||||||
client, ok := tcpService.mapClient[clientId]
|
client, ok := tcpService.mapClient[clientId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
tcpService.mapClientLocker.Unlock()
|
tcpService.mapClientLocker.Unlock()
|
||||||
return fmt.Errorf("client %d is disconnect!",clientId)
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
}
|
}
|
||||||
tcpService.mapClientLocker.Unlock()
|
tcpService.mapClientLocker.Unlock()
|
||||||
return client.tcpConn.WriteRawMsg(data)
|
return client.tcpConn.WriteRawMsg(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (tcpService *TcpService) GetConnNum() int {
|
func (tcpService *TcpService) GetConnNum() int {
|
||||||
tcpService.mapClientLocker.Lock()
|
tcpService.mapClientLocker.Lock()
|
||||||
connNum := len(tcpService.mapClient)
|
connNum := len(tcpService.mapClient)
|
||||||
@@ -252,14 +244,14 @@ func (tcpService *TcpService) GetConnNum() int {
|
|||||||
return connNum
|
return connNum
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TcpService) SetNetMempool(mempool bytespool.IBytesMempool){
|
func (tcpService *TcpService) SetNetMemPool(memPool bytespool.IBytesMemPool) {
|
||||||
server.tcpServer.SetNetMempool(mempool)
|
tcpService.tcpServer.SetNetMemPool(memPool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TcpService) GetNetMempool() bytespool.IBytesMempool {
|
func (tcpService *TcpService) GetNetMemPool() bytespool.IBytesMemPool {
|
||||||
return server.tcpServer.GetNetMempool()
|
return tcpService.tcpServer.GetNetMemPool()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *TcpService) ReleaseNetMem(byteBuff []byte) {
|
func (tcpService *TcpService) ReleaseNetMem(byteBuff []byte) {
|
||||||
server.tcpServer.GetNetMempool().ReleaseBytes(byteBuff)
|
tcpService.tcpServer.GetNetMemPool().ReleaseBytes(byteBuff)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import (
|
|||||||
"github.com/duanhf2012/origin/v2/network"
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
"github.com/duanhf2012/origin/v2/network/processor"
|
"github.com/duanhf2012/origin/v2/network/processor"
|
||||||
"github.com/duanhf2012/origin/v2/service"
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
"sync"
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WSService struct {
|
type WSService struct {
|
||||||
@@ -22,6 +22,7 @@ type WSService struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WSPackType int8
|
type WSPackType int8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
WPT_Connected WSPackType = 0
|
WPT_Connected WSPackType = 0
|
||||||
WPT_DisConnected WSPackType = 1
|
WPT_DisConnected WSPackType = 1
|
||||||
@@ -50,12 +51,12 @@ func (ws *WSService) OnInit() error{
|
|||||||
|
|
||||||
iConfig := ws.GetServiceCfg()
|
iConfig := ws.GetServiceCfg()
|
||||||
if iConfig == nil {
|
if iConfig == nil {
|
||||||
return fmt.Errorf("%s service config is error!", ws.GetName())
|
return fmt.Errorf("%s service config is error", ws.GetName())
|
||||||
}
|
}
|
||||||
wsCfg := iConfig.(map[string]interface{})
|
wsCfg := iConfig.(map[string]interface{})
|
||||||
addr, ok := wsCfg["ListenAddr"]
|
addr, ok := wsCfg["ListenAddr"]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return fmt.Errorf("%s service config is error!", ws.GetName())
|
return fmt.Errorf("%s service config is error", ws.GetName())
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.wsServer.Addr = addr.(string)
|
ws.wsServer.Addr = addr.(string)
|
||||||
@@ -79,8 +80,7 @@ func (ws *WSService) OnInit() error{
|
|||||||
|
|
||||||
ws.mapClient = make(map[string]*WSClient, ws.wsServer.MaxConnNum)
|
ws.mapClient = make(map[string]*WSClient, ws.wsServer.MaxConnNum)
|
||||||
ws.wsServer.NewAgent = ws.NewWSClient
|
ws.wsServer.NewAgent = ws.NewWSClient
|
||||||
ws.wsServer.Start()
|
return ws.wsServer.Start()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WSService) SetMessageType(messageType int) {
|
func (ws *WSService) SetMessageType(messageType int) {
|
||||||
@@ -129,7 +129,7 @@ func (slf *WSClient) Run() {
|
|||||||
for {
|
for {
|
||||||
bytes, err := slf.wsConn.ReadMsg()
|
bytes, err := slf.wsConn.ReadMsg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("read client id %s is error:%+v",slf.id,err)
|
log.Debugf("read client id %s is error:%+v", slf.id, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
data, err := slf.wsService.process.Unmarshal(slf.id, bytes)
|
data, err := slf.wsService.process.Unmarshal(slf.id, bytes)
|
||||||
@@ -148,27 +148,27 @@ func (slf *WSClient) OnClose(){
|
|||||||
delete(slf.wsService.mapClient, slf.GetId())
|
delete(slf.wsService.mapClient, slf.GetId())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WSService) SendMsg(clientid string,msg interface{}) error{
|
func (ws *WSService) SendMsg(clientId string, msg interface{}) error {
|
||||||
ws.mapClientLocker.Lock()
|
ws.mapClientLocker.Lock()
|
||||||
client,ok := ws.mapClient[clientid]
|
client, ok := ws.mapClient[clientId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
ws.mapClientLocker.Unlock()
|
ws.mapClientLocker.Unlock()
|
||||||
return fmt.Errorf("client %s is disconnect!",clientid)
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.mapClientLocker.Unlock()
|
ws.mapClientLocker.Unlock()
|
||||||
bytes,err := ws.process.Marshal(clientid,msg)
|
bytes, err := ws.process.Marshal(clientId, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return client.wsConn.WriteMsg(bytes)
|
return client.wsConn.WriteMsg(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WSService) Close(clientid string) {
|
func (ws *WSService) Close(clientId string) {
|
||||||
ws.mapClientLocker.Lock()
|
ws.mapClientLocker.Lock()
|
||||||
defer ws.mapClientLocker.Unlock()
|
defer ws.mapClientLocker.Unlock()
|
||||||
|
|
||||||
client,ok := ws.mapClient[clientid]
|
client, ok := ws.mapClient[clientId]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
func NewAesEncrypt(key string) (aes *AesEncrypt, err error) {
|
func NewAesEncrypt(key string) (aes *AesEncrypt, err error) {
|
||||||
keyLen := len(key)
|
keyLen := len(key)
|
||||||
if keyLen < 16 {
|
if keyLen < 16 {
|
||||||
err = fmt.Errorf("The length of res key shall not be less than 16")
|
err = fmt.Errorf("the length of res key shall not be less than 16")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
aes = &AesEncrypt{
|
aes = &AesEncrypt{
|
||||||
@@ -22,12 +22,12 @@ type AesEncrypt struct {
|
|||||||
StrKey string
|
StrKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *AesEncrypt) getKey() []byte {
|
func (ae *AesEncrypt) getKey() []byte {
|
||||||
keyLen := len(this.StrKey)
|
keyLen := len(ae.StrKey)
|
||||||
if keyLen < 16 {
|
if keyLen < 16 {
|
||||||
panic("The length of res key shall not be less than 16")
|
panic("The length of res key shall not be less than 16")
|
||||||
}
|
}
|
||||||
arrKey := []byte(this.StrKey)
|
arrKey := []byte(ae.StrKey)
|
||||||
if keyLen >= 32 {
|
if keyLen >= 32 {
|
||||||
//取前32个字节
|
//取前32个字节
|
||||||
return arrKey[:32]
|
return arrKey[:32]
|
||||||
@@ -40,33 +40,33 @@ func (this *AesEncrypt) getKey() []byte {
|
|||||||
return arrKey[:16]
|
return arrKey[:16]
|
||||||
}
|
}
|
||||||
|
|
||||||
//加密字符串
|
// Encrypt 加密字符串
|
||||||
func (this *AesEncrypt) Encrypt(strMesg string) ([]byte, error) {
|
func (ae *AesEncrypt) Encrypt(str string) ([]byte, error) {
|
||||||
key := this.getKey()
|
key := ae.getKey()
|
||||||
var iv = []byte(key)[:aes.BlockSize]
|
var iv = key[:aes.BlockSize]
|
||||||
encrypted := make([]byte, len(strMesg))
|
encrypted := make([]byte, len(str))
|
||||||
aesBlockEncrypter, err := aes.NewCipher(key)
|
aesBlockEncrypter, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
aesEncrypter := cipher.NewCFBEncrypter(aesBlockEncrypter, iv)
|
aesEncrypter := cipher.NewCFBEncrypter(aesBlockEncrypter, iv)
|
||||||
aesEncrypter.XORKeyStream(encrypted, []byte(strMesg))
|
aesEncrypter.XORKeyStream(encrypted, []byte(str))
|
||||||
return encrypted, nil
|
return encrypted, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//解密字符串
|
// Decrypt 解密字符串
|
||||||
func (this *AesEncrypt) Decrypt(src []byte) (strDesc string, err error) {
|
func (ae *AesEncrypt) Decrypt(src []byte) (strDesc string, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
//错误处理
|
//错误处理
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = e.(error)
|
err = e.(error)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
key := this.getKey()
|
key := ae.getKey()
|
||||||
var iv = []byte(key)[:aes.BlockSize]
|
var iv = key[:aes.BlockSize]
|
||||||
decrypted := make([]byte, len(src))
|
decrypted := make([]byte, len(src))
|
||||||
var aesBlockDecrypter cipher.Block
|
var aesBlockDecrypter cipher.Block
|
||||||
aesBlockDecrypter, err = aes.NewCipher([]byte(key))
|
aesBlockDecrypter, err = aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func setBitTagByIndex[Number BitNumber, UNumber UnsignedNumber](bitBuff []Number
|
|||||||
func GetBitwiseTag[Number BitNumber, UNumber UnsignedNumber](bitBuff []Number, bitPositionIndex UNumber) (bool, error) {
|
func GetBitwiseTag[Number BitNumber, UNumber UnsignedNumber](bitBuff []Number, bitPositionIndex UNumber) (bool, error) {
|
||||||
sliceIndex, sliceBitIndex, ret := getBitTagIndex(bitBuff, bitPositionIndex)
|
sliceIndex, sliceBitIndex, ret := getBitTagIndex(bitBuff, bitPositionIndex)
|
||||||
if ret == false {
|
if ret == false {
|
||||||
return false, errors.New("Invalid parameter")
|
return false, errors.New("invalid parameter")
|
||||||
}
|
}
|
||||||
|
|
||||||
return (bitBuff[sliceIndex] & (1 << sliceBitIndex)) > 0, nil
|
return (bitBuff[sliceIndex] & (1 << sliceBitIndex)) > 0, nil
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IBytesMempool interface {
|
type IBytesMemPool interface {
|
||||||
MakeBytes(size int) []byte
|
MakeBytes(size int) []byte
|
||||||
ReleaseBytes(byteBuff []byte) bool
|
ReleaseBytes(byteBuff []byte) bool
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func Go(callback interface{}, args ...interface{}) {
|
|||||||
go F(callback, 0, args...)
|
go F(callback, 0, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-1表示一直恢复
|
// GoRecover -1表示一直恢复
|
||||||
func GoRecover(callback interface{}, recoverNum int, args ...interface{}) {
|
func GoRecover(callback interface{}, recoverNum int, args ...interface{}) {
|
||||||
go F(callback, recoverNum, args...)
|
go F(callback, recoverNum, args...)
|
||||||
}
|
}
|
||||||
173
util/pattern/pubsub/pubsub.go
Normal file
173
util/pattern/pubsub/pubsub.go
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
package pubsub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"container/list"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TopicType int
|
||||||
|
type Key uint64
|
||||||
|
|
||||||
|
type IBaseSubscriber interface {
|
||||||
|
OnSubscribe(key Key)
|
||||||
|
GetKey() Key
|
||||||
|
}
|
||||||
|
|
||||||
|
type ISubscriber interface {
|
||||||
|
IBaseSubscriber
|
||||||
|
OnEvent(ctx ...any)
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPublisher interface {
|
||||||
|
Publish(topic TopicType, ctx ...any)
|
||||||
|
Subscribe(topic TopicType, sub ISubscriber)
|
||||||
|
UnSubscribe(topic TopicType)
|
||||||
|
UnSubscribeKey(key Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
var keyID uint64
|
||||||
|
|
||||||
|
func genKeyID() Key {
|
||||||
|
return Key(atomic.AddUint64(&keyID, 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyData struct {
|
||||||
|
subscriber ISubscriber
|
||||||
|
topicType TopicType
|
||||||
|
keyElement *list.Element
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubscriberSet map[Key]KeyData
|
||||||
|
type TopicSet map[TopicType]*list.List
|
||||||
|
|
||||||
|
type Publisher struct {
|
||||||
|
subscriberSet SubscriberSet
|
||||||
|
topicSet TopicSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *SubscriberSet) init() {
|
||||||
|
*set = make(SubscriberSet, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *SubscriberSet) add(keyElement *list.Element, topicType TopicType, subscriber ISubscriber) {
|
||||||
|
(*set)[keyElement.Value.(Key)] = KeyData{subscriber: subscriber, topicType: topicType, keyElement: keyElement}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *SubscriberSet) del(key Key) {
|
||||||
|
delete(*set, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *SubscriberSet) get(key Key) (KeyData, bool) {
|
||||||
|
keyData, ok := (*set)[key]
|
||||||
|
if !ok {
|
||||||
|
return keyData, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyData, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *TopicSet) init() {
|
||||||
|
*set = make(TopicSet, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *TopicSet) add(topic TopicType, key Key) *list.Element {
|
||||||
|
keyList := (*set)[topic]
|
||||||
|
if keyList == nil {
|
||||||
|
keyList = list.New()
|
||||||
|
(*set)[topic] = keyList
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyList.PushBack(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *TopicSet) del(topic TopicType, keyElement *list.Element) {
|
||||||
|
keyList := (*set)[topic]
|
||||||
|
if keyList == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
keyList.Remove(keyElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *TopicSet) foreach(topic TopicType, cb func(key Key)) {
|
||||||
|
keyList := (*set)[topic]
|
||||||
|
if keyList == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for e := keyList.Front(); e != nil; e = e.Next() {
|
||||||
|
cb(e.Value.(Key))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseSubscriber struct {
|
||||||
|
key Key
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *BaseSubscriber) OnSubscribe(key Key) {
|
||||||
|
bs.key = key
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *BaseSubscriber) GetKey() Key {
|
||||||
|
return bs.key
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pub *Publisher) lazyInit() {
|
||||||
|
if pub.subscriberSet == nil {
|
||||||
|
pub.subscriberSet.init()
|
||||||
|
}
|
||||||
|
if pub.topicSet == nil {
|
||||||
|
pub.topicSet.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pub *Publisher) add(topic TopicType, sub ISubscriber) Key {
|
||||||
|
key := genKeyID()
|
||||||
|
ele := pub.topicSet.add(topic, key)
|
||||||
|
pub.subscriberSet.add(ele, topic, sub)
|
||||||
|
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pub *Publisher) Publish(topic TopicType, ctx ...any) {
|
||||||
|
pub.lazyInit()
|
||||||
|
pub.topicSet.foreach(topic, func(key Key) {
|
||||||
|
keyData, ok := pub.subscriberSet.get(key)
|
||||||
|
if ok == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
keyData.subscriber.OnEvent(ctx...)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pub *Publisher) Subscribe(topic TopicType, sub ISubscriber) bool {
|
||||||
|
if topic == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub.lazyInit()
|
||||||
|
sub.OnSubscribe(pub.add(topic, sub))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pub *Publisher) UnSubscribe(topic TopicType) {
|
||||||
|
keyList := pub.topicSet[topic]
|
||||||
|
if keyList == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for e := keyList.Front(); e != nil; e = e.Next() {
|
||||||
|
pub.subscriberSet.del(e.Value.(Key))
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(pub.topicSet, topic)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pub *Publisher) UnSubscribeKey(key Key) {
|
||||||
|
keyData, ok := pub.subscriberSet.get(key)
|
||||||
|
if ok == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pub.topicSet.del(keyData.topicType, keyData.keyElement)
|
||||||
|
pub.subscriberSet.del(key)
|
||||||
|
}
|
||||||
54
util/pattern/pubsub/pubsub_test.go
Normal file
54
util/pattern/pubsub/pubsub_test.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package pubsub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Invalid TopicType = iota
|
||||||
|
Topic1
|
||||||
|
Topic2
|
||||||
|
)
|
||||||
|
|
||||||
|
var test *testing.T
|
||||||
|
|
||||||
|
type Subscriber1 struct {
|
||||||
|
BaseSubscriber
|
||||||
|
}
|
||||||
|
|
||||||
|
type Subscriber2 struct {
|
||||||
|
BaseSubscriber
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sub *Subscriber1) OnEvent(ctx ...any) {
|
||||||
|
test.Log("Subscriber1 OnEvent", " key ", sub.GetKey(), ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sub *Subscriber2) OnEvent(ctx ...any) {
|
||||||
|
test.Log("Subscriber2 OnEvent", " key ", sub.GetKey(), ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPubSub(t *testing.T) {
|
||||||
|
test = t
|
||||||
|
var publisher Publisher
|
||||||
|
|
||||||
|
// 创建3个订阅者
|
||||||
|
var subscriber []ISubscriber
|
||||||
|
subscriber = append(subscriber, &Subscriber1{}, &Subscriber1{}, &Subscriber2{})
|
||||||
|
|
||||||
|
// 分别注册进Publisher中
|
||||||
|
publisher.Subscribe(Topic1, subscriber[0])
|
||||||
|
publisher.Subscribe(Topic1, subscriber[1])
|
||||||
|
publisher.Subscribe(Topic2, subscriber[2])
|
||||||
|
|
||||||
|
// 发布订阅,两个Subscriber1都会调用OnEvent
|
||||||
|
publisher.Publish(Topic1, 1, 2, 3)
|
||||||
|
|
||||||
|
// 删除订阅,Publish后,只有Subscriber1的key2收到
|
||||||
|
publisher.UnSubscribeKey(subscriber[0].GetKey())
|
||||||
|
publisher.Publish(Topic1, 1, 2, 3)
|
||||||
|
|
||||||
|
// 删除Topic2,Publish将收不到
|
||||||
|
publisher.UnSubscribe(Topic2)
|
||||||
|
publisher.Publish(Topic2, 1)
|
||||||
|
}
|
||||||
@@ -2,10 +2,10 @@ package smath
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/v2/log"
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
"github.com/duanhf2012/origin/v2/util/typedef"
|
"github.com/duanhf2012/origin/v2/util/typ"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Max[NumType typedef.Number](number1 NumType, number2 NumType) NumType {
|
func Max[NumType typ.Number](number1 NumType, number2 NumType) NumType {
|
||||||
if number1 > number2 {
|
if number1 > number2 {
|
||||||
return number1
|
return number1
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ func Max[NumType typedef.Number](number1 NumType, number2 NumType) NumType {
|
|||||||
return number2
|
return number2
|
||||||
}
|
}
|
||||||
|
|
||||||
func Min[NumType typedef.Number](number1 NumType, number2 NumType) NumType {
|
func Min[NumType typ.Number](number1 NumType, number2 NumType) NumType {
|
||||||
if number1 < number2 {
|
if number1 < number2 {
|
||||||
return number1
|
return number1
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ func Min[NumType typedef.Number](number1 NumType, number2 NumType) NumType {
|
|||||||
return number2
|
return number2
|
||||||
}
|
}
|
||||||
|
|
||||||
func Abs[NumType typedef.Signed|typedef.Float](Num NumType) NumType {
|
func Abs[NumType typ.Signed | typ.Float](Num NumType) NumType {
|
||||||
if Num < 0 {
|
if Num < 0 {
|
||||||
return -1 * Num
|
return -1 * Num
|
||||||
}
|
}
|
||||||
@@ -29,33 +29,33 @@ func Abs[NumType typedef.Signed|typedef.Float](Num NumType) NumType {
|
|||||||
return Num
|
return Num
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddSafe[NumType typedef.Number](number1 NumType, number2 NumType) (NumType, bool) {
|
func AddSafe[NumType typ.Number](number1 NumType, number2 NumType) (NumType, bool) {
|
||||||
ret := number1 + number2
|
ret := number1 + number2
|
||||||
if number2 > 0 && ret < number1 {
|
if number2 > 0 && ret < number1 {
|
||||||
log.Stack("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
|
log.SStackError("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
|
||||||
return ret, false
|
return ret, false
|
||||||
} else if number2 < 0 && ret > number1 {
|
} else if number2 < 0 && ret > number1 {
|
||||||
log.Stack("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
|
log.SStackError("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
|
||||||
return ret, false
|
return ret, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, true
|
return ret, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func SubSafe[NumType typedef.Number](number1 NumType, number2 NumType) (NumType, bool) {
|
func SubSafe[NumType typ.Number](number1 NumType, number2 NumType) (NumType, bool) {
|
||||||
ret := number1 - number2
|
ret := number1 - number2
|
||||||
if number2 > 0 && ret > number1 {
|
if number2 > 0 && ret > number1 {
|
||||||
log.Stack("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
|
log.SStackError("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
|
||||||
return ret, false
|
return ret, false
|
||||||
} else if number2 < 0 && ret < number1 {
|
} else if number2 < 0 && ret < number1 {
|
||||||
log.Stack("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
|
log.SStackError("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
|
||||||
return ret, false
|
return ret, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, true
|
return ret, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func MulSafe[NumType typedef.Number](number1 NumType, number2 NumType) (NumType, bool) {
|
func MulSafe[NumType typ.Number](number1 NumType, number2 NumType) (NumType, bool) {
|
||||||
ret := number1 * number2
|
ret := number1 * number2
|
||||||
if number1 == 0 || number2 == 0 {
|
if number1 == 0 || number2 == 0 {
|
||||||
return ret, true
|
return ret, true
|
||||||
@@ -65,22 +65,21 @@ func MulSafe[NumType typedef.Number](number1 NumType, number2 NumType) (NumType,
|
|||||||
return ret, true
|
return ret, true
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Stack("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
|
log.SStackError("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
|
||||||
return ret, true
|
return ret, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func Add[NumType typedef.Number](number1 NumType, number2 NumType) NumType {
|
func Add[NumType typ.Number](number1 NumType, number2 NumType) NumType {
|
||||||
ret, _ := AddSafe(number1, number2)
|
ret, _ := AddSafe(number1, number2)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sub[NumType typedef.Number](number1 NumType, number2 NumType) NumType {
|
func Sub[NumType typ.Number](number1 NumType, number2 NumType) NumType {
|
||||||
ret, _ := SubSafe(number1, number2)
|
ret, _ := SubSafe(number1, number2)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func Mul[NumType typedef.Number](number1 NumType, number2 NumType) NumType {
|
func Mul[NumType typ.Number](number1 NumType, number2 NumType) NumType {
|
||||||
ret, _ := MulSafe(number1, number2)
|
ret, _ := MulSafe(number1, number2)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package srand
|
package srand
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duanhf2012/origin/v2/util/typedef"
|
"github.com/duanhf2012/origin/v2/util/typ"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"slices"
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Sum[E ~[]T, T typedef.Number](arr E) T {
|
func Sum[E ~[]T, T typ.Number](arr E) T {
|
||||||
var sum T
|
var sum T
|
||||||
for i := range arr {
|
for i := range arr {
|
||||||
sum += arr[i]
|
sum += arr[i]
|
||||||
@@ -14,7 +14,7 @@ func Sum[E ~[]T, T typedef.Number](arr E) T {
|
|||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
func SumFunc[E ~[]V, V any, T typedef.Number](arr E, getValue func(i int) T) T {
|
func SumFunc[E ~[]V, V any, T typ.Number](arr E, getValue func(i int) T) T {
|
||||||
var sum T
|
var sum T
|
||||||
for i := range arr {
|
for i := range arr {
|
||||||
sum += getValue(i)
|
sum += getValue(i)
|
||||||
@@ -39,16 +39,17 @@ func RandN[E ~[]T, T any](arr E, num int) []T {
|
|||||||
}
|
}
|
||||||
Shuffle(index)
|
Shuffle(index)
|
||||||
if len(index) > num {
|
if len(index) > num {
|
||||||
index = index
|
index = index[:num]
|
||||||
}
|
}
|
||||||
ret := make([]T, 0, len(index))
|
ret := make([]T, 0, len(index))
|
||||||
for i := range index {
|
for i := range index {
|
||||||
ret = append(ret, arr[index[i]])
|
ret = append(ret, arr[index[i]])
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func RandWeight[E ~[]T, T typedef.Integer](weights E) int {
|
func RandWeight[E ~[]T, T typ.Integer](weights E) int {
|
||||||
totalWeight := Sum(weights)
|
totalWeight := Sum(weights)
|
||||||
if totalWeight <= 0 {
|
if totalWeight <= 0 {
|
||||||
return -1
|
return -1
|
||||||
@@ -64,7 +65,7 @@ func RandWeight[E ~[]T, T typedef.Integer](weights E) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func RandWeightFunc[E ~[]U, U any, T typedef.Integer](arr E, getWeight func(i int) T) int {
|
func RandWeightFunc[E ~[]U, U any, T typ.Integer](arr E, getWeight func(i int) T) int {
|
||||||
weights := make([]T, 0, len(arr))
|
weights := make([]T, 0, len(arr))
|
||||||
for i := range arr {
|
for i := range arr {
|
||||||
weights = append(weights, getWeight(i))
|
weights = append(weights, getWeight(i))
|
||||||
@@ -72,7 +73,7 @@ func RandWeightFunc[E ~[]U, U any, T typedef.Integer](arr E, getWeight func(i in
|
|||||||
return RandWeight(weights)
|
return RandWeight(weights)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Get[E ~[]T, T any, U typedef.Integer](arr E, index U) (ret T, ok bool) {
|
func Get[E ~[]T, T any, U typ.Integer](arr E, index U) (ret T, ok bool) {
|
||||||
if index < 0 || int(index) >= len(arr) {
|
if index < 0 || int(index) >= len(arr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -81,7 +82,7 @@ func Get[E ~[]T, T any, U typedef.Integer](arr E, index U) (ret T, ok bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPointer[E ~[]T, T any, U typedef.Integer](arr E, index U) *T {
|
func GetPointer[E ~[]T, T any, U typ.Integer](arr E, index U) *T {
|
||||||
if index < 0 || int(index) >= len(arr) {
|
if index < 0 || int(index) >= len(arr) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ func (pool *Pool) Get() interface{}{
|
|||||||
default:
|
default:
|
||||||
return pool.syncPool.Get()
|
return pool.syncPool.Get()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pool *Pool) Put(data interface{}) {
|
func (pool *Pool) Put(data interface{}) {
|
||||||
@@ -94,5 +92,3 @@ func (pool *PoolEx) Put(data IPoolData){
|
|||||||
pool.syncPool.Put(data)
|
pool.syncPool.Put(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,10 @@ import (
|
|||||||
"github.com/duanhf2012/origin/v2/util/sync"
|
"github.com/duanhf2012/origin/v2/util/sync"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ITimer
|
|
||||||
type ITimer interface {
|
type ITimer interface {
|
||||||
GetId() uint64
|
GetId() uint64
|
||||||
Cancel()
|
Cancel()
|
||||||
@@ -27,7 +26,6 @@ type ITimer interface {
|
|||||||
type OnCloseTimer func(timer ITimer)
|
type OnCloseTimer func(timer ITimer)
|
||||||
type OnAddTimer func(timer ITimer)
|
type OnAddTimer func(timer ITimer)
|
||||||
|
|
||||||
// Timer
|
|
||||||
type Timer struct {
|
type Timer struct {
|
||||||
Id uint64
|
Id uint64
|
||||||
cancelled int32 //是否关闭
|
cancelled int32 //是否关闭
|
||||||
@@ -46,12 +44,10 @@ type Timer struct {
|
|||||||
ref bool
|
ref bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ticker
|
|
||||||
type Ticker struct {
|
type Ticker struct {
|
||||||
Timer
|
Timer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cron
|
|
||||||
type Cron struct {
|
type Cron struct {
|
||||||
Timer
|
Timer
|
||||||
}
|
}
|
||||||
@@ -101,7 +97,6 @@ func releaseCron(cron *Cron) {
|
|||||||
cronPool.Put(cron)
|
cronPool.Put(cron)
|
||||||
}
|
}
|
||||||
|
|
||||||
// one dispatcher per goroutine (goroutine not safe)
|
|
||||||
type Dispatcher struct {
|
type Dispatcher struct {
|
||||||
ChanTimer chan ITimer
|
ChanTimer chan ITimer
|
||||||
}
|
}
|
||||||
@@ -129,10 +124,7 @@ func (t *Timer) IsOpen() bool {
|
|||||||
func (t *Timer) Do() {
|
func (t *Timer) Do() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.Dump(string(buf[:l]),log.String("error",errString))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -175,7 +167,7 @@ func (t *Timer) Cancel() {
|
|||||||
atomic.StoreInt32(&t.cancelled, 1)
|
atomic.StoreInt32(&t.cancelled, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断定时器是否已经取消
|
// IsActive 判断定时器是否已经取消
|
||||||
func (t *Timer) IsActive() bool {
|
func (t *Timer) IsActive() bool {
|
||||||
return atomic.LoadInt32(&t.cancelled) == 0
|
return atomic.LoadInt32(&t.cancelled) == 0
|
||||||
}
|
}
|
||||||
@@ -215,10 +207,7 @@ func (c *Cron) Reset() {
|
|||||||
func (c *Cron) Do() {
|
func (c *Cron) Do() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.Dump(string(buf[:l]),log.String("error",errString))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -271,10 +260,7 @@ func (c *Cron) UnRef() {
|
|||||||
func (c *Ticker) Do() {
|
func (c *Ticker) Do() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
buf := make([]byte, 4096)
|
log.StackError(fmt.Sprint(r))
|
||||||
l := runtime.Stack(buf, false)
|
|
||||||
errString := fmt.Sprint(r)
|
|
||||||
log.Dump(string(buf[:l]),log.String("error",errString))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
54
util/typ/type.go
Normal file
54
util/typ/type.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package typ
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
type Signed interface {
|
||||||
|
~int | ~int8 | ~int16 | ~int32 | ~int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Unsigned interface {
|
||||||
|
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Float interface {
|
||||||
|
~float32 | ~float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Integer interface {
|
||||||
|
Signed | Unsigned
|
||||||
|
}
|
||||||
|
|
||||||
|
type Number interface {
|
||||||
|
Signed | Unsigned | Float
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ordered interface {
|
||||||
|
Number | Float | ~string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvertToNumber[DType Number](val interface{}) (DType, error) {
|
||||||
|
switch val.(type) {
|
||||||
|
case int64:
|
||||||
|
return DType(val.(int64)), nil
|
||||||
|
case int:
|
||||||
|
return DType(val.(int)), nil
|
||||||
|
case uint:
|
||||||
|
return DType(val.(uint)), nil
|
||||||
|
case uint64:
|
||||||
|
return DType(val.(uint64)), nil
|
||||||
|
case float32:
|
||||||
|
return DType(val.(float32)), nil
|
||||||
|
case float64:
|
||||||
|
return DType(val.(float64)), nil
|
||||||
|
case int32:
|
||||||
|
return DType(val.(int32)), nil
|
||||||
|
case uint32:
|
||||||
|
return DType(val.(uint32)), nil
|
||||||
|
case int16:
|
||||||
|
return DType(val.(int16)), nil
|
||||||
|
case uint16:
|
||||||
|
return DType(val.(uint16)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, errors.New("unsupported type")
|
||||||
|
}
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package typedef
|
|
||||||
|
|
||||||
type Signed interface {
|
|
||||||
~int | ~int8 | ~int16 | ~int32 | ~int64
|
|
||||||
}
|
|
||||||
|
|
||||||
type Unsigned interface {
|
|
||||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
type Float interface {
|
|
||||||
~float32 | ~float64
|
|
||||||
}
|
|
||||||
|
|
||||||
type Integer interface {
|
|
||||||
Signed|Unsigned
|
|
||||||
}
|
|
||||||
|
|
||||||
type Number interface {
|
|
||||||
Signed|Unsigned|Float
|
|
||||||
}
|
|
||||||
|
|
||||||
type Ordered interface {
|
|
||||||
Number|Float|~string
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user