// NewClient creates a new Hyperbahn client using the given channel. // config is the environment-specific configuration for Hyperbahn such as the list of initial nodes. // opts are optional, and are used to customize the client. func NewClient(ch *tchannel.Channel, config Configuration, opts *ClientOptions) (*Client, error) { client := &Client{tchan: ch, quit: make(chan struct{})} if opts != nil { client.opts = *opts } if client.opts.Timeout == 0 { client.opts.Timeout = 3 * time.Second } if client.opts.TimeoutPerAttempt == 0 { client.opts.TimeoutPerAttempt = time.Second } if client.opts.Handler == nil { client.opts.Handler = nullHandler{} } if client.opts.TimeSleep == nil { client.opts.TimeSleep = time.Sleep } if err := parseConfig(&config); err != nil { return nil, err } // Add the given initial nodes as peers. for _, node := range config.InitialNodes { addPeer(ch, node) } client.jsonClient = tjson.NewClient(ch, hyperbahnServiceName, nil) thriftClient := tthrift.NewClient(ch, hyperbahnServiceName, nil) client.hyperbahnClient = htypes.NewTChanHyperbahnClient(thriftClient) return client, nil }
func BenchmarkBothSerial(b *testing.B) { serverAddr, err := setupBenchServer() require.NoError(b, err, "setupBenchServer failed") opts := testutils.NewOpts().SetFramePool(tchannel.NewSyncFramePool()) clientCh := testutils.NewClient(b, opts) for _, addr := range serverAddr { clientCh.Peers().Add(addr) } thriftClient := thrift.NewClient(clientCh, "bench-server", nil) client := gen.NewTChanSecondServiceClient(thriftClient) ctx, cancel := thrift.NewContext(10 * time.Millisecond) client.Echo(ctx, "make connection") cancel() b.ResetTimer() for i := 0; i < b.N; i++ { ctx, cancel := thrift.NewContext(10 * time.Millisecond) defer cancel() _, err := client.Echo(ctx, "hello world") if err != nil { b.Errorf("Echo failed: %v", err) } } }
func TestThriftTracingPropagation(t *testing.T) { suite := &PropagationTestSuite{ Encoding: EncodingInfo{Format: tchannel.Thrift, HeadersSupported: true}, Register: func(t *testing.T, ch *tchannel.Channel) TracingCall { opts := &thrift.ClientOptions{HostPort: ch.PeerInfo().HostPort} thriftClient := thrift.NewClient(ch, ch.PeerInfo().ServiceName, opts) handler := &ThriftHandler{ TraceHandler: TraceHandler{Ch: ch}, t: t, thriftClient: gen.NewTChanSimpleServiceClient(thriftClient), } // Register Thrift handler server := thrift.NewServer(ch) server.Register(gen.NewTChanSimpleServiceServer(handler)) return handler.firstCall }, TestCases: map[TracerType][]PropagationTestCase{ Noop: { {ForwardCount: 2, TracingDisabled: true, ExpectedBaggage: "", ExpectedSpanCount: 0}, {ForwardCount: 2, TracingDisabled: false, ExpectedBaggage: "", ExpectedSpanCount: 0}, }, Mock: { {ForwardCount: 2, TracingDisabled: true, ExpectedBaggage: BaggageValue, ExpectedSpanCount: 0}, {ForwardCount: 2, TracingDisabled: false, ExpectedBaggage: BaggageValue, ExpectedSpanCount: 6}, }, Jaeger: { {ForwardCount: 2, TracingDisabled: true, ExpectedBaggage: BaggageValue, ExpectedSpanCount: 0}, {ForwardCount: 2, TracingDisabled: false, ExpectedBaggage: BaggageValue, ExpectedSpanCount: 6}, }, }, } suite.Run(t) }
func main() { // Create a TChannel. ch, err := tchannel.NewChannel("keyvalue-client", nil) if err != nil { log.Fatalf("Failed to create tchannel: %v", err) } // Set up Hyperbahn client. config := hyperbahn.Configuration{InitialNodes: os.Args[1:]} if len(config.InitialNodes) == 0 { log.Fatalf("No Autobahn nodes to connect to given") } hyperbahn.NewClient(ch, config, nil) thriftClient := thrift.NewClient(ch, "keyvalue", nil) client := keyvalue.NewTChanKeyValueClient(thriftClient) adminClient := keyvalue.NewTChanAdminClient(thriftClient) // Read commands from the command line and execute them. scanner := bufio.NewScanner(os.Stdin) printHelp() fmt.Printf("> ") for scanner.Scan() { parts := strings.Split(scanner.Text(), " ") if parts[0] == "" { continue } switch parts[0] { case "help": printHelp() case "get": if len(parts) < 2 { printHelp() break } get(client, parts[1]) case "set": if len(parts) < 3 { printHelp() break } set(client, parts[1], parts[2]) case "user": if len(parts) < 2 { printHelp() break } curUser = parts[1] case "clearAll": clear(adminClient) default: log.Printf("Unsupported command %q\n", parts[0]) } fmt.Print("> ") } scanner.Text() }
// NewZipkinTraceReporter returns a zipkin trace reporter that submits span to tcollector service. func NewZipkinTraceReporter(ch *tc.Channel) *ZipkinTraceReporter { thriftClient := thrift.NewClient(ch, tcollectorServiceName, nil) client := tcollector.NewTChanTCollectorClient(thriftClient) // create the goroutine method to actually to the submit Span. reporter := &ZipkinTraceReporter{ tchannel: ch, client: client, c: make(chan zipkinData, chanBufferSize), logger: ch.Logger(), } go reporter.zipkinSpanWorker() return reporter }
// Get the client for a certain destination from our internal cache, or // delegates the creation to the ClientFactory. func (r *router) GetClient(key string) (interface{}, error) { dest, err := r.ringpop.Lookup(key) if err != nil { return nil, err } r.rw.RLock() client, ok := r.clientCache[dest] r.rw.RUnlock() if ok { return client, nil } // no match so far, get a complete lock for creation r.rw.Lock() defer r.rw.Unlock() // double check it is not created between read and complete lock client, ok = r.clientCache[dest] if ok { return client, nil } me, err := r.ringpop.WhoAmI() if err != nil { return nil, err } // use the ClientFactory to get the client if dest == me { client = r.factory.GetLocalClient() } else { thriftClient := thrift.NewClient( r.channel, r.channel.ServiceName(), &thrift.ClientOptions{ HostPort: dest, }, ) client = r.factory.MakeRemoteClient(thriftClient) } // cache the client r.clientCache[dest] = client return client, nil }
func runClient2(hyperbahnService string, addr net.Addr) error { tchan, err := tchannel.NewChannel("client2", optsFor("client2")) if err != nil { return err } tchan.Peers().Add(addr.String()) tclient := thrift.NewClient(tchan, hyperbahnService, nil) client := gen.NewTChanSecondClient(tclient) go func() { for { ctx, cancel := thrift.NewContext(time.Second) client.Test(ctx) cancel() time.Sleep(100 * time.Millisecond) } }() return nil }
func runThrift(t crossdock.T, call call) { assert := crossdock.Assert(t) checks := crossdock.Checks(t) headers := map[string]string{ "hello": "thrift", } token := random.String(5) client := thrift.NewClient(call.Channel, serverName, &thrift.ClientOptions{HostPort: call.ServerHostPort}) resp, respHeaders, err := thriftCall(client, headers, token) if checks.NoError(err, "thrift: call failed") { assert.Equal(token, resp.Boop, "body echoed") respHeaders = internal.RemoveVariableMapKeys(respHeaders) assert.Equal(headers, respHeaders, "headers echoed") } runGauntlet(t, client) }
// NewTCollectorReporter return trace reporter that submits span to TCollector. func NewTCollectorReporter(ch *tc.Channel) *TCollectorReporter { thriftClient := thrift.NewClient(ch, tcollectorServiceName, nil) client := tcollector.NewTChanTCollectorClient(thriftClient) curHostIP, err := tc.ListenIP() if err != nil { ch.Logger().WithFields(tc.ErrField(err)).Warn("TCollector TraceReporter failed to get IP.") curHostIP = net.IPv4(0, 0, 0, 0) } // create the goroutine method to actually to the submit Span. reporter := &TCollectorReporter{ tchannel: ch, client: client, c: make(chan tc.TraceData, chanBufferSize), logger: ch.Logger(), curHostIP: inetAton(curHostIP.String()), } go reporter.worker() return reporter }
func (h *thriftHandler) callDownstream(ctx context.Context, target *Downstream) (*Response, error) { req := &Request{ ServerRole: target.ServerRole, Downstream: target.Downstream, } opts := &thrift.ClientOptions{HostPort: target.HostPort} thriftClient := thrift.NewClient(h.ch, target.ServiceName, opts) serviceClient := gen.NewTChanSimpleServiceClient(thriftClient) tReq, err := requestToThrift(req) if err != nil { return nil, err } log.Printf("Calling Thrift service %s (%s)", target.ServiceName, target.HostPort) tctx := thrift.Wrap(ctx) res, err := serviceClient.Call(tctx, tReq) if err != nil { return nil, err } return responseFromThrift(res) }
func runClient1(hyperbahnService string, addr net.Addr) error { tchan, err := tchannel.NewChannel("client1", optsFor("client1")) if err != nil { return err } tchan.Peers().Add(addr.String()) tclient := thrift.NewClient(tchan, hyperbahnService, nil) client := gen.NewTChanFirstClient(tclient) go func() { for { ctx, cancel := thrift.NewContext(time.Second) res, err := client.Echo(ctx, "Hi") log.Println("Echo(Hi) = ", res, ", err: ", err) log.Println("AppError() = ", client.AppError(ctx)) log.Println("BaseCall() = ", client.BaseCall(ctx)) cancel() time.Sleep(100 * time.Millisecond) } }() return nil }
func main() { ch, err := tchannel.NewChannel("tcheck", nil) if err != nil { fmt.Println("failed to create tchannel:", err) os.Exit(1) } hostsFile := flag.String("hostsFile", "/etc/uber/hyperbahn/hosts.json", "hyperbahn hosts file") serviceName := flag.String("serviceName", "hyperbahn", "service name to check health of") peer := flag.String("peer", "", "peer to hit directly") flag.Parse() var config hyperbahn.Configuration if *peer != "" { config = hyperbahn.Configuration{InitialNodes: []string{*peer}} } else { config = hyperbahn.Configuration{InitialNodesFile: *hostsFile} } hyperbahn.NewClient(ch, config, nil) thriftClient := thrift.NewClient(ch, *serviceName, nil) client := meta.NewTChanMetaClient(thriftClient) ctx, cancel := thrift.NewContext(time.Second) defer cancel() val, err := client.Health(ctx) if err != nil { fmt.Printf("NOT OK %v\nError: %v\n", *serviceName, err) os.Exit(2) } else if val.Ok != true { fmt.Printf("NOT OK %v\n", *val.Message) os.Exit(3) } else { fmt.Printf("OK\n") } }
func newInternalClient(hosts []string, opts *options) inProcClient { ch, err := tchannel.NewChannel(opts.svcName, &tchannel.ChannelOptions{ Logger: tchannel.NewLevelLogger(tchannel.NewLogger(os.Stderr), tchannel.LogLevelWarn), }) if err != nil { panic("failed to create channel: " + err.Error()) } for _, host := range hosts { ch.Peers().Add(host) } thriftClient := thrift.NewClient(ch, opts.svcName, nil) client := gen.NewTChanSecondServiceClient(thriftClient) return &internalClient{ ch: ch, sc: ch.GetSubChannel(opts.svcName), tClient: client, argBytes: getRequestBytes(opts.reqSize), argStr: getRequestString(opts.reqSize), opts: opts, } }
func main() { flag.Parse() ch, err := testutils.NewClient(nil) if err != nil { log.Fatalf("err") } for _, host := range flag.Args() { ch.Peers().Add(host) } thriftClient := thrift.NewClient(ch, *serviceName, nil) client := gen.NewTChanSecondServiceClient(thriftClient) fmt.Println("bench-client started") rdr := bufio.NewReader(os.Stdin) for { line, err := rdr.ReadString('\n') if err != nil { if err == io.EOF { return } log.Fatalf("stdin read failed: %v", err) } line = strings.TrimSuffix(line, "\n") switch line { case "call": makeCall(client) case "quit": return default: log.Fatalf("unrecognized command: %v", line) } } }