Skip to content

objenious/kitty

Repository files navigation

kitty

Travis-CI GoDoc GoReportCard Coverage Status

go get github.com/objenious/kitty

Kitty is a slightly opinionated framework based on go-kit. It's goal is to ease development of microservices deployed on Kubernetes (or any similar orchestration platform).

Kitty has an opinion on:

  • transports: HTTP only (additional transports can be added as long as they implement kitty.Transport, a Google Pub/Sub transport is available as a separate package),
  • errors: an error may be Retryable (e.g. 5XX status codes) or not (e.g. 4XX status codes),
  • status codes: unless specified, request decoding errors will generate 400 HTTP status codes.

Kitty has no opinion on:

  • logging: no logs are generated by default, you can plug your logger and it will get additional context,
  • packages: kitty only imports go-kit and the standard library,
  • routers: you can use any router (a Gorilla Mux implementation is available in a sub-package, other routers can easily be plugged),
  • encoding: use whatever encoding you want (JSON, messagepack, protobuf, ...),
  • monitoring, metrics and tracing: use Istio, a sidecar process or a middleware.

Kitty includes 2 sub-packages:

  • backoff: Retryable-aware exponential backoff (only Retryable errors trigger retries),
  • circuitbreaker: Retryable-aware circuit breaker (only Retryable errors trigger the circuit breaker).

Example

Server-side

t := kitty.NewHTTPTransport(kitty.Config{HTTPPort: 8081}).
  Router(gorilla.Router()).
  Endpoint("POST", "/foo", Foo, kitty.Decoder(decodeFooRequest)).
  Endpoint("GET", "/bar", Bar)

kitty.NewServer(t).Run(ctx)

// Foo is a go-kit Endpoint
func Foo(ctx context.Context, request interface{}) (interface{}, error) {
  fr := request.(fooRequest)
  return fooResponse{Message: fmt.Sprintf("Good morning %s !", fr.Name)}, nil
}

// decodeFooRequest
func decodeFooRequest(ctx context.Context, r *http.Request) (interface{}, error) {
  var request fooRequest
	if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
		return nil, err
	}
	return request, nil
}

Client-side (with circuit breaker & exponential backoff)

u, err := url.Parse("http://example.com/foo")
e := kitty.NewClient(
  "POST",
  u,
  kithttp.EncodeJSONRequest,
  decodeFooResponse
).Endpoint()
cb := gobreaker.NewCircuitBreaker(gobreaker.Settings{Name: "foo"})
e = kittycircuitbreaker.NewCircuitBreaker(cb)(e)
bo := backoff.NewExponentialBackOff()
e = kittybackoff.NewBackoff(bo)(e)

How-to

Log requests

kitty.NewServer(t).
  // Log as JSON
  Logger(log.NewJSONLogger(log.NewSyncWriter(os.Stdout))).
  // Add path and method to all log lines
  LogContext("http-path", "http-method").
  // Log request only if an error occurred
  Middlewares(kitty.LogEndpoint(kitty.LogErrors))

Integrate with Istio

TBD

Integrate liveness/readiness checks

Using github.com/heptiolabs/healthcheck:

health := healthcheck.NewHandler()
health.AddLivenessCheck("goroutine-threshold", healthcheck.GoroutineCountCheck(100))
health.AddReadinessCheck("database", healthcheck.DatabasePingCheck(db, 1*time.Second))

t := kitty.NewTransport(kitty.Config{}).Liveness(health.LiveEndpoint).Readiness(health.ReadyEndpoint)

Use Google Pub/Sub as a transport

https://github.com/objenious/kitty-gcp adds a Google Pub/Sub transport to kitty:

import "github.com/objenious/kitty-gcp/pubsub"

tr := pubsub.NewTransport(ctx, "project-id").
  Endpoint(subscriptionName, endpoint, Decoder(decodeFunc))
err := kitty.NewServer(tr).Run(ctx)

Requirements

Go > 1.11

Contribution guidelines

Contributions are welcome, as long as :

  • unit tests & comments are included,
  • no external package is added to the top-level package (implementations can be added as sub-packages).

Thanks

kitty is heavily inspired by gizmo/kit (https://godoc.org/github.com/NYTimes/gizmo/server/kit), with a different approach to server setup and without the gRPC clutter.

License

MIT - See LICENSE file

About

A microservice framework extending go-kit

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages