In the previous part I implemented a simple microservice using micro in Go.

micro service

The server part of the code is almost straight out of the micro example code.

const (
	dailyURL    = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"
	historicURL = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml"
)

func main() {
	service := micro.NewService(
		micro.Name("eurorate.server"),
		micro.RegisterTTL(time.Minute),
		micro.RegisterInterval(time.Second*30),
	)
	service.Init()

	dailyProvider := parser.HTTPLiveProvider(dailyURL)
	historicProvider := parser.HTTPHistoricProvider(historicURL)

	proto.RegisterRatesHandler(service.Server(), handler.NewRatesHandler(dailyProvider, historicProvider))

	if err := service.Run(); err != nil {
		log.Fatal(err)
	}
}

This exposes the handler through gRPC discoverable through whatever discoverable plugins micro exposes (by default consul).

Because this is a gRPC endpoint, we need a client to test this with…

micro client

Again, the code leans heavily on the micro example code, it uses the generated Protobuf file to create a service.

My test client looks remarkably similar…

package main

import (
	"flag"
	"fmt"

	proto "github.com/bigkevmcd/euroxref/proto"
	micro "github.com/micro/go-micro"
	"golang.org/x/net/context"
)

func main() {
	flag.Parse()
	args := flag.Args()
	service := micro.NewService(micro.Name("eurorate.client"))
	client := proto.NewRatesClient("eurorate.server", service.Client())

	rsp, err := client.Live(context.TODO(), &proto.LiveRequest{Currency: args[0]})
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(rsp.Rate)
}

This is pretty much straight out the micro example, but instantiates a NewRatesClient and then makes a call to fetch whatever currency is passed in as an arg on the command-line.

I’ve mostly skipped over the use of contexts in this this code, and here’s a case where I could use a context with a timeout, but I’ll reserve contextising the code for a later part.

Running the client and server

At long last, after all this code, we I get to test the service, this will require a running consul running:

$ consul agent -dev
$ go run cmd/server/main.go
2018/02/09 07:52:45 Listening on [::]:63738
2018/02/09 07:52:45 Broker Listening on [::]:63739
2018/02/09 07:52:45 Registering node: eurorate.server-3716b902-0d6e-11e8-8bc3-ba0039b89401
$ go run cmd/client/main.go GBP
currency:"GBP" rate:"0.87513" referenceDate:"2018-02-08"

The average time taken to run the client is 0.203s, but making 10 calls to the server from a client takes around 0.526s.

This is uncached…i.e. the server makes a request to the ECB for every request the client makes, which I’ll address in a future article.