example

package
v0.0.0-...-045890f Latest Latest
Warning

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

Go to latest
Published: Feb 20, 2019 License: Apache-2.0 Imports: 0 Imported by: 0

README

example

import "github.com/go-orion/Orion/example"

Overview

Lets create a minimal service with Orion

API Interface

Your service starts with the API interface, In orion we define all API interfaces as a protobuf file (stringsvc/stringproto/stringproto.proto)

syntax = "proto3";

package stringproto;

service StringService{

	rpc Upper (UpperRequest) returns (UpperResponse){
	}

	rpc Count (CountRequest) returns (CountResponse) {
	}
}

message UpperRequest {
	string msg = 1;
}

message UpperResponse {
	string msg = 1;
}

message CountRequest{
	string msg = 1;
}

message CountResponse{
	int64 count = 1;
}

Above protobuf file describes a service called "StringService" and defines the endpoints "Upper" and "Count", As we can see all our API Contracts are clearly laid out and makes it easy for other services to integrate with our service

Generating Service Code

we can execute

protoc -I . stringproto.proto --go_out=plugins=grpc:. --orion_out=.

to generate protobuf/orion code, you will see following files are generated

stringproto.pb.go
stringproto.pb.orion.go
Service Lifecycle

Orion manages lifecycle of the service by ServiceFactory (stringsvc/service/init.go)

package service

import "github.com/go-orion/Orion/orion"

type svcFactory struct{}

func (s *svcFactory) NewService(orion.Server) interface{} {
	return &svc{}
}

func (s *svcFactory) DisposeService(svc interface{}) {
	//do nothing
}

func GetFactory() orion.ServiceFactory {
	return &svcFactory{}
}

"NewService" is called when a new service is initialized, "DisposeService" is called when a service is disposed. A new service is initialized and older service is disposed every time config reloads.

Implementing Service

we need to implement the "StringServiceServer" interface generated by protoc plugin, this is where our application logic lives (stringsvc/service/service.go)

package service

import (
	"context"
	"strings"

	proto "github.com/go-orion/Orion/example/stringsvc/stringproto"
)

// svc implements proto.StringServiceServer
type svc struct{}

func (s *svc) Upper(ctx context.Context, req *proto.UpperRequest) (*proto.UpperResponse, error) {
	resp := new(proto.UpperResponse)
	resp.Msg = strings.ToUpper(req.GetMsg())
	return resp, nil
}

func (s *svc) Count(ctx context.Context, req *proto.CountRequest) (*proto.CountResponse, error) {
	resp := new(proto.CountResponse)
	resp.Count = int64(len(req.GetMsg()))
	return resp, nil
}
Building Server

in only a few lines of code we can get a server started serving gRPC and HTTP (stringsvc/cmd/server/main.go)

package main

import (
	"github.com/go-orion/Orion/example/stringsvc/service"
	proto "github.com/go-orion/Orion/example/stringsvc/stringproto"
	"github.com/go-orion/Orion/orion"
)

func main() {
	server := orion.GetDefaultServer("StringService")
	proto.RegisterStringServiceOrionServer(service.GetFactory(), server)
	server.Start()
	server.Wait()
}
Running Server

we can start the server by running "go run cmd/server/main.go"

ᐅ go run cmd/server/main.go
2018/02/01 16:20:57 msg Reading config
2018/02/01 16:20:57 Config config could not be read Config File "StringService" Not Found in "[. /opt/config]"
2018/02/01 16:20:57 HTTPListnerPort 9282
2018/02/01 16:20:57 gRPCListnerPort 9281
2018/02/01 16:20:57 HystrixPort 9283
2018/02/01 16:20:57 warning rollbar token is empty not initializing rollbar

  ___  ____  ___ ___  _   _
 / _ \|  _ \|_ _/ _ \| \ | |
| | | | |_) || | | | |  \| |
| |_| |  _ < | | |_| | |\  |
 \___/|_| \_\___\___/|_| \_|

2018/02/01 16:20:57 GRPC server starting
2018/02/01 16:20:57 PprofPort 9284
Mapped URLs:
	[POST] /stringservice/upper
	[POST] /stringservice/count

Orion automatically generates and initializes HTTP/gRPC servers based on our defined proto as we can see the path for our endpoints Upper and Count are as follows

[POST] /stringservice/upper
[POST] /stringservice/count
Making HTTP Calls

Lets call Upper

ᐅ curl -X POST -i -d '{"msg":"Hello World"}' <a href="http://127.0.0.1:9282/stringservice/upper">http://127.0.0.1:9282/stringservice/upper</a>
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 01 Feb 2018 08:27:32 GMT
Content-Length: 21

{"msg":"HELLO WORLD"}

By default orion responds in "application/json" for HTTP calls, We can even ask for response in "protobuf" by setting the Accept HTTP header

ᐅ curl -X POST -i -H "Accept:application/protobuf" -d '{"msg":"Hello World"}' <a href="http://127.0.0.1:9282/stringservice/upper">http://127.0.0.1:9282/stringservice/upper</a>
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Date: Thu, 01 Feb 2018 08:30:21 GMT
Content-Length: 13
			// binary data omitted
HELLO WORLD

Orion also logs response time and errors for each API call

2018/02/01 16:27:32 path /stringservice/upper method POST error <nil> took 132.96µs
2018/02/01 16:30:21 path /stringservice/upper method POST error <nil> took 766.984µs
Making gRPC calls

we can build a client using StringServiceClient generated by protoc grpc plugin (stringsvc/cmd/client/main.go)

package main

import (
	"context"
	"log"

	proto "github.com/go-orion/Orion/example/stringsvc/stringproto"
	"google.golang.org/grpc"
)

const (
	address = "127.0.0.1:9281"
)

func main() {
	// establish connection
	conn, err := grpc.Dial(address, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()

	client := proto.NewStringServiceClient(conn)
	uppercase(client)
}

func uppercase(client proto.StringServiceClient) {
	r := new(proto.UpperRequest)
	r.Msg = "Hello World"
	log.Println("making gRPC calls for Upper")
	resp, err := client.Upper(context.Background(), r)
	log.Println("resp", resp)
	log.Println("error", err)
}

On running this client we can see

ᐅ go run cmd/client/main.go
2018/02/01 16:50:06 making gRPC calls for Upper
2018/02/01 16:50:06 resp msg:"HELLO WORLD"
2018/02/01 16:50:06 error <nil>

we will see the following on server

2018/02/01 16:50:06 method /stringproto.StringService/Upper error <nil> took 19.764µs

Imported Packages

No packages beyond the Go standard library are imported.

Index

Package files

documentation.go


Generated by godoc2ghmd

Documentation

Overview

Lets create a minimal service with Orion

API Interface

Your service starts with the API interface, In orion we define all API interfaces as a protobuf file (stringsvc/stringproto/stringproto.proto)

syntax = "proto3";

package stringproto;

service StringService{

	rpc Upper (UpperRequest) returns (UpperResponse){
	}

	rpc Count (CountRequest) returns (CountResponse) {
	}
}

message UpperRequest {
	string msg = 1;
}

message UpperResponse {
	string msg = 1;
}

message CountRequest{
	string msg = 1;
}

message CountResponse{
	int64 count = 1;
}

Above protobuf file describes a service called "StringService" and defines the endpoints "Upper" and "Count", As we can see all our API Contracts are clearly laid out and makes it easy for other services to integrate with our service

Generating Service Code

we can execute

protoc -I . stringproto.proto --go_out=plugins=grpc:. --orion_out=.

to generate protobuf/orion code, you will see following files are generated

stringproto.pb.go
stringproto.pb.orion.go

Service Lifecycle

Orion manages lifecycle of the service by ServiceFactory (stringsvc/service/init.go)

package service

import "github.com/go-orion/Orion/orion"

type svcFactory struct{}

func (s *svcFactory) NewService(orion.Server) interface{} {
	return &svc{}
}

func (s *svcFactory) DisposeService(svc interface{}) {
	//do nothing
}

func GetFactory() orion.ServiceFactory {
	return &svcFactory{}
}

"NewService" is called when a new service is initialized, "DisposeService" is called when a service is disposed. A new service is initialized and older service is disposed every time config reloads.

Implementing Service

we need to implement the "StringServiceServer" interface generated by protoc plugin, this is where our application logic lives (stringsvc/service/service.go)

package service

import (
	"context"
	"strings"

	proto "github.com/go-orion/Orion/example/stringsvc/stringproto"
)

// svc implements proto.StringServiceServer
type svc struct{}

func (s *svc) Upper(ctx context.Context, req *proto.UpperRequest) (*proto.UpperResponse, error) {
	resp := new(proto.UpperResponse)
	resp.Msg = strings.ToUpper(req.GetMsg())
	return resp, nil
}

func (s *svc) Count(ctx context.Context, req *proto.CountRequest) (*proto.CountResponse, error) {
	resp := new(proto.CountResponse)
	resp.Count = int64(len(req.GetMsg()))
	return resp, nil
}

Building Server

in only a few lines of code we can get a server started serving gRPC and HTTP (stringsvc/cmd/server/main.go)

package main

import (
	"github.com/go-orion/Orion/example/stringsvc/service"
	proto "github.com/go-orion/Orion/example/stringsvc/stringproto"
	"github.com/go-orion/Orion/orion"
)

func main() {
	server := orion.GetDefaultServer("StringService")
	proto.RegisterStringServiceOrionServer(service.GetFactory(), server)
	server.Start()
	server.Wait()
}

Running Server

we can start the server by running "go run cmd/server/main.go"

ᐅ go run cmd/server/main.go
2018/02/01 16:20:57 msg Reading config
2018/02/01 16:20:57 Config config could not be read Config File "StringService" Not Found in "[. /opt/config]"
2018/02/01 16:20:57 HTTPListnerPort 9282
2018/02/01 16:20:57 gRPCListnerPort 9281
2018/02/01 16:20:57 HystrixPort 9283
2018/02/01 16:20:57 warning rollbar token is empty not initializing rollbar

  ___  ____  ___ ___  _   _
 / _ \|  _ \|_ _/ _ \| \ | |
| | | | |_) || | | | |  \| |
| |_| |  _ < | | |_| | |\  |
 \___/|_| \_\___\___/|_| \_|

2018/02/01 16:20:57 GRPC server starting
2018/02/01 16:20:57 PprofPort 9284
Mapped URLs:
	[POST] /stringservice/upper
	[POST] /stringservice/count

Orion automatically generates and initializes HTTP/gRPC servers based on our defined proto as we can see the path for our endpoints Upper and Count are as follows

[POST] /stringservice/upper
[POST] /stringservice/count

Making HTTP Calls

Lets call Upper

ᐅ curl -X POST -i -d '{"msg":"Hello World"}' http://127.0.0.1:9282/stringservice/upper
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 01 Feb 2018 08:27:32 GMT
Content-Length: 21

{"msg":"HELLO WORLD"}

By default orion responds in "application/json" for HTTP calls, We can even ask for response in "protobuf" by setting the Accept HTTP header

ᐅ curl -X POST -i -H "Accept:application/protobuf" -d '{"msg":"Hello World"}' http://127.0.0.1:9282/stringservice/upper
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Date: Thu, 01 Feb 2018 08:30:21 GMT
Content-Length: 13
			// binary data omitted
HELLO WORLD

Orion also logs response time and errors for each API call

2018/02/01 16:27:32 path /stringservice/upper method POST error <nil> took 132.96µs
2018/02/01 16:30:21 path /stringservice/upper method POST error <nil> took 766.984µs

Making gRPC calls

we can build a client using StringServiceClient generated by protoc grpc plugin (stringsvc/cmd/client/main.go)

package main

import (
	"context"
	"log"

	proto "github.com/go-orion/Orion/example/stringsvc/stringproto"
	"google.golang.org/grpc"
)

const (
	address = "127.0.0.1:9281"
)

func main() {
	// establish connection
	conn, err := grpc.Dial(address, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()

	client := proto.NewStringServiceClient(conn)
	uppercase(client)
}

func uppercase(client proto.StringServiceClient) {
	r := new(proto.UpperRequest)
	r.Msg = "Hello World"
	log.Println("making gRPC calls for Upper")
	resp, err := client.Upper(context.Background(), r)
	log.Println("resp", resp)
	log.Println("error", err)
}

On running this client we can see

ᐅ go run cmd/client/main.go
2018/02/01 16:50:06 making gRPC calls for Upper
2018/02/01 16:50:06 resp msg:"HELLO WORLD"
2018/02/01 16:50:06 error <nil>

we will see the following on server

2018/02/01 16:50:06 method /stringproto.StringService/Upper error <nil> took 19.764µs

Directories

Path Synopsis
echo
echo_proto
Package echo_proto is a generated protocol buffer package.
Package echo_proto is a generated protocol buffer package.
service
Package service must implement the generated proto's server interface
Package service must implement the generated proto's server interface
simple
simple_proto
Package simple_proto is a generated protocol buffer package.
Package simple_proto is a generated protocol buffer package.
stringsvc
stringproto
Package stringproto is a generated protocol buffer package.
Package stringproto is a generated protocol buffer package.
stringsvc2
stringproto
Package stringproto is a generated protocol buffer package.
Package stringproto is a generated protocol buffer package.

Jump to

Keyboard shortcuts

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