main.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "github.com/go-kit/kit/log"
  6. "github.com/hashicorp/consul/api"
  7. "math/rand"
  8. "net/http"
  9. "net/http/httputil"
  10. "os"
  11. "os/signal"
  12. "strings"
  13. "syscall"
  14. )
  15. func main() {
  16. // 创建环境变量
  17. var (
  18. //consulHost = flag.String("consul.host", "114.67.98.210", "consul server ip address")
  19. consulHost = flag.String("consul.host", "106.15.233.99", "consul server ip address")
  20. consulPort = flag.String("consul.port", "8500", "consul server port")
  21. )
  22. flag.Parse()
  23. //创建日志组件
  24. var logger log.Logger
  25. {
  26. logger = log.NewLogfmtLogger(os.Stderr)
  27. logger = log.With(logger, "ts", log.DefaultTimestampUTC)
  28. logger = log.With(logger, "caller", log.DefaultCaller)
  29. }
  30. // 创建consul api客户端
  31. consulConfig := api.DefaultConfig()
  32. consulConfig.Address = "http://" + *consulHost + ":" + *consulPort
  33. consulClient, err := api.NewClient(consulConfig)
  34. if err != nil {
  35. logger.Log("err", err)
  36. os.Exit(1)
  37. }
  38. //创建反向代理
  39. proxy := NewReverseProxy(consulClient, logger)
  40. errc := make(chan error)
  41. go func() {
  42. c := make(chan os.Signal)
  43. signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
  44. errc <- fmt.Errorf("%s", <-c)
  45. }()
  46. //开始监听
  47. go func() {
  48. logger.Log("transport", "HTTP", "addr", "9099")
  49. errc <- http.ListenAndServe(":9099", proxy)
  50. }()
  51. // 开始运行,等待结束
  52. logger.Log("exit", <-errc)
  53. }
  54. // NewReverseProxy 创建反向代理处理方法
  55. func NewReverseProxy(client *api.Client, logger log.Logger) *httputil.ReverseProxy {
  56. //创建Director
  57. director := func(req *http.Request) {
  58. //查询原始请求路径
  59. reqPath := req.URL.Path
  60. if reqPath == "" {
  61. return
  62. }
  63. //按照分隔符'/'对路径进行分解,获取服务名称serviceName
  64. pathArray := strings.Split(reqPath, "/")
  65. serviceName := pathArray[1]
  66. //调用consul api查询serviceName的服务实例列表
  67. result, _, err := client.Catalog().Service(serviceName, "", nil)
  68. if err != nil {
  69. logger.Log("ReverseProxy failed", "query service instance error", err.Error())
  70. return
  71. }
  72. if len(result) == 0 {
  73. logger.Log("ReverseProxy failed", "no such service instance", serviceName)
  74. return
  75. }
  76. //重新组织请求路径,去掉服务名称部分
  77. destPath := strings.Join(pathArray[2:], "/")
  78. //随机选择一个服务实例
  79. tgt := result[rand.Int()%len(result)]
  80. logger.Log("service id", tgt.ServiceID)
  81. //设置代理服务地址信息
  82. req.URL.Scheme = "http"
  83. req.URL.Host = fmt.Sprintf("%s:%d", tgt.ServiceAddress, tgt.ServicePort)
  84. req.URL.Path = "/" + destPath
  85. }
  86. return &httputil.ReverseProxy{Director: director}
  87. }