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 文件:
代码如下:
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 成功收集到服务信息:
下一篇文章,我们将三个微服务和一个网关构建成Docker镜像,在容器中启动整个应用。
完整代码:
https://github.com/Justin02180218/micro-kit
更多【分布式专辑】【架构实战专辑】系列文章,请关注公众号