focus

package module
v0.0.0-...-11dff32 Latest Latest
Warning

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

Go to latest
Published: Mar 13, 2024 License: BSD-2-Clause Imports: 8 Imported by: 0

README

Focus-go

Focus is the next generation cross language lightweight RPC framework. It can quickly and easily develop microservice applications, which greatly simplifies RPC programming.

Focus-go is the go language implementation of the Focus.

Install

go install github.com/golang/protobuf/protoc-gen-go
go install github.com/dinstone/focus-go/protoc-gen-focus

Quick Start

  1. create a demo project and import the focus package:
> go mod init demo
> go get github.com/dinstone/focus-go
  1. under the path of the project, create a protobuf file arith.proto:
syntax = "proto3";

package protobuf;
option go_package="/protobuf";

// ArithService Defining Computational Digital Services
service ArithService {
  // Add addition
  rpc Add(ArithRequest) returns (ArithResponse);
  // Sub subtraction
  rpc Sub(ArithRequest) returns (ArithResponse);
  // Mul multiplication
  rpc Mul(ArithRequest) returns (ArithResponse);
  // Div division
  rpc Div(ArithRequest) returns (ArithResponse);
}

message ArithRequest {
  int32 a = 1;
  int32 b = 2;
}

message ArithResponse {
  int32 c = 1;
}
  1. using protoc to generate code:
> protoc --focus_out=. arith.proto --go_out=. arith.proto

at this time, two files will be generated in the directory protobuf: arith.pb.go and arith.svr.go

  1. implement the ArithService in the file arith.svr.go :
package protobuf

import "errors"

// ArithService Defining Computational Digital Services
type ArithService struct{}

// Add addition
func (this *ArithService) Add(args *ArithRequest, reply *ArithResponse) error {
	reply.C = args.A + args.B
	return nil
}

// Sub subtraction
func (this *ArithService) Sub(args *ArithRequest, reply *ArithResponse) error {
	reply.C = args.A - args.B
	return nil
}

// Mul multiplication
func (this *ArithService) Mul(args *ArithRequest, reply *ArithResponse) error {
	reply.C = args.A * args.B
	return nil
}

// Div division
func (this *ArithService) Div(args *ArithRequest, reply *ArithResponse) error {
	if args.B == 0 {
		return errors.New("divided is zero")
	}
	reply.C = args.A / args.B
	return nil
}

Server

under the path of the project, we create a file named focus_server.go, create a focus server and publish service.

package main

import (
	"demo/protobuf"
	"log"
	"net"

	"github.com/dinstone/focus-go"
)

func main() {
	lis, err := net.Listen("tcp", ":8082")
	if err != nil {
		log.Fatal(err)
	}

	server := focus.NewServer()
	server.RegisterName("ArithService", new(protobuf.ArithService))
	server.Serve(lis)
}

Client

under the path of the project, we create a file named focus_client.go, create a focus client and call it synchronously with the Add function:

import (
	"demo/protobuf"
	"github.com/dinstone/focus-go"
...

conn, err := net.Dial("tcp", ":8082")
if err != nil {
	log.Fatal(err)
}
defer conn.Close()
client := focus.NewClient(conn)
resq := protobuf.ArithRequest{A: 20, B: 5}
resp := protobuf.ArithResponse{}
err = client.Call("ArithService.Add", &resq, &resp)
log.Printf("Arith.Add(%v, %v): %v ,Error: %v", resq.A, resq.B, resp.C, err)

you can also call asynchronously, which will return a channel of type *rpc.Call:


result := client.AsyncCall("ArithService.Add", &resq, &resp)
select {
case call := <-result:
	log.Printf("Arith.Add(%v, %v): %v ,Error: %v", resq.A, resq.B, resp.C, call.Error)
case <-time.After(100 * time.Microsecond):
	log.Fatal("time out")
}

of course, you can also compress with three supported formats gzip, snappy, zlib:

import (
    "github.com/dinstone/focus-go"
    "github.com/dinstone/focus-go/options"
    "github.com/dinstone/focus-go/serializer"
	"github.com/dinstone/focus-go/compressor"
)

...
client := focus.NewClient(conn, options.WithCompress(compressor.Gzip))

Custom Serializer

If you want to customize the serializer, you must implement the Serializer interface:

type Serializer interface {
    Marshal(message interface{}) ([]byte, error)
    Unmarshal(data []byte, message interface{}) error
    Type() string
}

JsonSerializer is a serializer based Json:

type JsonSerializer struct{}

func (_ JsonSerializer) Marshal(message interface{}) ([]byte, error) {
	return json.Marshal(message)
}

func (_ JsonSerializer) Unmarshal(data []byte, message interface{}) error {
	return json.Unmarshal(data, message)
}

now, we can create a HelloService with the following code:

type HelloRequest struct {
	Req string `json:"req"`
}

type HelloResponce struct {
	Resp string `json:"resp"`
}

type HelloService struct{}

func (_ *HelloService) SayHello(args *HelloRequest, reply *HelloResponce) error {
	reply.Resp = args.Req
	return nil
}

finally, we need to set the serializer on the focus server:

func main() {
	lis, err := net.Listen("tcp", ":8082")
	if err != nil {
		log.Fatal(err)
	}

	server := focus.NewServer(options.WithSerializer(serializer.Json))
	server.Register(new(HelloService))
	server.Serve(lis)
}

Remember that when the focus client calls the service, it also needs to set the serializer:

focus.NewClient(conn, options.WithSerializer(serializer.Json))

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	*rpc.Client
}

Client rpc client based on net/rpc implementation

func NewClient

func NewClient(conn io.ReadWriteCloser, opts ...options.Option) *Client

NewClient Create a new rpc client

func (*Client) AsyncCall

func (c *Client) AsyncCall(serviceMethod string, args interface{}, reply interface{}) chan *rpc.Call

AsyncCall asynchronously calls the rpc function and returns a channel of *rpc.Call

func (*Client) Call

func (c *Client) Call(serviceMethod string, args interface{}, reply interface{}) error

Call synchronously calls the rpc function

type Server

type Server struct {
	*rpc.Server
	// contains filtered or unexported fields
}

Server rpc server based on net/rpc implementation

func NewServer

func NewServer(opts ...options.Option) *Server

func (*Server) Register

func (s *Server) Register(rcvr interface{}) error

Register register rpc function

func (*Server) RegisterName

func (s *Server) RegisterName(name string, rcvr interface{}) error

RegisterName register the rpc function with the specified name

func (*Server) Serve

func (s *Server) Serve(lis net.Listener)

Serve start service

Directories

Path Synopsis
test

Jump to

Keyboard shortcuts

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