123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- package main
- import (
- "flag"
- "fmt"
- "github.com/go-kit/kit/log"
- "github.com/hashicorp/consul/api"
- "github.com/openzipkin/zipkin-go"
- zipkinhttpsvr "github.com/openzipkin/zipkin-go/middleware/http"
- zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http"
- "math/rand"
- "net/http"
- "net/http/httputil"
- "os"
- "os/signal"
- "strings"
- "syscall"
- )
- func main() {
- // 创建环境变量
- var (
- consulHost = flag.String("consul.host", "114.67.98.210", "consul server ip address")
- consulPort = flag.String("consul.port", "8500", "consul server port")
- zipkinURL = flag.String("zipkin.url", "http://114.67.98.210:9411/api/v2/spans", "Zipkin server url")
- )
- flag.Parse()
- //创建日志组件
- var logger log.Logger
- {
- logger = log.NewLogfmtLogger(os.Stderr)
- logger = log.With(logger, "ts", log.DefaultTimestampUTC)
- logger = log.With(logger, "caller", log.DefaultCaller)
- }
- var zipkinTracer *zipkin.Tracer
- {
- var (
- err error
- hostPort = "localhost:9090"
- serviceName = "gateway-service"
- useNoopTracer = (*zipkinURL == "")
- reporter = zipkinhttp.NewReporter(*zipkinURL)
- )
- defer reporter.Close()
- zEP, _ := zipkin.NewEndpoint(serviceName, hostPort)
- zipkinTracer, err = zipkin.NewTracer(
- reporter, zipkin.WithLocalEndpoint(zEP), zipkin.WithNoopTracer(useNoopTracer),
- )
- if err != nil {
- logger.Log("err", err)
- os.Exit(1)
- }
- if !useNoopTracer {
- logger.Log("tracer", "Zipkin", "type", "Native", "URL", *zipkinURL)
- }
- }
- // 创建consul api客户端
- consulConfig := api.DefaultConfig()
- consulConfig.Address = "http://" + *consulHost + ":" + *consulPort
- consulClient, err := api.NewClient(consulConfig)
- if err != nil {
- logger.Log("err", err)
- os.Exit(1)
- }
- //创建反向代理
- proxy := NewReverseProxy(consulClient, zipkinTracer, logger)
- tags := map[string]string{
- "component": "gateway_server",
- }
- handler := zipkinhttpsvr.NewServerMiddleware(
- zipkinTracer,
- zipkinhttpsvr.SpanName("gateway"),
- zipkinhttpsvr.TagResponseSize(true),
- zipkinhttpsvr.ServerTags(tags),
- )(proxy)
- errc := make(chan error)
- go func() {
- c := make(chan os.Signal)
- signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
- errc <- fmt.Errorf("%s", <-c)
- }()
- //开始监听
- go func() {
- logger.Log("transport", "HTTP", "addr", "9090")
- errc <- http.ListenAndServe(":9090", handler)
- }()
- // 开始运行,等待结束
- logger.Log("exit", <-errc)
- }
- // NewReverseProxy 创建反向代理处理方法
- func NewReverseProxy(client *api.Client, zikkinTracer *zipkin.Tracer, logger log.Logger) *httputil.ReverseProxy {
- //创建Director
- director := func(req *http.Request) {
- //查询原始请求路径,如:/string-service/op/10/5
- reqPath := req.URL.Path
- if reqPath == "" {
- return
- }
- //按照分隔符'/'对路径进行分解,获取服务名称serviceName
- pathArray := strings.Split(reqPath, "/")
- serviceName := pathArray[1]
- //调用consul api查询serviceName的服务实例列表
- result, _, err := client.Catalog().Service(serviceName, "", nil)
- if err != nil {
- logger.Log("ReverseProxy failed", "query service instace error", err.Error())
- return
- }
- if len(result) == 0 {
- logger.Log("ReverseProxy failed", "no such service instance", serviceName)
- return
- }
- //重新组织请求路径,去掉服务名称部分
- destPath := strings.Join(pathArray[2:], "/")
- //随机选择一个服务实例
- tgt := result[rand.Int()%len(result)]
- logger.Log("service id", tgt.ServiceID)
- //设置代理服务地址信息
- req.URL.Scheme = "http"
- req.URL.Host = fmt.Sprintf("%s:%d", tgt.ServiceAddress, tgt.ServicePort)
- req.URL.Path = "/" + destPath
- }
- // 为反向代理增加追踪逻辑,使用如下RoundTrip代替默认Transport
- roundTrip, _ := zipkinhttpsvr.NewTransport(zikkinTracer, zipkinhttpsvr.TransportTrace(true))
- return &httputil.ReverseProxy{
- Director: director,
- Transport: roundTrip,
- }
- }
|