用于快速创建网络和微服务代码的工具
#go #microservices #grpc #gin

sponge是一个微服务框架,是一种快速创建Web和微服务代码的工具。 Sponge具有丰富的生成代码命令,共有12个不同的功能代码,这些功能代码可以合并为完整的服务(类似于人为破碎的海绵单元,可以自动重组为新的海绵)。微服务代码功能包括日志记录,服务注册和发现,注册表,费率限制器,断路器,跟踪,指标监视,PPROF性能分析,统计信息,缓存,CICD。该代码使用分层结构,并且易于添加或替换功能代码。作为提高效率的工具,通常会自动生成通常重复的代码,并且只需根据生成的模板代码示例填充业务逻辑代码。

1海绵功能简介

1.1海绵命令框架

生成的代码基于三种方法 yaml sql ddl 协议缓冲器,每种都具有不同的功能代码生成,框架生成代码的图如图1-1所示。

sponge-framework
图1-1海绵代码框架图

  • yaml 生成与GO结构代码相对应的配置文件。
  • SQL DDL 生成的代码包括HTTP,处理程序,DAO,Model,Proto,RPC,Service,分为两种类型的Web和RPC,Web和RPC类型都有自己的子模块,每个模块代码可以可以可以单独生成,在模块之间,例如独立脱钩的洋葱层。该代码包括标准化的CRUD(添加,删除,更改,检查)业务逻辑,可以直接编译和使用。
    • Web类型代码:生成HTTP服务代码,包括处理程序,DAO,Model三个子模块代码,如图所示所示,相同的原理,生成处理程序模块包含DAO,模型两个子 - 模块代码。
    • RPC类型代码:生成RPC服务代码,包括服务,DAO,型号,协议缓冲四个子模块,如图所示,生成服务模块代码,包括DAO,Model Model,协议缓冲,三个Sub Sub Sub Suber - 模块代码。
  • 协议缓冲区生成的代码包括HTTP-PB,RPC-PB,RPC-GW-PB,也分为Web和RPC类型,其中通常使用HTTP-PB,RPC-PB结合DAO,由 sql ddl 生成的模型代码。
    • http-pb :HTTP服务代码包括两个子模块,路由器和处理程序模板,不包括操作数据库子模块,随后的业务逻辑代码填充到处理程序模板文件中。
    • RPC-PB :RPC服务代码包括服务模板一个子模块,不包括操作数据库模块,后续业务逻辑代码填充到服务模板文件。
    • RPC-GW-PB :RPC网关实际上是HTTP服务,包括两个子模型,路由器和服务模板,其中服务模板代码是与调用RPC服务有关的业务逻辑代码。

在同一文件夹中,如果发现最新生成的代码与原始代码冲突,海绵将取消生成过程,并且不会对原始代码进行任何更改,因此您不必担心编写业务编写业务被覆盖的逻辑代码。

1.2微服务框架

Sponge创建的微服务代码框架如图1-2所示,这是一个典型的微服务层次结构,包含通用服务治理功能。

microservice-framework
图1-2微服务框架图

微服务主要功能。

代码目录结构遵循project-layout,而代码目录结构如下所示。

.
├── api            # Proto files and the generated *pb.go directory
├── assets         # Directory of other assets used with the repository (images, logos, etc.)
├── build          # Package and continuous integration directory
├── cmd            # Program entry directory
├── configs        # Directory for configuration files
├── deployments    # Configuration and template directories for IaaS, PaaS, system and container orchestrated deployments
├─ docs            # Design documentation and interface documentation directory
├── internal       # The code directory for private applications and libraries
│ ├── cache        # Business wrapper based cache directory
│ ├── config       # The configuration file directory for the Go structure
│ ├── dao          # Data access directory
│ ├── ecode        # Custom business error code directory
│ ├── handler      # Http's business function implementation directory
│ ├── model        # Database model directory
│ ├── routers      # Http routing directory
│ ├── rpcclient    # The client directory to connect to the rpc service
│ ├── server       # Service entry, including http, rpc, etc.
│ ├── service      # Rpc's business function implementation directory
│ └── types        # Directory of request and response types for http
├── pkg            # The directory of libraries that external applications can use
├── scripts        # A directory of scripts for performing various build, installation, analysis, etc. operations
├── test           # Additional external test procedures and test data
└── third_party    # External helpers, forked code, and other third-party tools

Web服务和RPC服务目录结构基本上是相同的,Web服务独有的目录(路由器,处理程序,内部目录中的类型)和RPC服务独有的一些目录(内部目录中的服务) 。

2安装海绵和依赖工具

2.1窗口环境安装依赖项

如果您使用Windows环境,则需要先安装相关的依赖项,然后忽略其他环境。

(1)安装mingw64

mingw64代表极简主义的gnufor Windows,可以免费提供且可以自由分布的Windows特定标头文件集合,并使用GNU工具集导入库,请下载预编译的源生成的二进制文件

>

https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/8.1.0/threads-posix/seh/x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z

下载并提取到D:\Program Files\mingw64目录后,修改系统环境变量路径添加D:\Program Files\mingw64\bin

安装make命令

切换到D:\Program Files\mingw64\bin目录,查找mingw32-make.exe可执行文件,将其复制并将其重命名为make.exe

(2)安装cmder

cmder 是一个增强的命令行工具,包含一些海绵依赖命令(bash,git等),cmder cmder at

下载

https://github.com/cmderdev/cmder/releases/download/v1.3.20/cmder.zip

下载并提取到D:\Program Files\cmder目录后,修改系统环境变量路径以添加D:\Program Files\cmder

2.2安装海绵

(1)安装GO

https://go.dev/dl/https://golang.google.cn/dl/下载要安装的版本(> = 1.16),将$GOROOT/bin添加到系统路径中。

注意:如果您没有科学的互联网访问,建议建立国内代理go env -w GOPROXY=https://goproxy.cn,direct

(2)Protoc的安装

https://github.com/protocolbuffers/protobuf/releases/tag/v3.20.3下载并添加 ProtoC 文件位于SystemPath下的目录。

(3)海绵安装

go安装github.com/zhufuyi/sponge/cmd/sponge@latest

注意:海绵二进制所在的目录必须在SystemPath下。

(4)依赖插件和工具的安装

海绵init

依赖性插件和工具在执行命令之后自动安装:protoc-gen-goprotoc-gen-go-grpcprotoc-gen-validateprotoc-gen-gotagprotoc-gen-go-ginprotoc-gen-go-ginprotoc-gen-go-rpc-tmplprotoc-gen-go-rpc-tmpl45,protoc-gen-openapiv2protoc-gen-docprotoc-gen-docgolangci-lintgolangci-lintprotoc-gen-go-rpc-tmpl9.48,swag,Abiao48,.48,.48,

如果存在依赖项工具安装错误,请执行重试命令。

海绵工具 - 安装

查看依赖项工具的安装。

# linux environment
sponge tools

# windows environment, need to specify bash.exe location
sponge tools --executor="D:\Program Files\cmder\vendor\git-for-windows\bin\bash.exe"

所有因工具的列表。

Installed dependency tools:
    ✔  go
    ✔  protoc
    ✔  protoc-gen-go
    ✔  protoc-gen-go-grpc
    ✔  protoc-gen-validate
    ✔  protoc-gen-gotag
    ✔  protoc-gen-go-gin
    ✔  protoc-gen-go-rpc-tmpl
    ✔  protoc-gen-openapiv2
    ✔  protoc-gen-doc
    ✔  swag
    ✔  golangci-lint
    ✔  go-callvis

Sponge 命令的帮助信息已详细示例,将-h添加到命令末尾以查看,例如sponge web model -h,这是通过生成Gorm的模型代码返回的帮助信息基于MySQL表。

3快速创建Web项目

3.1从MySQL创建HTTP服务

3.1.1创建表

要基于MySQL的数据表生成代码,请首先准备MySQL服务(docker install mysql)。例如,MySQL在数据库下有一个数据库学校和一个数据表老师,如下所示。

CREATE DATABASE IF NOT EXISTS school DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;

use school;

create table teacher
(
    id bigint unsigned auto_increment
        primary key,
    created_at datetime null,
    updated_at datetime null,
    deleted_at datetime null,
    name varchar(50) not null comment 'username',
    password varchar(100) not null comment 'password',
    email varchar(50) not null comment 'mail',
    phone varchar(30) not null comment 'mobile phone number',
    avatar varchar(200) null comment 'avatar',
    gender tinyint not null comment 'gender, 1:male, 2:female, other values:unknown',
    age tinyint not null comment 'age',
    birthday varchar(30) not null comment 'date of birth',
    school_name varchar(50) not null comment 'school name',
    college varchar(50) not null comment 'college',
    title varchar(10) not null comment 'title',
    profile text not null comment 'personal profile'
)
    comment 'teacher';

create index teacher_deleted_at_index
    on teacher (deleted_at);

将SQL DDL导入MySQL,以创建一所数据库学校,并在学校下面有一个桌子老师。

3.1.2生成HTTP服务代码

打开终端并执行命令。

sponge web http \
  --module-name=edusys \
  --server-name=edusys \
  --project-name=edusys \
  --repo-addr=zhufuyi \
  --db-dsn=root:123456@(192.168.3.37:3306)/school \
  --db-table=teacher \
  --out=./edusys

检查参数描述命令sponge web http -h,请注意,参数 repo-addr 是图像存储库地址,如果您使用official docker image repository,则只需要填写注册的Docker Repository的用户名,如果使用私有存储库地址,则需要填写完整的存储库地址。

生成完整的HTTP服务代码在当前目录Edusys中,具有以下目录结构。

.
├── build
├── cmd
│    └── edusys
│          └── initial
├── configs
├── deployments
│    ├── docker-compose
│    └── kubernetes
├── docs
├── internal
│    ├── cache
│    ├── config
│    ├── dao
│    ├── ecode
│    ├── handler
│    ├── model
│    ├── routers
│    ├── server
│    └── types
└── scripts

Edusys目录中的makefile文件,该文件集成了与编译,测试,运行和部署相关的命令,切换到Edusys目录以在
上运行服务

# Update swagger documentation
make docs

# Compile and run services
make run

如图3-1所示,将http://localhost:8080/swagger/index.html复制到浏览器以测试CRUD API。

http-swag1
图3-1 HTTP Swagger文档图

默认情况下,仅针对指标集合,每分钟资源统计信息和其他服务治理启用该服务。在实际应用中,根据需要进行一些调整。

  • 要将Redis用作缓存,请打开配置文件configs/edusys.yml,将 cachetype 字段值更改为redis,然后填写 redis 配置地址和端口。
  • 默认情况下,速率限制器,断路器,跟踪,服务注册和发现功能关闭,您可以打开配置文件configs/edusys.yml以打开相关功能,如果打开跟踪功能,则必须填写Jaeger中配置信息;如果打开服务注册和发现功能,则必须填写一个领事,ETCD,NACOS配置信息。
  • 如果添加或修改了配置字段名称,请执行命令sponge config --server-dir=./edusys以更新相应的GO结构;无需执行更新命令以仅修改字段值。
  • 修改与crud api相对应的错误代码信息,打开ingernal/ecode/teacher_http.go,修改变量 teacherno 值,这是唯一不重复的值,返回消息描述是根据您的需求修改的,此处添加了教师表操作的API自定义错误代码。

3.1.3生成处理程序代码

在服务中,通常有多个数据表,因此,如果添加了新的数据表,则如何使用sponge web handler命令自动将生成的处理程序代码自动填充到现有服务代码中,例如添加了数据表课程教学

create table course
(
    id bigint unsigned auto_increment
        primary key,
    created_at datetime null,
    updated_at datetime null,
    deleted_at datetime null,
    code varchar(10) not null comment 'course code',
    name varchar(50) not null comment 'course name',
    credit tinyint not null comment 'credits',
    college varchar(50) not null comment 'college',
    semester varchar(20) not null comment 'semester',
    time varchar(30) not null comment 'class time',
    place varchar(30) not null comment 'place of class'
)
    comment 'course';

create index course_deleted_at_index
    on course (deleted_at);


create table teach
(
    id bigint unsigned auto_increment
        primary key,
    created_at datetime null,
    updated_at datetime null,
    deleted_at datetime null,
    teacher_id bigint not null comment 'teacher id',
    teacher_name varchar(50) not null comment 'teacher name',
    course_id bigint not null comment 'course id',
    course_name varchar(50) not null comment 'course name',
    score char(5) not null comment 'students evaluate the quality of teaching, 5 grades: A,B,C,D,E'
)
    comment 'teacher course';

create index teach_course_id_index
    on teach (course_id);

create index teach_deleted_at_index
    on teach (deleted_at);

create index teach_teacher_id_index
    on teach (teacher_id);

生成包含CRUD业务逻辑的处理程序代码。

sponge web handler \
  --db-dsn=root:123456@(192.168.3.37:3306)/school \
  --db-table=course,teach \
  --out=./edusys

检查参数描述命令sponge web handler -h,参数out是指定现有的服务文件夹edusys,如果参数out为空,则必须指定module-name参数,在当前目录中生成处理程序subpodule代码,然后复制处理程序,请复制处理程序。对文件夹Edusys的代码,两种方式的效果都是相同的。

执行命令后,在edusys/internal目录中生成了课程和教学相关代码。

.
└── internal
      ├── cache
      ├── dao
      ├── ecode
      ├── handler
      ├── model
      ├── routers
      └── types

切换到Edusys目录并执行命令以运行服务。

# Update swagger documentation
make docs

# Compile and run services
make run

如图3-2所示,将http://localhost:8080/swagger/index.html复制到浏览器以测试CRUD API。

http-swag2
图3-2 HTTP Swagger文档图

实际使用需要修改自定义crud api以返回错误代码和消息,打开文件ingernal/ecode/course_http.go以修改变量 courseno 值,并打开文件ingernal/ecode/teach_http.go以修改变量 thockno 值。

尽管生成了每个数据表的CRUD API,但它不一定适合实际的业务逻辑,因此您需要手动添加业务逻辑代码,将数据库操作代码填充到internal/dao目录和业务逻辑代码到internal/handler目录。

3.2从原始文件创建HTTP服务

如果不需要标准的CRUD API HTTP服务代码,则可以自定义Proto文件中的API并使用Spong命令来生成HTTP服务和API模板代码。

3.2.1自定义API

以下是一个示例文件,contert.proto,每种方法都定义了路由和Swagger文档的描述。标签和验证描述可根据需要添加到消息中。

syntax = "proto3";

package api.edusys.v1;

import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

option go_package = "edusys/api/edusys/v1;v1";

// Generate *.swagger.json basic information
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
  host: "localhost:8080"
  base_path: ""
  info: {
    title: "edusys api docs";
    version: "v0.0.0";
  };
  schemes: HTTP;
  schemes: HTTPS;
  consumes: "application/json";
  produces: "application/json";
};

service teacher {
  rpc Register(RegisterRequest) returns (RegisterReply) {
    // Set up routing
    option (google.api.http) = {
      post: "/api/v1/Register"
      body: "*"
    };
    // Set the swagger document corresponding to the route
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Registered Users",
      description: "Submit information for registration",
      tags: "teacher",
    };
  }

  rpc Login(LoginRequest) returns (LoginReply) {
    option (google.api.http) = {
      post: "/api/v1/login"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Login",
      description: "Login",
      tags: "teacher",
    };
  }
}

message RegisterRequest {
  string name = 1;
  string email = 2;
  string password = 3;
}

message RegisterReply {
  int64 id = 1;
}

message LoginRequest {
  string email = 1;
  string password = 2;
}

message LoginReply {
  string token = 1;
}

3.2.2生成HTTP服务代码

打开终端并执行命令。

sponge web http-pb \
  --module-name=edusys \
  --server-name=edusys \
  --project-name=edusys \
  --repo-addr=zhufuyi \
  --protobuf-file=./teacher.proto \
  --out=./edusys

检查支持 *符号匹配的参数描述命令sponge web http-pb -h(示例--protobuf-file=*.proto),表明代码是基于批量触发文件生成的,并且多个proto文件包括至少一项服务,否则不允许代码生成。

生成HTTP服务代码的目录如下所示,与sponge web http生成的HTTP服务代码目录有一些区别添加了目录,没有缓存 dao 模型类型 目录中的目录。 处理程序类型目录,其中处理程序是拥有业务逻辑模板代码的目录,该目录将由命令自动生成。

.  
├── api
│    └── edusys
│          └──v1
├── build
├── cmd
│    └── edusys
│          └── initial
├── configs
├── deployments
│    ├── docker-compose
│    └── kubernetes
├── docs
├── internal
│    ├── config
│    ├── ecode
│    ├── routers
│    └── server
├── scripts
└── third_party

切换到Edusys目录并执行命令以运行服务。

# Generate *pb.go file, generate handler template code, update swagger documentation
make proto

# Compile and run services
make run

http://localhost:8080/apis/swagger/index.html复制到浏览器测试API,如图3-3所示,请求返回500错误,因为模板代码(内部/handler/handler/thercer_logic.go文件)直接调用panic("implement me"),旨在提示商务提示要填写的逻辑代码。

http-pb-swag
图3-3 HTTP Swagger文档图

3.2.3添加新的API

根据业务需求,需要在两种情况下添加新的API。

(1)将新的API添加到原始原始文件

打开api/edusys/v1/teacher.proto,例如添加 bindphone 方法,并填写路由和Swagger文档说明信息以完成添加新的API。

执行订单。

# Generate *pb.go file, generate handler template code, update swagger documentation
make proto

internal/handlerinternal/ecode目录中生成新的模板文件,然后将最新生成的模板代码复制到业务逻辑代码区域中。

  • 带有后缀的模板代码文件 .gen.dateTime internal/handler目录中生成(example thercector_logic.go.go.gen.xxxxxx225619),因为choste_logic.go。编写的逻辑代码,因此生成了一个新文件。打开文件contert_logic.go.gen.gen.xxxx225619,将添加方法的模板代码 bindphone api复制到there_logic.go文件中,然后填写业务逻辑代码。
  • 带有后缀的模板代码文件 .gen.dateTime internal/ecode目录中生成,并且将 bindphone api错误代码复制到Teactor_http.go文件中。
  • 使用后缀 .gen.dateetime 删除所有文件。

(2)将API添加到新的原始文件

例如,如果添加了新的课程。第3.2.1章并将 course.proto 文件复制到api/edusys/v1目录以完成新添加的API。

执行订单。

# Generate *pb.go file, generate handler template code, update swagger documentation
make proto

通过执行以下两个操作,使用课程internal/handler”,internal/ecodeinternal/routers目录中的名称前缀。

  • internal/handler/course.go文件中填写业务代码。
  • internal/ecode/course_http.go文件中修改自定义错误代码和消息描述。

3.2.4完善HTTP服务

sponge web http-pb命令生成的HTTP服务代码没有与daocachemodel和其他操纵数据相关的代码,如果您使用MySQL数据库和REDIS CASCE,用户可以自己实现它直接生成daocachemodel代码的工具。

生成CRUD操作数据库代码命令。

sponge web dao \
  --db-dsn=root:123456@(192.168.3.37:3306)/school \
  --db-table=teacher \
  --include-init-db=true \
  --out=./edusys

检查参数描述命令sponge web dao -h,参数-include-init-db仅在服务中使用一次,请在下次生成dao代码时删除参数-include-init-db,否则将导致不生成最新的dao代码,因为DB初始化代码代码已经存在。

无论您自己实施dao代码还是使用Sponge生成的dao代码,此后需要进行许多操作。

  • 将MySQL和REDIS添加到服务的初始化和发布资源代码,打开cmd/edusys/initial/initApp.go文件,反向拨打到MySQL和REDIS初始化代码,打开cmd/edusys/initial/registerClose.go文件,向MySQL和REDIS Reports Repording Resource Code进行反馈,初始代码是一次性更改。
  • 生成的dao代码和自定义方法注册登录 您需要在文件internal/dao/teacher.go中手动来补充代码(文件名老师是表的名称),然后在internal/handler/teacher. go中填写业务逻辑代码(文件名教师是proto文件的名称),如果错误代码,则使用internal/ecode目录中定义的错误代码返回错误,如果错误消息直接返回,请求侧将接收一条未知的错误消息,即未定义的错误消息。
  • 默认值使用本地内存进行缓存,将其更改为使用REDIS作为缓存,将字段 cachetype 在配置文件configs/edusys.yml中的redis更改为redis,然后填写redis地址和端口。

切换到Edusys目录再次运行服务。

go mod tidy

# Compile and run services
make run

打开http://localhost:8080/apis/swagger/index.html再次请求API,并正确返回数据。

3.3摘要

有两种生成HTTP服务代码,MySQL和原始文件的方法。

  • 根据MySQL生成的HTTP服务代码包括每个数据表的CRUD API代码,随后添加新API,您可以参考添加业务逻辑代码的CRUD方法,新添加的API需要手动填写Swagger Descriage中信息。
  • 从原始文件生成的HTTP服务不包括操作数据库代码,也不包括CRUD API逻辑代码,可以使用sponge web dao命令生成以根据需要对数据库代码进行操作。随着新的API的添加,除了生成处理程序模板代码,Swagger文档,路由注册代码和API的错误代码外,还将自动生成。

两种方式都可以完成相同的HTTP服务API,根据实际应用程序选择其中一个,如果您执行后端管理服务,请使用MySQL直接生产CRUD API代码,可以更少编写代码。对于自定义API服务的大多数需要,请使用proto文件生成HTTP服务的方式,此方式在编写原始文件之后,除了业务逻辑代码外,还可以通过插件生成其他代码。 。

4快速创建微服务

4.1从MySQL创建RPC服务

4.1.1生成RPC服务代码

使用第3.1.1节中的教师表作为示例,创建RPC服务。

sponge micro rpc \
  --module-name=edusys \
  --server-name=edusys \
  --project-name=edusys \
  --repo-addr=zhufuyi \
  --db-dsn=root:123456@(192.168.3.37:3306)/school \
  --db-table=teacher \
  --out=./edusys

检查参数描述命令sponge micro rpc -h,该命令在当前的Edusys目录中生成RPC服务代码,并使用以下目录结构。

.
├── api
│    ├── edusys
│    │    └── v1
│    └── types
├── build
├── cmd
│    └── edusys
│          └── initial
├── configs
├── deployments
│    ├── docker-compose
│    └── kubernetes
├── docs
├── internal
│    ├── cache
│    ├── config
│    ├── dao
│    ├── ecode
│    ├── model
│    ├── server
│    └── service
├── scripts
└── third_party

edusys目录中的makefile文件集成了与编译,测试,运行,部署等相关的命令。切换到edusys目录并执行命令以运行服务:。

# Generate *pb.go
make proto

# Compile and run services
make run

使用 goland vs code 打开internal/service/teacher_client_test.go文件

  • 对于 test_teacherservice_methods下的方法测试,请在测试前填写测试参数。
  • test_teacherservice_benchmark下执行方法压力测试,在测试前填写压力测试参数,执行后生成压力测试报告,然后将压力测试报告文件路径复制到浏览器以查看统计信息,如图4-1所示。

performance-test
图4-1性能测试报告图

从服务启动日志中,您可以看到端口上的默认侦听 8282 (RPC服务)和端口 8283 (收集​​指标或配置文件)已打开每分钟资源统计。实际上,根据需要进行一些修改。

  • 要将Redis用作缓存,请打开配置文件configs/edusys.yml,将 cachetype 将字段值更改为redis,然后填写 redis 配置地址和端口。
  • 默认情况下,速率限制器,断路器,跟踪,服务注册和发现功能关闭,您可以打开配置文件configs/edusys.yml以打开相关功能,如果打开跟踪功能,则需要填写Jaeger配置信息,如果打开服务注册和发现功能,则需要填写一个领事,ETCD,NACOS配置信息。
  • 如果添加或修改了配置字段名称,请执行命令sponge config --server-dir=./edusys以更新相应的GO结构;您无需执行更新命令即可仅修改字段值。
  • 修改与CRUD方法相对应的错误代码和错误消息,Open ingernal/ecode/teacher_rpc.go,修改变量 Teacherno 值(值是唯一的),根据您的需求修改返回消息描述,这里添加了教师表操作的API错误消息。

4.1.2生成服务代码

添加了两个新的表课程和教学,数据表的结构如下 3.1.3 ,生成了服务代码。

sponge micro service \
  --db-dsn=root:123456@(192.168.3.37:3306)/school \
  --db-table=course,teach \
  --out=./edusys

查看参数描述命令sponge micro service -h,参数out指定现有的rpc服务文件夹edusys,如果参数out为空,则必须指定module-nameserver-name参数,在当前目录中生成服务代码,然后将其手动复制至将其复制到它将其复制至文件夹Edusys,两种方式的效果都是相同的。

执行命令后,在以下目录中生成了课程和教学相关代码,如果添加自定义方法或新的协议缓冲器文件,则代码也将在以下目录中手动添加。

.
├── api
│    └── edusys
│          └── v1
└── internal
      ├── cache
      ├── dao
      ├── ecode
      ├── model
      └── service

切换到Edusys目录并执行命令以运行服务。

# Update *.pb.go
make proto

# Compile and run services
make run

使用 goland vs code 打开internal/service/course_client_test.gointernal/service/teach_client_test.go文件以测试CRUD方法,您需要在测试之前填写参数。

4.2从原始文件创建RPC服务

海绵不仅支持基于MySQL创建RPC服务,还支持基于原始文件生成RPC服务。

4.2.1自定义方法

以下是示例原始文件老师。

syntax = "proto3";

package api.edusys.v1;
option go_package = "edusys/api/edusys/v1;v1";

service teacher {
  rpc Register(RegisterRequest) returns (RegisterReply) {}
  rpc Login(LoginRequest) returns (LoginReply) {}
}

message RegisterRequest {
  string name = 1;
  string email = 2;
  string password = 3;
}

message RegisterReply {
  int64 id = 1;
}

message LoginRequest {
  string email = 1;
  string password = 2;
}

message LoginReply {
  string token = 1;
}

4.2.2生成RPC服务代码

打开终端并执行命令。

sponge micro rpc-pb \
  --module-name=edusys \
  --server-name=edusys \
  --project-name=edusys \
  --repo-addr=zhufuyi \
  --protobuf-file=./teacher.proto \
  --out=./edusys

检查支持 *符号匹配的参数描述命令sponge micro rpc-pb -h(示例--protobuf-file=*.proto),表明代码是基于批量原始文件生成的,并且多个proto文件包含至少一个服务,否则不会生成代码。

生成的RPC服务代码目录如下所示,sponge micro rpc生成的RPC服务代码目录存在一些差异,没有 Cache dao 模型内部目录下的子目录。

.
├── api
│    └── edusys
│          └── v1
├── build
├── cmd
│    └── edusys
│          └── initial
├── configs
├── deployments
│    ├── docker-compose
│    └── kubernetes
├── docs
├── internal
│    ├── config
│    ├── ecode
│    ├── server
│    └── service
├── scripts
└── third_party

切换到Edusys目录并执行命令以运行服务。

# Generate *pb.go file, generate service template code
make proto

# Compile and run services
make run

启动RPC服务后,使用 goland vs code 打开internal/service/teacher_client_test.go文件并测试 test_teacher_methods 下的每种方法,填写测试参数在测试之前,您会发现请求返回内部错误,因为在模板代码文件中,internal/service/teacher.go(文件名老师是proto filename)插入了代码panic("implement me"),该代码旨在提示填写业务逻辑代码。

4.2.3添加新方法

根据业务需求,需要添加新方法,在两种情况下运行。

(1)将新方法添加到原始原始文件

打开api/edusys/v1/teacher.proto并添加 bindphone 方法。

执行订单。

# Generate *pb.go file, generate service template code
make proto

internal/serviceinternal/ecode目录中生成模板代码,然后将模板代码复制到商业逻辑代码区域。

  • 带有后缀的模板代码文件 .gen.dateTime internal/service目录中生成(示例conterc.go.gen.gen.xxxxx225732),因为老师已经存在并且不会覆盖业务逻辑代码最初是编写的,因此生成了一个新文件,打开文件conterc.go.gen.xxxxxx225732,将 bindphone 方法添加到contert.go文件中的模板代码,然后填写业务逻辑代码。
  • 带有后缀的文件 conterry_rpc.go.go.gen.datetime 在internal/ecode目录中生成,并且与 bindphone 方法相对应的错误代码被复制到Teachter_rpc中.go文件。
  • 使用后缀 .gen.datetime
  • 删除所有文件。

(2)向新的原始文件添加新方法

例如,如果添加了新的 course.proto 文件,请将 course.proto 文件复制到api/edusys/v1目录以完成新添加的API。

执行订单。

# Generate *pb.go file, generate service template code
make proto

通过执行以下两个操作,使用课程 internal/serviceinternal/ecodeinternal/routers目录中的名称前缀。

  • internal/service/course.go文件中填写业务代码。
  • internal/ecode/course_rpc.go文件中修改自定义错误代码和消息描述。

4.2.4完善RPC服务代码

sponge micro rpc-pb命令生成的RPC服务代码没有与daocachemodel和其他操纵数据相关的代码,如果您使用MySQL数据库和REDIS CACE,用户可以自己实现它生成daocachemodel代码的工具直接。

生成CRUD操作数据库代码命令。

sponge micro dao \
  --db-dsn=root:123456@(192.168.3.37:3306)/school \
  --db-table=teacher \
  --include-init-db=true \
  --out=./edusys

检查参数描述命令sponge micro dao -h,参数-include-init-db仅在服务中使用一次,请在下次生成dao代码时删除参数-include-init-db,否则会导致最新的dao代码不生成。

>>

>

无论是自己实施dao代码还是使用Sponge生成的dao代码,此后需要进行许多操作。

  • 将MySQL和REDIS添加到服务的初始化和发布资源代码,打开cmd/edusys/initial/initApp.go文件,反向拨打到MySQL和REDIS初始化代码,打开cmd/edusys/initial/registerClose.go文件,向MySQL和REDIS Reports Repording Resource Code进行反馈,初始代码是一次性更改。
  • 生成的dao代码和自定义方法注册登录 您需要在文件internal/dao/teacher.go中手动来补充代码(文件名老师是表的名称),然后在internal/handler/teacher. go中填写业务逻辑代码(文件名教师是proto文件的名称),如果错误代码,则使用internal/ecode目录中定义的错误代码返回错误,如果错误消息是直接返回的,请求端将接收一条未知的错误消息,即未定义的错误消息。
  • 默认值使用本地内存进行缓存,将其更改为使用redis作为缓存,将字段 cacheType 更改为REDIS在配置文件configs/edusys.yml中的REDIS,然后填充Redis地址和端口。

切换到Edusys目录再次运行服务。

go mod tidy

# Compile and run services
make run

启动RPC服务后,使用 goland vs code 打开internal/service/teacher_client_test.go文件以测试每种方法。

4.3从原始文件创建RPC网关服务

微服务通常提供细粒度的API,并且提供给客户的实际API是粗粒度的API,需要从不同的微服务中汇总的数据,以形成满足实际要求的API,这是RPC网关。 RPC网关本身也是HTTP服务,如图4-2所示。

rpc-gateway
图4-2 RPC网关框架图

4.3.1定义协议缓冲区

以电子商务微服务为例,产品详细信息页面具有诸如产品,库存和产品评估之类的信息,它们存储在不同的微服务中,并且通常很少要求每个微服务以获取数据,直接向微服务请求将导致网络压力繁殖,通常的做法是汇总多个微服务数据以立即返回。

以下四个文件夹在每个文件夹下都有一个简单的原始文件。

  • 评论:评论服务的原始目录
  • 库存:库存服务的原始目录
  • 产品:产品和服务的原始目录
  • shopgw :RPC网关服务的原始目录
.
├── comment
│    └── v1
│          └──comment.proto
├── inventory
│    └── v1
│          └── inventory.proto
├── product
│    └── v1
│          └── product.proto
└── shopgw
      └── v1
            └── shopgw.proto

comment.proto 文件如下。

syntax = "proto3";

package api.comment.v1;

option go_package = "shopgw/api/comment/v1;v1";

service Comment {
  rpc ListByProductID(ListByProductIDRequest) returns (ListByProductIDReply) {}
}

message ListByProductIDRequest {
  int64 productID = 1;
}

message CommentDetail {
  int64 id=1;
  string username = 2;
  string content = 3;
}

message ListByProductIDReply {
  int32 total = 1;
  int64 productID = 2;
  repeated CommentDetail commentDetails = 3;
}

intingrory.proto 文件如下。

syntax = "proto3";

package api.inventory.v1;

option go_package = "shopgw/api/inventory/v1;v1";

service Inventory {
  rpc GetByID(GetByIDRequest) returns (GetByIDReply) {}
}

message GetByIDRequest {
  int64 id = 1;
}

message InventoryDetail {
  int64 id = 1;
  float num = 4;
  int32 soldNum =3;
}

message GetByIDReply {
  InventoryDetail inventoryDetail = 1;
}

product.proto 文件如下。

syntax = "proto3";

package api.product.v1;

option go_package = "shopgw/api/product/v1;v1";

service Product {
  rpc GetByID(GetByIDRequest) returns (GetByIDReply) {}
}

message GetByIDRequest {
  int64 id = 1;
}

message ProductDetail {
  int64 id = 1;
  string name = 2;
  float price = 3;
  string description = 4;
}

message GetByIDReply {
  ProductDetail productDetail = 1;
  int64 inventoryID = 2;
}

shopgw.proto 文件的内容如下。 RPC网关服务的原始服务与其他微服务的原型有点不同,因为您需要指定方法的路由和Swagger描述信息。

syntax = "proto3";

package api.shopgw.v1;

import "api/product/v1/product.proto";
import "api/comment/v1/comment.proto";
import "api/inventory/v1/inventory.proto";
import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

option go_package = "shopgw/api/shopgw/v1;v1";

// default settings for generating *.swagger.json documents
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
  host: "localhost:8080"
  base_path: ""
  info: {
    title: "eshop api docs";
    version: "v0.0.0";
  };
  schemes: HTTP;
  schemes: HTTPS;
  consumes: "application/json";
  produces: "application/json";
};

service ShopGw {
  rpc GetDetailsByProductID(GetDetailsByProductIDRequest) returns (GetDetailsByProductIDReply) {
    option (google.api.http) = {
      get: "/api/v1/detail"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "get detail",
      description: "get detail from product id",
      tags: "shopgw",
    };
  }
}

message GetDetailsByProductIDRequest {
  int64 productID = 1;
}

message GetDetailsByProductIDReply {
  api.product.v1.ProductDetail productDetail = 1;
  api.inventory.v1.InventoryDetail inventoryDetail = 2;
  repeated api.comment.v1.CommentDetail commentDetails = 3;
}

4.3.2生成RPC网关服务代码

shopgw.proto 文件生成RPC网关服务代码。

sponge micro rpc-gw-pb \
  --module-name=shopgw \
  --server-name=shopgw \
  --project-name=eshop \
  --repo-addr=zhufuyi \
  --protobuf-file=./shopgw/v1/shopgw.proto \
  --out=./shopgw

查看参数说明命令sponge micro rpc-gw-pb -h,生成的RPC网关服务代码在当前的ShopGW目录中,带有以下目录结构。

.
├── api
│    └── shopgw
│          └── v1
├── build
├── cmd
│    └── shopgw
│          └── initial
├── configs
├── deployments
│    ├── docker-compose
│    └── kubernetes
├── docs
├── internal
│    ├── config
│    ├── ecode
│    ├── routers
│    ├── rpcclient
│    └── server
├── scripts
└── third_party

因为 product.proto 取决于文件 product.proto neventory.proto comment.proto ,将三个因原始文件复制到API目录,API目录结构如下。

.
├── comment
│    └── v1
│          └── comment.proto
├── inventory
│    └── v1
│          └── inventory.proto
├── product
│    └── v1
│          └── product.proto
└── shopgw
      └── v1
            └── shopgw.proto

切换到ShopGW目录以运行服务。

# Generate *pb.go files, generate template code, update swagger documentation
make proto

# Compile and run services
make run

http://localhost:8080/apis/swagger/index.html复制到浏览器以测试API,如图4-3所示。该请求返回500错误,因为模板代码(内部/service/shopgw_logic.go文件)直接致电panic("implement me"),这是为了提示填写业务逻辑代码。

rpc-gw-swag
图4-3 RPC网关图的Swagger文档API

4.3.3完善RPC网关服务代码

(1)生成代码以连接到RPC服务器

该服务尚未与RPC服务代码有连接,以下是生成客户端代码以连接到 product 库存,和评论 RPC服务。

sponge micro rpc-cli \
  --rpc-server-name=comment,inventory,product \
  --out=./shopgw

查看参数描述命令sponge micro rpc-cli -h,参数out指定现有的服务文件夹shopgw,生成的代码在internal/rpcclent目录中。

(2)初始化和关闭RPC连接

连接RPC服务器代码包括初始化和关闭功能,这些功能根据

的调用模板代码填充。
  • 在启动服务时初始化,根据cmd/shopgw/initial/initApp.go文件中的代码段// initializing the rpc server connection,根据模板调用初始化函数。
  • 要在关闭服务时发布资源,根据代码段// close the rpc client connection中的cmd/shopgw/initial/registerClose.go文件中的模板调用发布函数。

(3)配置的修改

连接 product 库存注释三个RPC服务代码,但尚未配置RPC服务地址,您需要要在字段grpcClient下添加配置文件configs/shopgw.yml以连接产品,库存,评论三个微服务配置信息。

grpcClient:
  - name: "product"
    host: "127.0.0.1"
    port: 8201
    registryDiscoveryType: ""
  - name: "inventory"
    host: "127.0.0.1"
    port: 8202
    registryDiscoveryType: ""  
  - name: "comment"
    host: "127.0.0.1"
    port: 8203
    registryDiscoveryType: ""

如果RPC服务使用注册和发现,则该字段registryDiscoveryType填写了支持领事等的服务注册和发现类型,以及NACOS。

生成相应的GO结构代码。

sponge config --server-dir=./shopgw

(4)填写操作代码

以下是在模板文件中填充的示例业务逻辑代码internal/service/shopgw_logic.go product 库存评论三个RPC服务中获取数据分别聚集在一起并返回。

package service

import (
    "context"

    commentV1 "shopgw/api/comment/v1"
    inventoryV1 "shopgw/api/inventory/v1"
    productV1 "shopgw/api/product/v1"
    shopgwV1 "shopgw/api/shopgw/v1"
    "shopgw/internal/rpcclient"
)

var _ shopgwV1.ShopGwLogicer = (*shopGwClient)(nil)

type shopGwClient struct {
    productCli productV1.ProductClient
    inventoryCli inventoryV1.InventoryClient
    commentCli commentV1.CommentClient
}

// NewShopGwClient creating rpc clients
func NewShopGwClient() shopgwV1.ShopGwLogicer {
    return &shopGwClient{
        productCli: productV1.NewProductClient(rpcclient.GetProductRPCConn()),
        inventoryCli: inventoryV1.NewInventoryClient(rpcclient.GetInventoryRPCConn()),
        commentCli: commentV1.NewCommentClient(rpcclient.GetCommentRPCConn()),
    }
}

func (c *shopGwClient) GetDetailsByProductID(ctx context.Context, req *shopgwV1.GetDetailsByProductIDRequest) (*shopgwV1.GetDetailsByProductIDReply, error) {
    productRep, err := c.productCli.GetByID(ctx, &productV1.GetByIDRequest{
        Id: req.ProductID,
    })
    if err ! = nil {
        return nil, err
    }

    inventoryRep, err := c.inventoryCli.GetByID(ctx, &inventoryV1.GetByIDRequest{
        Id: productRep.InventoryID,
    })
    if err ! = nil {
        return nil, err
    }

    commentRep, err := c.commentCli.ListByProductID(ctx, &commentV1.ListByProductIDRequest{
        ProductID: req,
    })
    if err ! = nil {
        return nil, err
    }

    return &shopgwV1.GetDetailsByProductIDReply{
        ProductDetail: productRep.ProductDetail,
        InventoryDetail: inventoryRep.InventoryDetail,
        CommentDetails: commentRep,
    }, nil
}

再次开始服务。

# Compile and run services
make run

在浏览器中访问http://localhost:8080/apis/swagger/index.html时,请求返回503错误(服务不可用),因为三个RPC服务 product 库存评论正在运行。

所有三种RPC服务的代码 product 库存评论尚不可用,因此如何正确启动它们。这三个RPC服务的原始文件已经可用,并且可以轻松地生成代码并根据 4.2节从proto Files创建RPC服务步骤

来启动服务。。

4.4摘要

RPC服务代码的生成基于MySQL和Proto Files,根据Proto File方法,除了支持RPC服务代码的生成外,还支持RPC Gateway Service(HTTP)代码的生成。

  • 根据MySQL生成的RPC服务代码包括每个数据表的CRUD方法逻辑代码和原始代码,随后,如果要添加新方法,只需在Proto File中定义它们,手动添加业务逻辑代码可以参考CRUD逻辑代码。
  • 基于原始文件生成的RPC服务代码不包括操作数据库代码,但是您可以使用sponge web dao命令来生成操作数据库代码,基于原始文件生成服务模板代码,并在模板代码中填充业务逻辑代码。 /li>
  • 生成基于原始文件的RPC网关服务代码,原始文件中的API定义,基于原始文件生成服务模板代码,在模板代码中填充业务逻辑代码,与sponge micro rpc-cli命令结合使用。

根据实际方案,选择生成相应的服务代码,如果主要是添加,删除和检查数据表,则根据MySQL生成的RPC服务可以更少编写代码;如果更多的自定义方法,请根据原始生成的RPC服务更合适; RPC到HTTP使用RPC网关服务。

5服务治理

5.1跟踪

5.1.1开始Jaeger和Elasticsearch Services

使用Jaeger进行跟踪和弹性搜索进行存储,并使用docker-compose在本地启动这两种服务。

(1)Elasticsearch Service

这是startup script for the elasticsearch service .env 文件是Elasticsearch的启动配置,启动Elasticsearch服务。

docker -compose -d

(2)Jaeger Services

这是jaeger service startup script .env 文件是配置Jaeger信息并启动Jaeger服务。

docker -compose -d

访问浏览器http://localhost:16686中的Jaeger查询主页。

5.1.2单个服务跟踪示例

使用第3.1.2节中创建的HTTP服务代码为例,请修改配置文件configs/edusys.yml启用跟踪(field enabletrace)并填写Jaeger配置信息。

>

如果要跟踪redis,启用redis缓存,将缓存类型字段更改为 cachetype 值重复并配置redis配置,并使用docker在本地启动redis服务,即redis service startup script。<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< /p>

启动HTTP服务。

# Compile and run services
make run

http://localhost:8080/swagger/index.html复制到浏览器以访问Swagger Home Page以请求GET查询为例,并连续两次请求相同的ID,并在图5-1中显示的跟踪。

one-server-trace
图5-1单服务痕迹图

从图中您可以看到第一个请求有4个跨度,

  • 请求接口/api/v1/teacher/1
  • Querying redis
  • 查询mysql
  • 设置redis缓存

这意味着第一个请求从redis抬起来,不会击中缓存,然后读取MySQL的数据,最后放置缓存。

第二个请求只有2个跨度。

  • 请求api /api/v1/teacher/1
  • Querying redis

这意味着第二个请求直接击中缓存,而查询MySQL和设置缓存过程少于第一个。

这些跨度是自动生成的,您需要手动添加自定义跨度,添加跨度示例。

import "github.com/zhufuyi/sponge/pkg/tracer"

tags := map[string]interface{}{"foo": "bar"}
_, span := tracer.NewSpan(ctx, "spanName", tags)  
defer span.End()

5.1.3多服务跟踪示例

第4.3节生成的RPC网关服务代码为例,总共四个服务 shopgw product 库存注释,修改四个服务的配置(在配置目录中),打开跟踪,填写Jaeger配置信息。

内部/服务 product 库存评论服务中,找到模板文件目录,填充代码代替panic("improve me")以使代码正确执行,并手动添加 span 添加随机延迟。

开始四个服务 shopgw product 库存评论,然后访问浏览器中的http://localhost:8080/apis/swagger/index.html要执行GET请求,并且跟踪页面如图5-2所示。

multi-servers-trace
图5-2多功能痕量图

从图中可以看到,有10个跨度,主链接。

  • 请求api /api/v1/detail
  • ShopGW服务致电产品客户
  • 产品的RPC服务器
  • Mockdao在产品服务中手动添加
  • ShopGW服务致电库存客户端
  • 库存的RPC服务器
  • 在库存服务中手动添加MockDao
  • ShopGW服务致电评论客户端
  • 评论的RPC服务器
  • Mockdao在评论服务中手动添加

shopgw服务调用 product 库存评论串行获取数据,但实际上,有效率更高的时间效率并行打电话给它们,但要小心控制并发过程的数量。

5.2监视

5.2.1开始普罗米修和格拉法纳服务

使用Prometheus用于收集指标和Grafana进行显示,并使用Docker在本地启动这两种服务。

(1)Prometheus Services

这是启动Prometheus服务的prometheus service startup script

docker -compose -d

访问您的浏览器http://localhost:9090中的Prometheus主页。

(2)Grafana服务

这是启动Grafana服务的grafana service startup script

docker -compose -d

访问浏览器中的Grafana主页http://localhost:33000,为Prometheus http://192.168.3.37:9090设置数据源,请记住Prometheus的数据源名称(这里是 Prometheus ),以及 dataSource 后来导入到监视面板中的JSON的值应相同。

5.2.2 HTTP服务监视

作为一个例子,第3.1.2节生成的HTTP服务代码默认情况下提供了指示器API http://localhost:8080/metrics

(1)将监视目标添加到Prometheus

打开Prometheus配置文件Prometheus.yml并添加采集目标。

  - job_name: 'http-edusys'
    scrape_interval: 10s
    static_configs:
      - targets: ['localhost:8080']

注意:如果您使用vim修改Prometheus.yml文件,则必须在修改它之前将文件Prometheus.yml权限更改为0777,否则修改配置文件不能同步到容器中。

>

执行使Prometheus配置生效的请求curl -X POST http://localhost:9090/-/reload,请等待片刻,然后在浏览器中访问http://localhost:9090/targets,以检查新添加的捕获目标是否生效。

(2)向Grafana添加一个监视面板

http monitoring panel导入Grafana,如果在监视接口中没有显示数据,请检查JSON名称中的数据源是否与Grafana配置Prometheus数据源名称相同。

(3)压缩测试API,观察监视数据

使用wrk工具进行压力测试API

# api 1
wrk -t2 -c10 -d10s http://192.168.3.27:8080/api/v1/teacher/1

# api 2
wrk -t2 -c10 -d10s http://192.168.3.27:8080/api/v1/course/1

监视接口如图5-3所示。

http-grafana
图5-3 HTTP服务监视图

5.2.3 RPC服务监视

作为示例,第4.1.1节生成的RPC服务代码默认情况下提供了指示器API http://localhost:8283/metrics

(1)将监视目标添加到Prometheus

打开Prometheus配置文件Prometheus.yml并添加采集目标。

  - job_name: 'rpc-server-edusys'
    scrape_interval: 10s
    static_configs:
      - targets: ['localhost:8283']

执行使Prometheus配置生效的请求curl -X POST http://localhost:9090/-/reload,请等待片刻,然后在浏览器中访问http://localhost:9090/targets,以检查新添加的捕获目标是否有效。

(2)向Grafana添加一个监视面板

rpc server monitoring panel导入Grafana,如果监视接口中未显示数据,请检查JSON中的数据源名称是否与Grafana配置Prometheus数据源名称相同。

(3)压电RPC方法,观察监测数据

使用 goland vs代码打开internal/service/teacher_client_test.go文件,并在 test_teacherservice_methods test_teacherservice_benchmark 中测试每种方法。 /p>

监视结果如图5-4所示。
rpc-grafana
图5-4 RPC服务器监视图

以上是对RPC服务器的监视,RPC客户端的监视是相似的,rpc client monitoring panel

5.2.4在普罗米修斯中自动添加和去除监测目标

Prometheus支持使用领事的服务注册和发现自动添加和删除监视目标的动态配置。

从本地开始领事服务,这是consul service startup script

打开Prometheus config Prometheus.yml并添加领事配置。

  - job_name: 'consul-micro-exporter'
    consul_sd_configs:
      - server: 'localhost:8500'
        services: []  
    relabel_configs:
      - source_labels: [__meta_consul_tags]
        regex: . *edusys.*
        action: keep
      - regex: __meta_consul_service_metadata_(. +)
        action: labelmap

执行使Prometheus配置进行的请求效用curl -X POST http://localhost:9090/-/reload

在Prometheus中配置了领事服务发现后,将服务的地址信息推向领事,然后推送信息Edusys_exporter.json文件如下。

{
  "ID": "edusys-exporter",
  "Name": "edusys",
  "Tags": [
    "edusys-exporter"
  ],
  "Address": "localhost",
  "Port": 8283,
  "Meta": {
    "env": "dev",
    "project": "edusys"
  },
  "EnableTagOverride": false,
  "Check": {
    "HTTP": "http://localhost:8283/metrics",
    "Interval": "10s"
  },
  "Weights": {
    "Passing": 10,
    "Warning": 1
  }
}

curl -xput -data @edusys_exporter.json http://localhost:8500/v1/agent/service/register

等待片刻,然后在浏览器中打开http://localhost:9090/targets,以检查新添加的采集目标是否有效。然后关闭服务,等待一段时间,然后检查收购目标是否自动删除。

对于您自己的服务,您通常会在开始服务的同时提交信息,将Edusys_exporter.json转换为GO struct,并在程序内拨打HTTP客户端以提交该客户端以提交为领事。

5.3收集GO计划配置文件

通常使用PPROF工具查找和找到程序问题,尤其是在线GO程序问题可以自动保存程序运行站点(配置文件),然后使用工具PPROF分析来找到问题。

海绵生成的服务支持 http api 系统信号通知要收集配置文件,默认情况下启用了系统信号通知方法,只需使用一个即可。

5.3.1通过HTTP收集配置文件

通过HTTP API收集配置文件的收集方式默认情况下,如果您需要打开,请将字段enableHTTPProfile的配置修改为true,通常用于开发或测试,如果线路打开会有很小的性能损失,则根据实际情况是否打开使用。

默认路由/debug/pprof go tool pprof 工具结合使用,您可以随时分析程序的当前运行状态。

5.3.2通过系统信号通知采集配置文件

使用HTTP API,程序背景是定期录制与配置文件相关的信息等,大多数时间都不会读取这些配置文件,只有在需要时才能得到改进,然后开始收集配置文件,自动关闭收集后,海绵生成的服务支持聆听系统信号以启动和停止收集配置文件,默认使用 sigtrap (5)系统信号(建议更改为Sigusr1,在Windows环境中不支持) ,向服务发送信号。

# View service pid by name (second column)
ps aux | grep service name

# Send a signal to the service
kill -trap pid value

# kill -usr1 pid value

服务接收到系统信号通知后,它开始收集配置文件并将其保存到/tmp/service_name_profile目录,默认集合长度为60秒,在60秒后,它自动停止收集配置文件,如果您只想收集。 30秒,发送第一个信号开始收集,大约30秒后发送第二个信号,以表明它停止收集配置文件,类似于开关。默认获取 cpu 内存 goroutine block mutex threadCreate 六种类型的配置文件,文件格式date_time_pid_service_name_profile_type.out,示例。

xxx221809_58546_edusys_cpu.out
xxx221809_58546_edusys_mem.out
xxx221809_58546_edusys_goroutine.out
xxx221809_58546_edusys_block.out
xxx221809_58546_edusys_mutex.out
xxx221809_58546_edusys_threadcreate.out

由于跟踪的配置文件相对较大,因此默认情况下不会捕获,并且可以根据实际需求捕获跟踪(服务启动时call.enabletrace())。

获得离线文件后,使用交互式或接口方法使用PPROF工具对其进行分析。

# Interactive
go tool pprof [options] source

# interface
go tool pprof -http=[host]:[port] [options] source

5.3.3自动配置文件捕获

上面的所有都是手动配置集合,通常希望在出现问题时自动收集配置文件。海绵生成的服务默认支持自动配置文件收集,并与资源统计的警报功能一起实现。警报条件。

  • 连续记录程序的CPU使用3次(默认每分钟一次),并在3次平均使用率超过80%时触发警报。
  • 记录程序连续3次使用物理内存(默认情况下一次),并在平均系统内存使用率超过80%时触发警报。
  • 如果警报阈值连续超过,则警报之间的默认间隔为15分钟。

当触发警报时,程序内部调用杀伤函数发送X系统信号以通知采集配置文件,并将获取的配置文件保存到/tmp/service name_profile目录,实际上是的基础。通过系统信号的采集配置文件将手动触发器更改为自动触发器,即使在深夜,程序的CPU或内存太高,第二天,您也可以分析配置文件以找出该程序的位置导致CPU或内存太高。

注意:自动配置文件集合不适合Windows环境。

5.4注册中心

海绵生成的服务默认情况下支持Nacos配置中心。配置中心的作用是统一不同环境和服务的配置管理,有效地解决了地面静态配置的缺点。

在本地启动NACOS服务,这是nacos service startup configuration,启动NACOS服务后,打开浏览器http://localhost:8848/nacos/index.html中的管理接口,登录到帐户密码以输入主接口。

使用第3.1.2节生成的HTTP服务代码作为使用配置中心NACOS的示例,在NACOS接口中创建命名空间edusys,然后创建具有edusys.yml的数据ID值的新配置,dev的组值,以及configs/edusys.yml文件内容的配置内容值,如图5-3所示。

nacos-config
图5-3 NACOS添加服务配置

在Edusys目录中打开配置中心文件configs/edusys_cc.yml并填写NACOS配置信息。

# Generate the go struct command: sponge config --server-dir=./serverDir

# nacos settings
nacos:
  ipAddr: "192.168.3.37" # server address
  port: 8848 # listening port
  scheme: "http" # http or https
  contextPath: "/nacos" # path
  namespaceID: "ecfe0595-cae3-43a2- 9e47-216dc92207f9" # namespace id
  group: "dev" # group name: dev, prod, test
  dataID: "edusys.yml" # config file id
  format: "yaml" # configuration file type: json,yaml,toml

编译和启动Edusys服务。

# Switch to the main.go location
cdd cmd/edusys

# Compilation
go build

# Run
./edusys -enable-cc -c=../../configs/edusys_cc.yml

启动服务参数-c表示指定了配置文件,并且参数-enable-cc表示配置是从配置中心获得的。

5.5费率限制器和断路器

Sponge创建的服务支持速率限制器和断路器,默认情况下是关闭的。打开服务配置文件并将字段 enableLimit 修改为true的值以启用速率限制器,并将字段 enableCircuitBreaker 修改为true启用断路器。

速率限制器和断路器使用第三方库aegis,该图书馆根据系统资源和错误率进行适应。由于不同的服务器具有不同的处理功能和参数的设置不佳,因此使用自适应参数避免了每个服务手动设置参数的麻烦。

6连续集成部署

Sponge Sponge支持构建和部署在jenkins中创建的服务,部署目标可以是Docker,k8s,部署脚本在 exployments 目录中,以下是使用K8S使用K8S的示例詹金斯。

6.1构建Jenkins-Go平台

为了能够在容器中编译GO代码,您需要构建一个已经构建的jenkins-go image的Jenkins-Go图像。如果您想自己构建jenkins-go图像,可以参考docker build脚本Dokerfile

准备jenkins-go图像后,您还需要准备一个K8S群集(有许多K8S群集教程在线),K8S Forensics File和命令行工具kubectl以确保您有权在k8中操作K8S在jenkins-go容器。

jenkins-go启动脚本,docker-compose.yml,读取

version: "3.7"
services:
  jenkins-go:
    image: zhufuyi/jenkins-go:2.37
    restart: always
    container_name: "jenkins-go"
    ports:
      - 38080:8080
    #- 50000:50000
    volumes:
      - $PWD/jenkins-volume:/var/jenkins_home
      # docker configuration
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/bin/docker:/usr/bin/docker
      - /root/.docker/:/root/.docker/
      # k8s api configuration directory, including config file
      - /usr/local/bin/kubectl:/usr/local/bin/kubectl
      - /root/.kube/:/root/.kube/
      # go related tools
      - /opt/go/bin/golangci-lint:/usr/local/bin/golangci-lint

启动jenkis-go服务。

docker -compose -d

访问浏览器中的http://localhost:38080,第一次启动它需要管理键(执行命令以获取docker exec jenkins-go cat /var/jenkins_home/secrets/initialAdminPassword),然后安装推荐的插件并设置admin帐户密码,然后安装一些您需要使用和使用和使用的插件一些自定义设置。

(1)插件的安装

# Chinese plugin
Locale

# Add parametric build plugins
Extended Choice Parameter

# Add git parameters plugin
Git Parameter

# Account management
Role-based Authorization Strategy

*(2)集中 *

单击[管理Jenkins] - > [配置系统]选项,查找[Locale]选项,输入[ZH_CN],检查以下选项,最后单击[Apply]。

(3)全局参数的配置

仪表板 - >系统管理 - >系统配置 - >检查环境变量

设置容器图像的存储库地址。

# Development environment image repository
DEV_REGISTRY_HOST http://localhost:27070

# Test environment image repository
TEST_REGISTRY_HOST http://localhost:28080

# Production environment image repository
PROD_REGISTRY_HOST http://localhost:29090

6.2创建模板

为Jenkins创建新任务的一种相对简单的方法是在创建新任务时导入现有模板,然后修改GIT存储库地址。您第一次使用Jenkins并且还没有模板,您可以按照以下步骤创建一个。

(1)创建一个新任务,如图6-1所示。

create-job
图6-1任务创建屏幕

(2)使用参数名称GIT_parameter,参数化配置设置,如图6-2所示。

parametric-construction
图6-2设置参数构建图

(3)设置管道,如图6-3所示。

pipe-line
图6-3设置管道屏幕图

(4)建筑项目

单击用参数构建在左菜单栏上,然后选择要分支或标签的分支或标签,如图6-4所示。

build-job
图6-4参数构建图

6.3部署到K8S

第3.1.2章中的Edusys服务为例,以Jenkins的形式构建并部署到K8。

该服务的第一个构建需要一些准备工作。

(1)将EDUSYS代码上传到代码存储库。

(2)准备Docker Image存储库,并确保Jenkins-Go所在的Docker有权将图像上传到图像存储库。

(3)确保您有权从K8S群集节点上的镜像中摘取图像,并执行命令以在已登录的Docker Image repository Server上生成键。

kubectl create secret generic docker-auth-secret \
    --from-file=.dockerconfigjson=/root/.docker/config.json \
    --type=kubernetes.io/dockerconfigjson

(4)在K8S创建相关资源。

# Switch to directory
cd deployments/kubernetes

# Create namespace, name corresponds to spong create service parameter project-name
kubectl apply -f ./*namespace.yml

# Create configmap, service
kubectl apply -f ./*configmap.yml
kubectl apply -f ./*svc.yml

(5)如果要使用固定通知查看构建部署结果,请在代码库下打开 jenkinsfile 文件,请找到字段 tel_num 并填写手机号码,找到 access_token 并填写令牌值。

准备准备后,使用上面创建的模板(名称海绵)创建一个新任务(名称Edusys),然后修改GIT存储库,保存任务并启动参数构建,构造的结果如图6-5所示。

run-job
图6-5 Jenkins构建结果图

使用命令kubectl get all -n edusys查看在K8S中运行的Edusys服务的状态。

NAME                             READY   STATUS    RESTARTS   AGE
pod/edusys-dm-77b4bcccc5-8xt8v   1/1     Running   0          21m

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/edusys-svc   ClusterIP   10.108.31.220   <none>        8080/TCP   27m

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/edusys-dm   1/1     1            1           21m

NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/edusys-dm-77b4bcccc5   1         1         1       21m

在本地测试以查看是否可以访问

# Proxy ports
kubectl port-forward --address=0.0.0.0 service/edusys-svc 8080:8080 -n edusys

# Requests
curl http://localhost:8080/api/v1/teacher/1

Sponge生成的服务包括Jenkinsfile,构建和上传图像脚本以及K8S部署脚本,这些脚本基本上可以在不修改脚本的情况下使用,或者您可以修改脚本以适合您的方案。

>

如果对您有用,请给它星星。