3 Star 9 Fork 1

os-lee/easy-paas

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
service.go 15.11 KB
一键复制 编辑 原始数据 按行查看 历史
lee 提交于 2024-07-20 00:09 . 监听采集日志的服务
package controller
import (
"encoding/json"
"fmt"
"gitee.com/os-lee/easy-paas/admin/config"
"gitee.com/os-lee/easy-paas/admin/internal/cache"
"gitee.com/os-lee/easy-paas/admin/internal/dao"
"gitee.com/os-lee/easy-paas/admin/internal/dto"
"gitee.com/os-lee/easy-paas/common"
"gitee.com/os-lee/easy-paas/common/discovery"
"gitee.com/os-lee/easy-paas/common/e"
"gitee.com/os-lee/easy-paas/common/flow"
"gitee.com/os-lee/easy-paas/common/logger"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
"strings"
"time"
)
type ServiceController struct{}
func ServiceRegister(group *gin.RouterGroup) {
sc := &ServiceController{}
group.GET("/list", sc.ServiceList)
group.GET("/detail", sc.ServiceDetail)
group.GET("/stat", sc.ServiceStat)
group.POST("/add", sc.ServiceAdd)
group.PUT("/update", sc.ServiceUpdate)
group.DELETE("/delete", sc.ServiceDelete)
}
// ServiceList godoc
// @Summary 服务列表
// @Description 服务列表
// @Tags 服务管理
// @ID /service/service_list
// @Accept json
// @Produce json
// @Param info query string false "关键词"
// @Param page_size query int true "每页个数"
// @Param page_no query int true "当前页数"
// @Success 200 {object} middleware.Response{data=dto.ServiceListOutput} "success"
// @Router /service/service_list [get]
func (service *ServiceController) ServiceList(c *gin.Context) {
params := &dto.ServiceListInput{}
if err := params.BindValidParam(c); err != nil {
common.ResponseError(c, e.ErrParams, err)
return
}
//从db中分页读取基本信息
serviceDao := dao.NewServiceInfoDao(c)
list, total, err := serviceDao.PageList(params)
if err != nil {
common.ResponseError(c, e.ErrDatabase, err)
return
}
// 服务发现 gateway
findName := config.Conf.Gateway.Name
services, err := discovery.EtcdCli.DiscoverServices(findName)
if err != nil {
common.ResponseError(c, e.ErrEtcd, err)
}
//格式化输出信息
var outList []dto.ServiceListItemOutput
for _, listItem := range list {
serviceDetail, err := serviceDao.ServiceDetail(c, &listItem)
if err != nil {
common.ResponseError(c, e.ErrDatabase, err)
return
}
//1、http后缀接入 clusterIP+clusterPort+path
//2、http域名接入 domain
//3、tcp、grpc接入 clusterIP+servicePort
serviceAddr := ""
if serviceDetail.Info.ProtocolType == common.ProtocolTypeHttp &&
serviceDetail.HTTPRule.RuleType == common.RuleTypeDomain {
for _, val := range services {
if val.ServiceProtocolCode == common.ProtocolTypeHttp {
serviceAddr += fmt.Sprintf("%s%s%s ",
common.ProtocolConverter(val.ServiceProtocolCode), val.ServiceAddr, serviceDetail.HTTPRule.Rule)
}
}
}
if serviceDetail.Info.ProtocolType == common.ProtocolTypeHttp &&
serviceDetail.HTTPRule.RuleType == common.RuleTypePrefixURL {
for _, val := range services {
if val.ServiceProtocolCode == common.ProtocolTypeHttp {
serviceAddr += fmt.Sprintf("%s%s%s ",
common.ProtocolConverter(val.ServiceProtocolCode), val.ServiceAddr, serviceDetail.HTTPRule.Rule)
}
}
}
if serviceDetail.Info.ProtocolType == common.ProtocolTypeHttps &&
serviceDetail.HTTPRule.RuleType == common.RuleTypePrefixURL {
for _, val := range services {
if val.ServiceProtocolCode == common.ProtocolTypeHttps {
serviceAddr += fmt.Sprintf("%s%s%s ",
common.ProtocolConverter(val.ServiceProtocolCode), val.ServiceAddr, serviceDetail.HTTPRule.Rule)
}
}
}
if serviceDetail.Info.ProtocolType == common.ProtocolTypeWebSocket &&
serviceDetail.HTTPRule.RuleType == common.RuleTypePrefixURL {
for _, val := range services {
if val.ServiceProtocolCode == common.ProtocolTypeWebSocket {
serviceAddr += fmt.Sprintf("%s%s%s ",
common.ProtocolConverter(val.ServiceProtocolCode), val.ServiceAddr, serviceDetail.HTTPRule.Rule)
}
}
}
// 获取当前业务的今日总请求数
today := time.Now().Format(common.DateFormat)
svcCounter := flow.ReqCounterHandler.GetReqCounterItem(serviceDetail.Info.ServiceName, cache.RedisCli)
hourlyCounts, err := svcCounter.GetHourlyCountsForDate(c, today)
if err != nil {
logger.Log.Warnf("获取当前业务的今日总请求数错误, 服务名: %s, Err: %s", serviceDetail.Info.ServiceName, err)
return
}
sumArray := common.SumArray(hourlyCounts)
// 获取当前业务的QPS
qpsCounter := flow.QpsCounterHandler.GetQpsCounterItem(serviceDetail.Info.ServiceName, cache.RedisCli)
qps, err := qpsCounter.GetQps(c)
if err != nil {
logger.Log.Warnf("获取当前网关的QPS, 服务名: %s, Err: %s", serviceDetail.Info.ServiceName, err)
// 可能key过期
qps = "0.00"
}
outItem := dto.ServiceListItemOutput{
ID: listItem.ID,
ProtocolType: listItem.ProtocolType,
ServiceName: listItem.ServiceName,
ServiceDesc: listItem.ServiceDesc,
ServiceAddr: serviceAddr,
Qps: qps,
Qpd: sumArray,
}
outList = append(outList, outItem)
}
out := &dto.ServiceListOutput{
Total: total,
List: outList,
}
common.ResponseSuccess(c, out)
}
// ServiceDelete godoc
// @Summary 服务删除
// @Description 服务删除
// @Tags 服务管理
// @ID /service/service_delete
// @Accept json
// @Produce json
// @Param id query string true "服务ID"
// @Success 200 {object} middleware.Response{data=string} "success"
// @Router /service/service_delete [get]
func (service *ServiceController) ServiceDelete(c *gin.Context) {
params := &dto.ServiceDeleteInput{}
if err := params.BindValidParam(c); err != nil {
common.ResponseError(c, e.ErrParams, err)
return
}
serviceInfoDao := dao.NewServiceInfoDao(c)
search := &dao.ServiceInfo{
ID: params.ID,
}
serviceInfo, err := serviceInfoDao.Find(search)
if err != nil {
common.ResponseError(c, e.ErrDatabase, err)
return
}
if err := serviceInfoDao.Delete(params.ID); err != nil {
common.ResponseError(c, e.ErrDatabase, err)
return
}
ruleDao := dao.NewHttpRuleDao(c)
if err := ruleDao.Delete(params.ID); err != nil {
common.ResponseError(c, e.ErrDatabase, err)
return
}
controlDao := dao.NewAccessControlDao(c)
if err := controlDao.Delete(params.ID); err != nil {
common.ResponseError(c, e.ErrDatabase, err)
return
}
balanceDao := dao.NewLoadBalanceDao(c)
if err := balanceDao.Delete(params.ID); err != nil {
common.ResponseError(c, e.ErrDatabase, err)
return
}
if err := service.putConfig(serviceInfo.ServiceName, "delete"); err != nil {
common.ResponseError(c, e.ErrEtcd, errors.New(fmt.Sprintf("向etcd写入配置错误, Err: %s", err)))
}
common.ResponseSuccess(c, "")
}
// ServiceDetail godoc
// @Summary 服务详情
// @Description 服务详情
// @Tags 服务管理
// @ID /service/service_detail
// @Accept json
// @Produce json
// @Param id query string true "服务ID"
// @Success 200 {object} middleware.Response{data=dao.ServiceDetail} "success"
// @Router /service/service_detail [get]
func (service *ServiceController) ServiceDetail(c *gin.Context) {
params := &dto.ServiceDeleteInput{}
if err := params.BindValidParam(c); err != nil {
common.ResponseError(c, e.ErrParams, err)
return
}
//读取基本信息
serviceInfo := &dao.ServiceInfo{ID: params.ID}
serviceInfoDao := dao.NewServiceInfoDao(c)
serviceInfo, err := serviceInfoDao.Find(serviceInfo)
if err != nil {
common.ResponseError(c, e.ErrDatabase, err)
return
}
serviceDetail, err := serviceInfoDao.ServiceDetail(c, serviceInfo)
if err != nil {
common.ResponseError(c, e.ErrDatabase, err)
return
}
common.ResponseSuccess(c, serviceDetail)
}
// ServiceStat godoc
// @Summary 服务统计
// @Description 服务统计
// @Tags 服务管理
// @ID /service/service_stat
// @Accept json
// @Produce json
// @Param id query string true "服务ID"
// @Success 200 {object} middleware.Response{data=dto.ServiceStatOutput} "success"
// @Router /service/service_stat [get]
func (service *ServiceController) ServiceStat(c *gin.Context) {
params := &dto.ServiceDeleteInput{}
if err := params.BindValidParam(c); err != nil {
common.ResponseError(c, e.ErrParams, err)
return
}
//今日流量全天小时级访问统计
var todayStat []int64
for i := 0; i <= time.Now().Hour(); i++ {
hourData := int64(i)
todayStat = append(todayStat, hourData)
}
//昨日流量全天小时级访问统计
var yesterdayStat []int64
for i := 0; i <= 23; i++ {
hourData := int64(10)
yesterdayStat = append(yesterdayStat, hourData)
}
stat := dto.StatisticsOutput{
Today: todayStat,
Yesterday: yesterdayStat,
}
common.ResponseSuccess(c, stat)
}
// ServiceAdd godoc
// @Summary 添加HTTP服务
// @Description 添加HTTP服务
// @Tags 服务管理
// @ID /service/service_add_http
// @Accept json
// @Produce json
// @Param body body dto.ServiceAddInput true "body"
// @Success 200 {object} middleware.Response{data=string} "success"
// @Router /service/service_add_http [post]
func (service *ServiceController) ServiceAdd(c *gin.Context) {
params := &dto.ServiceAddInput{}
if err := params.BindValidParam(c); err != nil {
common.ResponseError(c, e.ErrParams, err)
return
}
if params.RuleType == common.RuleTypePrefixURL {
if !strings.HasSuffix(params.Rule, "/") {
common.ResponseError(c, e.ErrParams, errors.New("接入路径格式不对,最后一个字符应为: / "))
return
}
}
tx := dao.NewDBClient(c).Begin()
serviceInfo := &dao.ServiceInfo{ServiceName: params.ServiceName}
serviceInfoDao := dao.NewServiceInfoDao(c, tx)
if rst, err := serviceInfoDao.Find(serviceInfo); rst.ID != 0 || err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, errors.New(fmt.Sprintf("服务名已存在: %s", params.ServiceName)))
return
}
httpRule := &dao.HttpRule{RuleType: params.RuleType, Rule: params.Rule}
httpRuleDao := dao.NewHttpRuleDao(c, tx)
if rst, err := httpRuleDao.Find(httpRule); rst.ID != 0 || err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, errors.New(fmt.Sprintf("服务的前缀或域名已存在: %s", params.ServiceName)))
return
}
serviceModel := &dao.ServiceInfo{
ProtocolType: params.ProtocolType,
ServiceName: params.ServiceName,
ServiceDesc: params.ServiceDesc,
}
if err := serviceInfoDao.Save(serviceModel); err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, err)
return
}
//serviceModel.ID
httpRule = &dao.HttpRule{
ServiceID: serviceModel.ID,
RuleType: params.RuleType,
Rule: params.Rule,
NeedStripUri: params.NeedStripUri,
UrlRewrite: params.UrlRewrite,
HeaderTransfor: params.HeaderTransfor,
}
if err := httpRuleDao.Save(httpRule); err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, err)
return
}
accessControl := &dao.AccessControl{
ServiceID: serviceModel.ID,
OpenAuth: params.OpenAuth,
BlackList: params.BlackList,
WhiteList: params.WhiteList,
ClientIPFlowLimit: params.ClientipFlowLimit,
ServiceFlowLimit: params.ServiceFlowLimit,
}
accessControlDao := dao.NewAccessControlDao(c, tx)
if err := accessControlDao.Save(accessControl); err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, err)
return
}
loadBalance := &dao.LoadBalance{
ServiceID: serviceModel.ID,
RoundType: params.RoundType,
ProxyName: params.ProxyName,
UpstreamConnectTimeout: params.UpstreamConnectTimeout,
UpstreamHeaderTimeout: params.UpstreamHeaderTimeout,
UpstreamIdleTimeout: params.UpstreamIdleTimeout,
UpstreamMaxIdle: params.UpstreamMaxIdle,
}
loadBalanceDao := dao.NewLoadBalanceDao(c, tx)
if err := loadBalanceDao.Save(loadBalance); err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, err)
return
}
tx.Commit()
if err := service.putConfig(params.ServiceName, "add"); err != nil {
common.ResponseError(c, e.ErrEtcd, errors.New(fmt.Sprintf("向etcd写入配置错误, Err: %s", err)))
}
common.ResponseSuccess(c, "")
}
// ServiceUpdate godoc
// @Summary 修改HTTP服务
// @Description 修改HTTP服务
// @Tags 服务管理
// @ID /service/service_update_http
// @Accept json
// @Produce json
// @Param body body dto.ServiceUpdateInput true "body"
// @Success 200 {object} middleware.Response{data=string} "success"
// @Router /service/service_update_http [post]
func (service *ServiceController) ServiceUpdate(c *gin.Context) {
params := &dto.ServiceUpdateInput{}
if err := params.BindValidParam(c); err != nil {
common.ResponseError(c, e.ErrParams, err)
return
}
tx := dao.NewDBClient(c).Begin()
serviceInfo := &dao.ServiceInfo{ServiceName: params.ServiceName}
serviceInfoDao := dao.NewServiceInfoDao(c, tx)
serviceInfo, err := serviceInfoDao.Find(serviceInfo)
if err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, errors.New(fmt.Sprintf("服务名不存在: %s", params.ServiceName)))
return
}
serviceDetail, err := serviceInfoDao.ServiceDetail(c, serviceInfo)
if err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, errors.New(fmt.Sprintf("查询该服务详情失败: %s", params.ServiceName)))
return
}
info := serviceDetail.Info
info.ProtocolType = params.ProtocolType
info.ServiceDesc = params.ServiceDesc
if err := serviceInfoDao.Save(info); err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, err)
return
}
httpRule := serviceDetail.HTTPRule
httpRule.NeedStripUri = params.NeedStripUri
httpRule.UrlRewrite = params.UrlRewrite
httpRule.HeaderTransfor = params.HeaderTransfor
httpRuleDao := dao.NewHttpRuleDao(c, tx)
if err := httpRuleDao.Save(httpRule); err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, err)
return
}
accessControl := serviceDetail.AccessControl
accessControl.OpenAuth = params.OpenAuth
accessControl.BlackList = params.BlackList
accessControl.WhiteList = params.WhiteList
accessControl.ClientIPFlowLimit = params.ClientipFlowLimit
accessControl.ServiceFlowLimit = params.ServiceFlowLimit
accessControlDao := dao.NewAccessControlDao(c, tx)
if err := accessControlDao.Save(accessControl); err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, err)
return
}
loadBalance := serviceDetail.LoadBalance
loadBalance.RoundType = params.RoundType
loadBalance.ProxyName = params.ProxyName
loadBalance.UpstreamConnectTimeout = params.UpstreamConnectTimeout
loadBalance.UpstreamHeaderTimeout = params.UpstreamHeaderTimeout
loadBalance.UpstreamIdleTimeout = params.UpstreamIdleTimeout
loadBalance.UpstreamMaxIdle = params.UpstreamMaxIdle
loadBalanceDao := dao.NewLoadBalanceDao(c, tx)
if err := loadBalanceDao.Save(loadBalance); err != nil {
tx.Rollback()
common.ResponseError(c, e.ErrDatabase, err)
return
}
tx.Commit()
if err := service.putConfig(params.ServiceName, "update"); err != nil {
common.ResponseError(c, e.ErrEtcd, errors.New(fmt.Sprintf("向etcd写入配置错误, Err: %s", err)))
}
common.ResponseSuccess(c, "")
}
// putConfig 根据服务名修改etcd配置,gateway监听该配置,重新加载
func (service *ServiceController) putConfig(serviceName, method string) error {
key := fmt.Sprintf("/config/%s", config.Conf.Gateway.Name)
value := discovery.ConfigMessage{
ServiceName: serviceName,
Method: method,
DateTime: time.Now().Format(common.TimeFormat),
}
jsonObj, _ := json.Marshal(value)
if err := discovery.EtcdCli.PutConfig(key, string(jsonObj)); err != nil {
return err
}
return nil
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/os-lee/easy-paas.git
git@gitee.com:os-lee/easy-paas.git
os-lee
easy-paas
easy-paas
6cf1638f64c0

搜索帮助