mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-17 08:52:27 +08:00
init commit
This commit is contained in:
221
light/consumer.go
Normal file
221
light/consumer.go
Normal file
@@ -0,0 +1,221 @@
|
||||
package light
|
||||
|
||||
import (
|
||||
airClient "flswld.com/air-api/client"
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/logger"
|
||||
"net/rpc"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Consumer struct {
|
||||
serviceName string
|
||||
serviceList *ServiceList
|
||||
//httpInstanceName string
|
||||
//keepalive bool
|
||||
}
|
||||
|
||||
type ServiceInstance struct {
|
||||
// 服务地址
|
||||
serviceAddress string
|
||||
// 服务连接
|
||||
serviceClient *rpc.Client
|
||||
}
|
||||
|
||||
type ServiceList struct {
|
||||
// 服务实列列表
|
||||
serviceInstanceList []*ServiceInstance
|
||||
// 服务负载均衡索引
|
||||
serviceLoadBalanceIndex int
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
func NewRpcConsumer(serviceName string) (r *Consumer) {
|
||||
r = new(Consumer)
|
||||
r.serviceName = serviceName
|
||||
r.serviceList = new(ServiceList)
|
||||
|
||||
// 服务注册
|
||||
//r.keepalive = true
|
||||
//r.httpInstanceName = RegisterHttpService(conf, log, &r.keepalive)
|
||||
|
||||
// 服务发现
|
||||
airClient.SetAirAddr(config.CONF.Air.Addr, config.CONF.Air.Port)
|
||||
go r.fetchAirService()
|
||||
go r.pollAirService()
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (c *Consumer) CloseRpcConsumer() {
|
||||
//c.keepalive = false
|
||||
//CancelHttpService(c.conf, c.log, c.httpInstanceName)
|
||||
}
|
||||
|
||||
func (c *Consumer) CallFunction(svcName string, funcName string, req any, res any) bool {
|
||||
serviceInstance := c.getServiceInstanceLoadBalance()
|
||||
if serviceInstance == nil {
|
||||
logger.LOG.Error("no rpc provider find, service: %v", c.serviceName)
|
||||
return false
|
||||
}
|
||||
if serviceInstance.serviceClient == nil {
|
||||
serviceClient, err := rpc.DialHTTP("tcp", serviceInstance.serviceAddress)
|
||||
if err != nil {
|
||||
logger.LOG.Error("rpc connect error: %v", err)
|
||||
return false
|
||||
}
|
||||
serviceInstance.serviceClient = serviceClient
|
||||
}
|
||||
serviceMethod := svcName + "." + funcName
|
||||
err := serviceInstance.serviceClient.Call(serviceMethod, req, res)
|
||||
if err != nil {
|
||||
logger.LOG.Error("rpc call error: %v", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Consumer) syncServiceList(responseData *airClient.ResponseData) {
|
||||
serviceAddressSlice := make([]string, 0)
|
||||
for _, v := range responseData.Instance {
|
||||
serviceAddressSlice = append(serviceAddressSlice, v.InstanceAddr)
|
||||
}
|
||||
|
||||
c.serviceList.lock.RLock()
|
||||
oldList := c.serviceList.serviceInstanceList
|
||||
c.serviceList.lock.RUnlock()
|
||||
// 相同服务列表
|
||||
sameList := make([]*ServiceInstance, 0)
|
||||
// 新增服务列表
|
||||
addList := make([]*ServiceInstance, 0)
|
||||
// 删除服务列表
|
||||
delList := make([]*ServiceInstance, 0)
|
||||
// 找出相同的服务
|
||||
for _, v := range serviceAddressSlice {
|
||||
for _, vv := range oldList {
|
||||
if v == vv.serviceAddress {
|
||||
sameList = append(sameList, vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 找出新增的服务
|
||||
for _, v := range serviceAddressSlice {
|
||||
hasItem := false
|
||||
for _, vv := range sameList {
|
||||
if v == vv.serviceAddress {
|
||||
hasItem = true
|
||||
}
|
||||
}
|
||||
if !hasItem {
|
||||
serviceInstance := new(ServiceInstance)
|
||||
serviceInstance.serviceAddress = v
|
||||
serviceInstance.serviceClient = nil
|
||||
addList = append(addList, serviceInstance)
|
||||
logger.LOG.Info("add service: %v, addr: %v", c.serviceName, serviceInstance.serviceAddress)
|
||||
}
|
||||
}
|
||||
// 找出删除的服务
|
||||
for _, v := range oldList {
|
||||
hasItem := false
|
||||
for _, vv := range sameList {
|
||||
if v.serviceAddress == vv.serviceAddress {
|
||||
hasItem = true
|
||||
}
|
||||
}
|
||||
if !hasItem {
|
||||
delList = append(delList, v)
|
||||
logger.LOG.Info("delete service: %v, addr: %v", c.serviceName, v.serviceAddress)
|
||||
}
|
||||
}
|
||||
c.serviceList.lock.Lock()
|
||||
c.serviceList.serviceInstanceList = make([]*ServiceInstance, len(sameList)+len(addList))
|
||||
copy(c.serviceList.serviceInstanceList, sameList)
|
||||
copy(c.serviceList.serviceInstanceList[len(sameList):], addList)
|
||||
c.serviceList.lock.Unlock()
|
||||
}
|
||||
|
||||
// 从注册中心获取服务实例
|
||||
func (c *Consumer) fetchAirService() {
|
||||
ticker := time.NewTicker(time.Second * 600)
|
||||
for {
|
||||
var responseData *airClient.ResponseData
|
||||
var err error
|
||||
responseData, err = airClient.FetchRpcService(c.serviceName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("fetch all rpc service error: %v", err)
|
||||
return
|
||||
}
|
||||
if responseData.Code != 0 {
|
||||
logger.LOG.Error("response code error")
|
||||
return
|
||||
}
|
||||
if len(responseData.Instance) == 0 {
|
||||
logger.LOG.Error("no %v service instance find", c.serviceName)
|
||||
return
|
||||
}
|
||||
c.syncServiceList(responseData)
|
||||
<-ticker.C
|
||||
}
|
||||
}
|
||||
|
||||
// 从注册中心长轮询监听服务实例变化
|
||||
func (c *Consumer) pollAirService() {
|
||||
lastTime := int64(0)
|
||||
for {
|
||||
nowTime := time.Now().UnixNano()
|
||||
if time.Duration(nowTime-lastTime) < time.Second {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
continue
|
||||
}
|
||||
lastTime = time.Now().UnixNano()
|
||||
var responseData *airClient.ResponseData
|
||||
var err error
|
||||
responseData, err = airClient.PollRpcService(c.serviceName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("poll all rpc service error: %v", err)
|
||||
continue
|
||||
}
|
||||
if responseData.Code != 0 {
|
||||
logger.LOG.Error("response code error")
|
||||
continue
|
||||
}
|
||||
if len(responseData.Instance) == 0 {
|
||||
logger.LOG.Error("no %v service instance find", c.serviceName)
|
||||
}
|
||||
c.syncServiceList(responseData)
|
||||
}
|
||||
}
|
||||
|
||||
// 负载均衡的方式获取服务实例
|
||||
func (c *Consumer) getServiceInstanceLoadBalance() (r *ServiceInstance) {
|
||||
c.serviceList.lock.RLock()
|
||||
index := c.serviceList.serviceLoadBalanceIndex
|
||||
length := len(c.serviceList.serviceInstanceList)
|
||||
c.serviceList.lock.RUnlock()
|
||||
|
||||
if length == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 下一个待轮询的服务已下线
|
||||
if index >= length {
|
||||
logger.LOG.Error("serviceLoadBalanceIndex out of range, len is: %d, but value is: %d", length, index)
|
||||
index = 0
|
||||
}
|
||||
|
||||
c.serviceList.lock.RLock()
|
||||
r = c.serviceList.serviceInstanceList[index]
|
||||
c.serviceList.lock.RUnlock()
|
||||
|
||||
c.serviceList.lock.Lock()
|
||||
// 轮询
|
||||
if c.serviceList.serviceLoadBalanceIndex < length-1 {
|
||||
c.serviceList.serviceLoadBalanceIndex += 1
|
||||
} else {
|
||||
c.serviceList.serviceLoadBalanceIndex = 0
|
||||
}
|
||||
c.serviceList.lock.Unlock()
|
||||
|
||||
return r
|
||||
}
|
||||
Reference in New Issue
Block a user