// Run runs the apachethrift behavior func Run(t crossdock.T) { fatals := crossdock.Fatals(t) server := t.Param(serverParam) fatals.NotEmpty(server, "apachethriftserver is required") baseURL := fmt.Sprintf("http://%v:%v", server, serverPort) thriftOutbound := http.NewOutbound(baseURL + "/thrift/ThriftTest") secondOutbound := http.NewOutbound(baseURL + "/thrift/SecondService") multiplexOutbound := http.NewOutbound(baseURL + "/thrift/multiplexed") dispatcher := yarpc.NewDispatcher(yarpc.Config{ Name: "apache-thrift-client", Outbounds: yarpc.Outbounds{ "ThriftTest": { Unary: thriftOutbound, Oneway: thriftOutbound, }, "SecondService": { Unary: secondOutbound, }, "Multiplexed": { Unary: multiplexOutbound, Oneway: multiplexOutbound, }, }, }) fatals.NoError(dispatcher.Start(), "could not start Dispatcher") defer dispatcher.Stop() // We can just run all the gauntlet tests against each URL because // tests for undefined methods are skipped. tests := []struct { ServerName string Services gauntlet.ServiceSet Options []thrift.ClientOption }{ { ServerName: "ThriftTest", Services: gauntlet.ThriftTest, }, { ServerName: "SecondService", Services: gauntlet.SecondService, }, { ServerName: "Multiplexed", Services: gauntlet.AllServices, Options: []thrift.ClientOption{thrift.Multiplexed}, }, } for _, tt := range tests { t.Tag("outbound", tt.ServerName) gauntlet.RunGauntlet(t, gauntlet.Config{ Dispatcher: dispatcher, ServerName: tt.ServerName, Envelope: true, Services: tt.Services, ClientOptions: tt.Options, }) } }
func withConnectedClient(t *testing.T, recorder *Recorder, f func(raw.Client)) { serverHTTP := http.NewInbound(":0") serverDisp := yarpc.NewDispatcher(yarpc.Config{ Name: "server", Inbounds: []transport.Inbound{serverHTTP}, }) serverDisp.Register(raw.Procedure("hello", func(ctx context.Context, reqMeta yarpc.ReqMeta, body []byte) ([]byte, yarpc.ResMeta, error) { return append(body, []byte(", World")...), nil, nil })) require.NoError(t, serverDisp.Start()) defer serverDisp.Stop() clientDisp := yarpc.NewDispatcher(yarpc.Config{ Name: "client", Outbounds: yarpc.Outbounds{ "server": { Unary: http.NewOutbound(fmt.Sprintf("http://%s", serverHTTP.Addr().String())), }, }, Filter: recorder, }) require.NoError(t, clientDisp.Start()) defer clientDisp.Stop() client := raw.New(clientDisp.Channel("server")) f(client) }
func main() { dispatcher := yarpc.NewDispatcher(yarpc.Config{ Name: "hello", Inbounds: []transport.Inbound{ http.NewInbound(":8086"), }, Outbounds: yarpc.Outbounds{ "hello": { Unary: http.NewOutbound("http://127.0.0.1:8086"), }, }, }) dispatcher.Register(helloserver.New(&helloHandler{})) client := helloclient.New(dispatcher.Channel("hello")) if err := dispatcher.Start(); err != nil { log.Fatal(err) } defer dispatcher.Stop() response, headers := call(client, "Hi There") fmt.Println(response, headers) select {} }
// 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, }, }, }) }
func (ht httpTransport) WithRegistry(r transport.Registry, f func(transport.UnaryOutbound)) { i := http.NewInbound("127.0.0.1:0") require.NoError(ht.t, i.Start(transport.ServiceDetail{Name: testService, Registry: r}, transport.NoDeps), "failed to start") defer i.Stop() addr := fmt.Sprintf("http://%v/", i.Addr().String()) o := http.NewOutbound(addr) require.NoError(ht.t, o.Start(transport.NoDeps), "failed to start outbound") defer o.Stop() f(o) }
func withDisconnectedClient(t *testing.T, recorder *Recorder, f func(raw.Client)) { clientDisp := yarpc.NewDispatcher(yarpc.Config{ Name: "client", Outbounds: yarpc.Outbounds{ "server": { Unary: http.NewOutbound("http://localhost:65535"), }, }, Filter: recorder, }) require.NoError(t, clientDisp.Start()) defer clientDisp.Stop() client := raw.New(clientDisp.Channel("server")) f(client) }
// 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 Benchmark_HTTP_YARPCToNetHTTP(b *testing.B) { clientCfg := yarpc.Config{ Name: "client", Outbounds: yarpc.Outbounds{ "server": { Unary: yhttp.NewOutbound("http://localhost:8998"), }, }, } withHTTPServer(b, ":8998", httpEcho(b), func() { withDispatcher(b, clientCfg, func(client yarpc.Dispatcher) { b.ResetTimer() runYARPCClient(b, raw.New(client.Channel("server"))) }) }) }
func newDispatcher(t crossdock.T) yarpc.Dispatcher { server := t.Param(params.Server) crossdock.Fatals(t).NotEmpty(server, "server is required") dispatcher := yarpc.NewDispatcher(yarpc.Config{ Name: "client", Outbounds: yarpc.Outbounds{ "oneway-test": { Oneway: http.NewOutbound(fmt.Sprintf("http://%s:8084", server)), }, }, //for call back Inbounds: []transport.Inbound{http.NewInbound(fmt.Sprintf("%s:8089", server))}, }) // register procedure for remote server to call us back on dispatcher.Register(raw.OnewayProcedure("call-back", callBack)) return dispatcher }
func createHTTPDispatcher(tracer opentracing.Tracer) yarpc.Dispatcher { // TODO: Use port 0 once https://github.com/yarpc/yarpc-go/issues/381 is // fixed. dispatcher := yarpc.NewDispatcher(yarpc.Config{ Name: "yarpc-test", Inbounds: []transport.Inbound{ http.NewInbound(":18080"), }, Outbounds: yarpc.Outbounds{ "yarpc-test": { Unary: http.NewOutbound("http://127.0.0.1:18080"), }, }, Tracer: tracer, }) return dispatcher }
// Run exercise a yarpc client against a rigged httpserver. func Run(t crossdock.T) { fatals := crossdock.Fatals(t) server := t.Param(params.HTTPServer) fatals.NotEmpty(server, "server is required") disp := yarpc.NewDispatcher(yarpc.Config{ Name: "client", Outbounds: yarpc.Outbounds{ "yarpc-test": { Unary: ht.NewOutbound(fmt.Sprintf("http://%s:8085", server)), }, }, }) fatals.NoError(disp.Start(), "could not start Dispatcher") defer disp.Stop() runRaw(t, disp) }
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 }
// Start starts the test server that clients will make requests to func Start() { h := onewayHandler{ Outbound: http.NewOutbound("http://127.0.0.1:8089"), } dispatcher = yarpc.NewDispatcher(yarpc.Config{ Name: "oneway-test", Inbounds: []transport.Inbound{ http.NewInbound(":8084"), }, Outbounds: yarpc.Outbounds{ "client": {Oneway: h.Outbound}, }, }) dispatcher.Register(raw.OnewayProcedure("echo/raw", h.EchoRaw)) dispatcher.Register(json.OnewayProcedure("echo/json", h.EchoJSON)) dispatcher.Register(onewayserver.New(&h)) if err := dispatcher.Start(); err != nil { fmt.Println("error:", err.Error()) } }
func Benchmark_HTTP_YARPCToYARPC(b *testing.B) { serverCfg := yarpc.Config{ Name: "server", Inbounds: []transport.Inbound{yhttp.NewInbound(":8999")}, } clientCfg := yarpc.Config{ Name: "client", Outbounds: yarpc.Outbounds{ "server": { Unary: yhttp.NewOutbound("http://localhost:8999"), }, }, } withDispatcher(b, serverCfg, func(server yarpc.Dispatcher) { server.Register(raw.Procedure("echo", yarpcEcho)) withDispatcher(b, clientCfg, func(client yarpc.Dispatcher) { b.ResetTimer() runYARPCClient(b, raw.New(client.Channel("server"))) }) }) }
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()) } }