十一,微服务监控

监控 PROMETHEUS

Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB),使用Go语言开发,是Google BorgMon监控系统的开源版本。prometheus存储的是时序数据,即按相同时序(相同名称和标签),以时间维度存储连续的数据的集合。

项目中应用

完整代码:

https://github.com/Justin02180218/micro-kit

配置文件

prometheus:
  namespace: "library"
  subsystem: "user_service"

config.go

type PrometheusConfig struct {
    Namespace string `json:"namespace" yaml:"namespace"`
    Subsystem string `json:"subsystem" yaml:"subsystem"`
}

pkg/monitors

在 pkg 下新建目录 monitors,创建 prometheus.go 文件:

十一,微服务监控_第1张图片

 

 代码如下:

type PrometheusParams struct {
    Counter   *kitprometheus.Counter
    Summary   *kitprometheus.Summary
    Gauge     *kitprometheus.Gauge
    Histogram *kitprometheus.Histogram
}
func MakePrometheusParams(conf *configs.PrometheusConfig) *PrometheusParams {
    fieldKeys := []string{"method"}
    requestCounter := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
        Namespace: conf.Namespace,
        Subsystem: conf.Subsystem,
        Name:      "request_count",
        Help:      "Number of requests received.",
    }, fieldKeys)
    requestLatency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
        Namespace: conf.Namespace,
        Subsystem: conf.Subsystem,
        Name:      "request_latency_microseconds",
        Help:      "Total duration of requests in microseconds.",
    }, fieldKeys)
    return &PrometheusParams{requestCounter, requestLatency, nil, nil}
}

service层

在 service 层创建 user_service_metrics.go,以 library-user-service 为例,其他微服务相同。

func MetricsMiddleware(prometheusParams *monitors.PrometheusParams) ServiceMiddleware {
    return func(next UserService) UserService {
        return metricsMiddleware{next, prometheusParams.Counter, prometheusParams.Summary}
    }
}

type metricsMiddleware struct {
    UserService
    requestCount   metrics.Counter
    requestLatency metrics.Histogram
}

func (mw metricsMiddleware) Register(ctx context.Context, vo *dto.RegisterUser) (*dto.UserInfo, error) {
    defer func(begin time.Time) {
        lvs := []string{"method", "Register"}
        mw.requestCount.With(lvs...).Add(1)
        mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
    }(time.Now())
    return mw.UserService.Register(ctx, vo)
}

func (mw metricsMiddleware) FindByID(ctx context.Context, id uint64) (*dto.UserInfo, error) {
    defer func(begin time.Time) {
        lvs := []string{"method", "FindByID"}
        mw.requestCount.With(lvs...).Add(1)
        mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
    }(time.Now())
    return mw.UserService.FindByID(ctx, id)
}

func (mw metricsMiddleware) FindByEmail(ctx context.Context, email string) (*dto.UserInfo, error) {
    defer func(begin time.Time) {
        lvs := []string{"method", "FindByEmail"}
        mw.requestCount.With(lvs...).Add(1)
        mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
    }(time.Now())
    return mw.UserService.FindByEmail(ctx, email)
}

func (mw metricsMiddleware) FindBooksByUserID(ctx context.Context, id uint64) (interface{}, error) {
    defer func(begin time.Time) {
        lvs := []string{"method", "FindBooksByUserID"}
        mw.requestCount.With(lvs...).Add(1)
        mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
    }(time.Now())
    return mw.UserService.FindBooksByUserID(ctx, id)
}

func (mw metricsMiddleware) HealthCheck() bool {
    defer func(begin time.Time) {
        lvs := []string{"method", "HealthCheck"}
        mw.requestCount.With(lvs...).Add(1)
        mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
    }(time.Now())
    return mw.UserService.HealthCheck()
}

transport层

修改 user_transport.go,以 library-user-service 为例,其他微服务相同。

r.GET("/metrics", func(c *gin.Context) {
    promhttp.Handler().ServeHTTP(c.Writer, c.Request)
})

修改 main.go

以 library-user-service 为例,其他微服务相同。

prometheusParams := monitors.MakePrometheusParams(configs.Conf.PrometheusConfig)

userService = service.MetricsMiddleware(prometheusParams)(userService)

启动 Prometheus

在工程目录下建立 deploy/prometheus 目录,创建 prometheus.yaml 配置文件:

global:
  scrape_interval: 15s
  external_labels:
    monitor: 'library-monitor'
scrape_configs:
  - job_name: 'prometheus'
    scrape_interval: 5s
    static_configs:
     - targets: ['IP:9090']
       labels:
        group: 'local'
  
  - job_name: 'library'
    scrape_interval: 5s
    static_configs:
      # 配置微服务的IP和Port  
      - targets: ['IP:10086', 'IP:10087', 'IP:10089']
        labels:
          group: 'library'

创建 docker-compose 文件 prometheus-grafana.yaml:

version: '3'
services:    
 prometheus:
  image: prom/prometheus
  ports:
    - 9090:9090
  volumes:
    - /micro-kit/deploy/prometheus/prometheus.yaml:/etc/prometheus/prometheus.yml
 grafana:
  image: grafana/grafana
  ports: 
    - 3000:3000
  environment:
    - GF_SECURITY_ADMIN_PASSWORD=123456
  volumes: 
    - /grafana_db:/var/lib/grafana grafana/grafana

执行命令:

docker-compose -f deploy/prometheus/prometheus-grafana.yaml up -d

依次启动 consul、zipkin、三个微服务和网关,然后在地址栏输入 http://localhost:9090/targets,可以看到 prometheus 成功收集到服务信息:

十一,微服务监控_第2张图片

十一,微服务监控_第3张图片

下一篇文章,我们将三个微服务和一个网关构建成Docker镜像,在容器中启动整个应用。

完整代码:

https://github.com/Justin02180218/micro-kit


更多【分布式专辑】【架构实战专辑】系列文章,请关注公众号

你可能感兴趣的