2016-06-20 03:54:06 +02:00
# Go Micro [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![GoDoc](https://godoc.org/github.com/micro/go-micro?status.svg)](https://godoc.org/github.com/micro/go-micro) [![Travis CI](https://api.travis-ci.org/micro/go-micro.svg?branch=master)](https://travis-ci.org/micro/go-micro) [![Go Report Card](https://goreportcard.com/badge/micro/go-micro)](https://goreportcard.com/report/github.com/micro/go-micro)
2015-01-14 01:31:27 +02:00
2017-11-30 11:16:54 +02:00
Go Micro is a pluggable RPC framework for distributed systems development.
2015-11-29 22:46:31 +02:00
2016-06-20 03:52:38 +02:00
The **Micro** philosophy is sane defaults with a pluggable architecture. We provide defaults to get you started quickly but everything can be easily swapped out. It comes with built in support for {json,proto}-rpc encoding, consul or multicast dns for service discovery, http for communication and random hashed client side load balancing.
Everything in go-micro is **pluggable** . You can find and contribute to plugins at [github.com/micro/go-plugins ](https://github.com/micro/go-plugins ).
2015-01-14 10:38:39 +02:00
2017-07-16 15:58:31 +02:00
Follow us on [Twitter ](https://twitter.com/microhq ) or join the [Slack ](http://slack.micro.mu/ ) community.
2016-12-25 22:53:08 +02:00
2016-12-07 18:54:19 +02:00
## Features
2016-07-03 03:49:13 +02:00
2017-06-15 20:57:27 +02:00
Go Micro abstracts away the details of distributed systems. Here are the main features.
2016-07-03 03:49:13 +02:00
2018-01-30 18:18:11 +02:00
- **Service Discovery** - Automatic service registration and name resolution
- **Load Balancing** - Client side load balancing built on discovery
- **Sync Comms** - RPC based communication with support for bidirectional streaming
- **Async Comms** - Native PubSub messaging built in for event driven architectures
2017-10-03 12:14:39 +02:00
- **Message Encoding** - Dynamic encoding based on content-type with protobuf and json out of the box
2018-01-30 18:18:11 +02:00
- **Service Interface** - All features are wrapped up in a simple high level interface
2016-07-03 03:49:13 +02:00
2017-06-01 13:26:57 +02:00
Go Micro supports both the Service and Function programming models. Read on to learn more.
2017-02-10 14:36:42 +02:00
## Docs
For more detailed information on the architecture, installation and use of go-micro checkout the [docs ](https://micro.mu/docs ).
2016-07-03 03:49:13 +02:00
## Learn By Example
2017-10-03 12:03:46 +02:00
An example service can be found in [**examples/service** ](https://github.com/micro/examples/tree/master/service ) and function in [**examples/function** ](https://github.com/micro/examples/tree/master/function ).
2015-01-14 10:38:39 +02:00
2017-10-03 12:03:46 +02:00
The [**examples** ](https://github.com/micro/examples ) directory contains examples for using things such as middleware/wrappers, selector filters, pub/sub, grpc, plugins and much more. For the complete greeter example look at [**examples/greeter** ](https://github.com/micro/examples/tree/master/greeter ). Other examples can be found throughout the GitHub repository.
Watch the [Golang UK Conf 2016 ](https://www.youtube.com/watch?v=xspaDovwk34 ) video for a high level overview.
2016-04-13 12:30:17 +02:00
2017-10-26 13:16:17 +02:00
## Getting started
2015-01-14 12:50:43 +02:00
2018-02-28 17:38:50 +02:00
- [Install Protobuf ](#install-protobuf )
2017-10-26 13:16:17 +02:00
- [Service Discovery ](#service-discovery )
- [Writing a Service ](#writing-a-service )
- [Writing a Function ](#writing-a-function )
- [Plugins ](#plugins )
- [Wrappers ](#wrappers )
2016-02-06 15:32:01 +02:00
2018-02-28 17:38:50 +02:00
## Install Protobuf
Protobuf is required for code generation
You'll need to install:
- [protoc ](https://github.com/google/protobuf )
- [protoc-gen-go ](https://github.com/golang/protobuf )
- [protoc-gen-micro ](https://github.com/micro/protoc-gen-micro )
2017-10-26 13:16:17 +02:00
## Service Discovery
2017-10-03 12:03:46 +02:00
2018-02-28 17:40:41 +02:00
Service discovery is used to resolve service names to addresses.
2016-11-19 16:31:07 +02:00
2017-01-22 16:12:53 +02:00
### Consul
2016-11-19 16:31:07 +02:00
2017-10-26 13:19:42 +02:00
[Consul ](https://www.consul.io/ ) is used as the default service discovery system.
2016-11-19 16:31:07 +02:00
2017-10-26 13:19:42 +02:00
Discovery is pluggable. Find plugins for etcd, kubernetes, zookeeper and more in the [micro/go-plugins ](https://github.com/micro/go-plugins ) repo.
2016-11-19 16:31:07 +02:00
2017-10-26 13:19:42 +02:00
[Install guide ](https://www.consul.io/intro/getting-started/install.html )
2017-01-22 16:12:53 +02:00
2017-10-26 13:16:17 +02:00
### Multicast DNS
2017-10-03 12:03:46 +02:00
2017-10-26 13:16:17 +02:00
[Multicast DNS ](https://en.wikipedia.org/wiki/Multicast_DNS ) is a built in service discovery plugin for a zero dependency configuration.
2015-01-14 10:38:39 +02:00
2018-02-01 15:54:37 +02:00
Pass `--registry=mdns` to any command or the enviroment variable `MICRO_REGISTRY=mdns`
2017-10-03 12:03:46 +02:00
```
2018-02-28 17:40:41 +02:00
MICRO_REGISTRY=mdns go run main.go
2015-01-14 10:38:39 +02:00
```
2015-01-14 12:50:43 +02:00
## Writing a service
2017-10-03 12:03:46 +02:00
This is a simple greeter RPC service example
Find this example at [examples/service ](https://github.com/micro/examples/tree/master/service ).
2016-12-07 18:54:19 +02:00
### Create service proto
2016-03-12 01:58:55 +02:00
2017-10-03 12:03:46 +02:00
One of the key requirements of microservices is strongly defined interfaces. Micro uses protobuf to achieve this.
2016-03-12 01:58:55 +02:00
2017-10-03 12:03:46 +02:00
Here we define the Greeter handler with the method Hello. It takes a HelloRequest and HelloResponse both with one string arguments.
2015-01-14 12:50:43 +02:00
2016-01-04 01:36:14 +02:00
```proto
2015-05-25 19:16:42 +02:00
syntax = "proto3";
2015-01-14 12:50:43 +02:00
2016-01-02 02:38:57 +02:00
service Greeter {
rpc Hello(HelloRequest) returns (HelloResponse) {}
2015-01-14 12:50:43 +02:00
}
2016-01-02 02:38:57 +02:00
message HelloRequest {
string name = 1;
2015-01-14 12:50:43 +02:00
}
2016-01-02 02:38:57 +02:00
message HelloResponse {
string greeting = 2;
}
```
2017-10-03 12:03:46 +02:00
### Generate the proto
2016-03-12 02:04:33 +02:00
2017-10-03 12:03:46 +02:00
After writing the proto definition we must compile it using protoc with the micro plugin.
2016-03-12 02:04:33 +02:00
2016-11-20 17:02:05 +02:00
```shell
2018-02-28 17:38:50 +02:00
protoc --proto_path=$GOPATH/src:. --micro_out=. --go_out=. path/to/greeter.proto
2016-03-12 02:04:33 +02:00
```
2015-01-14 12:50:43 +02:00
2017-10-03 12:03:46 +02:00
### Write the service
Below is the code for the greeter service.
2016-03-12 02:04:33 +02:00
2017-10-03 12:03:46 +02:00
It does the following:
2016-03-12 02:04:33 +02:00
2017-10-03 12:03:46 +02:00
1. Implements the interface defined for the Greeter handler
2. Initialises a micro.Service
3. Registers the Greeter handler
4. Runs the service
2015-01-14 12:50:43 +02:00
2015-02-02 20:53:16 +02:00
```go
2016-01-02 02:38:57 +02:00
package main
2015-01-14 12:50:43 +02:00
import (
2018-03-03 13:53:52 +02:00
"context"
2016-01-02 02:38:57 +02:00
"fmt"
2015-01-14 12:50:43 +02:00
2016-01-02 02:38:57 +02:00
micro "github.com/micro/go-micro"
2017-01-05 17:09:27 +02:00
proto "github.com/micro/examples/service/proto"
2015-01-14 12:50:43 +02:00
)
2016-01-02 02:38:57 +02:00
type Greeter struct{}
2015-01-14 12:50:43 +02:00
2016-01-02 02:38:57 +02:00
func (g *Greeter) Hello(ctx context.Context, req *proto.HelloRequest, rsp *proto.HelloResponse) error {
rsp.Greeting = "Hello " + req.Name
2015-11-08 13:12:09 +02:00
return nil
2015-01-14 12:50:43 +02:00
}
2016-01-02 02:38:57 +02:00
func main() {
// Create a new service. Optionally include some options here.
service := micro.NewService(
micro.Name("greeter"),
)
2017-07-14 09:24:46 +02:00
// Init will parse the command line flags.
2016-01-02 02:38:57 +02:00
service.Init()
// Register handler
proto.RegisterGreeterHandler(service.Server(), new(Greeter))
// Run the server
if err := service.Run(); err != nil {
fmt.Println(err)
}
}
2015-01-14 12:50:43 +02:00
```
2016-01-02 02:38:57 +02:00
### Run service
```
2016-03-14 13:01:10 +02:00
go run examples/service/main.go
2017-10-03 12:03:46 +02:00
```
Output
```
2016-03-14 13:01:10 +02:00
2016/03/14 10:59:14 Listening on [::]:50137
2016/03/14 10:59:14 Broker Listening on [::]:50138
2016/03/14 10:59:14 Registering node: greeter-ca62b017-e9d3-11e5-9bbb-68a86d0d36b6
2016-01-02 02:38:57 +02:00
```
### Define a client
2017-10-03 12:03:46 +02:00
Below is the client code to query the greeter service.
2016-03-12 02:04:33 +02:00
2017-10-03 12:03:46 +02:00
The generated proto includes a greeter client to reduce boilerplate code.
2015-01-14 12:50:43 +02:00
2015-02-02 20:53:16 +02:00
```go
2015-01-14 12:50:43 +02:00
package main
import (
2018-03-03 13:53:52 +02:00
"context"
2016-01-02 02:38:57 +02:00
"fmt"
micro "github.com/micro/go-micro"
2017-01-05 17:09:27 +02:00
proto "github.com/micro/examples/service/proto"
2015-01-14 12:50:43 +02:00
)
2015-05-25 19:16:42 +02:00
2016-01-02 02:38:57 +02:00
func main() {
// Create a new service. Optionally include some options here.
service := micro.NewService(micro.Name("greeter.client"))
2018-02-28 17:38:50 +02:00
service.Init()
2015-01-14 12:50:43 +02:00
2016-01-02 02:38:57 +02:00
// Create new greeter client
greeter := proto.NewGreeterClient("greeter", service.Client())
2015-01-14 12:50:43 +02:00
2016-01-02 02:38:57 +02:00
// Call the greeter
rsp, err := greeter.Hello(context.TODO(), & proto.HelloRequest{Name: "John"})
if err != nil {
fmt.Println(err)
2015-01-14 12:50:43 +02:00
}
2016-01-02 02:38:57 +02:00
// Print response
fmt.Println(rsp.Greeting)
2015-01-14 12:50:43 +02:00
}
```
2016-01-02 02:38:57 +02:00
### Run the client
```shell
go run client.go
2017-10-03 12:03:46 +02:00
```
Output
```
2016-01-02 02:38:57 +02:00
Hello John
2015-01-14 12:50:43 +02:00
```
2016-03-12 02:07:14 +02:00
2017-06-01 13:26:57 +02:00
## Writing a Function
2017-10-03 12:03:46 +02:00
Go Micro includes the Function programming model.
A Function is a one time executing Service which exits after completing a request.
2017-06-01 13:26:57 +02:00
### Defining a Function
```go
package main
import (
2018-03-03 13:53:52 +02:00
"context"
2017-06-01 13:26:57 +02:00
proto "github.com/micro/examples/function/proto"
"github.com/micro/go-micro"
)
type Greeter struct{}
func (g *Greeter) Hello(ctx context.Context, req *proto.HelloRequest, rsp *proto.HelloResponse) error {
rsp.Greeting = "Hello " + req.Name
return nil
}
func main() {
// create a new function
fnc := micro.NewFunction(
2018-03-09 21:11:42 +02:00
micro.Name("greeter"),
2017-06-01 13:26:57 +02:00
)
// init the command line
fnc.Init()
// register a handler
fnc.Handle(new(Greeter))
// run the function
fnc.Run()
}
```
It's that simple.
2016-12-07 18:54:19 +02:00
## Plugins
2016-10-04 18:34:45 +02:00
By default go-micro only provides a few implementation of each interface at the core but it's completely pluggable. There's already dozens of plugins which are available at [github.com/micro/go-plugins ](https://github.com/micro/go-plugins ). Contributions are welcome!
2017-01-04 16:54:31 +02:00
### Build with plugins
If you want to integrate plugins simply link them in a separate file and rebuild
Create a plugins.go file
2017-02-15 17:17:10 +02:00
2017-01-04 16:54:31 +02:00
```go
import (
// etcd v3 registry
_ "github.com/micro/go-plugins/registry/etcdv3"
// nats transport
_ "github.com/micro/go-plugins/transport/nats"
// kafka broker
_ "github.com/micro/go-plugins/broker/kafka"
2017-01-04 18:43:43 +02:00
)
2017-01-04 16:54:31 +02:00
```
Build binary
2017-02-15 17:17:10 +02:00
2017-01-04 16:54:31 +02:00
```shell
// For local use
go build -i -o service ./main.go ./plugins.go
```
Flag usage of plugins
```shell
service --registry=etcdv3 --transport=nats --broker=kafka
```
2018-01-30 18:18:11 +02:00
### Plugin as option
Alternatively you can set the plugin as an option to a service
```go
import (
"github.com/micro/go-micro"
// etcd v3 registry
"github.com/micro/go-plugins/registry/etcdv3"
// nats transport
"github.com/micro/go-plugins/transport/nats"
// kafka broker
"github.com/micro/go-plugins/broker/kafka"
)
func main() {
registry := etcdv3.NewRegistry()
broker := kafka.NewBroker()
transport := nats.NewTransport()
service := micro.NewService(
micro.Name("greeter"),
micro.Registry(registry),
micro.Broker(broker),
micro.Transport(transport),
)
service.Init()
service.Run()
}
```
### Write plugins
Plugins are a concept built on Go's interface. Each package maintains a high level interface abstraction.
Simply implement the interface and pass it in as an option to the service.
The service discovery interface is called [Registry ](https://godoc.org/github.com/micro/go-micro/registry#Registry ).
Anything which implements this interface can be used as a registry. The same applies to the other packages.
```go
type Registry interface {
Register(*Service, ...RegisterOption) error
Deregister(*Service) error
GetService(string) ([]*Service, error)
ListServices() ([]*Service, error)
Watch() (Watcher, error)
String() string
}
```
Browse [go-plugins ](https://github.com/micro/go-plugins ) to get a better idea of implementation details.
2017-10-26 13:02:10 +02:00
## Wrappers
Go-micro includes the notion of middleware as wrappers. The client or handlers can be wrapped using the decorator pattern.
### Handler
Here's an example service handler wrapper which logs the incoming request
2017-10-26 13:02:52 +02:00
```go
2017-10-26 13:02:10 +02:00
// implements the server.HandlerWrapper
func logWrapper(fn server.HandlerFunc) server.HandlerFunc {
return func(ctx context.Context, req server.Request, rsp interface{}) error {
fmt.Printf("[%v] server request: %s", time.Now(), req.Method())
return fn(ctx, req, rsp)
}
}
```
It can be initialised when creating the service
2017-10-26 13:02:52 +02:00
```go
2017-10-26 13:02:10 +02:00
service := micro.NewService(
micro.Name("greeter"),
// wrap the handler
micro.WrapHandler(logWrapper),
)
```
### Client
Here's an example of a client wrapper which logs requests made
2017-10-26 13:02:52 +02:00
```go
2017-10-26 13:02:10 +02:00
type logWrapper struct {
client.Client
}
func (l *logWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
fmt.Printf("[wrapper] client request to service: %s method: %s\n", req.Service(), req.Method())
return l.Client.Call(ctx, req, rsp)
}
// implements client.Wrapper as logWrapper
func logWrap(c client.Client) client.Client {
return & logWrapper{c}
}
```
It can be initialised when creating the service
2017-10-26 13:02:52 +02:00
```go
2017-10-26 13:02:10 +02:00
service := micro.NewService(
micro.Name("greeter"),
// wrap the client
micro.WrapClient(logWrap),
)
```
2017-02-07 20:33:50 +02:00
## Other Languages
2017-02-15 16:31:20 +02:00
Check out [ja-micro ](https://github.com/Sixt/ja-micro ) to write services in Java
2017-02-07 20:33:50 +02:00
2016-04-26 13:18:18 +02:00
## Sponsors
2016-12-25 22:53:08 +02:00
Open source development of Micro is sponsored by Sixt
2016-04-26 13:18:18 +02:00
2017-02-11 16:26:47 +02:00
< a href = "https://micro.mu/blog/2016/04/25/announcing-sixt-sponsorship.html" > < img src = "https://micro.mu/sixt_logo.png" width = 150px height = "auto" / > < / a >