nano

package module
v0.0.0-...-6976cfd Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 3, 2016 License: MIT Imports: 0 Imported by: 1

README

Build Status Coverage Status GoDoc

go-nano

A framework for writting web services in Go.

Design

Rational

Developers should focus on writing the business logic.

Highlight
  • Transport agnostic (TCP, HTTP, AMQP ...)
  • Protocol agnostic (JSON-RPC, ProtocolBuffer, ...)
  • Plain Old Go Struct for business logic
  • Handle boilerplate for setting up a service
  • Convention over configuration
  • RPC.
Components
                                    +------------ +     +---------+
                                    | Middlewares | <-> | Handler |
                                    +------------ +     +---------+
+-----------+     +----------+
| Transport | <-> | Protocol | <->
+-----------+     +----------+
                                    +------------ +     +---------+
                                    | Extensions  | <-> | Client  |
                                    +------------ +     +---------+

Features

Transports:

  • AMQP Transport (Minimal)
  • HTTP2 Transport
  • HTTP Transport

Protocols:

Client:

  • Client
  • Circuit Breaker
  • Timeout
  • Retry
  • Remote errors
  • Async

Server:

  • Multiple services namespaces (a la net/rpc)
  • Tracing middleware
  • Rate limit middleware
  • Registration

Command lines:

  • gonano request
  • gonano get
  • gonano list

Misc:

Examples

Please check examples folder

Documentation

Overview

Package nano is a toolkit for building services in golang. It's build on exiting mature golang library and best practices to give it's user a nice (I am biased) api on how to create and manage services in golang.

A usual service written with Nano is composed of a "handler" which is where business logic reside, on top of that developers can use/write a "middlewares" which wraps a "handler" to implement application logic e.g. logging, tracing, auth, rate limiting ... . that's from producer side, from consumer side Nano contains a client to talk to services with client extensions which are same as middlewares but for client side, example of such extensions is retry, backoff, circuit breaker ... .

A "handler" can be exposed using multiple transport and protocol, this make services written in Nano usable from other services written using different stacks.

To give you more concrete description on how Nano can be used, we will start by writting a simple echo service.

Nano was designed in a way that hide the complexity of creating a service by letting it's users focus more on the business logic of your service which is usually where you should start when writing a service.

In Nano word, business logic live inside what we call a "handler". To create a handler you can either create a simple golang struct and let Nano reflect it:

package main

import (
	"github.com/mouadino/go-nano/handler"
)

type Echo struct {}

func (Echo) Echo(msg string) (string, error) {
	return msg, nil
}

var hdlr = handler.New(Echo{})

Or by implementing the handler.Handler interface directly:

package main

import (
	"github.com/mouadino/go-nano/handler"
	"github.com/mouadino/go-nano/protocol"
)

var hdlr = handler.HandlerFunc(func(rw protocol.ResponseWriter, req *protocol.Request) {
	msg := req.Params["_0"].(string)
	rw.Set(msg)
}

Now that we have our business logic done, the next step it to expose it as a service. With Nano you can expose your handler using different transport/protocol (multiple at the same time if necessary), for our simple example we will expose our handler using HTTP transport and JSON/RPC protocol:

package main

import (
	"github.com/mouadino/go-nano/server"
	"github.com/mouadino/go-nano/protocol/jsonrpc"
	"github.com/mouadino/go-nano/transport/http"
)

func main() {
	serv := server.New(jsonrpc.New(http.New()))
	serv.Register("echo", hdlr)
	serv.Serve()
}

Something that is also very common when exposing a service is to be able to register it under a discovery system (like zookeeper), in this case our main function should be:

func main() {
	serv := server.New(jsonrpc.New(http.New()))
	serv.Register("echo", hdlr)
	serv.ServeAndAnnounce(zookeeper.New([]string{"127.0.0.1:2181"}))
}

This make our handler available under the name "echo".

Now to consume our service using Nano, we will create a client and call our echo function:

package main

import (
	"fmt"

	"github.com/mouadino/go-nano/client"
	"github.com/mouadino/go-nano/protocol/jsonrpc"
	"github.com/mouadino/go-nano/transport/http"
)

func main() {
	c := client.New("http://127.0.0.1:23765", jsonrpc.New(http.New()))

	msg, err := c.Call("echo", "Hello, World!")
	// Or c.Call("echo.echo", ...) If reflection was used to create the handler.
	if err != nil {
		panic(err)
	}
	fmt.Printf("Echo returned %s", msg)
}

If service discovery was used there will be no need to have a hardcoded echo service endpoint, instead our client setup will look like this:

func main() {
	lb := loadbalancer.New(
		zookeeper.New([]string{"127.0.0.1:2181"}),
		loadbalancer.NewRoundRobin(),
	)

	c := client.New(echo, jsonrpc.New(http.New()), lb)

	// Then use client like above.

}

Directories

Path Synopsis
cli
Package client represents an RPC client to make request to a remote services.
Package client represents an RPC client to make request to a remote services.
loadbalancer
package loadbalancer defines how to balance and distribute requests between multiple service instances.
package loadbalancer defines how to balance and distribute requests between multiple service instances.
zookeeper
package zookeeper contains definition of discovery logic to announce rpc instances in zookeeper and resolve them.
package zookeeper contains definition of discovery logic to announce rpc instances in zookeeper and resolve them.
examples
package handler includes the logic that define a service as an object that implements the Handler interface.
package handler includes the logic that define a service as an object that implements the Handler interface.
middleware
package middleware contains common handler middlewares, example: logger, tracer, recoverer ...
package middleware contains common handler middlewares, example: logger, tracer, recoverer ...
Package server define how to serve RPC services.
Package server define how to serve RPC services.
Package transport defines logic to send and receive RPC requests and responses.
Package transport defines logic to send and receive RPC requests and responses.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL