lile

package module
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Jan 11, 2023 License: MIT Imports: 28 Imported by: 0

README

Lile是可以帮助您快速创建基于gRPC通讯,或者可以通过gateway创建通讯结构

Lile主要是用于过创建基本结构,测试示例,Dockerfile,Makefile等基础骨架。

Lile也是一个简单的服务生成器,扩展了基本的gRPC服务器,包括诸如指标(如Prometheus)。

功能如下:

  • 根据proto文件自动生成服务端代码及单元测试1
  • tls模式下同一端口https,grpc可同时访问
  • 如果有定义grpc-gateway相关,可生成swagger文档
  • 链路追踪

lile 改编自https://github.com/lileio/lile

改进如下:

  1. 去除google的消息订阅,这个国内没法用
  2. 增加tls访问,可以同一端口grpc,https自动协议判断。
  3. 增加swagger文档生成
  4. 增加jaeger链路追踪 (待实现)
  5. proto插件bug修正

安装

安装Lile很容易,使用go get便可以安装Lile的命令行工具来生成新的服务和所需的库。

$ go get -u github.com/fghosth/lile/...

您还需要安装Google的Protocol Buffers

入门

Lilek可以自动根据username/service生成一个完整的路径。

$ lile new --name users

指南

安装

  • mac
brew install fghosth/lile

安装lile和protoc-gen-lile-server 插件

首先,你需要确保您在您安装Lile之前已经安装了Go。

安装Lile很容易,使用go get便可以安装Lile的命令行工具来生成新的服务和所需的库。

$ go get github.com/fghosth/lile/...
cd lile
go build
cp lile /usr/local/bin

您还需要安装Google的[Protocol Buffers]Protocol Buffers

在MacOS你可以使用brew install protobuf来安装。

安装 protoc-gen-lile-server插件

 cd protoc-gen-lile-server
 go build
 cp protoc-gen-lile-server /usr/local/bin

初始化项目

make init

生成pb文件

make proto

创建服务

Lile使用生成器来快速生成新的Lile服务。

Lile遵循Go关于$GOPATH的约定(参见如何写Go),并且自动解析您的新服务的名称,以在正确的位置创建服务。

如果您的Github用户名是lileio,并且您想创建一个新的服务为了发布消息到Slack,您可以使用如下命令:

lile new --name slack

这将创建一个项目到$GOPATH/src/github.com/lileio/slack

服务定义

Lile服务主要使用gRPC,因此使用protocol buffers作为接口定义语言(IDL),用于描述有效负载消息的服务接口和结构。 如果需要,可以使用其他替代品。

我强烈建议您先阅读Google API设计文档,以获得有关RPC方法和消息的一般命名的好建议,以及如果需要,可以将其转换为REST/JSON。

您可以在Lile中发现一个简单的例子account_service

service AccountService {
  rpc List (ListAccountsRequest) returns (ListAccountsResponse) {}
  rpc GetById (GetByIdRequest) returns (Account) {}
  rpc GetByEmail (GetByEmailRequest) returns (Account) {}
  rpc AuthenticateByEmail (AuthenticateByEmailRequest) returns (Account) {}
  rpc GeneratePasswordToken (GeneratePasswordTokenRequest) returns (GeneratePasswordTokenResponse) {}
  rpc ResetPassword (ResetPasswordRequest) returns (Account) {}
  rpc ConfirmAccount (ConfirmAccountRequest) returns (Account) {}
  rpc Create (CreateAccountRequest) returns (Account) {}
  rpc Update (UpdateAccountRequest) returns (Account) {}
  rpc Delete (DeleteAccountRequest) returns (google.protobuf.Empty) {}
}

生成RPC方法

默认情况下,Lile将创建一个RPC方法和一个简单的请求和响应消息。

syntax = "proto3";
option go_package = "github.com/fghosth/slack";
package slack;

message Request {
  string id = 1;
}

message Response {
  string id = 1;
}

service Slack {
  rpc Read (Request) returns (Response) {}
}

我们来修改一下使它能够提供真正的服务,并添加自己的方法。

我们来创建一个Announce方法向Slack发布消息。

我们假设Slack团队和身份验证已经由服务配置来处理,所以我们服务的用户只需要提供一个房间和他们的消息。 该服务将发送特殊的空响应,因为我们只需要知道是否发生错误,也不需要知道其他任何内容。

现在我们的proto文件看起来像这样:

syntax = "proto3";
option go_package = "github.com/fghosth/slack";
import "google/protobuf/empty.proto";
package slack;

message AnnounceRequest {
  string channel = 1;
  string msg = 2;
}

service Slack {
  rpc Announce (AnnounceRequest) returns (google.protobuf.Empty) {}
}

现在我们运行protoc工具我们的文件,以及Lile生成器插件。

protoc -I . slack.proto --lile-server_out=. --go_out=plugins=grpc:$GOPATH/src

Lile提供了一个Makefile,每个项目都有一个已经配置的proto构建步骤。 所以我们可以运行它。

make proto

我们可以看到,Lile将在server目录中为我们创建两个文件。

$ make proto
protoc -I . slack.proto --lile-server_out=. --go_out=plugins=grpc:$GOPATH/src
2017/07/12 15:44:01 [Creating] server/announce.go
2017/07/12 15:44:01 [Creating test] server/announce_test.go

我们来看看Lile为我们创建的announce.go文件。

package server

import (
    "errors"

    "github.com/golang/protobuf/ptypes/empty"
    "github.com/lileio/slack"
    context "golang.org/x/net/context"
)

func (s SlackServer) Announce(ctx context.Context, r *slack.AnnounceRequest) (*empty.Empty, error) {
  return nil, errors.New("not yet implemented")
}

接下来我们实现这个生成的方法,让我们从测试开始吧!

编写并运行测试

当您使用Lile生成RPC方法时,也会创建一个对应的测试文件。例如,给定我们的announce.go文件,Lile将在同一目录中创建announce_test.go

看起来如下:

package server

import (
	"testing"

	"github.com/fghosth/slack"
	"github.com/stretchr/testify/assert"
	context "golang.org/x/net/context"
)

func TestAnnounce(t *testing.T) {
	ctx := context.Background()
	req := &slack.AnnounceRequest{}

	res, err := cli.Announce(ctx, req)
	assert.Nil(t, err)
	assert.NotNil(t, res)
}

您现在可以使用Makefile运行测试,并运行make test命令

$ make test
=== RUN   TestAnnounce
--- FAIL: TestAnnounce (0.00s)
        Error Trace:    announce_test.go:16
        Error:          Expected nil, but got: &status.statusError{Code:2, Message:"not yet implemented", Details:[]*any.Any(nil)}
        Error Trace:    announce_test.go:17
        Error:          Expected value not to be nil.
FAIL
coverage: 100.0% of statements
FAIL    github.com/lileio/slack/server  0.011s
make: *** [test] Error 2

我们的测试失败了,因为我们还没有实现我们的方法,在我们的方法中返回一个“未实现”的错误。

让我们在announce.go中实现Announce方法,这里是一个使用nlopesslack library的例子。

package server

import (
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"

	"github.com/golang/protobuf/ptypes/empty"
	"github.com/fghosth/slack"
	sl "github.com/nlopes/slack"
	context "golang.org/x/net/context"
)

var api = sl.New(os.Getenv("SLACK_TOKEN"))

func (s SlackServer) Announce(ctx context.Context, r *slack.AnnounceRequest) (*empty.Empty, error) {
	_, _, err := api.PostMessage(r.Channel, r.Msg, sl.PostMessageParameters{})
	if err != nil {
		return nil, status.Errorf(codes.Internal, err.Error())
	}
   
	return &empty.Empty{}, nil
}

我们再次修改我们的测试用力,然后再次运行我们的测试

package server

import (
	"testing"

	"github.com/fghosth/slack"
	"github.com/stretchr/testify/assert"
	context "golang.org/x/net/context"
)

func TestAnnounce(t *testing.T) {
	ctx := context.Background()
	req := &slack.AnnounceRequest{
		Channel: "@alex",
		Msg:     "hellooo",
	}

	res, err := cli.Announce(ctx, req)
	assert.Nil(t, err)
	assert.NotNil(t, res)
}

现在如果我使用我的Slack令牌作为环境变量运行测试,我应该看到通过测试!

$ alex@slack: SLACK_TOKEN=zbxkkausdkasugdk make test
go test -v ./... -cover
?       github.com/lileio/slack [no test files]
=== RUN   TestAnnounce
--- PASS: TestAnnounce (0.32s)
PASS
coverage: 75.0% of statements
ok      github.com/lileio/slack/server  0.331s  coverage: 75.0% of statements
?       github.com/lileio/slack/slack   [no test files]
?       github.com/lileio/slack/slack/cmd       [no test files]
?       github.com/lileio/slack/subscribers     [no test files]

使用生成的命令行

生成您的服务时,Lile生成一个命令行应用程序。 您可以使用自己的命令行扩展应用程序或使用内置的命令行来运行服务。

运行没有任何参数的命令行应用程序将打印生成的帮助。

例如go run orders/main.go

服务

运行serve将运行RPC服务。

up

运行up将同时运行RPC服务器和发布订阅的订阅者。

自定义命令行

要添加您自己的命令行,您可以使用cobra,它是Lile的内置的命令行生成器。

$ cd orders
$ cobra add import

您现在可以编辑生成的文件,以创建您的命令行,cobra会自动将命令行的名称添加到帮助中。

暴露Prometheus采集指标

默认情况下,Lile将Prometheus的采集指标暴露在:9000/metrics

如果您的服务正在运行,您可以使用cURL来预览Prometheus指标。

$ curl :9000/metrics

你应该看到如下的一些输出:

# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
...
...

Lile的Prometheus指标实现使用go-grpc-promesheus的拦截器将其内置到自身的gPRC中,提供如以下的指标:

grpc_server_started_total
grpc_server_msg_received_total
grpc_server_msg_sent_total
grpc_server_handling_seconds_bucket

有关使用Prometheus的更多信息,收集和绘制这些指标,请参阅Prometheus入门

有关gRPC Prometheus查询的示例,请参阅查询示例

Protobuf消息自动解码。

追踪(未实现)

Lile已经建立了跟踪,将opentracing 兼容的跟踪器设置为GlobalTracer

Documentation

Overview

Package lile provides helper methods to quickly create RPC based services that have metrics, tracing and pub/sub support

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddGRPCGatewayHeader

func AddGRPCGatewayHeader(header map[string]string)

add GRPCGatewayHeader

func AddGRPCGatewayOption

func AddGRPCGatewayOption(opt grpc.DialOption)

add grpcGatewayOption

func AddGRPCOption

func AddGRPCOption(opt grpc.ServerOption)

add grpcOption

func AddStreamInterceptor

func AddStreamInterceptor(sint grpc.StreamServerInterceptor)

AddStreamInterceptor adds a stream interceptor to the RPC server

func AddUnaryInterceptor

func AddUnaryInterceptor(unint grpc.UnaryServerInterceptor)

AddUnaryInterceptor adds a unary interceptor to the RPC server

func BaseCommand

func BaseCommand(serviceName, shortDescription string) *cobra.Command

BaseCommand provides the basic flags vars for running a service

func ContextClientInterceptor

func ContextClientInterceptor() grpc.UnaryClientInterceptor

ContextClientInterceptor passes around headers for tracing and linkerd

func EnableCORS added in v1.0.7

func EnableCORS(opt ...handlers.CORSOption)

enable cors

func GrpcGatewayServer

func GrpcGatewayServer(r func(ctx context.Context, mux *runtime.ServeMux, endpoint string, dopts []grpc.DialOption))

grpc gateway server

func Name

func Name(n string)

Name sets the name for the service

func NewTestServer

func NewTestServer(s *grpc.Server) (string, func())

NewTestServer is a helper function to create a gRPC server on a non-network socket and it returns the socket location and a func to call which starts the server

func Run

func Run() error

Run is a blocking cmd to run the gRPC and metrics server. You should listen to os signals and call Shutdown() if you want a graceful shutdown or want to handle other goroutines

func ServeGRPC

func ServeGRPC() error

ServeGRPC creates and runs a blocking gRPC server

func Server

func Server(r func(s *grpc.Server))

Server attaches the gRPC implementation to the service

func SetAddress added in v1.0.6

func SetAddress(host string, port int)

修改host,port

func SetTLS

func SetTLS(serverCert, serverKey, clientKey, clientCert, caCert, serverName string)

Set TLS

func Shutdown

func Shutdown()

Shutdown gracefully shuts down the gRPC and metrics servers

func TestConn

func TestConn(addr string) *grpc.ClientConn

TestConn is a connection that connects to a socket based connection

func URLForService

func URLForService(name string) string

URLForService returns a service URL via a registry or a simple DNS name if not available via the registry

Types

type RegisterGrpcGatewayImpl

type RegisterGrpcGatewayImpl func(ctx context.Context, mux *runtime.ServeMux, endpoint string, opt []grpc.DialOption)

type RegisterImplementation

type RegisterImplementation func(s *grpc.Server)

RegisterImplementation allows you to register your gRPC server

type Registry

type Registry interface {
	// Register a service
	Register(s *Service) error
	// Deregister a service
	DeRegister(s *Service) error
	// Get a service by name
	Get(name string) (string, error)
}

Registry is the interface to implement for external registry providers

type ServerConfig

type ServerConfig struct {
	Port int
	Host string
}

ServerConfig is a generic server configuration

func (*ServerConfig) Address

func (c *ServerConfig) Address() string

Address Gets a logical addr for a ServerConfig

type Service

type Service struct {
	ID   string
	Name string

	//tls
	ServerCert string //server文件路径
	ServerKey  string //server路文件径
	ClientKey  string //文件路径
	ClientCert string //文件路径
	CACert     string //文件路径
	ServerName string //tls 对应name

	//cors
	Cors       bool //是否跨域true 支持跨域,false: 不支持跨域
	CORSOption []handlers.CORSOption

	// Interceptors
	UnaryInts  []grpc.UnaryServerInterceptor
	StreamInts []grpc.StreamServerInterceptor

	// The RPC server implementation
	GRPCImplementation RegisterImplementation
	GRPCOptions        []grpc.ServerOption

	//grpc-gateway implementation
	GRPCGatewayOption []grpc.DialOption
	GRPCGatewayImpl   RegisterGrpcGatewayImpl
	GRPCGatewayHeader map[string]string

	// gRPC and Prometheus endpoints
	Config           ServerConfig
	PrometheusConfig ServerConfig

	// Registry allows Lile to work with external registeries like
	// consul, zookeeper or similar
	Registry Registry

	// Private utils, exposed so they can be useful if needed
	ServiceListener  net.Listener
	GRPCServer       *grpc.Server
	PrometheusServer *http.Server
}

Service is a gRPC based server with extra features

func GlobalService

func GlobalService() *Service

GlobalService returns the global service

func NewService

func NewService(n string) *Service

NewService creates a new service with a given name

Directories

Path Synopsis
cmd
Package test is a generated protocol buffer package.
Package test is a generated protocol buffer package.

Jump to

Keyboard shortcuts

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