Simplifying Microservices with Micro

Simplifying Microservices with Micro

Presented at the Golang UK Conference on August 19th 2016.


Asim Aslam

August 19, 2016


  1. Simplifying Microservices With Micro

  2. Bio Asim Aslam Mostly build platforms Micro Enjoy all things

    scale Hailo Write lots of cruft Google @chuhnk
  3. What is Micro?

  4. Micro is a lot of things... Framework… toolkit… library… community…

    company… It’s a toolkit! It’s an ecosystem! It’s an overloaded term...sorry! Let’s just talk about the toolkit
  5. A microservice toolkit Building blocks {discovery, encoding, communication, etc} Simplifying

    distributed systems Pluggable framework Sane defaults Low barrier to entry No magic
  6. What are microservices?

  7. Microservices “Loosely coupled service oriented architecture with a bounded context”

  8. “Turning a big ball of cruft into smaller balls of

    cruft which communicate over a network” @chuhnk
  9. Monolith Microservices

  10. Why microservices?

  11. So many reasons 1. The monolith becomes brittle as it

    grows 2. Most large scale systems are naturally distributed 3. Teams are easier to scale with microservices 4. Faster development cycles 5. Independently managed services 6. More enjoyable to write 7. So many more reasons 8. Do you really like monoliths? 9. Insert more reasons here
  12. But to be clear There are tradeoffs Operational overhead Many

    moving parts aka distributed Requires a different set of skills Not the answer for everything! Be pragmatic!
  13. Why a toolkit?

  14. Building distributed systems is still hard.

  15. Distributed Systems Fallacies 1. The network is reliable 2. Latency

    is zero 3. Bandwidth is infinite 4. The network is secure 5. Topology doesn’t change 6. There is one administrator 7. Transport code is zero 8. The network is homogeneous
  16. None
  17. None
  18. None
  19. How do I actually write distributed systems?

  20. The origin of Micro

  21. The Motivation 2014 Nothing really out there Enjoyed the Hailo

    way of building services We had no plans to open source Everyone was building bespoke in-house frameworks Wanted to rally around one OSS effort
  22. Humble Beginnings Started with go-micro A pluggable RPC framework Service

    discovery, encoding, synch/asynch communication Leveraged youtube/vitess/rpcplus Open sourced January 2015
  23. Evolved into a toolkit Lots of plugins for go-micro Multiple

    companies in production Sponsored by Sixt Working full time on Micro Present Day
  24. The Go Landscape

  25. The Past 2014 net/http net/rpc gorilla/rpc kite custom in-house framework

  26. The Present 2016 gizmo net/http go-kit net/rpc gRPC gorilla/rpc micro

    in-house frameworks Plus many more!
  27. Beyond Go Netflix OSS Java Seneca Node.JS Nameko Python Finagle

    JVM Linkerd Agnostic
  28. The Micro Toolkit

  29. The Toolkit Fundamental Building blocks Go-micro (RPC Framework) Sidecar

    (HTTP Proxy) API (HTTP => RPC) Web (UI + Proxy) CLI (Terminal) Bot (Hubot)
  30. go-micro Pluggable RPC framework Strongly defined interfaces Addresses core

    requirements for microservices Sane defaults; consul, http, {json, proto}-rpc Extensible via wrappers/middleware
  31. go-micro features Service discovery Message encoding RPC client/server Request-Response Publish-Subscribe

    Client side load balancing Service Client Server Transport Selector Registry Codec Broker
  32. Pluggable

  33. Interfaces A way to specify the behavior of an object

    If something can do this then it can be used here
  34. Registry Service Discovery type Registry interface { Register(*Service, ...RegisterOption) error

    Deregister(*Service) error GetService(string) ([]*Service, error) ListServices() ([]*Service, error) Watch() (Watcher, error) String() string }
  35. Consul Implement the interface type consulRegistry struct {} func (c

    *consulRegistry) Register(*Service, ...RegisterOption) error {…} func (c *consulRegistry) Deregister(*Service) error {…} func (c *consulRegistry) GetService(string) ([]*Service, error) {…} func (c *consulRegistry) ListServices() ([]*Service, error) {…} func (c *consulRegistry) Watch() (Watcher, error) {…} func (c *consulRegistry) String() string { return "consul" } func NewRegistry(...Option) Registry { return &consulRegistry{} }
  36. Transport Request-Response type Transport interface { Dial(addr string, opts ...DialOption)

    (Client, error) Listen(addr string, opts ...ListenOption) (Listener, error) String() string } type Listener interface { Addr() string Close() error Accept(func(Socket)) error }
  37. Mock Testing type mockTransport struct {} func (m *mockTransport) Dial(string,

    ...DialOption) (Client, error) {…} func (m *mockTransport) Listen(string, ...ListenOption) (Listener, error) {…} func (m *mockTransport) String() string { return "mock" } func NewTransport(opts ...Option) Transport { return &mockTransport{} }
  38. Writing a service

  39. go-micro define API syntax = "proto3"; service Greeter { rpc

    Hello(Request) returns (Response) {} } message Request { string name = 1; } message Response { string greeting = 1; }
  40. go-micro define handler import ( "" "" ) type Greeter

    struct{} func (g *Greeter) Hello(ctx context.Context, req *proto.Request, rsp *proto.Response) error { rsp.Greeting = "Hello " + req.Name return nil }
  41. go-micro create service service := micro.NewService( micro.Name("com.example.srv.greeter"), micro.Version("1.0.0"), ) service.Init()

    proto.RegisterGreeterHandler(service.Server(), new(Greeter)) if err := service.Run(); err != nil { log.Fatal(err) }
  42. go-micro call service greeter := proto.NewGreeterClient("com.example.srv.greeter", service.Client()) rsp, err :=

    greeter.Hello(context.TODO(), &proto.Request{ Name: "John" }) if err != nil { // Blurgh?!? } fmt.Println(rsp.Greeting) // Hello John
  43. Beneath the covers

  44. go-micro service.Run Generate service definition {Name, Version, Address...} Register with

    service discovery Listen and accept requests Decode and handle requests Optionally heartbeat with discovery
  45. go-micro client.Call(“service”) Request encoding Service lookup Node selection Connection pooling

    Retries, timeouts, backoff Oh and making the request
  46. What about rate limiting, circuit breaking, authentication, etc

  47. Wrappers

  48. Decorator Pattern A design pattern allowing behavior to be added

    to an individual object, without affecting the behavior of other objects
  49. Client or Handler Authentication Circuit breaking Rate limiting Logging Event

    notifications Instrumentation Context injection
  50. go-micro wrappers client type Wrapper func(Client) Client server type HandlerWrapper

    func(HandlerFunc) HandlerFunc … service := micro.NewService( micro.Name("com.example.srv.foobar"), micro.WrapClient(circuitBreaker(3)), micro.WrapHandler(rateLimiter(10)), )
  51. Example Terrible Rate Limit Wrapper func rateLimiter(rate int) server.HandlerWrapper {

    tokens := make(chan bool, rate) for i := 0; i < rate; i++ { tokens <- true } return func(handler server.HandlerFunc) server.HandlerFunc { return func(ctx context.Context, req server.Request, rsp interface{}) error { token := <-tokens defer func() { tokens <- token }() return handler(ctx, req, rsp) } } }
  52. Go forth and write Micro services!

  53. Wait... How do I access these things externally?

  54. Entry Points

  55. API > micro api External gateway aka API Gateway API

    service layer HTTP => RPC or Reverse Proxy Path based resolution /[service]/[method] Zero config
  56. API > micro api

  57. Web > micro web Dashboard Proxy Web apps as microservices

    First class citizens
  58. Logical separation of responsibilities

  59. Sidecar > micro sidecar Replicates the features of go-micro as

    a HTTP interface * CLI Proxy for remote environments with --proxy_address flag
  60. CLI > micro get service $ micro get service go.micro.srv.greeter

    service go.micro.srv.greeter version 1.0.0 Id Address Port Metadata go.micro.srv.greeter-e081eb6a-325f-11e6-8303-68a86d0d36b6 62628 server=rpc,registry=consul,transport=http,broker=http Endpoint: Say.Hello Metadata: stream=false Request: { name string } Response: { msg string }
  61. Bot > micro bot CLI features via messaging Supports slack

    and hipchat Pluggable Inputs and Commands Messaging is an entry point much like an API or CLI
  62. Beyond the toolkit

  63. Plugins “Implement the interface” Swap out backends broker/kafka registry/etcd

    transport/nats Plus many more! Contributions welcome!
  64. Platform “A microservice platform” Higher level requirements Authentication Dynamic

    configuration Distributed tracing Metrics Monitoring Structured logging Synchronisation
  65. Community “Share the journey” All things microservices Discuss micro

    Discuss microservices Discuss production use Discuss the tradeoffs
  66. In Closing Micro is a toolkit to help simplify microservices

    Micro is opinionated Micro is not everyone’s cup of tea and that’s ok Micro services are not the answer for everything Pick the tools and patterns that work for you!
  67. Thanks! @microhq