mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-16 02:22:26 +08:00
init commit
This commit is contained in:
6
air/cmd/application.toml
Normal file
6
air/cmd/application.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
http_port = 8086
|
||||
|
||||
[logger]
|
||||
level = "DEBUG"
|
||||
method = "CONSOLE"
|
||||
track_line = true
|
||||
55
air/cmd/main.go
Normal file
55
air/cmd/main.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"air/controller"
|
||||
"air/service"
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/logger"
|
||||
"github.com/arl/statsviz"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filePath := "./application.toml"
|
||||
config.InitConfig(filePath)
|
||||
|
||||
logger.InitLogger()
|
||||
logger.LOG.Info("air start")
|
||||
|
||||
go func() {
|
||||
// 性能检测
|
||||
err := statsviz.RegisterDefault()
|
||||
if err != nil {
|
||||
logger.LOG.Error("statsviz init error: %v", err)
|
||||
}
|
||||
err = http.ListenAndServe("0.0.0.0:1234", nil)
|
||||
if err != nil {
|
||||
logger.LOG.Error("perf debug http start error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
svc := service.NewService()
|
||||
|
||||
_ = controller.NewController(svc)
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
|
||||
for {
|
||||
s := <-c
|
||||
logger.LOG.Info("get a signal %s", s.String())
|
||||
switch s {
|
||||
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
|
||||
logger.LOG.Info("air exit")
|
||||
time.Sleep(time.Second)
|
||||
return
|
||||
case syscall.SIGHUP:
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
48
air/controller/controller.go
Normal file
48
air/controller/controller.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"air/service"
|
||||
"flswld.com/common/config"
|
||||
"github.com/gin-gonic/gin"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
service *service.Service
|
||||
}
|
||||
|
||||
func NewController(service *service.Service) (r *Controller) {
|
||||
r = new(Controller)
|
||||
r.service = service
|
||||
go r.registerRouter()
|
||||
return r
|
||||
}
|
||||
|
||||
func (c *Controller) registerRouter() {
|
||||
if config.CONF.Logger.Level == "DEBUG" {
|
||||
gin.SetMode(gin.DebugMode)
|
||||
} else {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
engine := gin.Default()
|
||||
// HTTP
|
||||
engine.GET("/http/fetch", c.fetchHttpService)
|
||||
engine.GET("/http/fetch/all", c.fetchAllHttpService)
|
||||
engine.POST("/http/reg", c.registerHttpService)
|
||||
engine.POST("/http/cancel", c.cancelHttpService)
|
||||
engine.POST("/http/ka", c.httpKeepalive)
|
||||
// RPC
|
||||
engine.GET("/rpc/fetch", c.fetchRpcService)
|
||||
engine.GET("/rpc/fetch/all", c.fetchAllRpcService)
|
||||
engine.POST("/rpc/reg", c.registerRpcService)
|
||||
engine.POST("/rpc/cancel", c.cancelRpcService)
|
||||
engine.POST("/rpc/ka", c.rpcKeepalive)
|
||||
// 长轮询
|
||||
engine.GET("/poll/http", c.pollHttpService)
|
||||
engine.GET("/poll/http/all", c.pollAllHttpService)
|
||||
engine.GET("/poll/rpc", c.pollRpcService)
|
||||
engine.GET("/poll/rpc/all", c.pollAllRpcService)
|
||||
port := strconv.FormatInt(int64(config.CONF.HttpPort), 10)
|
||||
portStr := ":" + port
|
||||
_ = engine.Run(portStr)
|
||||
}
|
||||
39
air/controller/fetch_controller.go
Normal file
39
air/controller/fetch_controller.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package controller
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
// 获取HTTP服务
|
||||
func (c *Controller) fetchHttpService(context *gin.Context) {
|
||||
inst := c.service.FetchHttpService(context.Query("name"))
|
||||
context.JSON(200, gin.H{
|
||||
"code": 0,
|
||||
"instance": inst,
|
||||
})
|
||||
}
|
||||
|
||||
// 获取所有HTTP服务
|
||||
func (c *Controller) fetchAllHttpService(context *gin.Context) {
|
||||
svc := c.service.FetchAllHttpService()
|
||||
context.JSON(200, gin.H{
|
||||
"code": 0,
|
||||
"service": svc,
|
||||
})
|
||||
}
|
||||
|
||||
// 获取RPC服务
|
||||
func (c *Controller) fetchRpcService(context *gin.Context) {
|
||||
inst := c.service.FetchRpcService(context.Query("name"))
|
||||
context.JSON(200, gin.H{
|
||||
"code": 0,
|
||||
"instance": inst,
|
||||
})
|
||||
}
|
||||
|
||||
// 获取所有RPC服务
|
||||
func (c *Controller) fetchAllRpcService(context *gin.Context) {
|
||||
svc := c.service.FetchAllRpcService()
|
||||
context.JSON(200, gin.H{
|
||||
"code": 0,
|
||||
"service": svc,
|
||||
})
|
||||
}
|
||||
35
air/controller/keepalive_controller.go
Normal file
35
air/controller/keepalive_controller.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"air/entity"
|
||||
"flswld.com/logger"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// HTTP心跳
|
||||
func (c *Controller) httpKeepalive(context *gin.Context) {
|
||||
inst := new(entity.Instance)
|
||||
err := context.ShouldBindJSON(inst)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse json error: %v", err)
|
||||
return
|
||||
}
|
||||
c.service.HttpKeepalive(*inst)
|
||||
context.JSON(200, gin.H{
|
||||
"code": 0,
|
||||
})
|
||||
}
|
||||
|
||||
// RPC心跳
|
||||
func (c *Controller) rpcKeepalive(context *gin.Context) {
|
||||
inst := new(entity.Instance)
|
||||
err := context.ShouldBindJSON(inst)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse json error: %v", err)
|
||||
return
|
||||
}
|
||||
c.service.RpcKeepalive(*inst)
|
||||
context.JSON(200, gin.H{
|
||||
"code": 0,
|
||||
})
|
||||
}
|
||||
85
air/controller/poll_controller.go
Normal file
85
air/controller/poll_controller.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *Controller) pollHttpService(context *gin.Context) {
|
||||
serviceName := context.Query("name")
|
||||
recvrNtfr := c.service.RegistryHttpNotifyReceiver(serviceName)
|
||||
timeout := time.NewTicker(time.Second * 30)
|
||||
select {
|
||||
case inst := <-recvrNtfr.NotifyChannel:
|
||||
c.service.CancelHttpNotifyReceiver(serviceName, recvrNtfr.Id)
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"instance": inst,
|
||||
})
|
||||
case <-timeout.C:
|
||||
c.service.CancelHttpNotifyReceiver(serviceName, recvrNtfr.Id)
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"instance": nil,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) pollAllHttpService(context *gin.Context) {
|
||||
recvrNtfr := c.service.RegistryAllHttpNotifyReceiver()
|
||||
timeout := time.NewTicker(time.Second * 30)
|
||||
select {
|
||||
case svc := <-recvrNtfr.NotifyChannel:
|
||||
c.service.CancelAllHttpNotifyReceiver(recvrNtfr.Id)
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"service": svc,
|
||||
})
|
||||
case <-timeout.C:
|
||||
c.service.CancelAllHttpNotifyReceiver(recvrNtfr.Id)
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"service": nil,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) pollRpcService(context *gin.Context) {
|
||||
serviceName := context.Query("name")
|
||||
recvrNtfr := c.service.RegistryRpcNotifyReceiver(serviceName)
|
||||
timeout := time.NewTicker(time.Second * 30)
|
||||
select {
|
||||
case inst := <-recvrNtfr.NotifyChannel:
|
||||
c.service.CancelRpcNotifyReceiver(serviceName, recvrNtfr.Id)
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"instance": inst,
|
||||
})
|
||||
case <-timeout.C:
|
||||
c.service.CancelRpcNotifyReceiver(serviceName, recvrNtfr.Id)
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"instance": nil,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) pollAllRpcService(context *gin.Context) {
|
||||
recvrNtfr := c.service.RegistryAllRpcNotifyReceiver()
|
||||
timeout := time.NewTicker(time.Second * 30)
|
||||
select {
|
||||
case svc := <-recvrNtfr.NotifyChannel:
|
||||
c.service.CancelAllRpcNotifyReceiver(recvrNtfr.Id)
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"service": svc,
|
||||
})
|
||||
case <-timeout.C:
|
||||
c.service.CancelAllRpcNotifyReceiver(recvrNtfr.Id)
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"service": nil,
|
||||
})
|
||||
}
|
||||
}
|
||||
63
air/controller/registry_controller.go
Normal file
63
air/controller/registry_controller.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"air/entity"
|
||||
"flswld.com/logger"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 注册HTTP服务
|
||||
func (c *Controller) registerHttpService(context *gin.Context) {
|
||||
inst := new(entity.Instance)
|
||||
err := context.ShouldBindJSON(inst)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse json error: %v", err)
|
||||
return
|
||||
}
|
||||
c.service.RegisterHttpService(*inst)
|
||||
context.JSON(200, gin.H{
|
||||
"code": 0,
|
||||
})
|
||||
}
|
||||
|
||||
// 取消注册HTTP服务
|
||||
func (c *Controller) cancelHttpService(context *gin.Context) {
|
||||
inst := new(entity.Instance)
|
||||
err := context.ShouldBindJSON(inst)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse json error: %v", err)
|
||||
return
|
||||
}
|
||||
c.service.CancelHttpService(*inst)
|
||||
context.JSON(200, gin.H{
|
||||
"code": 0,
|
||||
})
|
||||
}
|
||||
|
||||
// 注册RPC服务
|
||||
func (c *Controller) registerRpcService(context *gin.Context) {
|
||||
inst := new(entity.Instance)
|
||||
err := context.ShouldBindJSON(inst)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse json error: %v", err)
|
||||
return
|
||||
}
|
||||
c.service.RegisterRpcService(*inst)
|
||||
context.JSON(200, gin.H{
|
||||
"code": 0,
|
||||
})
|
||||
}
|
||||
|
||||
// 取消注册RPC服务
|
||||
func (c *Controller) cancelRpcService(context *gin.Context) {
|
||||
inst := new(entity.Instance)
|
||||
err := context.ShouldBindJSON(inst)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse json error: %v", err)
|
||||
return
|
||||
}
|
||||
c.service.CancelRpcService(*inst)
|
||||
context.JSON(200, gin.H{
|
||||
"code": 0,
|
||||
})
|
||||
}
|
||||
8
air/entity/instance.go
Normal file
8
air/entity/instance.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package entity
|
||||
|
||||
// 服务实例实体类
|
||||
type Instance struct {
|
||||
ServiceName string `json:"service_name"`
|
||||
InstanceName string `json:"instance_name"`
|
||||
InstanceAddr string `json:"instance_addr"`
|
||||
}
|
||||
33
air/go.mod
Normal file
33
air/go.mod
Normal file
@@ -0,0 +1,33 @@
|
||||
module air
|
||||
|
||||
go 1.19
|
||||
|
||||
require flswld.com/common v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/common => ../common
|
||||
|
||||
require flswld.com/logger v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/logger => ../logger
|
||||
|
||||
require github.com/gin-gonic/gin v1.6.3
|
||||
|
||||
require github.com/arl/statsviz v0.5.1
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.2.0 // indirect
|
||||
github.com/golang/protobuf v1.3.3 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/json-iterator/go v1.1.9 // indirect
|
||||
github.com/leodido/go-urn v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
|
||||
github.com/ugorji/go/codec v1.1.7 // indirect
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
)
|
||||
52
air/go.sum
Normal file
52
air/go.sum
Normal file
@@ -0,0 +1,52 @@
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/arl/statsviz v0.5.1 h1:3HY0ZEB738JtguWsD1Tf1pFJZiCcWUmYRq/3OTYKaSI=
|
||||
github.com/arl/statsviz v0.5.1/go.mod h1:zDnjgRblGm1Dyd7J5YlbH7gM1/+HRC+SfkhZhQb5AnM=
|
||||
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
89
air/service/fetch_service.go
Normal file
89
air/service/fetch_service.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package service
|
||||
|
||||
import "air/entity"
|
||||
|
||||
// 获取HTTP服务
|
||||
func (s *Service) FetchHttpService(name string) (r []entity.Instance) {
|
||||
s.httpServiceMapLock.RLock()
|
||||
instanceMap := s.httpServiceMap[name]
|
||||
s.httpServiceMapLock.RUnlock()
|
||||
r = make([]entity.Instance, 0)
|
||||
if instanceMap == nil {
|
||||
return r
|
||||
}
|
||||
instanceMap.lock.RLock()
|
||||
for k, v := range instanceMap.Imap {
|
||||
instance := new(entity.Instance)
|
||||
instance.ServiceName = name
|
||||
instance.InstanceName = k
|
||||
instance.InstanceAddr = v.Address
|
||||
r = append(r, *instance)
|
||||
}
|
||||
instanceMap.lock.RUnlock()
|
||||
return r
|
||||
}
|
||||
|
||||
// 获取所有HTTP服务
|
||||
func (s *Service) FetchAllHttpService() (r map[string][]entity.Instance) {
|
||||
s.httpServiceMapLock.RLock()
|
||||
serviceMap := s.httpServiceMap
|
||||
s.httpServiceMapLock.RUnlock()
|
||||
r = make(map[string][]entity.Instance)
|
||||
for k, v := range serviceMap {
|
||||
instanceSlice := make([]entity.Instance, 0)
|
||||
v.lock.RLock()
|
||||
for kk, vv := range v.Imap {
|
||||
instance := new(entity.Instance)
|
||||
instance.ServiceName = k
|
||||
instance.InstanceName = kk
|
||||
instance.InstanceAddr = vv.Address
|
||||
instanceSlice = append(instanceSlice, *instance)
|
||||
}
|
||||
v.lock.RUnlock()
|
||||
r[k] = instanceSlice
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// 获取RPC服务
|
||||
func (s *Service) FetchRpcService(name string) (r []entity.Instance) {
|
||||
s.rpcServiceMapLock.RLock()
|
||||
instanceMap := s.rpcServiceMap[name]
|
||||
s.rpcServiceMapLock.RUnlock()
|
||||
r = make([]entity.Instance, 0)
|
||||
if instanceMap == nil {
|
||||
return r
|
||||
}
|
||||
instanceMap.lock.RLock()
|
||||
for k, v := range instanceMap.Imap {
|
||||
instance := new(entity.Instance)
|
||||
instance.ServiceName = name
|
||||
instance.InstanceName = k
|
||||
instance.InstanceAddr = v.Address
|
||||
r = append(r, *instance)
|
||||
}
|
||||
instanceMap.lock.RUnlock()
|
||||
return r
|
||||
}
|
||||
|
||||
// 获取所有RPC服务
|
||||
func (s *Service) FetchAllRpcService() (r map[string][]entity.Instance) {
|
||||
s.rpcServiceMapLock.RLock()
|
||||
serviceMap := s.rpcServiceMap
|
||||
s.rpcServiceMapLock.RUnlock()
|
||||
r = make(map[string][]entity.Instance)
|
||||
for k, v := range serviceMap {
|
||||
instanceSlice := make([]entity.Instance, 0)
|
||||
v.lock.RLock()
|
||||
for kk, vv := range v.Imap {
|
||||
instance := new(entity.Instance)
|
||||
instance.ServiceName = k
|
||||
instance.InstanceName = kk
|
||||
instance.InstanceAddr = vv.Address
|
||||
instanceSlice = append(instanceSlice, *instance)
|
||||
}
|
||||
v.lock.RUnlock()
|
||||
r[k] = instanceSlice
|
||||
}
|
||||
return r
|
||||
}
|
||||
136
air/service/keepalive_service.go
Normal file
136
air/service/keepalive_service.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"air/entity"
|
||||
"flswld.com/logger"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HTTP心跳
|
||||
func (s *Service) HttpKeepalive(instance entity.Instance) {
|
||||
nowTime := time.Now().Unix()
|
||||
s.httpServiceMapLock.RLock()
|
||||
instanceMap := s.httpServiceMap[instance.ServiceName]
|
||||
s.httpServiceMapLock.RUnlock()
|
||||
if instanceMap != nil {
|
||||
instanceMap.lock.Lock()
|
||||
instanceData := instanceMap.Imap[instance.InstanceName]
|
||||
if instanceData != nil {
|
||||
instanceData.LastAliveTime = nowTime
|
||||
} else {
|
||||
logger.LOG.Error("recv not exist instance http keepalive, instance name: %v", instance.InstanceName)
|
||||
}
|
||||
instanceMap.lock.Unlock()
|
||||
} else {
|
||||
logger.LOG.Error("recv not exist service http keepalive, service name: %v", instance.ServiceName)
|
||||
}
|
||||
}
|
||||
|
||||
// RPC心跳
|
||||
func (s *Service) RpcKeepalive(instance entity.Instance) {
|
||||
nowTime := time.Now().Unix()
|
||||
s.rpcServiceMapLock.RLock()
|
||||
instanceMap := s.rpcServiceMap[instance.ServiceName]
|
||||
s.rpcServiceMapLock.RUnlock()
|
||||
if instanceMap != nil {
|
||||
instanceMap.lock.Lock()
|
||||
instanceData := instanceMap.Imap[instance.InstanceName]
|
||||
if instanceData != nil {
|
||||
instanceData.LastAliveTime = nowTime
|
||||
} else {
|
||||
logger.LOG.Error("recv not exist instance rpc keepalive, instance name: %v", instance.InstanceName)
|
||||
}
|
||||
instanceMap.lock.Unlock()
|
||||
} else {
|
||||
logger.LOG.Error("recv not exist service rpc keepalive, service name: %v", instance.ServiceName)
|
||||
}
|
||||
}
|
||||
|
||||
// 定时移除掉线服务
|
||||
func (s *Service) removeDeadService() {
|
||||
ticker := time.NewTicker(time.Second * 60)
|
||||
for {
|
||||
<-ticker.C
|
||||
nowTime := time.Now().Unix()
|
||||
|
||||
httpSvcChgFlagMap := make(map[string]bool)
|
||||
httpSvcChgMap := make(map[string]*InstanceMap)
|
||||
httpSvcDelMap := make(map[string]*InstanceMap)
|
||||
s.httpServiceMapLock.RLock()
|
||||
for svcName, svcInstMap := range s.httpServiceMap {
|
||||
svcInstMap.lock.Lock()
|
||||
for instName, instData := range svcInstMap.Imap {
|
||||
if nowTime-instData.LastAliveTime > 60 {
|
||||
httpSvcChgFlagMap[svcName] = true
|
||||
if httpSvcDelMap[svcName] == nil {
|
||||
httpSvcDelMap[svcName] = new(InstanceMap)
|
||||
httpSvcDelMap[svcName].Imap = make(map[string]*InstanceData)
|
||||
}
|
||||
httpSvcDelMap[svcName].Imap[instName] = instData
|
||||
delete(svcInstMap.Imap, instName)
|
||||
} else {
|
||||
if httpSvcChgMap[svcName] == nil {
|
||||
httpSvcChgMap[svcName] = new(InstanceMap)
|
||||
httpSvcChgMap[svcName].Imap = make(map[string]*InstanceData)
|
||||
}
|
||||
httpSvcChgMap[svcName].Imap[instName] = instData
|
||||
}
|
||||
}
|
||||
svcInstMap.lock.Unlock()
|
||||
}
|
||||
s.httpServiceMapLock.RUnlock()
|
||||
for svcName, instMap := range httpSvcDelMap {
|
||||
for instName, instData := range instMap.Imap {
|
||||
logger.LOG.Info("remove timeout http service, service name: %v, instance name: %v, instance data: %v", svcName, instName, instData)
|
||||
}
|
||||
}
|
||||
for svcName, _ := range httpSvcChgMap {
|
||||
if !httpSvcChgFlagMap[svcName] {
|
||||
delete(httpSvcChgMap, svcName)
|
||||
}
|
||||
}
|
||||
if len(httpSvcChgMap) != 0 {
|
||||
s.httpSvcChgNtfCh <- httpSvcChgMap
|
||||
}
|
||||
|
||||
rpcSvcChgFlagMap := make(map[string]bool)
|
||||
rpcSvcChgMap := make(map[string]*InstanceMap)
|
||||
rpcSvcDelMap := make(map[string]*InstanceMap)
|
||||
s.rpcServiceMapLock.RLock()
|
||||
for svcName, svcInstMap := range s.rpcServiceMap {
|
||||
svcInstMap.lock.Lock()
|
||||
for instName, instData := range svcInstMap.Imap {
|
||||
if nowTime-instData.LastAliveTime > 60 {
|
||||
rpcSvcChgFlagMap[svcName] = true
|
||||
if rpcSvcDelMap[svcName] == nil {
|
||||
rpcSvcDelMap[svcName] = new(InstanceMap)
|
||||
rpcSvcDelMap[svcName].Imap = make(map[string]*InstanceData)
|
||||
}
|
||||
rpcSvcDelMap[svcName].Imap[instName] = instData
|
||||
delete(svcInstMap.Imap, instName)
|
||||
} else {
|
||||
if rpcSvcChgMap[svcName] == nil {
|
||||
rpcSvcChgMap[svcName] = new(InstanceMap)
|
||||
rpcSvcChgMap[svcName].Imap = make(map[string]*InstanceData)
|
||||
}
|
||||
rpcSvcChgMap[svcName].Imap[instName] = instData
|
||||
}
|
||||
}
|
||||
svcInstMap.lock.Unlock()
|
||||
}
|
||||
s.rpcServiceMapLock.RUnlock()
|
||||
for svcName, instMap := range rpcSvcDelMap {
|
||||
for instName, instData := range instMap.Imap {
|
||||
logger.LOG.Info("remove timeout rpc service, service name: %v, instance name: %v, instance data: %v", svcName, instName, instData)
|
||||
}
|
||||
}
|
||||
for svcName, _ := range rpcSvcChgMap {
|
||||
if !rpcSvcChgFlagMap[svcName] {
|
||||
delete(rpcSvcChgMap, svcName)
|
||||
}
|
||||
}
|
||||
if len(rpcSvcChgMap) != 0 {
|
||||
s.rpcSvcChgNtfCh <- rpcSvcChgMap
|
||||
}
|
||||
}
|
||||
}
|
||||
190
air/service/poll_service.go
Normal file
190
air/service/poll_service.go
Normal file
@@ -0,0 +1,190 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"air/entity"
|
||||
"flswld.com/logger"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (s *Service) watchServiceChange() {
|
||||
s.watcher.receiverNotifierIdCounter = 0
|
||||
s.watcher.httpRecvrNtfrMap = make(map[string]map[uint64]*ReceiverNotifier)
|
||||
s.watcher.httpAllSvcRecvrNtfrMap = make(map[uint64]*AllServiceReceiverNotifier)
|
||||
s.watcher.rpcRecvrNtfrMap = make(map[string]map[uint64]*ReceiverNotifier)
|
||||
s.watcher.rpcAllSvcRecvrNtfrMap = make(map[uint64]*AllServiceReceiverNotifier)
|
||||
go func() {
|
||||
for {
|
||||
imap := <-s.httpSvcChgNtfCh
|
||||
for svcName, instMap := range imap {
|
||||
// 给某个服务的接收者通知器发送消息
|
||||
s.watcher.httpRecvrNtfrMapLock.RLock()
|
||||
recvrNtfrMap := s.watcher.httpRecvrNtfrMap[svcName]
|
||||
instList := make([]entity.Instance, 0)
|
||||
for instName, instData := range instMap.Imap {
|
||||
inst := new(entity.Instance)
|
||||
inst.ServiceName = svcName
|
||||
inst.InstanceName = instName
|
||||
inst.InstanceAddr = instData.Address
|
||||
instList = append(instList, *inst)
|
||||
}
|
||||
if recvrNtfrMap == nil || len(recvrNtfrMap) == 0 {
|
||||
s.watcher.httpRecvrNtfrMapLock.RUnlock()
|
||||
continue
|
||||
}
|
||||
for _, recvrNtfr := range recvrNtfrMap {
|
||||
if time.Now().UnixNano()-recvrNtfr.CreateTime < int64(time.Second*30) {
|
||||
logger.LOG.Debug("send http service change notify to receiver: %d", recvrNtfr.Id)
|
||||
recvrNtfr.NotifyChannel <- instList
|
||||
}
|
||||
close(recvrNtfr.NotifyChannel)
|
||||
}
|
||||
s.watcher.httpRecvrNtfrMapLock.RUnlock()
|
||||
}
|
||||
|
||||
// 给全体服务的接收者通知器发送消息
|
||||
s.watcher.httpAllSvcRecvrNtfrMapLock.RLock()
|
||||
if len(s.watcher.httpAllSvcRecvrNtfrMap) == 0 {
|
||||
s.watcher.httpAllSvcRecvrNtfrMapLock.RUnlock()
|
||||
continue
|
||||
}
|
||||
svcMap := s.FetchAllHttpService()
|
||||
for _, recvrNtfr := range s.watcher.httpAllSvcRecvrNtfrMap {
|
||||
if time.Now().UnixNano()-recvrNtfr.CreateTime < int64(time.Second*30) {
|
||||
logger.LOG.Debug("send all http service change notify to receiver: %d", recvrNtfr.Id)
|
||||
recvrNtfr.NotifyChannel <- svcMap
|
||||
}
|
||||
close(recvrNtfr.NotifyChannel)
|
||||
}
|
||||
s.watcher.httpAllSvcRecvrNtfrMapLock.RUnlock()
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
imap := <-s.rpcSvcChgNtfCh
|
||||
for svcName, instMap := range imap {
|
||||
// 给某个服务的接收者通知器发送消息
|
||||
s.watcher.rpcRecvrNtfrMapLock.RLock()
|
||||
recvrNtfrMap := s.watcher.rpcRecvrNtfrMap[svcName]
|
||||
instList := make([]entity.Instance, 0)
|
||||
for instName, instData := range instMap.Imap {
|
||||
inst := new(entity.Instance)
|
||||
inst.ServiceName = svcName
|
||||
inst.InstanceName = instName
|
||||
inst.InstanceAddr = instData.Address
|
||||
instList = append(instList, *inst)
|
||||
}
|
||||
if recvrNtfrMap == nil || len(recvrNtfrMap) == 0 {
|
||||
s.watcher.rpcRecvrNtfrMapLock.RUnlock()
|
||||
continue
|
||||
}
|
||||
for _, recvrNtfr := range recvrNtfrMap {
|
||||
if time.Now().UnixNano()-recvrNtfr.CreateTime < int64(time.Second*30) {
|
||||
logger.LOG.Debug("send rpc service change notify to receiver: %d", recvrNtfr.Id)
|
||||
recvrNtfr.NotifyChannel <- instList
|
||||
}
|
||||
close(recvrNtfr.NotifyChannel)
|
||||
}
|
||||
s.watcher.rpcRecvrNtfrMapLock.RUnlock()
|
||||
}
|
||||
|
||||
// 给全体服务的接收者通知器发送消息
|
||||
s.watcher.rpcAllSvcRecvrNtfrMapLock.RLock()
|
||||
if len(s.watcher.rpcAllSvcRecvrNtfrMap) == 0 {
|
||||
s.watcher.rpcAllSvcRecvrNtfrMapLock.RUnlock()
|
||||
continue
|
||||
}
|
||||
svcMap := s.FetchAllRpcService()
|
||||
for _, recvrNtfr := range s.watcher.rpcAllSvcRecvrNtfrMap {
|
||||
if time.Now().UnixNano()-recvrNtfr.CreateTime < int64(time.Second*30) {
|
||||
logger.LOG.Debug("send all rpc service change notify to receiver: %d", recvrNtfr.Id)
|
||||
recvrNtfr.NotifyChannel <- svcMap
|
||||
}
|
||||
close(recvrNtfr.NotifyChannel)
|
||||
}
|
||||
s.watcher.rpcAllSvcRecvrNtfrMapLock.RUnlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// 注册HTTP服务变化通知接收者
|
||||
func (s *Service) RegistryHttpNotifyReceiver(serviceName string) *ReceiverNotifier {
|
||||
recvrNtfr := new(ReceiverNotifier)
|
||||
recvrNtfr.Id = atomic.AddUint64(&s.watcher.receiverNotifierIdCounter, 1)
|
||||
recvrNtfr.CreateTime = time.Now().UnixNano()
|
||||
recvrNtfr.NotifyChannel = make(chan []entity.Instance, 0)
|
||||
s.watcher.httpRecvrNtfrMapLock.Lock()
|
||||
if s.watcher.httpRecvrNtfrMap[serviceName] == nil {
|
||||
s.watcher.httpRecvrNtfrMap[serviceName] = make(map[uint64]*ReceiverNotifier)
|
||||
}
|
||||
s.watcher.httpRecvrNtfrMap[serviceName][recvrNtfr.Id] = recvrNtfr
|
||||
s.watcher.httpRecvrNtfrMapLock.Unlock()
|
||||
return recvrNtfr
|
||||
}
|
||||
|
||||
// 取消HTTP服务变化通知接收者
|
||||
func (s *Service) CancelHttpNotifyReceiver(serviceName string, id uint64) {
|
||||
s.watcher.httpRecvrNtfrMapLock.Lock()
|
||||
delete(s.watcher.httpRecvrNtfrMap[serviceName], id)
|
||||
s.watcher.httpRecvrNtfrMapLock.Unlock()
|
||||
}
|
||||
|
||||
// 注册全体HTTP服务变化通知接收者
|
||||
func (s *Service) RegistryAllHttpNotifyReceiver() *AllServiceReceiverNotifier {
|
||||
recvrNtfr := new(AllServiceReceiverNotifier)
|
||||
recvrNtfr.Id = atomic.AddUint64(&s.watcher.receiverNotifierIdCounter, 1)
|
||||
recvrNtfr.CreateTime = time.Now().UnixNano()
|
||||
recvrNtfr.NotifyChannel = make(chan map[string][]entity.Instance, 0)
|
||||
s.watcher.httpAllSvcRecvrNtfrMapLock.Lock()
|
||||
s.watcher.httpAllSvcRecvrNtfrMap[recvrNtfr.Id] = recvrNtfr
|
||||
s.watcher.httpAllSvcRecvrNtfrMapLock.Unlock()
|
||||
return recvrNtfr
|
||||
}
|
||||
|
||||
// 取消全体HTTP服务变化通知接收者
|
||||
func (s *Service) CancelAllHttpNotifyReceiver(id uint64) {
|
||||
s.watcher.httpAllSvcRecvrNtfrMapLock.Lock()
|
||||
delete(s.watcher.httpAllSvcRecvrNtfrMap, id)
|
||||
s.watcher.httpAllSvcRecvrNtfrMapLock.Unlock()
|
||||
}
|
||||
|
||||
// 注册RPC服务变化通知接收者
|
||||
func (s *Service) RegistryRpcNotifyReceiver(serviceName string) *ReceiverNotifier {
|
||||
recvrNtfr := new(ReceiverNotifier)
|
||||
recvrNtfr.Id = atomic.AddUint64(&s.watcher.receiverNotifierIdCounter, 1)
|
||||
recvrNtfr.CreateTime = time.Now().UnixNano()
|
||||
recvrNtfr.NotifyChannel = make(chan []entity.Instance, 0)
|
||||
s.watcher.rpcRecvrNtfrMapLock.Lock()
|
||||
if s.watcher.rpcRecvrNtfrMap[serviceName] == nil {
|
||||
s.watcher.rpcRecvrNtfrMap[serviceName] = make(map[uint64]*ReceiverNotifier)
|
||||
}
|
||||
s.watcher.rpcRecvrNtfrMap[serviceName][recvrNtfr.Id] = recvrNtfr
|
||||
s.watcher.rpcRecvrNtfrMapLock.Unlock()
|
||||
return recvrNtfr
|
||||
}
|
||||
|
||||
// 取消RPC服务变化通知接收者
|
||||
func (s *Service) CancelRpcNotifyReceiver(serviceName string, id uint64) {
|
||||
s.watcher.rpcRecvrNtfrMapLock.Lock()
|
||||
delete(s.watcher.rpcRecvrNtfrMap[serviceName], id)
|
||||
s.watcher.rpcRecvrNtfrMapLock.Unlock()
|
||||
}
|
||||
|
||||
// 注册全体RPC服务变化通知接收者
|
||||
func (s *Service) RegistryAllRpcNotifyReceiver() *AllServiceReceiverNotifier {
|
||||
recvrNtfr := new(AllServiceReceiverNotifier)
|
||||
recvrNtfr.Id = atomic.AddUint64(&s.watcher.receiverNotifierIdCounter, 1)
|
||||
recvrNtfr.CreateTime = time.Now().UnixNano()
|
||||
recvrNtfr.NotifyChannel = make(chan map[string][]entity.Instance, 0)
|
||||
s.watcher.rpcAllSvcRecvrNtfrMapLock.Lock()
|
||||
s.watcher.rpcAllSvcRecvrNtfrMap[recvrNtfr.Id] = recvrNtfr
|
||||
s.watcher.rpcAllSvcRecvrNtfrMapLock.Unlock()
|
||||
return recvrNtfr
|
||||
}
|
||||
|
||||
// 取消全体RPC服务变化通知接收者
|
||||
func (s *Service) CancelAllRpcNotifyReceiver(id uint64) {
|
||||
s.watcher.rpcAllSvcRecvrNtfrMapLock.Lock()
|
||||
delete(s.watcher.rpcAllSvcRecvrNtfrMap, id)
|
||||
s.watcher.rpcAllSvcRecvrNtfrMapLock.Unlock()
|
||||
}
|
||||
103
air/service/registry_service.go
Normal file
103
air/service/registry_service.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"air/entity"
|
||||
"flswld.com/common/utils/object"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 注册HTTP服务
|
||||
func (s *Service) RegisterHttpService(instance entity.Instance) bool {
|
||||
nowTime := time.Now().Unix()
|
||||
s.httpServiceMapLock.Lock()
|
||||
instanceMap := s.httpServiceMap[instance.ServiceName]
|
||||
if instanceMap == nil {
|
||||
instanceMap = new(InstanceMap)
|
||||
instanceMap.Imap = make(map[string]*InstanceData)
|
||||
}
|
||||
instanceMap.lock.Lock()
|
||||
instanceData := instanceMap.Imap[instance.InstanceName]
|
||||
if instanceData == nil {
|
||||
instanceData = new(InstanceData)
|
||||
}
|
||||
instanceData.Address = instance.InstanceAddr
|
||||
instanceData.LastAliveTime = nowTime
|
||||
instanceMap.Imap[instance.InstanceName] = instanceData
|
||||
s.httpServiceMap[instance.ServiceName] = instanceMap
|
||||
instanceMap.lock.Unlock()
|
||||
s.httpServiceMapLock.Unlock()
|
||||
changeInst := make(map[string]*InstanceMap)
|
||||
instanceMapCopy := new(InstanceMap)
|
||||
instanceMap.lock.RLock()
|
||||
_ = object.ObjectDeepCopy(instanceMap, instanceMapCopy)
|
||||
instanceMap.lock.RUnlock()
|
||||
changeInst[instance.ServiceName] = instanceMapCopy
|
||||
s.httpSvcChgNtfCh <- changeInst
|
||||
return true
|
||||
}
|
||||
|
||||
// 取消注册HTTP服务
|
||||
func (s *Service) CancelHttpService(instance entity.Instance) bool {
|
||||
s.httpServiceMapLock.RLock()
|
||||
instanceMap := s.httpServiceMap[instance.ServiceName]
|
||||
s.httpServiceMapLock.RUnlock()
|
||||
instanceMap.lock.Lock()
|
||||
delete(instanceMap.Imap, instance.InstanceName)
|
||||
instanceMap.lock.Unlock()
|
||||
changeInst := make(map[string]*InstanceMap)
|
||||
instanceMapCopy := new(InstanceMap)
|
||||
instanceMap.lock.RLock()
|
||||
_ = object.ObjectDeepCopy(instanceMap, instanceMapCopy)
|
||||
instanceMap.lock.RUnlock()
|
||||
changeInst[instance.ServiceName] = instanceMapCopy
|
||||
s.httpSvcChgNtfCh <- changeInst
|
||||
return true
|
||||
}
|
||||
|
||||
// 注册RPC服务
|
||||
func (s *Service) RegisterRpcService(instance entity.Instance) bool {
|
||||
nowTime := time.Now().Unix()
|
||||
s.rpcServiceMapLock.Lock()
|
||||
instanceMap := s.rpcServiceMap[instance.ServiceName]
|
||||
if instanceMap == nil {
|
||||
instanceMap = new(InstanceMap)
|
||||
instanceMap.Imap = make(map[string]*InstanceData)
|
||||
}
|
||||
instanceMap.lock.Lock()
|
||||
instanceData := instanceMap.Imap[instance.InstanceName]
|
||||
if instanceData == nil {
|
||||
instanceData = new(InstanceData)
|
||||
}
|
||||
instanceData.Address = instance.InstanceAddr
|
||||
instanceData.LastAliveTime = nowTime
|
||||
instanceMap.Imap[instance.InstanceName] = instanceData
|
||||
s.rpcServiceMap[instance.ServiceName] = instanceMap
|
||||
instanceMap.lock.Unlock()
|
||||
s.rpcServiceMapLock.Unlock()
|
||||
changeInst := make(map[string]*InstanceMap)
|
||||
instanceMapCopy := new(InstanceMap)
|
||||
instanceMap.lock.RLock()
|
||||
_ = object.ObjectDeepCopy(instanceMap, instanceMapCopy)
|
||||
instanceMap.lock.RUnlock()
|
||||
changeInst[instance.ServiceName] = instanceMapCopy
|
||||
s.rpcSvcChgNtfCh <- changeInst
|
||||
return true
|
||||
}
|
||||
|
||||
// 取消注册RPC服务
|
||||
func (s *Service) CancelRpcService(instance entity.Instance) bool {
|
||||
s.rpcServiceMapLock.RLock()
|
||||
instanceMap := s.rpcServiceMap[instance.ServiceName]
|
||||
s.rpcServiceMapLock.RUnlock()
|
||||
instanceMap.lock.Lock()
|
||||
delete(instanceMap.Imap, instance.InstanceName)
|
||||
instanceMap.lock.Unlock()
|
||||
changeInst := make(map[string]*InstanceMap)
|
||||
instanceMapCopy := new(InstanceMap)
|
||||
instanceMap.lock.RLock()
|
||||
_ = object.ObjectDeepCopy(instanceMap, instanceMapCopy)
|
||||
instanceMap.lock.RUnlock()
|
||||
changeInst[instance.ServiceName] = instanceMapCopy
|
||||
s.rpcSvcChgNtfCh <- changeInst
|
||||
return true
|
||||
}
|
||||
75
air/service/service.go
Normal file
75
air/service/service.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"air/entity"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 实例数据
|
||||
type InstanceData struct {
|
||||
// 实例地址
|
||||
Address string
|
||||
// 最后心跳时间
|
||||
LastAliveTime int64
|
||||
}
|
||||
|
||||
// 服务实例集合
|
||||
type InstanceMap struct {
|
||||
// key:实例名 value:实例数据
|
||||
Imap map[string]*InstanceData
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
type ReceiverNotifier struct {
|
||||
Id uint64
|
||||
CreateTime int64
|
||||
NotifyChannel chan []entity.Instance
|
||||
}
|
||||
|
||||
type AllServiceReceiverNotifier struct {
|
||||
Id uint64
|
||||
CreateTime int64
|
||||
NotifyChannel chan map[string][]entity.Instance
|
||||
}
|
||||
|
||||
type Watcher struct {
|
||||
receiverNotifierIdCounter uint64
|
||||
// key1:服务名 key2:接收者通知器id value:接收者通知器
|
||||
httpRecvrNtfrMap map[string]map[uint64]*ReceiverNotifier
|
||||
httpRecvrNtfrMapLock sync.RWMutex
|
||||
// key:接收者通知器id value:接收者通知器
|
||||
httpAllSvcRecvrNtfrMap map[uint64]*AllServiceReceiverNotifier
|
||||
httpAllSvcRecvrNtfrMapLock sync.RWMutex
|
||||
// key1:服务名 key2:接收者通知器id value:接收者通知器
|
||||
rpcRecvrNtfrMap map[string]map[uint64]*ReceiverNotifier
|
||||
rpcRecvrNtfrMapLock sync.RWMutex
|
||||
// key:接收者通知器id value:接收者通知器
|
||||
rpcAllSvcRecvrNtfrMap map[uint64]*AllServiceReceiverNotifier
|
||||
rpcAllSvcRecvrNtfrMapLock sync.RWMutex
|
||||
}
|
||||
|
||||
// 注册服务
|
||||
type Service struct {
|
||||
// key:服务名 value:服务实例集合
|
||||
httpServiceMap map[string]*InstanceMap
|
||||
httpServiceMapLock sync.RWMutex
|
||||
httpSvcChgNtfCh chan map[string]*InstanceMap
|
||||
// key:服务名 value:服务实例集合
|
||||
rpcServiceMap map[string]*InstanceMap
|
||||
rpcServiceMapLock sync.RWMutex
|
||||
rpcSvcChgNtfCh chan map[string]*InstanceMap
|
||||
watcher *Watcher
|
||||
}
|
||||
|
||||
// 构造函数
|
||||
func NewService() (r *Service) {
|
||||
r = new(Service)
|
||||
r.httpServiceMap = make(map[string]*InstanceMap)
|
||||
r.rpcServiceMap = make(map[string]*InstanceMap)
|
||||
r.httpSvcChgNtfCh = make(chan map[string]*InstanceMap, 0)
|
||||
r.rpcSvcChgNtfCh = make(chan map[string]*InstanceMap, 0)
|
||||
r.watcher = new(Watcher)
|
||||
go r.removeDeadService()
|
||||
go r.watchServiceChange()
|
||||
return r
|
||||
}
|
||||
Reference in New Issue
Block a user