Example #1
0
// 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
}
Example #2
0
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)
		}
	}
}
Example #3
0
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)
}
Example #4
0
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
}
Example #6
0
// 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
}
Example #7
0
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
}
Example #8
0
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)
}
Example #9
0
// 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
}
Example #10
0
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)
}
Example #11
0
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
}
Example #12
0
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")
	}
}
Example #13
0
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,
	}
}
Example #14
0
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)
		}
	}
}