Micro

Micro - a microservices toolkit


By now you may have heard of this new phenomenon, microservices. If you’re not yet familiar and interested in learning more, checkout our introductory post here.

In this blog post we’re going to discuss Micro, an open source microservices toolkit. Micro provides the core requirements for building and managing microservices. It consists of a set of libraries and tools which are primarily geared towards development in the programming language Go, however looks to solve for other languages via HTTP using a Sidecar.

Before we get to the details of Micro, let’s talk about why we decided to dedicate our time to it.

Development or Deployment

It’s clear from our past experiences and what we’re seeing in the industry that there’s a need for a focus on development rather than deployment. PaaS solutions are readily available. Companies like AWS, Google and Microsoft are providing feature rich platforms while also rapidly moving towards supporting container orchestration if not already doing so. All of this gives us access to large scale compute with the click of a few buttons.

This new world sounds great. You might say this solves all your problems, right? Well, while we now have access to massive scale computing power, we’re still lacking the tools that enable us to write software that’s capable of leveraging it. Not only that, in this new world, containers are likely more ephemeral, coming and going as the runtime reschedules them or machines they’re running on fail.

Scaling challenges

The other issue we’ve seen time and time again is the way in which organisations fall victim to their monolithic architectures. With a need to grow at a blistering pace, there’s the tendency to cram features into the existing system and incur technical debt which snowballs into an unmanageable situation. Aside from this, as the organisation attempts to grow the engineering team, it becomes infinitely more difficult for developers to collaborate on a single code base or do feature development in parallel without being blocked at time of release.

There’s an inevitable need to rearchitect and an eventual path to SOA or microservice based architectures. Companies end up taking on an R&D effort in house, learning by trial and error. If only there were tools to help create scalable systems, reduce the likely hood of R&D and provide domain expertise from those with past experience.

Enter Micro

At Micro we’re building a microservice ecosystem that includes tools, services and solutions for microservice development. We’re building the foundation of that ecosystem with a tool by the same name. Micro is a microservice toolkit, which will enable the creation of a scalable architectures and increase speed of execution.

Let’s dig into the features of Micro.

Go Micro

Go Micro is a pluggable RPC framework used to build microservices in Go. It delivers the essential features required to create, discover and communicate with services. The core of any good microservice architecture begins by addressing service discovery, synchronous and asynchronous communication.

Included packages and features:

Where Go Micro differs from most libraries is it’s pluggable architecture. This allows the implementation and backend system for every package to be swapped out. For example; the default service discovery mechanism for the registry is Consul but this can easily be swapped with a plugin for etcd, zookeeper or anything else you choose to implement. Plugins we’re implementing can be found at github.com/micro/go-plugins.

The value in a pluggable system is the ability to choose the platform used to support your microservices without having to rewrite any code. Go Micro requires zero code changes, just a mere import of a plugin and you’re done.

Go Micro is the starting point for writing microservices. The readme provides an overview of how to write, run and query a service. There’s a greeter example here micro/examples/greeter and more example services throughout the repo github.com/micro.

go micro

Sidecar

So Go Micro provides a way to write services in Go but how about other languages? How do we create a polygot ecosystem where anyone can leverage the advantages of Micro? While Micro is written in Go, we wanted to allow a quicky and easy way to integrate applications written in any language.

Enter the Sidecar, a lightweight companion service which is conceptually “attached” to the main (aka Parent) application and complements it by providing the features of the Micro system that are otherwise available using the Go Micro library. The sidecar is a process that runs alongside your application, delivering the features of Go Micro via a HTTP interface.

Features of the sidecar:

Examples of using the Sidecar with ruby or python can be found here micro/examples/greeter. We’ll look to add more sample code in the near future to help with understanding how to integrate the sidecar.

sidecar

API

Making RPC requests from one service to another is pretty straight forward with Go Micro but not ideal for external access. Instances of a service can fail, they may be rescheduled elsewhere or end up binding to any random port. The API provides a single entry point to query microservices and should be used as the gateway for external access.

The API provides a few different types of request handlers.

1. /rpc

Individual services can be queried via RPC using the /rpc endpoint. Example:

curl \
	-d "service=go.micro.srv.greeter" \
	-d "method=Say.Hello" \
	-d "request={\"name\": \"John\"}" \
	http://localhost:8080/rpc

{"msg":"Hello John"}

2. api.Request

The API can be used to breakdown URLs to be served by individual microservices. This is a powerful method of API composition. Here the API uses the first part of the request path along with a namespace component to determine the service to route requests to. HTTP requests are then converted to an api.Request and forwarded appropriately.

At Micro we use a pattern of creating API microservices to serve requests at the edge. Separating the responsibility of backend versus frontend services.

An example of API request handling:

Request

GET /greeter/say/hello?name=John

Becomes

service: go.micro.api.greeter (default namespace go.micro.api is applied)
method: Say.Hello
request {
	"method": "GET",
	"path": "/greeter/say/hello",
	"get": {
		"name": "John"
	}
}

The structure of an api.Request and api.Response:

syntax = "proto3";

message Pair {
	optional string key = 1;
	repeated string values = 2;
}

message Request {
	optional string method = 1;   // GET, POST, etc
	optional string path = 2;     // e.g /greeter/say/hello
	map<string, Pair> header = 3; 
	map<string, Pair> get = 4;    // The URI query params
	map<string, Pair> post = 5;   // The post body params
	optional string body = 6;     // raw request body; if not application/x-www-form-urlencoded
}

message Response {
	optional int32 statusCode = 1;
	map<string, Pair> header = 2;
	optional string body = 3;
}

An example of how to create an API service can be found here. Greeter API

3. proxy

The final method of request handling for the API is a reverse proxy. Just as above, the API uses the request path and a namespace component to determine the service to route requests to. By providing reverse proxying and microservice request routing we’re able to support REST, a widely sought after requirement.

The proxy can be enabling by passing the --api_handler=proxy flag.

An example of how to build a RESTful API can be found here micro/examples/greeter/api.

api

Web UI

The web UI provides a simple dashboard for observing and interacting with a running system. Not only that but it also provides a reverse proxy much like the API. Our goal with a “web proxy” is to enable the development of web apps as microservices. Again, just like the API, the request path is used along with a namespace to determine the service to route requests to. The web proxy also supports web sockets as we see realtime being a core part of delivering web apps.

web

CLI

The CLI is a command line tool which provides a way to observe, interact and manage services in a running environment. The current feature set allows you to inspect the registry, check basic health of services and execute queries against services themselves.

The other nifty feature, is the ability to use the Sidecar as a proxy for the CLI. It’s as simple as specifying the address for the sidecar as a flag --proxy_address=example.proxy.com when executing the CLI.

cli

Putting it all together

We’ve written an example of full end-to-end flow through the system using a simple greeter service.

The flow is as follows:

  1. HTTP GET request is made to the micro API at path /greeter/say/hello with the query name=John.
  2. The API translates this using the default namespace to the api service go.micro.api.greeter and method Say.Hello. The request is structured as an api.Request.
  3. The API using Go Micro, queries the registry to find all the nodes for the service go.micro.api.greeter and forwards the request to one of the nodes.
  4. The greeter api parses the request, generates a hello.Request and makes a request to the rpc service go.micro.srv.greeter. Again the same registry/discovery mechanism is used to find the nodes for the service.
  5. The greeter rpc service responds with a hello.Response.
  6. The greeter api translates the response into a api.Response and passes it back to the API.
  7. The micro API parses the response and responds to the client’s HTTP request.

In a more complex example, an API service may call out to many other RPC services, aggregate and transform the data and then pass back a final summarised result to the client. This allows you to maintain a consistent external entry point and change services in the background without the knowledge of the client.

greeter service

Demo

If you want to kick the tyres on a running system, checkout our demo at web.micro.pm.

We’re running Micro On Kubernetes using Google Container Engine. The demo is open source if you want to run it yourself. You can find the k8s config here github.com/micro/kubernetes.

Summary

Micro provides the fundamental building blocks for writing and managing microservices. Go Micro includes the core requirements; discovery, client/server and pub/sub. The CLI let’s you interact with your environment and services. The sidecar enables integration of any non Micro application. The API is a single entry point for rpc requests and enables the creation of REST endpoints. With pluggable interfaces you can pick and choose the systems you want to leverage in building your architecture.

Our goal at Micro is to enable development at scale, increase speed of execution and provide value starting from the very beginning of the developer lifecycle. We feel Micro is the best way to do all those things. Over time the ecosystem of tools will grow to include more feature rich services for discovery, routing and obversability.

If you want to learn more about the services we offer or microservices, checkout the website micro.mu or the github repo.

Follow us on Twitter at @MicroHQ or join the Slack community here.

Micro