func main() { flag.Parse() channel, err := tchannel.NewChannel("worker", &tchannel.ChannelOptions{ // Logger: tchannel.NewLevelLogger(tchannel.SimpleLogger, tchannel.LogLevelWarn), }) if err != nil { log.Fatalf("could not create channel: %v", err) } worker := newWorker(*hostport, channel) server := thrift.NewServer(channel.GetSubChannel("pingpong")) server.Register(pingpong.NewTChanPingPongServer(worker)) if err := channel.ListenAndServe(*hostport); err != nil { log.Fatalf("could not listen on hostport: %v", err) } bsopts := new(ringpop.BootstrapOptions) bsopts.File = *hostfile bsopts.Stopped = true if _, err := worker.ringpop.Bootstrap(bsopts); err != nil { log.Fatalf("could not bootstrap ringpop: %v", err) } // block select {} }
func setupBenchServer() ([]string, error) { ch, err := testutils.NewServerChannel(testutils.NewOpts(). SetServiceName(benchServerName). SetFramePool(tchannel.NewSyncFramePool())) if err != nil { return nil, err } fmt.Println(benchServerName, "started on", ch.PeerInfo().HostPort) server := thrift.NewServer(ch) server.Register(gen.NewTChanSecondServiceServer(benchSecondHandler{})) if !*useHyperbahn { return []string{ch.PeerInfo().HostPort}, nil } // Set up a Hyperbahn client and advertise it. nodes := strings.Split(*hyperbahnNodes, ",") config := hyperbahn.Configuration{InitialNodes: nodes} hc, err := hyperbahn.NewClient(ch, config, nil) if err := hc.Advertise(); err != nil { return nil, err } return nodes, nil }
func (s *ForwarderTestSuite) registerPong(address string, channel *tchannel.Channel) { hmap := map[string]interface{}{ "/ping": func(ctx json.Context, ping *Ping) (*Pong, error) { return &Pong{"Hello, world!", address}, nil }, "/error": func(ctx json.Context, ping *Ping) (*Pong, error) { return nil, errors.New("remote error") }, } s.Require().NoError(json.Register(channel, hmap, func(ctx context.Context, err error) {})) thriftHandler := &pingpong.MockTChanPingPong{} // successful request thriftHandler.On("Ping", mock.Anything, &pingpong.Ping{ Key: "success", }).Return(&pingpong.Pong{ Source: address, }, nil) // error request thriftHandler.On("Ping", mock.Anything, &pingpong.Ping{ Key: "error", }).Return(nil, &pingpong.PingError{}) server := thrift.NewServer(channel) server.Register(pingpong.NewTChanPingPongServer(thriftHandler)) }
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) }
// NewServer returns a new Server that can recieve Thrift calls or raw calls. func NewServer(optFns ...Option) Server { opts := getOptions(optFns) if opts.external { return newExternalServer(opts) } 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()) } if err := ch.ListenAndServe("127.0.0.1:0"); err != nil { panic("failed to listen on port 0: " + err.Error()) } s := &internalServer{ ch: ch, opts: opts, } tServer := thrift.NewServer(ch) tServer.Register(gen.NewTChanSecondServiceServer(handler{calls: &s.thriftCalls})) ch.Register(raw.Wrap(rawHandler{calls: &s.rawCalls}), "echo") if len(opts.advertiseHosts) > 0 { if err := s.Advertise(opts.advertiseHosts); err != nil { panic("failed to advertise: " + err.Error()) } } return s }
// Register the different endpoints of the test subject func register(ch *tchannel.Channel) { ch.Register(raw.Wrap(echoRawHandler{}), "echo/raw") ch.Register(raw.Wrap(handlerTimeoutRawHandler{}), "handlertimeout/raw") json.Register(ch, json.Handlers{"echo": echoJSONHandler}, onError) tserver := thrift.NewServer(ch) tserver.Register(echo.NewTChanEchoServer(&echoThriftHandler{})) tserver.Register(gauntlet_tchannel.NewTChanThriftTestServer(&thriftTestHandler{})) tserver.Register(gauntlet_tchannel.NewTChanSecondServiceServer(&secondServiceHandler{})) }
func setupServer(h *mocks.TChanTCollector) (*tchannel.Channel, error) { tchan, err := testutils.NewServer(&testutils.ChannelOpts{ ServiceName: tcollectorServiceName, }) if err != nil { return nil, err } server := thrift.NewServer(tchan) server.Register(gen.NewTChanTCollectorServer(h)) return tchan, nil }
func SetupServer(t *testing.T, fn thrift.HealthFunc) (*tchannel.Channel, string) { _, cancel := tchannel.NewContext(time.Second * 10) defer cancel() opts := testutils.NewOpts(). SetServiceName("testing"). DisableLogVerification() tchan := testutils.NewServer(t, opts) if fn != nil { server := thrift.NewServer(tchan) server.RegisterHealthHandler(fn) } return tchan, tchan.PeerInfo().HostPort }
func setupServer() (net.Listener, error) { tchan, err := tchannel.NewChannel("server", optsFor("server")) if err != nil { return nil, err } listener, err := net.Listen("tcp", ":0") if err != nil { return nil, err } server := thrift.NewServer(tchan) server.Register(gen.NewTChanFirstServer(&firstHandler{})) server.Register(gen.NewTChanSecondServer(&secondHandler{})) // Serve will set the local peer info, and start accepting sockets in a separate goroutine. tchan.Serve(listener) return listener, nil }
func main() { // Create a TChannel and register the Thrift handlers. ch, err := tchannel.NewChannel("keyvalue", nil) if err != nil { log.Fatalf("Failed to create tchannel: %v", err) } // Register both the KeyValue and Admin services. // We can register multiple Thrift services on a single Hyperbahn service. h := newKVHandler() server := thrift.NewServer(ch) server.Register(keyvalue.NewTChanKeyValueServer(h)) server.Register(keyvalue.NewTChanAdminServer(h)) pprof.Register(ch) // Listen for connections on the external interface so we can receive connections. ip, err := tchannel.ListenIP() if err != nil { log.Fatalf("Failed to find IP to Listen on: %v", err) } // We use port 0 which asks the OS to assign any available port. // Static port allocations are not necessary for services on Hyperbahn. ch.ListenAndServe(fmt.Sprintf("%v:%v", ip, 0)) // Advertising registers this service instance with Hyperbahn so // that Hyperbahn can route requests for "keyvalue" to us. config := hyperbahn.Configuration{InitialNodes: os.Args[1:]} if len(config.InitialNodes) == 0 { log.Fatalf("No Autobahn nodes to advertise with") } client, err := hyperbahn.NewClient(ch, config, nil) if err != nil { log.Fatalf("hyperbahn.NewClient failed: %v", err) } if err := client.Advertise(); err != nil { log.Fatalf("Hyperbahn advertise failed: %v", err) } // The service is now started up, run it till we receive a ctrl-c. log.Printf("KeyValue service has started on %v", ch.PeerInfo().HostPort) select {} }
// New returns a mock Hyperbahn server that can be used for testing. func New() (*Mock, error) { ch, err := tchannel.NewChannel("hyperbahn", nil) if err != nil { return nil, err } mh := &Mock{ ch: ch, respCh: make(chan int), discoverResults: make(map[string][]string), } if err := json.Register(ch, json.Handlers{"ad": mh.adHandler}, nil); err != nil { return nil, err } thriftServer := thrift.NewServer(ch) thriftServer.Register(hthrift.NewTChanHyperbahnServer(mh)) return mh, ch.ListenAndServe("127.0.0.1:0") }
// New returns a mock Hyperbahn server that can be used for testing. func New() (*Mock, error) { table := &mockTable{} ch, err := tchannel.NewChannel("hyperbahn", &tchannel.ChannelOptions{ RelayHosts: table, RelayLocalHandlers: []string{"hyperbahn"}, }) if err != nil { return nil, err } table.ch = ch mh := &Mock{ ch: ch, respCh: make(chan int), discoverResults: make(map[string][]string), } if err := json.Register(ch, json.Handlers{"ad": mh.adHandler}, nil); err != nil { return nil, err } thriftServer := thrift.NewServer(ch) thriftServer.Register(hthrift.NewTChanHyperbahnServer(mh)) return mh, ch.ListenAndServe("127.0.0.1:0") }
func (b *Behavior) registerThrift(ch *tchannel.Channel) { handler := &thriftHandler{b: b, ch: ch} server := thrift.NewServer(ch) server.Register(gen.NewTChanSimpleServiceServer(handler)) b.thriftCall = handler.callDownstream }
func main() { flag.Parse() channel, err := tchannel.NewChannel("pingpong", &tchannel.ChannelOptions{}) if err != nil { log.Fatalf("could not create channel: %v", err) } server := thrift.NewServer(channel) // The actual service implementation worker := newWorker(*hostport, channel) // wrap the PingPong worker by a ringpop adapter for routing RPC calls // NewRingpopPingPongAdapter is in the package containing the generated code // Its name is derived from the thrift service name as follows: `NewRingpop[Service Name]Adapter` adapter, err := gen.NewRingpopPingPongAdapter(worker, worker.ringpop, channel, // PingPongConfiguration contains the configuration for ringpop forwarding regaring this service // The name is derived as follows `[Service Name]Configuration` gen.PingPongConfiguration{ // The ping member of the configuration refers to the Ping endpoint within the service. // Configuring an endpoint is optional and unconfigured endpoints will work but not be // forwarded to a different ringpop node during invocation // The name of the configuration struct passed in here is derived as follows: // `[Service Name][Endpoint Name]Configuration` Ping: &gen.PingPongPingConfiguration{ // The configuration structs only member is the Key closure. The purpose of this closure // is to return the key used for ringpop sharding and forwarding. Calls that are sharded // on the same key are guaranteed to be forwarded to the same node. // The input signature for this closure is the same as the signature for your // implementation. The output is always the tuple (shardKey string, err error). Key: func(ctx thrift.Context, request *gen.Ping) (shardKey string, err error) { // The body of the Key closure can perform whatever logic is needed to come to a // meaningful shardKey for the the request if request == nil { return "", errors.New("missing request in call to Ping") } // Here we route the ping's for the same key to the same machine return request.Key, nil }, }, }, ) if err != nil { log.Fatalf("unable to wrap the worker: %q", err) } // now pass the ringpop adapter into the TChannel Thrift server for the PingPong Service server.Register(gen.NewTChanPingPongServer(adapter)) if err := channel.ListenAndServe(*hostport); err != nil { log.Fatalf("could not listen on hostport: %v", err) } bsopts := new(swim.BootstrapOptions) bsopts.File = *hostfile bsopts.Stopped = true if _, err := worker.ringpop.Bootstrap(bsopts); err != nil { log.Fatalf("could not bootstrap ringpop: %v", err) } // block select {} }
func setupServer(t *testing.T, h *mocks.TChanTCollector) *tchannel.Channel { tchan := testutils.NewServer(t, testutils.NewOpts().SetServiceName(tcollectorServiceName)) server := thrift.NewServer(tchan) server.Register(gen.NewTChanTCollectorServer(h)) return tchan }