func initializeDopplerPool(config *config.Config, logger *gosteno.Logger) (*clientpool.DopplerPool, error) { adapter, err := storeAdapterProvider(config.EtcdUrls, config.EtcdMaxConcurrentRequests) if err != nil { return nil, err } err = adapter.Connect() if err != nil { logger.Warnd(map[string]interface{}{ "error": err.Error(), }, "Failed to connect to etcd") } preferInZone := func(relativePath string) bool { return strings.HasPrefix(relativePath, "/"+config.Zone+"/") } var tlsConfig *tls.Config if config.PreferredProtocol == "tls" { c := config.TLSConfig tlsConfig, err = listeners.NewTLSConfig(c.CertFile, c.KeyFile, c.CAFile) if err != nil { return nil, err } tlsConfig.ServerName = "doppler" } clientPool := clientpool.NewDopplerPool(logger, func(logger *gosteno.Logger, url string) (clientpool.Client, error) { client, err := clientpool.NewClient(logger, url, tlsConfig) if err == nil && client.Scheme() != config.PreferredProtocol { logger.Warnd(map[string]interface{}{ "url": url, }, "Doppler advertising UDP only") } return client, err }) onUpdate := func(all map[string]string, preferred map[string]string) { clientPool.Set(all, preferred) } dopplers, err := dopplerservice.NewFinder(adapter, config.PreferredProtocol, preferInZone, onUpdate, logger) if err != nil { return nil, err } dopplers.Start() onLegacyUpdate := func(all map[string]string, preferred map[string]string) { clientPool.SetLegacy(all, preferred) } legacyDopplers := dopplerservice.NewLegacyFinder(adapter, config.LoggregatorDropsondePort, preferInZone, onLegacyUpdate, logger) legacyDopplers.Start() return clientPool, nil }
func initializeClientPool(config *config.Config, logger *gosteno.Logger) (*clientpool.DopplerPool, error) { adapter := storeAdapterProvider(config.EtcdUrls, config.EtcdMaxConcurrentRequests) err := adapter.Connect() if err != nil { return nil, err } preferInZone := func(relativePath string) bool { return strings.HasPrefix(relativePath, "/"+config.Zone+"/") } clientPool := clientpool.NewDopplerPool(logger, func(logger *gosteno.Logger, url string) (loggregatorclient.Client, error) { client, err := clientpool.NewClient(logger, url) if err == nil && client.Scheme() != config.PreferredProtocol { logger.Warnd(map[string]interface{}{ "url": url, }, "Doppler advertising UDP only") } return client, err }) onUpdate := func(all map[string]string, preferred map[string]string) { clientPool.Set(all, preferred) } dopplers, err := dopplerservice.NewFinder(adapter, config.PreferredProtocol, preferInZone, onUpdate, logger) if err != nil { return nil, err } dopplers.Start() onLegacyUpdate := func(all map[string]string, preferred map[string]string) { clientPool.SetLegacy(all, preferred) } legacyDopplers := dopplerservice.NewLegacyFinder(adapter, config.LoggregatorDropsondePort, preferInZone, onLegacyUpdate, logger) legacyDopplers.Start() return clientPool, nil }
"github.com/cloudfoundry/storeadapter/etcdstoreadapter" "doppler/dopplerservice" "doppler/dopplerservice/fakes" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) //go:generate counterfeiter -o fakes/fakestoreadapter.go ../../github.com/cloudfoundry/storeadapter StoreAdapter var _ = Describe("Finder", func() { var finder dopplerservice.Finder Context("validation", func() { It("returns an error when protocol is invalid", func() { _, err := dopplerservice.NewFinder(nil, "bogus", nil, nil, loggertesthelper.Logger()) Expect(err).To(HaveOccurred()) }) }) Describe("Running", func() { var ( order chan string fakeAdapter *fakes.FakeStoreAdapter errChan chan error stopChan chan bool ) BeforeEach(func() { order = make(chan string, 2) stopChan = make(chan bool)
port int preferredDopplerZone string finder *dopplerservice.Finder ) BeforeEach(func() { preferredDopplerZone = "" protocols = nil mockStoreAdapter = newMockStoreAdapter() port = 1234 testLogger = gosteno.NewLogger("TestLogger") }) JustBeforeEach(func() { finder = dopplerservice.NewFinder(mockStoreAdapter, port, protocols, preferredDopplerZone, testLogger) Expect(finder).ToNot(BeNil()) }) Describe("WebsocketServers", func() { var ( metaNode, legacyNode storeadapter.StoreNode metaServers map[string][]string legacyServers map[string]string expectedServers []string ) BeforeEach(func() { port = 8081 protocols = []string{"udp"} preferredDopplerZone = ""
func initializeDopplerPool(conf *config.Config, logger *gosteno.Logger) (*eventmarshaller.EventMarshaller, error) { adapter, err := storeAdapterProvider(conf.EtcdUrls, conf.EtcdMaxConcurrentRequests) if err != nil { return nil, err } err = adapter.Connect() if err != nil { logger.Warnd(map[string]interface{}{ "error": err.Error(), }, "Failed to connect to etcd") } var protocols []string clientPool := make(map[string]clientreader.ClientPool) writers := make(map[string]eventmarshaller.ByteWriter) for _, protocol := range conf.Protocols { proto := string(protocol) protocols = append(protocols, proto) switch proto { case "udp": udpCreator := clientpool.NewUDPClientCreator(logger) udpWrapper := dopplerforwarder.NewUDPWrapper([]byte(conf.SharedSecret), logger) udpPool := clientpool.NewDopplerPool(logger, udpCreator) udpForwarder := dopplerforwarder.New(udpWrapper, udpPool, logger) clientPool[proto] = udpPool writers[proto] = udpForwarder case "tcp": tcpCreator := clientpool.NewTCPClientCreator(logger, nil) tcpWrapper := dopplerforwarder.NewWrapper(logger, proto) tcpPool := clientpool.NewDopplerPool(logger, tcpCreator) tcpForwarder := dopplerforwarder.New(tcpWrapper, tcpPool, logger) tcpBatchInterval := time.Duration(conf.TCPBatchIntervalMilliseconds) * time.Millisecond batchWriter, err := batch.NewWriter(tcpForwarder, conf.TCPBatchSizeBytes, tcpBatchInterval, logger) if err != nil { return nil, err } clientPool[proto] = tcpPool writers[proto] = batchWriter case "tls": c := conf.TLSConfig tlsConfig, err := listeners.NewTLSConfig(c.CertFile, c.KeyFile, c.CAFile) if err != nil { return nil, err } tlsConfig.ServerName = "doppler" tlsCreator := clientpool.NewTCPClientCreator(logger, tlsConfig) tlsWrapper := dopplerforwarder.NewWrapper(logger, proto) tlsPool := clientpool.NewDopplerPool(logger, tlsCreator) tlsForwarder := dopplerforwarder.New(tlsWrapper, tlsPool, logger) tcpBatchInterval := time.Duration(conf.TCPBatchIntervalMilliseconds) * time.Millisecond batchWriter, err := batch.NewWriter(tlsForwarder, conf.TCPBatchSizeBytes, tcpBatchInterval, logger) if err != nil { return nil, err } clientPool[proto] = tlsPool writers[proto] = batchWriter } } finder := dopplerservice.NewFinder(adapter, conf.LoggregatorDropsondePort, protocols, conf.Zone, logger) marshaller := eventmarshaller.New(logger) finder.Start() go func() { for { protocol := clientreader.Read(clientPool, protocols, finder.Next()) logger.Infof("Chose protocol %s from last etcd event, updating writer...", protocol) marshaller.SetWriter(writers[protocol]) } }() return marshaller, nil }
func initializeDopplerPool(conf *config.Config, batcher *metricbatcher.MetricBatcher, logger *gosteno.Logger) (*eventmarshaller.EventMarshaller, error) { adapter, err := storeAdapterProvider(conf) if err != nil { return nil, err } backoffStrategy := retrystrategy.Exponential() err = backoff.Connect(adapter, backoffStrategy, logger, connectionRetries) if err != nil { return nil, err } var protocols []string clientPool := make(map[string]clientreader.ClientPool) writers := make(map[string]eventmarshaller.BatchChainByteWriter) ip, err := localip.LocalIP() if err != nil { return nil, err } for protocol := range conf.Protocols { proto := string(protocol) protocols = append(protocols, proto) switch proto { case "udp": udpCreator := clientpool.NewUDPClientCreator(logger) udpWrapper := dopplerforwarder.NewUDPWrapper([]byte(conf.SharedSecret), logger) udpPool := clientpool.NewDopplerPool(logger, udpCreator) udpForwarder := dopplerforwarder.New(udpWrapper, udpPool, logger) clientPool[proto] = udpPool writers[proto] = udpForwarder case "tcp": tcpCreator := clientpool.NewTCPClientCreator(logger, nil) tcpWrapper := dopplerforwarder.NewWrapper(logger, proto) tcpPool := clientpool.NewDopplerPool(logger, tcpCreator) tcpForwarder := dopplerforwarder.New(tcpWrapper, tcpPool, logger) tcpBatchInterval := time.Duration(conf.TCPBatchIntervalMilliseconds) * time.Millisecond dropCounter := batch.NewDroppedCounter(tcpForwarder, batcher, origin, ip, conf) batchWriter, err := batch.NewWriter( "tcp", tcpForwarder, dropCounter, conf.TCPBatchSizeBytes, tcpBatchInterval, logger, ) if err != nil { return nil, err } clientPool[proto] = tcpPool writers[proto] = batchWriter case "tls": c := conf.TLSConfig tlsConfig, err := listeners.NewTLSConfig(c.CertFile, c.KeyFile, c.CAFile) if err != nil { return nil, err } tlsConfig.ServerName = "doppler" tlsCreator := clientpool.NewTCPClientCreator(logger, tlsConfig) tlsWrapper := dopplerforwarder.NewWrapper(logger, proto) tlsPool := clientpool.NewDopplerPool(logger, tlsCreator) tlsForwarder := dopplerforwarder.New(tlsWrapper, tlsPool, logger) tcpBatchInterval := time.Duration(conf.TCPBatchIntervalMilliseconds) * time.Millisecond dropCounter := batch.NewDroppedCounter(tlsForwarder, batcher, origin, ip, conf) batchWriter, err := batch.NewWriter( "tls", tlsForwarder, dropCounter, conf.TCPBatchSizeBytes, tcpBatchInterval, logger, ) if err != nil { return nil, err } clientPool[proto] = tlsPool writers[proto] = batchWriter } } finder := dopplerservice.NewFinder(adapter, conf.LoggregatorDropsondePort, conf.Protocols.Strings(), conf.Zone, logger) finder.Start() marshaller := eventmarshaller.New(batcher, logger) go func() { for { protocol := clientreader.Read(clientPool, conf.Protocols.Strings(), finder.Next()) logger.Infof("Chose protocol %s from last etcd event, updating writer...", protocol) marshaller.SetWriter(writers[protocol]) } }() return marshaller, nil }
func main() { flag.Parse() config, err := config.ParseConfig(*logLevel, *configFile) if err != nil { panic(fmt.Errorf("Unable to parse config: %s", err)) } transport := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: config.SkipCertVerify}} http.DefaultClient.Transport = transport ipAddress, err := localip.LocalIP() if err != nil { panic(fmt.Errorf("Unable to resolve own IP address: %s", err)) } log := logger.NewLogger(*logLevel, *logFilePath, "loggregator trafficcontroller", config.Syslog) log.Info("Startup: Setting up the loggregator traffic controller") dropsonde.Initialize(net.JoinHostPort(config.MetronHost, strconv.Itoa(config.MetronPort)), "LoggregatorTrafficController") go func() { err := http.ListenAndServe(net.JoinHostPort(ipAddress, pprofPort), nil) if err != nil { log.Errorf("Error starting pprof server: %s", err.Error()) } }() uptimeMonitor := monitor.NewUptimeMonitor(time.Duration(config.MonitorIntervalSeconds) * time.Second) go uptimeMonitor.Start() defer uptimeMonitor.Stop() etcdAdapter := defaultStoreAdapterProvider(config.EtcdUrls, config.EtcdMaxConcurrentRequests) err = etcdAdapter.Connect() if err != nil { panic(fmt.Errorf("Unable to connect to ETCD: %s", err)) } logAuthorizer := authorization.NewLogAccessAuthorizer(*disableAccessControl, config.ApiHost) uaaClient := uaa_client.NewUaaClient(config.UaaHost, config.UaaClientId, config.UaaClientSecret) adminAuthorizer := authorization.NewAdminAccessAuthorizer(*disableAccessControl, &uaaClient) // TODO: The preferredProtocol of udp tells the finder to pull out the Doppler URLs from the legacy ETCD endpoint. // Eventually we'll have a separate websocket client pool finder := dopplerservice.NewFinder(etcdAdapter, int(config.DopplerPort), []string{"udp"}, "", log) finder.Start() // Draining the finder's events channel in order to not block the finder from handling etcd events. go func() { for { finder.Next() } }() var accessMiddleware, legacyAccessMiddleware func(middleware.HttpHandler) *middleware.AccessHandler if config.SecurityEventLog != "" { accessLog, err := os.OpenFile(config.SecurityEventLog, os.O_APPEND|os.O_WRONLY, os.ModeAppend) if err != nil { panic(fmt.Errorf("Unable to open access log: %s", err)) } defer func() { accessLog.Sync() accessLog.Close() }() accessLogger := accesslogger.New(accessLog, log) accessMiddleware = middleware.Access(accessLogger, ipAddress, config.OutgoingDropsondePort, log) legacyAccessMiddleware = middleware.Access(accessLogger, ipAddress, config.OutgoingPort, log) } dopplerCgc := channel_group_connector.NewChannelGroupConnector(finder, newDropsondeWebsocketListener, marshaller.DropsondeLogMessage, log) dopplerHandler := http.Handler(dopplerproxy.NewDopplerProxy(logAuthorizer, adminAuthorizer, dopplerCgc, dopplerproxy.TranslateFromDropsondePath, "doppler."+config.SystemDomain, log)) if accessMiddleware != nil { dopplerHandler = accessMiddleware(dopplerHandler) } startOutgoingProxy(net.JoinHostPort(ipAddress, strconv.FormatUint(uint64(config.OutgoingDropsondePort), 10)), dopplerHandler) legacyCgc := channel_group_connector.NewChannelGroupConnector(finder, newLegacyWebsocketListener, marshaller.LoggregatorLogMessage, log) legacyHandler := http.Handler(dopplerproxy.NewDopplerProxy(logAuthorizer, adminAuthorizer, legacyCgc, dopplerproxy.TranslateFromLegacyPath, "loggregator."+config.SystemDomain, log)) if legacyAccessMiddleware != nil { legacyHandler = legacyAccessMiddleware(legacyHandler) } startOutgoingProxy(net.JoinHostPort(ipAddress, strconv.FormatUint(uint64(config.OutgoingPort), 10)), legacyHandler) killChan := signalmanager.RegisterKillSignalChannel() dumpChan := signalmanager.RegisterGoRoutineDumpSignalChannel() for { select { case <-dumpChan: signalmanager.DumpGoRoutine() case <-killChan: log.Info("Shutting down") return } } }