Example #1
0
func TestBreaker(t *testing.T) {
	// setup
	r := mock.NewRegistry()
	s := selector.NewSelector(selector.Registry(r))

	c := client.NewClient(
		// set the selector
		client.Selector(s),
		// add the breaker wrapper
		client.Wrap(NewClientWrapper()),
	)

	req := c.NewJsonRequest("test.service", "Test.Method", map[string]string{
		"foo": "bar",
	})

	var rsp map[string]interface{}

	// Force to point of trip
	for i := 0; i < (hystrix.DefaultVolumeThreshold * 2); i++ {
		c.Call(context.TODO(), req, rsp)
	}

	err := c.Call(context.TODO(), req, rsp)
	if err == nil {
		t.Error("Expecting tripped breaker, got nil error")
	}

	if err.Error() != "hystrix: circuit open" {
		t.Errorf("Expecting tripped breaker, got %v", err)
	}
}
Example #2
0
func TestLabelSelector(t *testing.T) {
	counts := map[string]int{}

	r := mock.NewRegistry()
	r.Register(&registry.Service{
		Name:    "bar",
		Version: "latest",
		Nodes: []*registry.Node{
			&registry.Node{
				Id: "1",
				Metadata: map[string]string{
					"key1": "val1",
				},
			},
			&registry.Node{
				Id: "2",
				Metadata: map[string]string{
					"key2": "val2",
				},
			},
		},
	})

	r.Register(&registry.Service{
		Name:    "bar",
		Version: "1.0.0",
		Nodes: []*registry.Node{
			&registry.Node{
				Id: "3",
				Metadata: map[string]string{
					"key1": "val1",
				},
			},
			&registry.Node{
				Id: "4",
			},
		},
	})

	ls := NewSelector(
		selector.Registry(r),
		Label("key2", "val2"),
		Label("key1", "val1"),
	)

	next, err := ls.Select("bar")
	if err != nil {
		t.Errorf("Unexpected error calling ls select: %v", err)
	}

	for i := 0; i < 100; i++ {
		node, err := next()
		if err != nil {
			t.Errorf("Expected node err, got err: %v", err)
		}
		counts[node.Id]++
	}

	t.Logf("Label Select Counts %v", counts)
}
Example #3
0
func (s *server) proxy() http.Handler {
	sel := selector.NewSelector(
		selector.Registry((*cmd.DefaultOptions().Registry)),
	)

	director := func(r *http.Request) {
		parts := strings.Split(r.URL.Path, "/")
		if len(parts) < 2 {
			return
		}
		if !re.MatchString(parts[1]) {
			return
		}
		next, err := sel.Select(Namespace + "." + parts[1])
		if err != nil {
			return
		}
		r.URL.Scheme = "http"
		s, err := next()
		if err != nil {
			return
		}
		r.URL.Host = fmt.Sprintf("%s:%d", s.Address, s.Port)
		r.URL.Path = "/" + strings.Join(parts[2:], "/")
	}
	return &httputil.ReverseProxy{
		Director: director,
	}
}
Example #4
0
File: proxy.go Project: Zerak/micro
// Proxy is a reverse proxy used by the micro web and api
func Proxy(ns string, ws bool) http.Handler {
	return &proxy{
		Namespace: ns,
		Selector: selector.NewSelector(
			selector.Registry((*cmd.DefaultOptions().Registry)),
		),
		re: regexp.MustCompile("^[a-zA-Z0-9]+$"),
		ws: ws,
	}
}
Example #5
0
// Registry sets the registry for the service
// and the underlying components
func Registry(r registry.Registry) Option {
	return func(o *Options) {
		o.Registry = r
		// Update Client and Server
		o.Client.Init(client.Registry(r))
		o.Server.Init(server.Registry(r))
		// Update Selector
		o.Client.Options().Selector.Init(selector.Registry(r))
	}
}
Example #6
0
func TestGRPCClient(t *testing.T) {
	l, err := net.Listen("tcp", ":0")
	if err != nil {
		t.Fatalf("failed to listen: %v", err)
	}
	defer l.Close()

	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &greeterServer{})

	go s.Serve(l)
	defer s.Stop()

	parts := strings.Split(l.Addr().String(), ":")
	port, _ := strconv.Atoi(parts[len(parts)-1])
	addr := strings.Join(parts[:len(parts)-1], ":")

	r := mock.NewRegistry()
	r.Register(&registry.Service{
		Name:    "test",
		Version: "test",
		Nodes: []*registry.Node{
			&registry.Node{
				Id:      "test-1",
				Address: addr,
				Port:    port,
			},
		},
	})

	se := selector.NewSelector(
		selector.Registry(r),
	)

	c := NewClient(
		client.Registry(r),
		client.Selector(se),
	)

	req := c.NewRequest("test", "/helloworld.Greeter/SayHello", &pb.HelloRequest{
		Name: "John",
	})

	rsp := pb.HelloReply{}

	err = c.Call(context.TODO(), req, &rsp)
	if err != nil {
		t.Fatal(err)
	}

	if rsp.Message != "Hello John" {
		t.Fatalf("Got unexpected response %v", rsp.Message)
	}
}
Example #7
0
func newClient(opts ...client.Option) client.Client {
	options := client.Options{
		CallOptions: client.CallOptions{
			Backoff:        client.DefaultBackoff,
			Retry:          client.DefaultRetry,
			Retries:        client.DefaultRetries,
			RequestTimeout: client.DefaultRequestTimeout,
			DialTimeout:    transport.DefaultDialTimeout,
		},
	}

	for _, o := range opts {
		o(&options)
	}

	if len(options.ContentType) == 0 {
		options.ContentType = "application/grpc+proto"
	}

	if options.Broker == nil {
		options.Broker = broker.DefaultBroker
	}

	if options.Registry == nil {
		options.Registry = registry.DefaultRegistry
	}

	if options.Selector == nil {
		options.Selector = selector.NewSelector(
			selector.Registry(options.Registry),
		)
	}

	rc := &grpcClient{
		once: sync.Once{},
		opts: options,
	}

	c := client.Client(rc)

	// wrap in reverse
	for i := len(options.Wrappers); i > 0; i-- {
		c = options.Wrappers[i-1](c)
	}

	return c
}
Example #8
0
File: web.go Project: Zerak/micro
func (s *srv) proxy() http.Handler {
	sel := selector.NewSelector(
		selector.Registry((*cmd.DefaultOptions().Registry)),
	)

	director := func(r *http.Request) {
		kill := func() {
			r.URL.Host = ""
			r.URL.Path = ""
			r.URL.Scheme = ""
			r.Host = ""
			r.RequestURI = ""
		}

		parts := strings.Split(r.URL.Path, "/")
		if len(parts) < 2 {
			kill()
			return
		}
		if !re.MatchString(parts[1]) {
			kill()
			return
		}
		next, err := sel.Select(Namespace + "." + parts[1])
		if err != nil {
			kill()
			return
		}

		s, err := next()
		if err != nil {
			kill()
			return
		}

		r.Header.Set(BasePathHeader, "/"+parts[1])
		r.URL.Host = fmt.Sprintf("%s:%d", s.Address, s.Port)
		r.URL.Path = "/" + strings.Join(parts[2:], "/")
		r.URL.Scheme = "http"
		r.Host = r.URL.Host
	}

	return &proxy{
		Default:  &httputil.ReverseProxy{Director: director},
		Director: director,
	}
}
Example #9
0
func TestDefaultSelector(t *testing.T) {
	counts := map[string]int{}

	rs := newSelector(selector.Registry(mock.NewRegistry()))

	next, err := rs.Select("foo")
	if err != nil {
		t.Errorf("Unexpected error calling default select: %v", err)
	}

	for i := 0; i < 100; i++ {
		node, err := next()
		if err != nil {
			t.Errorf("Expected node err, got err: %v", err)
		}
		counts[node.Id]++
	}

	t.Logf("Default Counts %v", counts)
}
Example #10
0
func TestCacheSelector(t *testing.T) {
	counts := map[string]int{}

	cache := NewSelector(selector.Registry(mock.NewRegistry()))

	next, err := cache.Select("foo")
	if err != nil {
		t.Errorf("Unexpected error calling cache select: %v", err)
	}

	for i := 0; i < 100; i++ {
		node, err := next()
		if err != nil {
			t.Errorf("Expected node err, got err: %v", err)
		}
		counts[node.Id]++
	}

	t.Logf("Cache Counts %v", counts)
}
Example #11
0
func newOptions(options ...Option) Options {
	opts := Options{
		Codecs: make(map[string]codec.NewCodec),
		CallOptions: CallOptions{
			Backoff:        DefaultBackoff,
			Retries:        DefaultRetries,
			RequestTimeout: DefaultRequestTimeout,
			DialTimeout:    transport.DefaultDialTimeout,
		},
		PoolSize: DefaultPoolSize,
		PoolTTL:  DefaultPoolTTL,
	}

	for _, o := range options {
		o(&opts)
	}

	if len(opts.ContentType) == 0 {
		opts.ContentType = defaultContentType
	}

	if opts.Broker == nil {
		opts.Broker = broker.DefaultBroker
	}

	if opts.Registry == nil {
		opts.Registry = registry.DefaultRegistry
	}

	if opts.Selector == nil {
		opts.Selector = selector.NewSelector(
			selector.Registry(opts.Registry),
		)
	}

	if opts.Transport == nil {
		opts.Transport = transport.DefaultTransport
	}

	return opts
}
Example #12
0
func (c *cmd) Before(ctx *cli.Context) error {
	// Due to logger issues with glog, we need to do this
	os.Args = os.Args[:1]
	flag.Set("logtostderr", fmt.Sprintf("%v", ctx.Bool("logtostderr")))
	flag.Set("alsologtostderr", fmt.Sprintf("%v", ctx.Bool("alsologtostderr")))
	flag.Set("stderrthreshold", ctx.String("stderrthreshold"))
	flag.Set("log_backtrace_at", ctx.String("log_backtrace_at"))
	flag.Set("log_dir", ctx.String("log_dir"))
	flag.Set("vmodule", ctx.String("vmodule"))
	flag.Set("v", ctx.String("v"))
	flag.Parse()

	// If flags are set then use them otherwise do nothing
	var serverOpts []server.Option
	var clientOpts []client.Option

	// Set the broker
	if len(ctx.String("broker")) > 0 {
		if b, ok := c.opts.Brokers[ctx.String("broker")]; ok {
			n := b(strings.Split(ctx.String("broker_address"), ","))
			*c.opts.Broker = n
		} else {
			return fmt.Errorf("Broker %s not found", ctx.String("broker"))
		}

		serverOpts = append(serverOpts, server.Broker(*c.opts.Broker))
		clientOpts = append(clientOpts, client.Broker(*c.opts.Broker))

	}

	// Set the registry
	if len(ctx.String("registry")) > 0 {
		if r, ok := c.opts.Registries[ctx.String("registry")]; ok {
			n := r(strings.Split(ctx.String("registry_address"), ","))
			*c.opts.Registry = n
		} else {
			return fmt.Errorf("Registry %s not found", ctx.String("registry"))
		}

		serverOpts = append(serverOpts, server.Registry(*c.opts.Registry))
		clientOpts = append(clientOpts, client.Registry(*c.opts.Registry))

		(*c.opts.Selector).Init(selector.Registry(*c.opts.Registry))
		clientOpts = append(clientOpts, client.Selector(*c.opts.Selector))

		(*c.opts.Broker).Init(broker.Registry(*c.opts.Registry))
	}

	// Set the selector
	if len(ctx.String("selector")) > 0 {
		if s, ok := c.opts.Selectors[ctx.String("selector")]; ok {
			n := s(selector.Registry(*c.opts.Registry))
			*c.opts.Selector = n
		} else {
			return fmt.Errorf("Selector %s not found", ctx.String("selector"))
		}

		// No server option here. Should there be?
		clientOpts = append(clientOpts, client.Selector(*c.opts.Selector))
	}

	// Set the transport
	if len(ctx.String("transport")) > 0 {
		if t, ok := c.opts.Transports[ctx.String("transport")]; ok {
			n := t(strings.Split(ctx.String("transport_address"), ","))
			*c.opts.Transport = n
		} else {
			return fmt.Errorf("Transport %s not found", ctx.String("transport"))
		}

		serverOpts = append(serverOpts, server.Transport(*c.opts.Transport))
		clientOpts = append(clientOpts, client.Transport(*c.opts.Transport))
	}

	// Parse the server options
	metadata := make(map[string]string)
	for _, d := range ctx.StringSlice("server_metadata") {
		var key, val string
		parts := strings.Split(d, "=")
		key = parts[0]
		if len(parts) > 1 {
			val = strings.Join(parts[1:], "=")
		}
		metadata[key] = val
	}

	if len(metadata) > 0 {
		serverOpts = append(serverOpts, server.Metadata(metadata))
	}

	if len(ctx.String("server_name")) > 0 {
		serverOpts = append(serverOpts, server.Name(ctx.String("server_name")))
	}

	if len(ctx.String("server_version")) > 0 {
		serverOpts = append(serverOpts, server.Version(ctx.String("server_version")))
	}

	if len(ctx.String("server_id")) > 0 {
		serverOpts = append(serverOpts, server.Id(ctx.String("server_id")))
	}

	if len(ctx.String("server_address")) > 0 {
		serverOpts = append(serverOpts, server.Address(ctx.String("server_address")))
	}

	if len(ctx.String("server_advertise")) > 0 {
		serverOpts = append(serverOpts, server.Advertise(ctx.String("server_advertise")))
	}

	// We have some command line opts for the server.
	// Lets set it up
	if len(serverOpts) > 0 {
		(*c.opts.Server).Init(serverOpts...)
	}

	// Use an init option?
	if len(clientOpts) > 0 {
		(*c.opts.Client).Init(clientOpts...)
	}

	return nil
}
Example #13
0
func TestWatcher(t *testing.T) {
	r := setupRegistry()
	c := cache.NewSelector(selector.Registry(r))

	// wait for watcher to get setup
	time.Sleep(time.Millisecond)

	// check that service is blank
	if _, err := c.Select("foo.service"); err != registry.ErrNotFound {
		log.Fatal("expected registry.ErrNotFound")
	}

	// setup svc
	svc1 := &registry.Service{Name: "foo.service", Version: "1"}
	register(r, "pod-1", svc1)
	time.Sleep(time.Millisecond)

	var wg sync.WaitGroup
	wg.Add(3)

	c.Select("foo.service", selector.WithFilter(func(svcs []*registry.Service) []*registry.Service {
		defer wg.Done()
		if !hasServices(svcs, []*registry.Service{svc1}) {
			t.Fatal("expected services to match")
		}
		return nil
	}))

	// setup svc
	svc2 := &registry.Service{Name: "foo.service", Version: "1"}
	register(r, "pod-2", svc2)
	time.Sleep(time.Millisecond)

	c.Select("foo.service", selector.WithFilter(func(svcs []*registry.Service) []*registry.Service {
		defer wg.Done()
		if !hasNodes(svcs[0].Nodes, []*registry.Node{svc1.Nodes[0], svc2.Nodes[0]}) {
			t.Fatal("expected to have same nodes")
		}
		return nil
	}))

	// deregister
	os.Setenv("HOSTNAME", "pod-1")
	r.Deregister(svc1)
	time.Sleep(time.Millisecond)

	c.Select("foo.service", selector.WithFilter(func(svcs []*registry.Service) []*registry.Service {

		defer wg.Done()
		if !hasServices(svcs, []*registry.Service{svc2}) {
			t.Fatal("expected services to match")
		}
		return nil
	}))

	// remove pods
	teardownRegistry()
	time.Sleep(time.Millisecond)

	if _, err := c.Select("foo.service"); err != registry.ErrNotFound {
		log.Fatal("expected registry.ErrNotFound")
	}

	out := make(chan bool)
	go func() {
		wg.Wait()
		close(out)
	}()

	select {
	case <-out:
		return
	case <-time.After(time.Second):
		t.Fatal("expected c.Select() to be called 3 times")
	}

}
Example #14
0
func TestBlackList(t *testing.T) {
	return

	r := mock.NewRegistry()

	r.Register(&registry.Service{
		Name: "test",
		Nodes: []*registry.Node{
			&registry.Node{
				Id:      "test-1",
				Address: "localhost",
				Port:    10001,
			},
			&registry.Node{
				Id:      "test-2",
				Address: "localhost",
				Port:    10002,
			},
			&registry.Node{
				Id:      "test-3",
				Address: "localhost",
				Port:    10002,
			},
		},
	})

	rs := newSelector(selector.Registry(r))

	next, err := rs.Select("test")
	if err != nil {
		t.Fatal(err)
	}

	node, err := next()
	if err != nil {
		t.Fatal(err)
	}

	for i := 0; i < 4; i++ {
		rs.Mark("test", node, errors.New("error"))
	}

	next, err = rs.Select("test")
	if err != nil {
		t.Fatal(err)
	}

	// still expecting 2 nodes
	seen := make(map[string]bool)

	for i := 0; i < 10; i++ {
		node, err = next()
		if err != nil {
			t.Fatal(err)
		}
		seen[node.Id] = true
	}

	if len(seen) != 2 {
		t.Fatalf("Expected seen to be 2 %+v", seen)
	}

	// blacklist all of it
	for i := 0; i < 20; i++ {
		node, err = next()
		if err != nil {
			t.Fatal(err)
		}
		rs.Mark("test", node, errors.New("error"))
	}

	next, err = rs.Select("test")
	if err != selector.ErrNoneAvailable {
		t.Fatalf("Expected %v got %v", selector.ErrNoneAvailable, err)
	}

}
Example #15
0
func (c *cmd) Before(ctx *cli.Context) error {
	// If flags are set then use them otherwise do nothing
	var serverOpts []server.Option
	var clientOpts []client.Option

	// Set the broker
	if name := ctx.String("broker"); len(name) > 0 || len(ctx.String("broker_address")) > 0 {
		if len(name) == 0 {
			name = defaultBroker
		}

		if b, ok := c.opts.Brokers[name]; ok {
			n := b(broker.Addrs(strings.Split(ctx.String("broker_address"), ",")...))
			*c.opts.Broker = n
		} else {
			return fmt.Errorf("Broker %s not found", name)
		}

		serverOpts = append(serverOpts, server.Broker(*c.opts.Broker))
		clientOpts = append(clientOpts, client.Broker(*c.opts.Broker))

	}

	// Set the registry
	if name := ctx.String("registry"); len(name) > 0 || len(ctx.String("registry_address")) > 0 {
		if len(name) == 0 {
			name = defaultRegistry
		}

		if r, ok := c.opts.Registries[name]; ok {
			n := r(registry.Addrs(strings.Split(ctx.String("registry_address"), ",")...))
			*c.opts.Registry = n
		} else {
			return fmt.Errorf("Registry %s not found", name)
		}

		serverOpts = append(serverOpts, server.Registry(*c.opts.Registry))
		clientOpts = append(clientOpts, client.Registry(*c.opts.Registry))

		(*c.opts.Selector).Init(selector.Registry(*c.opts.Registry))
		clientOpts = append(clientOpts, client.Selector(*c.opts.Selector))

		(*c.opts.Broker).Init(broker.Registry(*c.opts.Registry))
	}

	// Set the selector
	if name := ctx.String("selector"); len(name) > 0 {
		if s, ok := c.opts.Selectors[name]; ok {
			n := s(selector.Registry(*c.opts.Registry))
			*c.opts.Selector = n
		} else {
			return fmt.Errorf("Selector %s not found", name)
		}

		// No server option here. Should there be?
		clientOpts = append(clientOpts, client.Selector(*c.opts.Selector))
	}

	// Set the transport
	if name := ctx.String("transport"); len(name) > 0 || len(ctx.String("transport_address")) > 0 {
		if len(name) == 0 {
			name = defaultTransport
		}

		if t, ok := c.opts.Transports[name]; ok {
			n := t(transport.Addrs(strings.Split(ctx.String("transport_address"), ",")...))
			*c.opts.Transport = n
		} else {
			return fmt.Errorf("Transport %s not found", name)
		}

		serverOpts = append(serverOpts, server.Transport(*c.opts.Transport))
		clientOpts = append(clientOpts, client.Transport(*c.opts.Transport))
	}

	// Parse the server options
	metadata := make(map[string]string)
	for _, d := range ctx.StringSlice("server_metadata") {
		var key, val string
		parts := strings.Split(d, "=")
		key = parts[0]
		if len(parts) > 1 {
			val = strings.Join(parts[1:], "=")
		}
		metadata[key] = val
	}

	if len(metadata) > 0 {
		serverOpts = append(serverOpts, server.Metadata(metadata))
	}

	if len(ctx.String("server_name")) > 0 {
		serverOpts = append(serverOpts, server.Name(ctx.String("server_name")))
	}

	if len(ctx.String("server_version")) > 0 {
		serverOpts = append(serverOpts, server.Version(ctx.String("server_version")))
	}

	if len(ctx.String("server_id")) > 0 {
		serverOpts = append(serverOpts, server.Id(ctx.String("server_id")))
	}

	if len(ctx.String("server_address")) > 0 {
		serverOpts = append(serverOpts, server.Address(ctx.String("server_address")))
	}

	if len(ctx.String("server_advertise")) > 0 {
		serverOpts = append(serverOpts, server.Advertise(ctx.String("server_advertise")))
	}

	// client opts
	if r := ctx.Int("client_retries"); r > 0 {
		clientOpts = append(clientOpts, client.Retries(r))
	}

	if t := ctx.String("client_request_timeout"); len(t) > 0 {
		d, err := time.ParseDuration(t)
		if err != nil {
			return fmt.Errorf("failed to parse client_request_timeout: %v", t)
		}
		clientOpts = append(clientOpts, client.RequestTimeout(d))
	}

	if r := ctx.Int("client_pool_size"); r > 0 {
		clientOpts = append(clientOpts, client.PoolSize(r))
	}

	if t := ctx.String("client_pool_ttl"); len(t) > 0 {
		d, err := time.ParseDuration(t)
		if err != nil {
			return fmt.Errorf("failed to parse client_pool_ttl: %v", t)
		}
		clientOpts = append(clientOpts, client.PoolTTL(d))
	}

	// We have some command line opts for the server.
	// Lets set it up
	if len(serverOpts) > 0 {
		(*c.opts.Server).Init(serverOpts...)
	}

	// Use an init option?
	if len(clientOpts) > 0 {
		(*c.opts.Client).Init(clientOpts...)
	}

	return nil
}
Example #16
0
func TestRPCHandler(t *testing.T) {
	r := rmock.NewRegistry()

	(*cmd.DefaultOptions().Client).Init(
		client.Registry(r),
		client.Selector(selector.NewSelector(selector.Registry(r))),
	)

	(*cmd.DefaultOptions().Server).Init(
		server.Name("test"),
		server.Registry(r),
	)

	(*cmd.DefaultOptions().Server).Handle(
		(*cmd.DefaultOptions().Server).NewHandler(&TestHandler{t, metadata.Metadata{"Foo": "Bar"}}),
	)

	if err := server.Start(); err != nil {
		t.Fatal(err)
	}

	if err := server.Register(); err != nil {
		t.Fatal(err)
	}

	w := httptest.NewRecorder()

	request := map[string]string{
		"service": "test",
		"method":  "TestHandler.Exec",
		"request": "{}",
	}

	rb, err := json.Marshal(request)
	if err != nil {
		t.Fatal(err)
	}

	b := bytes.NewBuffer(rb)

	req, err := http.NewRequest("POST", "/rpc", b)
	if err != nil {
		t.Fatal(err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Foo", "Bar")

	RPC(w, req)

	if err := server.Deregister(); err != nil {
		t.Fatal(err)
	}

	if err := server.Stop(); err != nil {
		t.Fatal(err)
	}

	if w.Code != 200 {
		t.Fatalf("Expected 200 response got %d %s", w.Code, w.Body.String())
	}

}