main.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package main
  2. import (
  3. "encoding/json"
  4. "flag"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "net/url"
  9. "os"
  10. "strconv"
  11. "strings"
  12. "gopkg.in/yaml.v2"
  13. )
  14. var (
  15. infile string
  16. appname string
  17. host string
  18. )
  19. var usage = func() {
  20. fmt.Fprintf(os.Stderr, "Usage of cache admin import conf tool:\n")
  21. flag.PrintDefaults()
  22. }
  23. func main() {
  24. flag.StringVar(&appname, "app", "", "server app name")
  25. flag.StringVar(&host, "h", "http://sven.bilibili.co", "sven host")
  26. flag.StringVar(&infile, "in", "twemproxy.yml", "server yml file")
  27. flag.Usage = usage
  28. flag.Parse()
  29. if appname == "" {
  30. panic("app name cannot be nil")
  31. }
  32. b, err := ioutil.ReadFile(infile)
  33. if err != nil {
  34. panic(err)
  35. }
  36. confs := make(map[string]server)
  37. err = yaml.Unmarshal(b, &confs)
  38. if err != nil {
  39. panic(err)
  40. }
  41. // one service can't use 5168 memcaches at the same time.
  42. redisPort := 26379
  43. mcPort := 21211
  44. for name, conf := range confs {
  45. var (
  46. addr string
  47. cacheType string
  48. )
  49. if conf.Redis {
  50. addr = fmt.Sprintf("0.0.0.0:%d", redisPort)
  51. cacheType = "redis"
  52. redisPort++
  53. } else {
  54. addr = fmt.Sprintf("0.0.0.0:%d", mcPort)
  55. cacheType = "memcache"
  56. mcPort++
  57. }
  58. addCluster(appname, name, addr, cacheType, conf.AutoEjectHosts, conf.ServerFailureLimit)
  59. var nodes []*node
  60. for _, n := range conf.Servers {
  61. ss := strings.Split(n, " ")
  62. idx := strings.LastIndex(ss[0], ":")
  63. weight, _ := strconv.ParseInt(ss[0][idx+1:], 10, 64)
  64. nodes = append(nodes, &node{Addr: ss[0][:idx], Weigth: weight, Alias: ss[1]})
  65. }
  66. addNode(name, nodes)
  67. }
  68. }
  69. type server struct {
  70. AutoEjectHosts bool `yaml:"auto_eject_hosts"`
  71. Backlog int `yaml:"backlog"`
  72. Distribution string `yaml:"distribution"`
  73. Hash string `yaml:"hash"`
  74. Listen string `yaml:"listen"`
  75. Preconnect bool `yaml:"preconnect"`
  76. Timeout int `yaml:"timeout"`
  77. Redis bool `yaml:"redis"`
  78. ServerConnections int `yaml:"server_connections"`
  79. ServerFailureLimit int `yaml:"server_failure_limit"`
  80. ServerRetryTimeout int `yaml:"server_retry_timeout"`
  81. Servers []string `yaml:"servers"`
  82. }
  83. const (
  84. readTimeout = "1000"
  85. writeTimeout = "1000"
  86. conn = "20"
  87. dialTimeout = "100"
  88. proto = "tcp"
  89. )
  90. var (
  91. addCluURL = "%s/x/admin/cache/cluster/add"
  92. addNodeURL = "%s/x/admin/cache/cluster/node/modify"
  93. )
  94. func addCluster(app, cluster, addr, tp string, reject bool, fail int) {
  95. params := url.Values{}
  96. params.Add("dail_timeout", dialTimeout)
  97. params.Add("ping_fail_limit", strconv.FormatInt(int64(fail), 10))
  98. params.Add("ping_auto_reject", strconv.FormatBool(reject))
  99. params.Add("hash_distribution", "ketama")
  100. params.Add("read_timeout", readTimeout)
  101. params.Add("write_timeout", writeTimeout)
  102. params.Add("node_conn", conn)
  103. params.Add("type", tp)
  104. params.Add("app_id", app)
  105. params.Add("name", cluster)
  106. params.Add("hash_method", "fnv1a_64")
  107. params.Add("listen_proto", proto)
  108. params.Add("listen_addr", addr)
  109. url := fmt.Sprintf(addCluURL, host)
  110. req, err := http.NewRequest("POST", url, strings.NewReader(params.Encode()))
  111. if err != nil {
  112. fmt.Printf("add cluster req err %v", err)
  113. return
  114. }
  115. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  116. resp, err := http.DefaultClient.Do(req)
  117. if err != nil {
  118. fmt.Println("add cluster err", err)
  119. return
  120. }
  121. defer resp.Body.Close()
  122. bs, err := ioutil.ReadAll(resp.Body)
  123. fmt.Printf("add cluster req %v resp %v err %v\n", params.Encode(), string(bs), err)
  124. }
  125. type node struct {
  126. Addr string `json:"addr"`
  127. Weigth int64 `json:"weight"`
  128. Alias string `json:"alias"`
  129. }
  130. func addNode(name string, nodes []*node) {
  131. params := url.Values{}
  132. bs, err := json.Marshal(nodes)
  133. if err != nil {
  134. fmt.Println("node marshal err", err)
  135. return
  136. }
  137. params.Add("action", "1")
  138. params.Add("name", name)
  139. params.Add("nodes", string(bs))
  140. url := fmt.Sprintf(addNodeURL, host)
  141. req, err := http.NewRequest("POST", url, strings.NewReader(params.Encode()))
  142. if err != nil {
  143. fmt.Printf("add node req err %v", err)
  144. return
  145. }
  146. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  147. resp, err := http.DefaultClient.Do(req)
  148. if err != nil {
  149. fmt.Println("add node err", err)
  150. return
  151. }
  152. defer resp.Body.Close()
  153. bs, err = ioutil.ReadAll(resp.Body)
  154. fmt.Printf("add node req %v resp %v err %v\n", params.Encode(), string(bs), err)
  155. }