func Benchmark_TChannel_YARPCToYARPC(b *testing.B) { serverCh, err := tchannel.NewChannel("server", nil) require.NoError(b, err, "failed to build server TChannel") serverCfg := yarpc.Config{ Name: "server", Inbounds: []transport.Inbound{ytchannel.NewInbound(serverCh)}, } clientCh, err := tchannel.NewChannel("client", nil) require.NoError(b, err, "failed to build client TChannel") // no defer close on channels because YARPC will take care of that withDispatcher(b, serverCfg, func(server yarpc.Dispatcher) { server.Register(raw.Procedure("echo", yarpcEcho)) // Need server already started to build client config clientCfg := yarpc.Config{ Name: "client", Outbounds: yarpc.Outbounds{ "server": { Unary: ytchannel.NewOutbound(clientCh, ytchannel.HostPort(serverCh.PeerInfo().HostPort)), }, }, } withDispatcher(b, clientCfg, func(client yarpc.Dispatcher) { b.ResetTimer() runYARPCClient(b, raw.New(client.Channel("server"))) }) }) }
func Benchmark_TChannel_YARPCToTChannel(b *testing.B) { serverCh, err := tchannel.NewChannel("server", nil) require.NoError(b, err, "failed to build server TChannel") defer serverCh.Close() serverCh.Register(traw.Wrap(tchannelEcho{t: b}), "echo") require.NoError(b, serverCh.ListenAndServe(":0"), "failed to start up TChannel") clientCh, err := tchannel.NewChannel("client", nil) require.NoError(b, err, "failed to build client TChannel") clientCfg := yarpc.Config{ Name: "client", Outbounds: yarpc.Outbounds{ "server": { Unary: ytchannel.NewOutbound(clientCh, ytchannel.HostPort(serverCh.PeerInfo().HostPort)), }, }, } withDispatcher(b, clientCfg, func(client yarpc.Dispatcher) { b.ResetTimer() runYARPCClient(b, raw.New(client.Channel("server"))) }) }
// Run exercises a YARPC client against a tchannel server. func Run(t crossdock.T) { fatals := crossdock.Fatals(t) encoding := t.Param(params.Encoding) server := t.Param(params.Server) serverHostPort := fmt.Sprintf("%v:%v", server, serverPort) ch, err := tchannel.NewChannel("yarpc-client", nil) fatals.NoError(err, "could not create channel") dispatcher := yarpc.NewDispatcher(yarpc.Config{ Name: "yarpc-client", Outbounds: yarpc.Outbounds{ serverName: { Unary: tch.NewOutbound(ch, tch.HostPort(serverHostPort)), }, }, }) fatals.NoError(dispatcher.Start(), "could not start Dispatcher") defer dispatcher.Stop() switch encoding { case "raw": runRaw(t, dispatcher) case "json": runJSON(t, dispatcher) case "thrift": runThrift(t, dispatcher) default: fatals.Fail("", "unknown encoding %q", encoding) } }
// Create creates an RPC from the given parameters or fails the whole behavior. func Create(t crossdock.T) yarpc.Dispatcher { fatals := crossdock.Fatals(t) server := t.Param(params.Server) fatals.NotEmpty(server, "server is required") var unaryOutbound transport.UnaryOutbound trans := t.Param(params.Transport) switch trans { case "http": unaryOutbound = ht.NewOutbound(fmt.Sprintf("http://%s:8081", server)) case "tchannel": ch, err := tchannel.NewChannel("client", nil) fatals.NoError(err, "couldn't create tchannel") unaryOutbound = tch.NewOutbound(ch, tch.HostPort(server+":8082")) default: fatals.Fail("", "unknown transport %q", trans) } return yarpc.NewDispatcher(yarpc.Config{ Name: "client", Outbounds: yarpc.Outbounds{ "yarpc-test": { Unary: unaryOutbound, }, }, }) }
// Phone implements the phone procedure func Phone(ctx context.Context, reqMeta yarpc.ReqMeta, body *PhoneRequest) (*PhoneResponse, yarpc.ResMeta, error) { var outbound transport.UnaryOutbound switch { case body.Transport.HTTP != nil: t := body.Transport.HTTP url := fmt.Sprintf("http://%s:%d", t.Host, t.Port) outbound = ht.NewOutbound(url) case body.Transport.TChannel != nil: t := body.Transport.TChannel hostport := fmt.Sprintf("%s:%d", t.Host, t.Port) ch, err := tchannel.NewChannel("yarpc-test-client", nil) if err != nil { return nil, nil, fmt.Errorf("failed to build TChannel: %v", err) } outbound = tch.NewOutbound(ch, tch.HostPort(hostport)) default: return nil, nil, fmt.Errorf("unconfigured transport") } if err := outbound.Start(transport.NoDeps); err != nil { return nil, nil, err } defer outbound.Stop() // TODO use reqMeta.Service for caller client := json.New(channel.MultiOutbound("yarpc-test", body.Service, transport.Outbounds{ Unary: outbound, })) resBody := PhoneResponse{ Service: "yarpc-test", // TODO use reqMeta.Service Procedure: reqMeta.Procedure(), } ctx, cancel := context.WithTimeout(ctx, 500*time.Millisecond) defer cancel() _, err := client.Call( ctx, yarpc.NewReqMeta().Procedure(body.Procedure), body.Body, &resBody.Body) if err != nil { return nil, nil, err } return &resBody, nil, nil }
func (tt tchannelTransport) WithRegistry(r transport.Registry, f func(transport.UnaryOutbound)) { serverOpts := testutils.NewOpts().SetServiceName(testService) clientOpts := testutils.NewOpts().SetServiceName(testCaller) testutils.WithServer(tt.t, serverOpts, func(ch *tchannel.Channel, hostPort string) { i := tch.NewInbound(ch) require.NoError(tt.t, i.Start(transport.ServiceDetail{Name: testService, Registry: r}, transport.NoDeps), "failed to start") defer i.Stop() // ^ the server is already listening so this will just set up the // handler. client := testutils.NewClient(tt.t, clientOpts) o := tch.NewOutbound(client, tch.HostPort(hostPort)) require.NoError(tt.t, o.Start(transport.NoDeps), "failed to start outbound") defer o.Stop() f(o) }) }
func buildDispatcher(t crossdock.T) (dispatcher yarpc.Dispatcher, tconfig server.TransportConfig) { fatals := crossdock.Fatals(t) self := t.Param("ctxclient") subject := t.Param("ctxserver") fatals.NotEmpty(self, "ctxclient is required") fatals.NotEmpty(subject, "ctxserver is required") ch, err := tchannel.NewChannel("ctxclient", nil) fatals.NoError(err, "failed to create TChannel") var outbound transport.UnaryOutbound switch trans := t.Param(params.Transport); trans { case "http": outbound = ht.NewOutbound(fmt.Sprintf("http://%s:8081", subject)) tconfig.TChannel = &server.TChannelTransport{Host: self, Port: 8087} case "tchannel": outbound = tch.NewOutbound(ch, tch.HostPort(fmt.Sprintf("%s:8082", subject))) tconfig.HTTP = &server.HTTPTransport{Host: self, Port: 8086} default: fatals.Fail("", "unknown transport %q", trans) } dispatcher = yarpc.NewDispatcher(yarpc.Config{ Name: "ctxclient", Inbounds: []transport.Inbound{ tch.NewInbound(ch, tch.ListenAddr(":8087")), ht.NewInbound(":8086"), }, Outbounds: yarpc.Outbounds{ "yarpc-test": { Unary: outbound, }, }, }) return dispatcher, tconfig }
func createTChannelDispatcher(tracer opentracing.Tracer, t *testing.T) yarpc.Dispatcher { // Establish the TChannel ch, err := tchannel.NewChannel("yarpc-test", &tchannel.ChannelOptions{ Tracer: tracer, }) assert.NoError(t, err) hp := "127.0.0.1:4040" ch.ListenAndServe(hp) dispatcher := yarpc.NewDispatcher(yarpc.Config{ Name: "yarpc-test", Inbounds: []transport.Inbound{ ytchannel.NewInbound(ch), }, Outbounds: yarpc.Outbounds{ "yarpc-test": { Unary: ytchannel.NewOutbound(ch, ytchannel.HostPort(hp)), }, }, Tracer: tracer, }) return dispatcher }
func main() { outboundName := "" flag.StringVar( &outboundName, "outbound", "", "name of the outbound to use (http/tchannel)", ) flag.Parse() var outbound transport.UnaryOutbound switch strings.ToLower(outboundName) { case "http": outbound = http.NewOutbound("http://localhost:24034") case "tchannel": channel, err := tchannel.NewChannel("keyvalue-client", nil) if err != nil { log.Fatalln(err) } outbound = tch.NewOutbound(channel, tch.HostPort("localhost:28941")) default: log.Fatalf("invalid outbound: %q\n", outboundName) } cache := NewCacheFilter() dispatcher := yarpc.NewDispatcher(yarpc.Config{ Name: "keyvalue-client", Outbounds: yarpc.Outbounds{ "keyvalue": { Unary: outbound, }, }, Filter: cache, }) if err := dispatcher.Start(); err != nil { log.Fatalf("failed to start Dispatcher: %v", err) } defer dispatcher.Stop() client := keyvalueclient.New(dispatcher.Channel("keyvalue")) scanner := bufio.NewScanner(os.Stdin) rootCtx := context.Background() for scanner.Scan() { line := scanner.Text() args := strings.Split(line, " ") if len(args) < 1 || len(args[0]) < 3 { continue } cmd := args[0] args = args[1:] switch cmd { case "get": if len(args) != 1 { fmt.Println("usage: get key") continue } key := args[0] ctx, cancel := context.WithTimeout(rootCtx, 100*time.Millisecond) defer cancel() if value, _, err := client.GetValue(ctx, nil, &key); err != nil { fmt.Printf("get %q failed: %s\n", key, err) } else { fmt.Println(key, "=", value) } continue case "set": if len(args) != 2 { fmt.Println("usage: set key value") continue } key, value := args[0], args[1] cache.Invalidate() ctx, cancel := context.WithTimeout(rootCtx, 100*time.Millisecond) defer cancel() if _, err := client.SetValue(ctx, nil, &key, &value); err != nil { fmt.Printf("set %q = %q failed: %v\n", key, value, err.Error()) } continue case "exit": return default: fmt.Println("invalid command", cmd) fmt.Println("valid commansd are: get, set, exit") } } if err := scanner.Err(); err != nil { fmt.Println("error:", err.Error()) } }