【go-zero】go分布式微服务中计算http请求时长 go-zero中 api与rpc 整个链路时长(go计算方法耗时 go请求ip)

发布于:2023-01-21 ⋅ 阅读:(204) ⋅ 点赞:(0)

本教程以go-zero分布式go微服务框架为基础
在此框架之上去实现获取整个链路的请求时长

一、创建middleware

1、如何在go-zero创建局部中间件

官方文档:middleware 的创建方式

这里稍微对新使用go-zero用户说明一下
如果需要再中间件中使用其他服务的rpc,就需要在svc中注册时,对中间件进行传值

1.1 svc注册如下

这里加上了其他rpc服务供middleware中调用

type ServiceContext struct {
	AdminAuthRpc  adminauthrpc.Adminauthrpc
	AminRbacRpc   adminrbacrpc.AdminrbacRpc
	// 中间件
	RbacMiddle rest.Middleware
}

func NewServiceContext(c config.Config) *ServiceContext {
	redisCLient := c.Cache[0].NewRedis()
	aminRbacRpc := adminrbacrpc.NewAdminrbacRpc(zrpc.MustNewClient(c.AdminRbac))
	aminAuthRpc := adminauthrpc.NewAdminauthrpc(zrpc.MustNewClient(c.AdminAuthRpc))
	return &ServiceContext{
		Config:        c,
		RedisClient:   redisCLient,
		RbacMiddle:    middleware.NewRbacMiddleMiddleware(redisCLient, aminRbacRpc, aminAuthRpc).Handle,
	}
}

1.2 middleware中使用

package middleware

type RbacMiddleMiddleware struct {
	RedisClient *redis.Redis
	AminRbacRpc adminrbacrpc.AdminrbacRpc
	AminAuthRpc adminauthrpc.Adminauthrpc
}

func NewRbacMiddleMiddleware(redisClient *redis.Redis, adminRbacRpc adminrbacrpc.AdminrbacRpc, aminAuthRpc adminauthrpc.Adminauthrpc) *RbacMiddleMiddleware { //, aminAuthRpc adminauthrpc.Adminauthrpc
	return &RbacMiddleMiddleware{
		RedisClient: redisClient,
		AminRbacRpc: adminRbacRpc,
		AminAuthRpc: aminAuthRpc,
	}
}

func (m *RbacMiddleMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {

	return func(w http.ResponseWriter, r *http.Request) {
		startTime := timex.Now() // 计算耗时(开始时间)

		// 这里是执行api的logic种具体的方法
		next(w, r)

		// 所有api-rpc请求后,返回结果前
		duration := timex.Since(startTime) //整个链路执行时间
		//获取所有请求参数
		query := r.URL.Query()
		jsonStr, _ := json.Marshal(query)

		_, err = m.AminAuthRpc.AddSysLog(ctx, &adminauthrpc.SysLog{
			Username:  strconv.FormatInt(userId, 10),
			Operation: r.Method,
			Method:    route,
			Params:    string(jsonStr),
			Time:      duration.String(),
			Ip:        GetRemoteClientIp(r),
		})

		if err != nil {
			logx.Errorf(err.Error())
		}
	}
}

// GetRemoteClientIp 获取远程客户端IP
func GetRemoteClientIp(r *http.Request) string {
	remoteIp := r.RemoteAddr

	if ip := r.Header.Get("X-Real-IP"); ip != "" {
		remoteIp = ip
	} else if ip = r.Header.Get("X-Forwarded-For"); ip != "" {
		remoteIp = ip
	} else {
		remoteIp, _, _ = net.SplitHostPort(remoteIp)
	}
	//本地ip
	if remoteIp == "::1" {
		remoteIp = "127.0.0.1"
	}
	return remoteIp
}

func handler(w http.ResponseWriter, r *http.Request) {
	//获取所有请求参数
	query := r.URL.Query()
	jsonStr, err := json.Marshal(query)
	if err != nil {
		log.Fatalf("%v\n", err)
	}
	fmt.Fprintf(w, "get all param: "+string(jsonStr)+"\n")
	//获取指定请求参数
	names, ok := query["name"]
	if !ok || len(names[0]) < 1 {
		log.Println("Url Param 'name' is missing")
		return
	}
	fmt.Fprintf(w, "name="+names[0]+"\n")
}

二、依赖middleware计算链路时间长度

1、如何算请求链路的完整时长计算

在middleware中有一个关联的方法
如下代码:

func (m *RbacMiddleMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 这里是执行api的logic具体的方法
		next(w, r)
	}
}

方法:next(w,r)

  • 在next()方法前,为进入api的logic之前要执行的方法,这里我们还可以做rbac的权限校验
  • 在next()方法后,为执行api的logic内所有方法后,在api接口返回前处理,这里我们可以计算出最后的用时

2、go计算方法耗时

startTime := timex.Now() // 计算耗时(开始时间)
duration := timex.Since(startTime) //整个链路执行时间
// 计算最后时长:
str :=duration.String()
// 输出结果如下:
871.498ms

3、go获取获取远程客户端IP

// GetRemoteClientIp 获取远程客户端IP
func GetRemoteClientIp(r *http.Request) string {
	remoteIp := r.RemoteAddr

	if ip := r.Header.Get("X-Real-IP"); ip != "" {
		remoteIp = ip
	} else if ip = r.Header.Get("X-Forwarded-For"); ip != "" {
		remoteIp = ip
	} else {
		remoteIp, _, _ = net.SplitHostPort(remoteIp)
	}
	//本地ip
	if remoteIp == "::1" {
		remoteIp = "127.0.0.1"
	}
	return remoteIp
}

三、操作日志

1、通过middleware做切面保存所有请求日志

1.1、日志表

CREATE TABLE `sys_log` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',
  `operation` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户操作',
  `method` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '请求方法',
  `params` varchar(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '请求参数',
  `time` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行时长(毫秒)',
  `ip` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'IP地址',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=303 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='系统日志';

1.2、存入日志表

_, err = m.AminAuthRpc.AddSysLog(ctx, &adminauthrpc.SysLog{
	Username:  strconv.FormatInt(userId, 10),
	Operation: r.Method,
	Method:    route,
	Params:    string(jsonStr),
	Time:      duration.String(),
	Ip:        GetRemoteClientIp(r),
})

网站公告

今日签到

点亮在社区的每一天
去签到