工作中经常需要排查接口性能问题, 特此记录
可以从Nginx请求日志中, 把时延高的请求筛选出来进行分析 Nginx access log 格式如下
log_format access '$remote_addr\t$remote_user\t[$time_local]\t$request\t$status\t$body_bytes_sent\t$http_referer\t$http_user_agent\t$http_x_forwarded_for\t$host\t$request_time\t$upstream_addr\t$upstream_status\t$upstream_response_time\t$upstream_response_length'
一. 关注access_log 倒数第二列:$upstream_response_time 即 接口返回时间 (可能位于13,14列)
二. 查询指定接口返回时间大于指定时间的请求, 例如查找返回耗时在500ms以上
shellgrep /v1/request_xxx /application/website/xxx.com-access_20230113* | awk '{if($14>0.5) print $13,$14,$15}'
可从以下几个方面进行分析
一. 若发生高时延的请求集中出现, 很可能是机器某方面指标遇到瓶颈, 可以从监控平台查看当时的机器指标, 例如cpu, 内存, I/O, 网络带宽使用率, 如果接口有第三方依赖, 亦要获取当时第三方请求的时延状态;
二. 若高时延的请求分散出现, 很可能是机器抖动, 可以先通过全链路分析工具, 判断是否某个环节时延过高导致;
Go 中的for range组合可以和方便的实现对一个数组或切片进行遍历,但是在某些情况下使用for range时很可能就会被"坑",下面用一段代码来模拟下:
golangfunc main() {
arr1 := []int{1, 2, 3}
arr2 := make([]*int, len(arr1))
for i, v := range arr1 {
arr2[i] = &v
}
for _, v := range arr2 {
fmt.Println(*v)
}
}
从代码上看,打印出来的结果应该是
1 2 3
然而真正的结果是
3 3 3
因为for range在遍历值类型时,其中的v变量是一个,当使用&获取指针时,实际上是获取到v这个临时变量的指针,而v变量在for range中只会创建一次,之后循环中会被一直重复使用,所以在arr2赋值的时候其实都是v变量的指针,而&v最终会指向arr1最后一个元素的值拷贝。
来看看下面这个代码,用for i来模拟for range,这样更易于理解:
golangfunc main() {
arr1 := []int{1, 2, 3}
arr2 := make([]*int, len(arr1))
var v int
for i:=0;i<len(arr1);i++ {
v = arr1[i]
arr2[i] = &v
}
for _, v := range arr2 {
fmt.Println(*v)
}
}
传递原始指针
golangfunc main() {
arr1 := []int{1, 2, 3}
arr2 := make([]*int, len(arr1))
for i := range arr1 {
arr2[i] = &arr1[i]
}
for _, v := range arr2 {
fmt.Println(*v)
}
}
使用临时变量
golangfunc main() {
arr1 := []int{1, 2, 3}
arr2 := make([]*int, len(arr1))
for i, v := range arr1 {
t := v
arr2[i] = &t
}
for _, v := range arr2 {
fmt.Println(*v)
}
}
官方提示 由于这一问题过于普遍,Golang甚至将其写入了文档的『常见错误』部分:链接
https://www.jb51.net/article/254968.htm
https://www.xiaolincoding.com/mysql/log/how_update.html
https://juejin.cn/post/6844903936755761165
https://blog.csdn.net/xiaomage1314/article/details/77892258
session其实就是将用户凭证存放在后端,前端使用cookie携带相关凭证与session匹配,达到认证效果,cookie信息可以用相关算法进行加密;