logid让你的请求完整可追溯
今天是在博客园开园的第一天
一时间其实并不能想起来到底该写什么文章,其实想写的东西挺多
今天就以logid这个主题开始吧,网上写这个的文章似乎不多,但是的确是在实际生产中相当重要的一个能力,也是容易被大多数新手程序员所忽视的。
logid:在我的定义里,logid是一个能够代表一条请求唯一性的字段。完整请求包含请求到达、请求转发、服务处理、数据存取等多个阶段,logid在其中充当的就是一个定位标识,当然这个字段叫法可能不能可以是traceID或者其他XXID等等
以典型的php服务为例,整条请求轨迹可能包含下面的几个组成部分:
client => 外层网关(四层负载均衡) => nginx集群(七层负载均衡) => 你自己服务的nginx => 业务日志 => rpc日志 => mysqlproxy => mysql
=> redisproxy => redis
=> 其他基础服务(图片服务\评论服务等等)
上面展示的是一个比较完善的请求转发路径,而这样的长路径上,任何一个位置都可能产生问题。大部分情况下,每个阶段也都会打日志
如何把这些日志串联起来、让问题可追溯、请求可定位,这便是logid做的事情。
典型的使用场景例如:
案例一:业务可用性出现问题,如何排查问题出在哪里?
假设你自己的服务机器nginx出现了大量的499报错,499错误源于客户端主动断开连接。
那么问题可能处在哪里?
- 客户端的超时时间设置有问题,太短了(这个原因引起的499错误,只存在于上新服务。如果服务存在很久了,这个原因基本可以忽略)
- 客户端和你之前的网络故障,这也是一个常见的引起因素。(这个问题的定位可以把nginx_proc_time和upstream_time都打出来即可辨别)
- 极大的可能问题出在你的服务请求别人或者自己的机器负载过高导致的
今天主要讨论第三种,如何定位?
关键是看这条请求从nginx => pfm => php执行 => rpc请求这些过程哪些步骤出现了问题
没有logid的时候你怎么做?
nginx找到问题日志,根据get参数或者post参数去业务日志找,请求少的还好,如果大量重复请求呢?你是没办法精确定位到一个请求的
并且大部分rpc的日志不会打get参数,我们的rpc日志每秒百条,所以需要有一个线索,穿起来
logid就是扮演这个角色
nginx把请求上游的logid通过fastcgi带给php,php通过$SERVER中取到,然后rpc框架和php代码约定好从哪里取logid
done!下次再来问题,直接一步定位,不需要肉身来定位了
案例二: sql问题反查业务日志
假设某天DBA找到你说Proxy日志发现了大量的sql存在注入风险,并且抛给你一堆sql、来源IP和时间
一般如何处理?找到来源ip机器、找到对应时间的日志、翻译sql中的关键字到你的日志关键字(人肉),这个步骤如果没法对应起来,可能很困难
但是如果你们约定好了sql发出去的时候带上logid字段,这个情况是不是迎刃而解?你只需要grep相应的logid便可以找到对应的,效率也会高很多
如何在发sql请求带上logid?可以使用类似下面的sql语句,proxy完成sql日志打印
/*logid=xxx*/select count(1) from tableA
当然还有很多案例
logid存在的核心价值是让每一个请求都可以被唯一定位!
具体logid的协议如何定制需要具体问题具体分析,但是意识上在遇到类似问题的时候应该想到,你的服务需要在日志中打印线索ID:logid来让你的每一个请求可以被定位
当然前提是log打的充分、也要恰当
logid让你的请求完整可追溯的更多相关文章
- ASP.NET Core获取请求完整的Url
在ASP.NET项目中获取请求完整的Url: 获取System.Web命名空间下的类名为HttpRequestBase的Url方法: /// <summary>在派生类中替代时,获取有关当 ...
- 95秀-异步http请求完整过程
最终调用时的代码 private void ansyClearApplyInfor() { RequestParams params = new RequestParams() ...
- HTTP深入浅出 http请求完整过程
HTTP(HyperText Transfer Protocol)是一套计算机通过网络进行通信的规则.计算机专家设计出HTTP,使HTTP客户(如Web浏览器)能够从HTTP服务器(Web服务器)请求 ...
- java拦截器获取请求完整参数
public class OptLogAspect implements HandlerInterceptor { @Override public boolean preHandle(HttpSer ...
- MOOC(7)- case依赖、读取json配置文件进行多个接口请求-完整的测试类,含依赖测试(15)
ddt.依赖测试.断言.测试数据写回 # -*- coding: utf-8 -*- # @Time : 2020/2/12 23:07 # @File : test_class_15.py # @A ...
- java如何得到GET和POST请求URL和参数列表(转)
在servlet中GET请求可以通过HttpServletRequest的getRequestURL方法和getQueryString()得到完整的请求路径和请求所有参数列表,POST的需要getPa ...
- java如何得到GET和POST请求URL和参数列表
转载:http://blog.csdn.net/yaerfeng/article/details/18942739 在servlet中GET请求可以通过HttpServletRequest的getRe ...
- servlet获得完整路径
request.getQueryString() request.getParameterMap() request.getParameterNames() 在servlet中GET请求可以通过Htt ...
- JavaEE:response响应和request请求
Web服务器接收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象.request和response对象既然代表请求和响应,那么我 ...
随机推荐
- import torch错误解决
import torch出现 ”from torch._C import * ImportError: DLL load failed: 找不到指定的模块“错误这里torch=1.0.1,torchv ...
- 树莓派安装QT(全部库包括)
在网上现有的资料中大部分只有前两个命令,少量有三个命令,因此写下该博客 在树莓派上安装QT5的全部库,包括QtQuick.QtMultimedia库. sudo apt-get install qt5 ...
- 栈(Java实现)
栈是最基本的数据结构之一,其特点是先进后出. 1.基于数组的可动态调节大小的栈 public class ResizingArrayStack<Item> { private Item[] ...
- 预处理、const、static与sizeof-用宏定义得到一个字的高位和低位字节
1:代码如下: #define WORD_LO(XXX) ((byte) (word)(XXX) & 255) #define WORD_HI(XXX) ((byte) (word)(XXX) ...
- java实现自定义同步组件的过程
实现同步组件twinsLock:可以允许两个线程同时获取到锁,多出的其它线程将被阻塞. 以下是自定义的同步组件类,一般我们将自定义同步器Sync定义为同步组件TwinsLock的静态内部类. 实现同步 ...
- 【转载】详解CI、CD相关概念
在软件的编译发布的过程中,经常能够看到CI.CD这样的词语.其实他们是专业的缩写短语,这里介绍下他们的概念和区别. 敏捷软件开发 敏捷软件开发,英文全称:Agile software developm ...
- legend3---8、烦请节约时间
legend3---8.烦请节约时间 一.总结 一句话总结: 时间不要浪费在垃圾情绪和无效社交上面. 1.商标不能以个人的名义注册? 可以先注册个体工商户,然后再可以注册商标 2.注册一个商标大概花多 ...
- 在debian下安装QT 5.10 32位
准备工作: 在开始之前最好把GCC升级到5.0以上. 如果升级后出现“libstdc++.so.6: version `CXXABI_1.3.9' not found”错误,可以参考https://b ...
- mongodb 的云数据库产品 mlab 的使用
mongodb的云数据库产品mlab,新用户注册,提供500m免费的空间,对于创建测试的网站数据库来说,足够使用.虽然是服务器是在美国,但是链接稳定.下面就介绍注册和使用的流程. 浏览器中,输入网址h ...
- leetcode84 柱状图
O(n^2) time 应用heights[r]<=heights[r+1]剪枝: class Solution { public: int largestRectangleArea(vecto ...