215 lines
5.2 KiB
Go
215 lines
5.2 KiB
Go
package http
|
||
|
||
import (
|
||
"encoding/json"
|
||
"net"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"go-common/app/admin/main/cache/model"
|
||
"go-common/library/ecode"
|
||
bm "go-common/library/net/http/blademaster"
|
||
|
||
yaml "gopkg.in/yaml.v2"
|
||
)
|
||
|
||
// @params ClustersReq
|
||
// @router get /x/admin/cache/clusters
|
||
// @response ClustersResp
|
||
func clusters(ctx *bm.Context) {
|
||
req := new(model.ClusterReq)
|
||
if err := ctx.Bind(req); err != nil {
|
||
return
|
||
}
|
||
req.Cookie = ctx.Request.Header.Get("Cookie")
|
||
ctx.JSON(srv.Clusters(ctx, req))
|
||
}
|
||
|
||
// @params AddClusterReq
|
||
// @router post /x/admin/cache/cluster/add
|
||
// @response EmpResp
|
||
func addCluster(ctx *bm.Context) {
|
||
req := new(model.AddClusterReq)
|
||
if err := ctx.Bind(req); err != nil {
|
||
return
|
||
}
|
||
ctx.JSON(srv.AddCluster(ctx, req))
|
||
}
|
||
|
||
// @params delClusterReq
|
||
// @router post /x/admin/cache/cluster/del
|
||
// @response EmpResp
|
||
func delCluster(ctx *bm.Context) {
|
||
req := new(model.DelClusterReq)
|
||
if err := ctx.Bind(req); err != nil {
|
||
return
|
||
}
|
||
ctx.JSON(srv.DelCluster(ctx, req))
|
||
}
|
||
|
||
// @params ClusterReq
|
||
// @router get /x/admin/cache/cluster
|
||
// @response []Cluster
|
||
func cluster(ctx *bm.Context) {
|
||
req := new(model.ClusterReq)
|
||
if err := ctx.Bind(req); err != nil {
|
||
return
|
||
}
|
||
|
||
if req.AppID != "" {
|
||
resp, err := srv.Cluster(ctx, req)
|
||
if err != nil {
|
||
ctx.JSON(nil, err)
|
||
return
|
||
}
|
||
ctx.JSON(&model.ClusterResp{Clusters: resp}, nil)
|
||
} else {
|
||
req.Cookie = ctx.Request.Header.Get("Cookie")
|
||
ctx.JSON(srv.Clusters(ctx, req))
|
||
}
|
||
}
|
||
|
||
// @params ClusterDtlReq
|
||
// @router get /x/admin/cache/cluster/detail
|
||
// @response ClusterDtlResp
|
||
func clusterDtl(ctx *bm.Context) {
|
||
req := new(model.ClusterDtlReq)
|
||
if err := ctx.Bind(req); err != nil {
|
||
return
|
||
}
|
||
ctx.JSON(srv.ClusterDtl(ctx, req))
|
||
}
|
||
|
||
// @params ModifyClusterReq
|
||
// @router post /x/admin/cache/cluster/modify
|
||
// @response EmpResp
|
||
func modifyCluster(ctx *bm.Context) {
|
||
req := new(model.ModifyClusterReq)
|
||
if err := ctx.Bind(req); err != nil {
|
||
return
|
||
}
|
||
ctx.JSON(srv.ModifyCluster(ctx, req))
|
||
}
|
||
|
||
func toml(ctx *bm.Context) {
|
||
req := new(model.ClusterReq)
|
||
if err := ctx.Bind(req); err != nil {
|
||
return
|
||
}
|
||
resp, err := srv.Toml(ctx, req)
|
||
if err != nil {
|
||
ctx.Status(500)
|
||
return
|
||
}
|
||
ctx.Writer.Write(resp)
|
||
}
|
||
|
||
// @params addFromYml
|
||
// @router post /x/admin/cache/cluster/from/yml
|
||
// @response EmpResp
|
||
func addFromYml(ctx *bm.Context) {
|
||
req := new(model.ClusterFromYml)
|
||
if err := ctx.Bind(req); err != nil {
|
||
ctx.JSONMap(map[string]interface{}{
|
||
"message": "参数有问题:app_id,zone,tw_yml",
|
||
}, ecode.RequestErr)
|
||
return
|
||
}
|
||
type server struct {
|
||
AutoEjectHosts bool `yaml:"auto_eject_hosts"`
|
||
Backlog int `yaml:"backlog"`
|
||
Distribution string `yaml:"distribution"`
|
||
Hash string `yaml:"hash"`
|
||
Listen string `yaml:"listen"`
|
||
Preconnect bool `yaml:"preconnect"`
|
||
Timeout int `yaml:"timeout"`
|
||
Redis bool `yaml:"redis"`
|
||
ServerConnections int `yaml:"server_connections"`
|
||
ServerFailureLimit int `yaml:"server_failure_limit"`
|
||
ServerRetryTimeout int `yaml:"server_retry_timeout"`
|
||
Servers []string `yaml:"servers"`
|
||
}
|
||
type node struct {
|
||
Addr string `json:"addr"`
|
||
Weigth int64 `json:"weight"`
|
||
Alias string `json:"alias"`
|
||
}
|
||
confs := make(map[string]server)
|
||
err := yaml.Unmarshal([]byte(req.TwYml), &confs)
|
||
if err != nil {
|
||
ctx.JSONMap(map[string]interface{}{
|
||
"message": "解析twemproxy.yml文件失败",
|
||
}, ecode.RequestErr)
|
||
return
|
||
}
|
||
mcPort := 11211
|
||
rdPort := 26379
|
||
for name, conf := range confs {
|
||
ctp := "memcache"
|
||
if conf.Redis {
|
||
ctp = "redis"
|
||
}
|
||
if conf.Hash != "fnv1a_64" {
|
||
ctx.JSONMap(map[string]interface{}{
|
||
"message": "不支持除了fnv1a_64之外的hash方法",
|
||
}, ecode.RequestErr)
|
||
return
|
||
}
|
||
addr := "0.0.0.0:"
|
||
_, port, err := net.SplitHostPort(conf.Listen)
|
||
if err == nil {
|
||
addr = addr + port
|
||
} else {
|
||
if conf.Redis {
|
||
addr = addr + strconv.Itoa(rdPort)
|
||
rdPort++
|
||
} else {
|
||
addr = addr + strconv.Itoa(mcPort)
|
||
mcPort++
|
||
}
|
||
}
|
||
clst := &model.AddClusterReq{
|
||
Type: ctp,
|
||
AppID: req.AppID,
|
||
Zone: req.Zone,
|
||
HashMethod: "fnv1a_64",
|
||
HashDistribution: "ketama",
|
||
HashTag: "",
|
||
Name: name,
|
||
DailTimeout: 1000,
|
||
ReadTimeout: 1000,
|
||
WriteTimeout: 1000,
|
||
NodeConn: 2,
|
||
PingFailLimit: 3,
|
||
PingAutoEject: true,
|
||
ListenProto: "tcp",
|
||
ListenAddr: addr,
|
||
}
|
||
if _, err := srv.AddCluster(ctx, clst); err != nil {
|
||
ctx.JSONMap(map[string]interface{}{
|
||
"message": "添加cluster失败:" + name + " " + err.Error(),
|
||
}, ecode.RequestErr)
|
||
return
|
||
}
|
||
var nodes []*node
|
||
for _, n := range conf.Servers {
|
||
ss := strings.Split(n, " ")
|
||
idx := strings.LastIndex(ss[0], ":")
|
||
weight, _ := strconv.ParseInt(ss[0][idx+1:], 10, 64)
|
||
nodes = append(nodes, &node{Addr: ss[0][:idx], Weigth: weight, Alias: ss[1]})
|
||
}
|
||
ns, _ := json.Marshal(nodes)
|
||
cn := &model.ModifyClusterReq{
|
||
Name: name,
|
||
Action: 1,
|
||
Nodes: string(ns),
|
||
}
|
||
if _, err := srv.ModifyCluster(ctx, cn); err != nil {
|
||
ctx.JSONMap(map[string]interface{}{
|
||
"message": "添加cluster node失败:" + name + " " + err.Error(),
|
||
}, ecode.RequestErr)
|
||
return
|
||
}
|
||
}
|
||
}
|