func newProxy(cfg *config.Config) *proxy.Proxy { if err := route.SetPickerStrategy(cfg.Proxy.Strategy); err != nil { log.Fatal("[FATAL] ", err) } log.Printf("[INFO] Using routing strategy %q", cfg.Proxy.Strategy) tr := &http.Transport{ ResponseHeaderTimeout: cfg.Proxy.ResponseHeaderTimeout, MaxIdleConnsPerHost: cfg.Proxy.MaxConn, Dial: (&net.Dialer{ Timeout: cfg.Proxy.DialTimeout, KeepAlive: cfg.Proxy.KeepAliveTimeout, }).Dial, } return proxy.New(tr, cfg.Proxy) }
/** 使用配置信息创建并返回HTTP代理服务器的句柄 */ func newHTTPProxy(cfg *config.Config) http.Handler { // 设置路由拣选策略 if err := route.SetPickerStrategy(cfg.Proxy.Strategy); err != nil { exit.Fatal("[FATAL] ", err) } log.Printf("[INFO] Using routing strategy %q", cfg.Proxy.Strategy) // 设置路由匹配器 if err := route.SetMatcher(cfg.Proxy.Matcher); err != nil { exit.Fatal("[FATAL] ", err) } log.Printf("[INFO] Using routing matching %q", cfg.Proxy.Matcher) // 配置转换器 tr := &http.Transport{ ResponseHeaderTimeout: cfg.Proxy.ResponseHeaderTimeout, MaxIdleConnsPerHost: cfg.Proxy.MaxConn, Dial: (&net.Dialer{ Timeout: cfg.Proxy.DialTimeout, KeepAlive: cfg.Proxy.KeepAliveTimeout, }).Dial, } /** @todo 上面代码中有疑问,如下代码: Dial: (&net.Dialer{ Timeout: cfg.Proxy.DialTimeout, KeepAlive: cfg.Proxy.KeepAliveTimeout, }).Dial 第一行为何用 &net.Dialer ? 即为何使用引用? 原因是 net包的Dialer结构体(struct)的方法Dial是指针类型,所以只有使用引用定义的时候才能访问到该函数 */ // 生成并返回HTTP代理句柄 return proxy.NewHTTPProxy(tr, cfg.Proxy) }
func main() { var cfg string var v bool flag.StringVar(&cfg, "cfg", "", "path to config file") flag.BoolVar(&v, "v", false, "show version") flag.Parse() if v { fmt.Println(version) return } log.Printf("[INFO] Version %s starting", version) if cfg != "" { if err := loadConfig(cfg); err != nil { log.Fatal("[FATAL] ", err) } } if err := metrics.Init(metricsTarget, metricsPrefix, metricsInterval, metricsGraphiteAddr); err != nil { log.Fatal("[FATAL] ", err) } if os.Getenv("GOMAXPROCS") == "" { log.Print("[INFO] Setting GOMAXPROCS=", gomaxprocs) runtime.GOMAXPROCS(gomaxprocs) } else { log.Print("[INFO] Using GOMAXPROCS=", os.Getenv("GOMAXPROCS"), " from env") } if os.Getenv("GOGC") == "" { log.Print("[INFO] Setting GOGC=", gogc) debug.SetGCPercent(gogc) } else { log.Print("[INFO] Using GOGC=", os.Getenv("GOGC"), " from env") } if proxyRoutes == "" { useDynamicRoutes() } else { useStaticRoutes() } if err := route.SetPickerStrategy(proxyStrategy); err != nil { log.Fatal("[FATAL] ", err) } consul.Addr = consulAddr consul.URL = consulURL dc, err := consul.Datacenter() if err != nil { log.Fatal("[FATAL] ", err) } log.Printf("[INFO] Using routing strategy %q", proxyStrategy) log.Printf("[INFO] Connecting to consul on %q in datacenter %q", consulAddr, dc) log.Printf("[INFO] Consul can be reached via %q", consulURL) log.Printf("[INFO] UI listening on %q", uiAddr) go func() { if err := ui.Start(uiAddr, consulKVPath); err != nil { log.Fatal("[FATAL] ui: ", err) } }() tr := &http.Transport{ ResponseHeaderTimeout: proxyTimeout, MaxIdleConnsPerHost: proxyMaxConn, Dial: (&net.Dialer{ Timeout: proxyDialTimeout, KeepAlive: proxyTimeout, }).Dial, } proxy := route.NewProxy(tr, proxyHeaderClientIP, proxyHeaderTLS, proxyHeaderTLSValue) listen(proxyAddr, proxyShutdownWait, proxy) }