Example #1
0
/*
 使用了第三方 github.com/armon/go-proxyproto 包
 @todo 两次调用了 ln.Close() 为什么不会引发问题?
 	defer ln.Close()

	// close the socket on exit to terminate the accept loop
	go func() {
		<-quit
		ln.Close()
	}()
*/
func listenAndServeTCP(l config.Listen, h proxy.TCPProxy) {
	log.Print("[INFO] TCP+SNI proxy listening on ", l.Addr)

	// 生成 Listener 结构体类型
	ln, err := net.Listen("tcp", l.Addr)
	if err != nil {
		exit.Fatal("[FATAL] ", err)
	}
	ln = &proxyproto.Listener{Listener: tcpKeepAliveListener{ln.(*net.TCPListener)}}
	defer ln.Close()

	// close the socket on exit to terminate the accept loop
	go func() {
		<-quit
		ln.Close()
	}()

	for {
		// 接收连接请求
		conn, err := ln.Accept()
		if err != nil {
			select {
			case <-quit:
				return
			default:
				exit.Fatal("[FATAL] ", err)
			}
		}
		// 处理连接
		go h.Serve(conn)
	}
}
Example #2
0
func listenAndServe(l config.Listen, h http.Handler) {
	srv := &http.Server{
		Handler:      h,
		Addr:         l.Addr,
		ReadTimeout:  l.ReadTimeout,
		WriteTimeout: l.WriteTimeout,
	}

	if l.Scheme == "https" {
		src, err := cert.NewSource(l.CertSource)
		if err != nil {
			exit.Fatal("[FATAL] ", err)
		}

		srv.TLSConfig, err = cert.TLSConfig(src)
		if err != nil {
			exit.Fatal("[FATAL] ", err)
		}
	}

	if srv.TLSConfig != nil {
		log.Printf("[INFO] HTTPS proxy listening on %s", l.Addr)
		if srv.TLSConfig.ClientAuth == tls.RequireAndVerifyClientCert {
			log.Printf("[INFO] Client certificate authentication enabled on %s", l.Addr)
		}
	} else {
		log.Printf("[INFO] HTTP proxy listening on %s", l.Addr)
	}

	if err := serve(srv); err != nil {
		exit.Fatal("[FATAL] ", err)
	}
}
Example #3
0
File: main.go Project: eBay/fabio
func initMetrics(cfg *config.Config) {
	if cfg.Metrics.Target == "" {
		log.Printf("[INFO] Metrics disabled")
		return
	}

	var err error
	if metrics.DefaultRegistry, err = metrics.NewRegistry(cfg.Metrics); err != nil {
		exit.Fatal("[FATAL] ", err)
	}
	if route.ServiceRegistry, err = metrics.NewRegistry(cfg.Metrics); err != nil {
		exit.Fatal("[FATAL] ", err)
	}
}
Example #4
0
// NewRegistry creates a new metrics registry.
func NewRegistry(cfg config.Metrics) (r Registry, err error) {

	if prefix, err = parsePrefix(cfg.Prefix); err != nil {
		return nil, fmt.Errorf("metrics: invalid Prefix template. %s", err)
	}

	if names, err = parseNames(cfg.Names); err != nil {
		return nil, fmt.Errorf("metrics: invalid names template. %s", err)
	}

	switch cfg.Target {
	case "stdout":
		log.Printf("[INFO] Sending metrics to stdout")
		return gmStdoutRegistry(cfg.Interval)

	case "graphite":
		log.Printf("[INFO] Sending metrics to Graphite on %s as %q", cfg.GraphiteAddr, prefix)
		return gmGraphiteRegistry(prefix, cfg.GraphiteAddr, cfg.Interval)

	case "statsd":
		log.Printf("[INFO] Sending metrics to StatsD on %s as %q", cfg.StatsDAddr, prefix)
		return gmStatsDRegistry(prefix, cfg.StatsDAddr, cfg.Interval)

	case "circonus":
		return circonusRegistry(prefix, cfg.Circonus, cfg.Interval)

	default:
		exit.Fatal("[FATAL] Invalid metrics target ", cfg.Target)
	}
	panic("unreachable")
}
Example #5
0
func defaultPrefix() string {
	host, err := hostname()
	if err != nil {
		exit.Fatal("[FATAL] ", err)
	}
	exe := filepath.Base(os.Args[0])
	return clean(host) + "." + clean(exe)
}
Example #6
0
File: main.go Project: eBay/fabio
func startAdmin(cfg *config.Config) {
	log.Printf("[INFO] Admin server listening on %q", cfg.UI.Addr)
	go func() {
		if err := admin.ListenAndServe(cfg, version); err != nil {
			exit.Fatal("[FATAL] ui: ", err)
		}
	}()
}
Example #7
0
File: main.go Project: eBay/fabio
func initBackend(cfg *config.Config) {
	var err error

	switch cfg.Registry.Backend {
	case "file":
		registry.Default, err = file.NewBackend(cfg.Registry.File.Path)
	case "static":
		registry.Default, err = static.NewBackend(cfg.Registry.Static.Routes)
	case "consul":
		registry.Default, err = consul.NewBackend(&cfg.Registry.Consul)
	default:
		exit.Fatal("[FATAL] Unknown registry backend ", cfg.Registry.Backend)
	}

	if err != nil {
		exit.Fatal("[FATAL] Error initializing backend. ", err)
	}
	if err := registry.Default.Register(); err != nil {
		exit.Fatal("[FATAL] Error registering backend. ", err)
	}
}
Example #8
0
File: main.go Project: eBay/fabio
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,
	}

	return proxy.NewHTTPProxy(tr, cfg.Proxy)
}
Example #9
0
func serve(srv *http.Server) error {
	ln, err := net.Listen("tcp", srv.Addr)
	if err != nil {
		exit.Fatal("[FATAL] ", err)
	}

	ln = &proxyproto.Listener{Listener: tcpKeepAliveListener{ln.(*net.TCPListener)}}

	if srv.TLSConfig != nil {
		ln = tls.NewListener(ln, srv.TLSConfig)
	}

	return srv.Serve(ln)
}
Example #10
0
/**
  使用配置信息创建并返回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)
}
Example #11
0
func Init(cfg config.Metrics) error {
	pfx = cfg.Prefix
	if pfx == "default" {
		pfx = defaultPrefix()
	}

	switch cfg.Target {
	case "stdout":
		log.Printf("[INFO] Sending metrics to stdout")
		return initStdout(cfg.Interval)
	case "graphite":
		if cfg.GraphiteAddr == "" {
			return errors.New("metrics: graphite addr missing")
		}

		log.Printf("[INFO] Sending metrics to Graphite on %s as %q", cfg.GraphiteAddr, pfx)
		return initGraphite(cfg.GraphiteAddr, cfg.Interval)
	case "":
		log.Printf("[INFO] Metrics disabled")
	default:
		exit.Fatal("[FATAL] Invalid metrics target ", cfg.Target)
	}
	return nil
}
Example #12
0
func initMetrics(cfg *config.Config) {
	if err := metrics.Init(cfg.Metrics); err != nil {
		exit.Fatal("[FATAL] ", err)
	}
}