| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 | package mainimport (	"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,	}}
 |