介绍

经过一个完好比方,介绍怎么高雅封闭 gogf/gf 微服务。

什么是高雅封闭?

在进程收到封闭信号时,我们需求封闭后台运转的逻辑,比方,MySQL 衔接等等。

我们将会运用 rk-boot 来发动 gogf/gf 微服务。 rk-boot 是一个可经过 YAML 发动多种 Web 服务的结构。请参阅本文最终章节,了解 rk-boot 细节。

请访问如下地址获取完好教程:rkdocs.netlify.app/cn

装置

go get github.com/rookie-ninja/rk-boot/gf

快速开始

1.创立 boot.yaml

boot.yaml 文件会告知 rk-boot 怎么发动 gogf/gf 服务。

---
gf:
  - name: greeter
    port: 8080
    enabled: true

2.创立 main.go

经过 AddShutdownHookFunc() 来增加 shutdownhook 函数。

这儿需求增加: import _ “github.com/rookie-ninja/rk-boot/gf”

否则 rk-boot 无法读取 boot.yaml 文件里的内容。

// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main
import (
	"context"
	"fmt"
	"github.com/rookie-ninja/rk-boot"
	_ "github.com/rookie-ninja/rk-boot/gf"
)
func main() {
	// Create a new boot instance.
	boot := rkboot.NewBoot()
	boot.AddShutdownHookFunc("shutdown-hook", func() {
		fmt.Println("shutting down")
	})
	// Bootstrap
	boot.Bootstrap(context.Background())
	// Wait for shutdown sig
	boot.WaitForShutdownSig(context.Background())
}

3.发动 main.go

$ go run main.go
2022-01-05T18:24:36.293+0800    INFO    boot/gf_entry.go:1050   Bootstrap gfEntry       {"eventId": "fabd662e-801c-4c8b-b596-f55001a66d62", "entryName": "greeter"}
------------------------------------------------------------------------
endTime=2022-01-05T18:24:36.293501+08:00
startTime=2022-01-05T18:24:36.293309+08:00
elapsedNano=191536
timezone=CST
ids={"eventId":"fabd662e-801c-4c8b-b596-f55001a66d62"}
app={"appName":"rk","appVersion":"","entryName":"greeter","entryType":"GfEntry"}
env={"arch":"amd64","az":"*","domain":"*","hostname":"lark.local","localIP":"10.8.0.2","os":"darwin","realm":"*","region":"*"}
payloads={"gfPort":8080}
error={}
counters={}
pairs={}
timing={}
remoteAddr=localhost
operation=Bootstrap
resCode=OK
eventStatus=Ended
EOE

4.ctrl-c

经过 ctrl-c 封闭程序,我们会看到打印如下信息。

shutting down
2022-01-05T18:24:39.674+0800    INFO    boot/gf_entry.go:1050   Interrupt gfEntry       {"eventId": "f400e32e-6b99-4733-8ec3-1fe186fe8abe", "entryName": "greeter"}
------------------------------------------------------------------------
endTime=2022-01-05T18:24:39.674817+08:00
startTime=2022-01-05T18:24:39.674688+08:00
elapsedNano=128645
timezone=CST
ids={"eventId":"f400e32e-6b99-4733-8ec3-1fe186fe8abe"}
app={"appName":"rk","appVersion":"","entryName":"greeter","entryType":"GfEntry"}
env={"arch":"amd64","az":"*","domain":"*","hostname":"lark.local","localIP":"10.8.0.2","os":"darwin","realm":"*","region":"*"}
payloads={"gfPort":8080}
error={}
counters={}
pairs={}
timing={}
remoteAddr=localhost
operation=Interrupt
resCode=OK
eventStatus=Ended
EOE

rk-boot 介绍

rk-boot 是一个可经过 YAML 发动多种 Web 服务的结构。 有点类似于 Spring boot。经过集成 rk-xxx 系列库,能够发动多种 Web 结构。当然,用户也能够自定义 rk-xxx 库集成到 rk-boot 中。

GoFrame 框架:优雅关闭进程

rk-boot 亮点

经过同样格式的 YAML 文件,发动不同 Web 结构。

比方,我们能够经过如下文件,在一个进程中同时发动 gRPC, Gin, Echo, GoFrame 结构。一致团队内部的微服务布局。

  • 依靠装置
go get github.com/rookie-ninja/rk-boot/grpc
go get github.com/rookie-ninja/rk-boot/gin
go get github.com/rookie-ninja/rk-boot/echo
go get github.com/rookie-ninja/rk-boot/gf
  • boot.yaml
---
grpc:
  - name: grpc-server
    port: 8080
    enabled: true
    commonService:
      enabled: true
gin:
  - name: gin-server
    port: 8081
    enabled: true
    commonService:
      enabled: true
echo:
  - name: echo-server
    port: 8082
    enabled: true
    commonService:
      enabled: true
gf:
  - name: gf-server
    port: 8083
    enabled: true
    commonService:
      enabled: true
  • main.go
// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main
import (
	"context"
	"github.com/rookie-ninja/rk-boot"
	_ "github.com/rookie-ninja/rk-boot/echo"
	_ "github.com/rookie-ninja/rk-boot/gf"
	_ "github.com/rookie-ninja/rk-boot/gin"
	_ "github.com/rookie-ninja/rk-boot/grpc"
)
// Application entrance.
func main() {
	// Create a new boot instance.
	boot := rkboot.NewBoot()
	// Bootstrap
	boot.Bootstrap(context.Background())
	// Wait for shutdown sig
	boot.WaitForShutdownSig(context.Background())
}
  • 验证
# gRPC throuth grpc-gateway
$ curl localhost:8080/rk/v1/healthy
{"healthy":true}
# Gin
$ curl localhost:8081/rk/v1/healthy
{"healthy":true}
# Echo
$ curl localhost:8082/rk/v1/healthy
{"healthy":true}
# GoFrame
$ curl localhost:8083/rk/v1/healthy
{"healthy":true}

rk-boot 支撑的 Web 结构

欢迎贡献新的 Web 结构到 rk-boot 系列中。

参阅 docs & rk-gin 作为比方。

结构 开发状况 装置 依靠
Gin Stable go get github.com/rookie-ninja/rk-boot/gin rk-gin
gRPC Stable go get github.com/rookie-ninja/rk-boot/grpc rk-grpc
Echo Stable go get github.com/rookie-ninja/rk-boot/echo rk-echo
GoFrame Stable go get github.com/rookie-ninja/rk-boot/gf rk-gf
Fiber Testing go get github.com/rookie-ninja/rk-boot/fiber rk-fiber
go-zero Testing go get github.com/rookie-ninja/rk-boot/zero rk-zero
GorillaMux Testing go get github.com/rookie-ninja/rk-boot/mux rk-mux

rk-gf 介绍

rk-gf 用于经过 YAML 发动 gogf/gf Web 服务。

GoFrame 框架:优雅关闭进程

支撑的功用

依据 YAML 文件初始化如下的实例,如果是外部以来,均坚持原生用法。

实例 介绍
ghttp.Server 原生 gogf/gf
Config 原生 spf13/viper 参数实例
Logger 原生 uber-go/zap 日志实例
EventLogger 用于记录 RPC 恳求日志,运用 rk-query
Credential 用于从长途服务,例如 ETCD 拉取 Credential
Cert 从长途服务(ETCD 等等)中获取 TLS/SSL 证书,并发动 SSL/TLS
Prometheus 发动 Prometheus 客户端,并依据需求推送到 pushgateway
Swagger 本地发动 Swagger UI
CommonService 露出通用 API
TV TV 网页,展示微服务的基本信息
StaticFileHandler 发动 Web 方式的静态文件下载服务,后台存储支撑本地文件系统 和 pkger.

支撑的中间件

rk-gf 会依据 YAML 文件初始化中间件。

Middleware Description
Metrics 搜集 RPC Metrics,并发动 prometheus
Log 运用 rk-query 记录每一个 RPC 日志
Trace 搜集 RPC 调用链,而且发送数据到 stdout, 本地文件或许 jaeger open-telemetry/opentelemetry-go.
Panic Recover from panic for RPC requests and log it.
Meta 搜集服务元信息,增加到回来 Header 中
Auth 支撑 [Basic Auth] & [API Key] 验证中间件
RateLimit RPC 限速中间件
Timeout RPC 超时中间件
CORS CORS 中间件
JWT JWT 验证
Secure 服务端安全中间件
CSRF CSRF 中间件

GoFrame 完好 YAML 配置

---
#app:
#  description: "this is description"                      # Optional, default: ""
#  keywords: ["rk", "golang"]                              # Optional, default: []
#  homeUrl: "http://example.com"                           # Optional, default: ""
#  iconUrl: "http://example.com"                           # Optional, default: ""
#  docsUrl: ["http://example.com"]                         # Optional, default: []
#  maintainers: ["rk-dev"]                                 # Optional, default: []
#zapLogger:
#  - name: zap-logger                                      # Required
#    description: "Description of entry"                   # Optional
#eventLogger:
#  - name: event-logger                                    # Required
#    description: "Description of entry"                   # Optional
#cred:
#  - name: "local-cred"                                    # Required
#    provider: "localFs"                                   # Required, etcd, consul, localFs, remoteFs are supported options
#    description: "Description of entry"                   # Optional
#    locale: "*::*::*::*"                                  # Optional, default: *::*::*::*
#    paths:                                                # Optional
#      - "example/boot/full/cred.yaml"
#cert:
#  - name: "local-cert"                                    # Required
#    provider: "localFs"                                   # Required, etcd, consul, localFs, remoteFs are supported options
#    description: "Description of entry"                   # Optional
#    locale: "*::*::*::*"                                  # Optional, default: *::*::*::*
#    serverCertPath: "example/boot/full/server.pem"        # Optional, default: "", path of certificate on local FS
#    serverKeyPath: "example/boot/full/server-key.pem"     # Optional, default: "", path of certificate on local FS
#    clientCertPath: "example/client.pem"                  # Optional, default: "", path of certificate on local FS
#    clientKeyPath: "example/client.pem"                   # Optional, default: "", path of certificate on local FS
#config:
#  - name: rk-main                                         # Required
#    path: "example/boot/full/config.yaml"                 # Required
#    locale: "*::*::*::*"                                  # Required, default: *::*::*::*
#    description: "Description of entry"                   # Optional
gf:
  - name: greeter                                          # Required
    port: 8080                                             # Required
    enabled: true                                          # Required
#    description: "greeter server"                         # Optional, default: ""
#    cert:
#      ref: "local-cert"                                   # Optional, default: "", reference of cert entry declared above
#    sw:
#      enabled: true                                       # Optional, default: false
#      path: "sw"                                          # Optional, default: "sw"
#      jsonPath: ""                                        # Optional
#      headers: ["sw:rk"]                                  # Optional, default: []
#    commonService:
#      enabled: true                                       # Optional, default: false
#    static:
#      enabled: true                                       # Optional, default: false
#      path: "/rk/v1/static"                               # Optional, default: /rk/v1/static
#      sourceType: local                                   # Required, options: pkger, local
#      sourcePath: "."                                     # Required, full path of source directory
#    tv:
#      enabled:  true                                      # Optional, default: false
#    prom:
#      enabled: true                                       # Optional, default: false
#      path: ""                                            # Optional, default: "metrics"
#      pusher:
#        enabled: false                                    # Optional, default: false
#        jobName: "greeter-pusher"                         # Required
#        remoteAddress: "localhost:9091"                   # Required
#        basicAuth: "user:pass"                            # Optional, default: ""
#        intervalMs: 10000                                 # Optional, default: 1000
#        cert:                                             # Optional
#          ref: "local-test"                               # Optional, default: "", reference of cert entry declared above
#    logger:
#      zapLogger:
#        ref: zap-logger                                   # Optional, default: logger of STDOUT, reference of logger entry declared above
#      eventLogger:
#        ref: event-logger                                 # Optional, default: logger of STDOUT, reference of logger entry declared above
#    interceptors:
#      loggingZap:
#        enabled: true                                     # Optional, default: false
#        zapLoggerEncoding: "json"                         # Optional, default: "console"
#        zapLoggerOutputPaths: ["logs/app.log"]            # Optional, default: ["stdout"]
#        eventLoggerEncoding: "json"                       # Optional, default: "console"
#        eventLoggerOutputPaths: ["logs/event.log"]        # Optional, default: ["stdout"]
#      metricsProm:
#        enabled: true                                     # Optional, default: false
#      auth:
#        enabled: true                                     # Optional, default: false
#        basic:
#          - "user:pass"                                   # Optional, default: []
#        ignorePrefix:
#          - "/rk/v1"                                      # Optional, default: []
#        apiKey:
#          - "keys"                                        # Optional, default: []
#      meta:
#        enabled: true                                     # Optional, default: false
#        prefix: "rk"                                      # Optional, default: "rk"
#      tracingTelemetry:
#        enabled: true                                     # Optional, default: false
#        exporter:                                         # Optional, default will create a stdout exporter
#          file:
#            enabled: true                                 # Optional, default: false
#            outputPath: "logs/trace.log"                  # Optional, default: stdout
#          jaeger:
#            agent:
#              enabled: false                              # Optional, default: false
#              host: ""                                    # Optional, default: localhost
#              port: 0                                     # Optional, default: 6831
#            collector:
#              enabled: true                               # Optional, default: false
#              endpoint: ""                                # Optional, default: http://localhost:14268/api/traces
#              username: ""                                # Optional, default: ""
#              password: ""                                # Optional, default: ""
#      rateLimit:
#        enabled: false                                    # Optional, default: false
#        algorithm: "leakyBucket"                          # Optional, default: "tokenBucket"
#        reqPerSec: 100                                    # Optional, default: 1000000
#        paths:
#          - path: "/rk/v1/healthy"                        # Optional, default: ""
#            reqPerSec: 0                                  # Optional, default: 1000000
#      jwt:
#        enabled: true                                     # Optional, default: false
#        signingKey: "my-secret"                           # Required
#        ignorePrefix:                                     # Optional, default: []
#          - "/rk/v1/tv"
#          - "/sw"
#          - "/rk/v1/assets"
#        signingKeys:                                      # Optional
#          - "key:value"
#        signingAlgo: ""                                   # Optional, default: "HS256"
#        tokenLookup: "header:<name>"                      # Optional, default: "header:Authorization"
#        authScheme: "Bearer"                              # Optional, default: "Bearer"
#      secure:
#        enabled: true                                     # Optional, default: false
#        xssProtection: ""                                 # Optional, default: "1; mode=block"
#        contentTypeNosniff: ""                            # Optional, default: nosniff
#        xFrameOptions: ""                                 # Optional, default: SAMEORIGIN
#        hstsMaxAge: 0                                     # Optional, default: 0
#        hstsExcludeSubdomains: false                      # Optional, default: false
#        hstsPreloadEnabled: false                         # Optional, default: false
#        contentSecurityPolicy: ""                         # Optional, default: ""
#        cspReportOnly: false                              # Optional, default: false
#        referrerPolicy: ""                                # Optional, default: ""
#        ignorePrefix: []                                  # Optional, default: []
#      csrf:
#        enabled: true
#        tokenLength: 32                                   # Optional, default: 32
#        tokenLookup: "header:X-CSRF-Token"                # Optional, default: "header:X-CSRF-Token"
#        cookieName: "_csrf"                               # Optional, default: _csrf
#        cookieDomain: ""                                  # Optional, default: ""
#        cookiePath: ""                                    # Optional, default: ""
#        cookieMaxAge: 86400                               # Optional, default: 86400
#        cookieHttpOnly: false                             # Optional, default: false
#        cookieSameSite: "default"                         # Optional, default: "default", options: lax, strict, none, default
#        ignorePrefix: []                                  # Optional, default: []