diff --git a/ComingSoon.md b/ComingSoon.md new file mode 100644 index 0000000..cafb8b9 --- /dev/null +++ b/ComingSoon.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待!有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/README.md b/README.md index fd06536..b67a080 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +!> 本笔记是[Gitee柠檬夕桐](https://gitee.com/yu120)博主所整理,供大家交流学习! + 收纳了 操作系统、JAVA、算法、数据库、中间件、解决方案、架构、DevOps 和 大数据 等技术栈总结!其内容有来源笔者个人总结的内容,也有来源于互联网各种经典场景或案例的总结(感谢对应的笔者),目的在于把常用的技术内容进行归纳整理记录。 同时提供一个微信交流群:请加笔者个人微信(echo-lry),备注拉群,笔者通过后,会发送邀请入群。 diff --git a/_coverpage.md b/_coverpage.md index 3f2eb7a..ae47a76 100644 --- a/_coverpage.md +++ b/_coverpage.md @@ -1,10 +1,10 @@ ![](lemon.png) -# lemon-guide 1.0 +# lemon 1.0 > 一款优秀的开源笔记 - 操作系统、算法、解决方案 - JAVA、数据库、中间件 - 架构、DevOps、大数据 -[Gitee](https://gitee.com/yu120/lemon-guide) +[回到博客](https://view6view.club/) [点击进入](./README.md) \ No newline at end of file diff --git a/_navbar.md b/_navbar.md new file mode 100644 index 0000000..1be191e --- /dev/null +++ b/_navbar.md @@ -0,0 +1,11 @@ +* 🏁 笔记分类 + * [✍ 操作系统](src/OS/README) + * [✍ 算法](src/Algorithm/README) + * [✍ JAVA](src/JAVA/README) + * [✍ JVM](src/JVM/README) + * [✍ 数据库](src/Database/README) + * [✍ 中间件](src/Middleware/README) + * [✍ 架构](src/Architecture/README) + * [✍ 大数据](src/BigData/README) + * [✍ DevOps](src/DevOps/README) + * [✍ 其它](src/Others/README) \ No newline at end of file diff --git a/_sidebar.md b/_sidebar.md index 830c05b..1be191e 100644 --- a/_sidebar.md +++ b/_sidebar.md @@ -1,6 +1,11 @@ -* 🏁分类 - * [✍操作系统](src/OS/README) - * [✍算法](src/Algorithm/README) - * [✍JAVA](src/JAVA/README) - * [✍数据库](src/Database/README) - * [✍中间件](src/Middleware/README) \ No newline at end of file +* 🏁 笔记分类 + * [✍ 操作系统](src/OS/README) + * [✍ 算法](src/Algorithm/README) + * [✍ JAVA](src/JAVA/README) + * [✍ JVM](src/JVM/README) + * [✍ 数据库](src/Database/README) + * [✍ 中间件](src/Middleware/README) + * [✍ 架构](src/Architecture/README) + * [✍ 大数据](src/BigData/README) + * [✍ DevOps](src/DevOps/README) + * [✍ 其它](src/Others/README) \ No newline at end of file diff --git a/index.html b/index.html index 03d42df..fb5b8bd 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ - lemon-guide + lemon @@ -29,25 +29,33 @@ - + - - + + + + diff --git a/lemon.png b/lemon.png index d01db01..9fc2988 100644 Binary files a/lemon.png and b/lemon.png differ diff --git a/src/Algorithm/_sidebar.md b/src/Algorithm/_sidebar.md index dfeea30..45a9042 100644 --- a/src/Algorithm/_sidebar.md +++ b/src/Algorithm/_sidebar.md @@ -1,21 +1,21 @@ -* 🏁Data Structure - * [✍位运算](src/Algorithm/1 "位运算") - * [✍常用数据结构](src/Algorithm/2 "常用数据结构") - * [✍高级数据结构](src/Algorithm/3 "高级数据结构") -* 🏁Algorithm - * [✍复杂度](src/Algorithm/101 "复杂度") - * [✍算法思想](src/Algorithm/102 "算法思想") - * [✍算法模板](src/Algorithm/103 "算法模板") - * [✍查找算法](src/Algorithm/104 "查找算法") - * [✍搜素算法](src/Algorithm/105 "搜素算法") - * [✍排序算法](src/Algorithm/106 "排序算法") -* 🏁Case - * [✍双指针](src/Algorithm/201 "双指针") - * [✍反转](src/Algorithm/202 "反转") - * [✍栈](src/Algorithm/203 "栈") - * [✍FIFO队列](src/Algorithm/204 "FIFO队列") - * [✍单调队列](src/Algorithm/205 "单调队列") -* 🏁Design Pattern - * [✍创建型模式](src/Algorithm/301 "创建型模式") - * [✍结构型模式](src/Algorithm/302 "结构型模式") - * [✍行为型模式](src/Algorithm/303 "进程和线程") \ No newline at end of file +* 🏁 Data Structure + * [✍ 位运算](src/Algorithm/1 "位运算") + * [✍ 常用数据结构](src/Algorithm/2 "常用数据结构") + * [✍ 高级数据结构](src/Algorithm/3 "高级数据结构") +* 🏁 Algorithm + * [✍ 复杂度](src/Algorithm/101 "复杂度") + * [✍ 算法思想](src/Algorithm/102 "算法思想") + * [✍ 算法模板](src/Algorithm/103 "算法模板") + * [✍ 查找算法](src/Algorithm/104 "查找算法") + * [✍ 搜素算法](src/Algorithm/105 "搜素算法") + * [✍ 排序算法](src/Algorithm/106 "排序算法") +* 🏁 Case + * [✍ 双指针](src/Algorithm/201 "双指针") + * [✍ 反转](src/Algorithm/202 "反转") + * [✍ 栈](src/Algorithm/203 "栈") + * [✍ FIFO队列](src/Algorithm/204 "FIFO队列") + * [✍ 单调队列](src/Algorithm/205 "单调队列") +* 🏁 Design Pattern + * [✍ 创建型模式](src/Algorithm/301 "创建型模式") + * [✍ 结构型模式](src/Algorithm/302 "结构型模式") + * [✍ 行为型模式](src/Algorithm/303 "进程和线程") \ No newline at end of file diff --git a/src/Architecture/1.md b/src/Architecture/1.md new file mode 100644 index 0000000..7ec5af8 --- /dev/null +++ b/src/Architecture/1.md @@ -0,0 +1,157 @@ +有没有想过要设计多大的企业规模系统?在主要的软件开发开始之前,我们必须选择一个合适的体系结构,它将为我们提供所需的功能和质量属性。因此,在将它们应用到我们的设计之前,我们应该了解不同的体系结构。 + +![软件架构模式](images/Architecture/软件架构模式.png) + +架构模式是一个通用的、可重用的解决方案,用于在给定上下文中的软件体系结构中经常出现的问题。架构模式与软件设计模式类似,但具有更广泛的范围。 + + + +### 分层模式 + +这种模式也称为多层体系架构模式。它可以用来构造可以分解为子任务组的程序,每个子任务都处于一个特定的抽象级别。每个层都为下一个提供更高层次服务。 + +一般信息系统中最常见的是如下所列的4层。 + +- 表示层(也称为UI层) +- 应用层(也称为服务层) +- 业务逻辑层(也称为领域层) +- 数据访问层(也称为持久化层) + +使用场景: + +- 一般的桌面应用程序 +- 电子商务Web应用程序 + +![Layered-pattern](images/Architecture/Layered-pattern.png) + + + +### 客户端-服务器模式 + +这种模式由两部分组成:一个服务器和多个客户端。服务器组件将为多个客户端组件提供服务。客户端从服务器请求服务,服务器为这些客户端提供相关服务。此外,服务器持续侦听客户机请求。 + +使用场景: + +- 电子邮件,文件共享和银行等在线应用程序 + +![Client-server-pattern](images/Architecture/Client-server-pattern.png) + + + +### 主从设备模式 + +这种模式由两方组成;主设备和从设备。主设备组件在相同的从设备组件中分配工作,并计算最终结果,这些结果是由从设备返回的结果。 + +使用场景: + +- 在数据库复制中,主数据库被认为是权威的来源,并且要与之同步 +- 在计算机系统中与总线连接的外围设备(主和从驱动器) + +![Master-slave-pattern](images/Architecture/Master-slave-pattern.png) + + + +### 管道-过滤器模式 + +此模式可用于构造生成和处理数据流的系统。每个处理步骤都封装在一个过滤器组件内。要处理的数据是通过管道传递的。这些管道可以用于缓冲或用于同步。 + +使用场景: + +- 编译器。连续的过滤器执行词法分析、解析、语义分析和代码生成 +- 生物信息学的工作流 + +![Pipe-filter-pattern](images/Architecture/Pipe-filter-pattern.png) + + + +### 代理模式 + +此模式用于构造具有解耦组件的分布式系统。这些组件可以通过远程服务调用彼此交互。代理组件负责组件之间的通信协调。 + +服务器将其功能(服务和特征)发布给代理。客户端从代理请求服务,然后代理将客户端重定向到其注册中心的适当服务。 + +使用场景: + +- 消息代理软件,如Apache ActiveMQ,Apache Kafka,RabbitMQ和JBoss Messaging + +![Broker-pattern](images/Architecture/Broker-pattern.png) + + + +### 点对点模式 + +在这种模式中,单个组件被称为对等点。对等点可以作为客户端,从其他对等点请求服务,作为服务器,为其他对等点提供服务。对等点可以充当客户端或服务器或两者的角色,并且可以随时间动态地更改其角色。 + +使用场景: + +- 像Gnutella和G2这样的文件共享网络 +- 多媒体协议,如P2PTV和PDTP +- 像Spotify这样的专有多媒体应用程序 + +![Peer-to-peer-pattern](images/Architecture/Peer-to-peer-pattern.png) + + + +### 事件总线模式 + +这种模式主要是处理事件,包括4个主要组件:事件源、事件监听器、通道和事件总线。消息源将消息发布到事件总线上的特定通道上。侦听器订阅特定的通道。侦听器会被通知消息,这些消息被发布到它们之前订阅的一个通道上。 + +使用场景: + +- 安卓开发 +- 通知服务 + +![Event-bus-pattern](images/Architecture/Event-bus-pattern.png) + + + +### 模型-视图-控制器模式 + +这种模式,也称为MVC模式,把一个交互式应用程序划分为3个部分, + +- 模型:包含核心功能和数据 +- 视图:将信息显示给用户(可以定义多个视图) +- 控制器:处理用户输入的信息 + +这样做是为了将信息的内部表示与信息的呈现方式分离开来,并接受用户的请求。它分离了组件,并允许有效的代码重用。 + +使用场景: + +- 在主要编程语言中互联网应用程序的体系架构 +- 像Django和Rails这样的Web框架 + +![Model-view-controller-pattern](images/Architecture/Model-view-controller-pattern.png) + + + +### 黑板模式 + +这种模式对于没有确定解决方案策略的问题是有用的。黑板模式由3个主要组成部分组成。 + +- 黑板——包含来自解决方案空间的对象的结构化全局内存 +- 知识源——专门的模块和它们自己的表示 +- 控制组件——选择、配置和执行模块 + +所有的组件都可以访问黑板。组件可以生成添加到黑板上的新数据对象。组件在黑板上查找特定类型的数据,并通过与现有知识源的模式匹配来查找这些数据。 + +使用场景: + +- 语音识别 +- 车辆识别和跟踪 +- 蛋白质结构识别 +- 声纳信号的解释 + +![Blackboard-pattern](images/Architecture/Blackboard-pattern.png) + + + +### 解释器模式 + +这个模式用于设计一个解释用专用语言编写的程序的组件。它主要指定如何评估程序的行数,即以特定的语言编写的句子或表达式。其基本思想是为每种语言的符号都有一个分类。 + +使用场景: + +- 数据库查询语言,比如SQL +- 用于描述通信协议的语言 + +![Interpreter-pattern](images/Architecture/Interpreter-pattern.png) \ No newline at end of file diff --git a/src/Architecture/1001.md b/src/Architecture/1001.md new file mode 100644 index 0000000..2b0655b --- /dev/null +++ b/src/Architecture/1001.md @@ -0,0 +1,35 @@ +- **时间限制:60秒后才能再次发送** + + 从发送验证码开始,前端(客户端)会进行一个60秒的倒数,在这一分钟之内,用户是无法提交多次发送信息的请求的。这种方法虽然使用得比较普遍,但是却不是非常有用,技术稍微好点的人完全可以绕过这个限制,直接发送短信验证码。 + +- **手机号限制:同一个手机号,24小时之内不能够超过5条** + + 对使用同一个手机号码进行注册或者其他发送短信验证码的操作的时候,系统可以对这个手机号码进行限制,例如,24小时只能发送5条短信验证码,超出限制则进行报错(如:系统繁忙,请稍后再试)。然而,这也只能够避免人工手动刷短信而已,对于批量使用不同手机号码来刷短信的机器,这种方法也是无可奈何的。 + +- **短信验证码限制:30分钟之内发送同一个验证码** + + 网上还有一种方法说:30分钟之内,所有的请求,所发送的短信验证码都是同一个验证码。第一次请求短信接口,然后缓存短信验证码结果,30分钟之内再次请求,则直接返回缓存的内容。对于这种方式,不是很清楚短信接口商会不会对发送缓存信息收取费用,如果有兴趣可以了解了解。 + +- **前后端校验:提交Token参数校验** + + 这种方式比较少人说到,个人觉得可以这种方法值得一试。前端(客户端)在请求发送短信的时候,同时向服务端提交一个Token参数,服务端对这个Token参数进行校验,校验通过之后,再向请求发送短信的接口向用户手机发送短信。 + +- **唯一性限制:微信产品,限制同一个微信ID用户的请求数量** + + 如果是微信的产品的话,可以通过微信ID来进行识别,然后对同一个微信ID的用户限制,24小时之内最多只能够发送一定量的短信。 + +- **产品流程限制:分步骤进行** + + 例如注册的短信验证码使用场景,我们将注册的步骤分成2步,用户在输入手机号码并设置了密码之后,下一步才进入验证码的验证步骤。 + +- **图形验证码限制:图形验证通过后再请求接口** + + 用户输入图形验证码并通过之后,再请求短信接口获取验证码。为了有更好的用户体验,也可以设计成:一开始不需要输入图形验证码,在操作达到一定量之后,才需要输入图形验证码。具体情况请根据具体场景来进行设计。 + +- **IP及Cookie限制:限制相同的IP/Cookie信息最大数量** + + 使用Cookie或者IP,能够简单识别同一个用户,然后对相同的用户进行限制(如:24小时内最多只能够发送20条短信)。然而,Cookie能够清理、IP能够模拟,而且IP还会出现局域网相同IP的情况,因此,在使用此方法的时候,应该根据具体情况来思考。 + +- **短信预警机制,做好出问题之后的防护** + + 以上的方法并不一定能够完全杜绝短信被刷,因此,我们也应该做好短信的预警机制,即当短信的使用量达到一定量之后,向管理员发送预警信息,管理员可以立刻对短信的接口情况进行监控和防护。 \ No newline at end of file diff --git a/src/Architecture/101.md b/src/Architecture/101.md new file mode 100644 index 0000000..1868d5b --- /dev/null +++ b/src/Architecture/101.md @@ -0,0 +1,161 @@ +### QPS + +**QPS**`Queries Per Second` 是每秒查询率 ,是**一台服务器**每秒能够相应的查询次数,是对一个特定的查询服务器**在规定时间内**所处理流量多少的衡量标准, 即每秒的响应请求数,也即是最大吞吐能力。 + +`峰值QPS=(日总PV×80%)/(日总秒数×20%)` + + + +### TPS + +**TPS**`Transactions Per Second`也就是事务数/秒。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。 + + + +**QPS和TPS区别** + +**Tps即每秒处理事务数,包括了** + +- 用户请求服务器 +- 服务器自己的内部处理 +- 服务器返回给用户 + +这三个过程,每秒能够完成N个这三个过程,Tps也就是N; + +Qps基本类似于Tps,但是不同的是,对于一个页面的一次访问,形成一个Tps;但一次页面请求,可能产生多次对服务器的请求,服务器对这些请求,就可计入“Qps”之中。 + + + +### 并发数 + +并发数(并发度):指系统同时能处理的请求数量,同样反应了系统的负载能力。这个数值可以分析机器1s内的访问日志数量来得到。 + + + +### 吐吞量 + +吞吐量是指系统在单位时间内处理请求的数量,TPS、QPS都是吞吐量的常用量化指标。 + + + +**系统吞吐量要素** + +一个系统的吞吐量(承压能力)与request(请求)对cpu的消耗,外部接口,IO等等紧密关联。 + +单个request 对cpu消耗越高,外部系统接口,IO影响速度越慢,系统吞吐能力越低,反之越高。 + + + +**重要参数** + +- QPS(TPS):每秒钟request/事务数量 +- 并发数:系统同时处理的request/事务数 +- 响应时间:一般取平均响应时间 + + + +**关系** + +QPS(TPS)=并发数/平均响应时间 + +一个系统吞吐量通常有QPS(TPS),并发数两个因素决定,每套系统这个两个值都有一个相对极限值,在应用场景访问压力下,只要某一项达到系统最高值,系统吞吐量就上不去了,如果压力继续增大,系统的吞吐量反而会下降,原因是系统超负荷工作,上下文切换,内存等等其他消耗导致系统性能下降。 + + + +### PV + +**PV**(Page View)是页面访问量,即页面浏览量或点击量,用户每次刷新即被计算一次。可以统计服务一天的访问日志得到。 + + + +### UV + +**UV**(Unique Visitor)是独立访客,统计1天内访问某站点的用户数。可以统计服务一天的访问日志并根据用户的唯一标识去重得到。响应时间(RT):响应时间是指系统对请求作出响应的时间,一般取平均响应时间。可以通过Nginx、Apache之类的Web Server得到。 + + + +### DAU + +**DAU**(Daily Active User)是日活跃用户数量。常用于反映网站、互联网应用或网络游戏的运营情况。DAU通常统计一日(统计日)之内,登录或使用了某个产品的用户数(去除重复登录的用户),与UV概念相似。 + + + +### MAU + +**MAU**(Month Active User)是月活跃用户数量,指网站、app等去重后的月活跃用户数量。 + + + +### 系统吞吐量评估 + +我们在做系统设计的时候就需要考虑CPU运算,IO,外部系统响应因素造成的影响以及对系统性能的初步预估。 + +而通常情况下,我们面对需求,我们评估出来的出来QPS,并发数之外,还有另外一个维度:日pv。 + +通过观察系统的访问日志发现,在用户量很大的情况下,各个时间周期内的同一时间段的访问流量几乎一样。比如工作日的每天早上。只要能拿到日流量图和QPS我们就可以推算日流量。 + +通常的技术方法: + +- 找出系统的最高TPS和日PV,这两个要素有相对比较稳定的关系(除了放假、季节性因素影响之外) +- 通过压力测试或者经验预估,得出最高TPS,然后跟进1的关系,计算出系统最高的日吞吐量。B2B中文和淘宝面对的客户群不一样,这两个客户群的网络行为不应用,他们之间的TPS和PV关系比例也不一样 + + + +### 指标测试 + +#### 基准测试 + +性能基线指标测试是当软件系统中增加一个新的模块的时候,需要做基准测试,以判断新模块对整个软件系统的性能影响。按照基准测试的方法,需要打开/关闭新模块至少各做一次测试。关闭模块之前的系统各个性能指标记下来作为基准(Benchmark),然后与打开模块状态下的系统性能指标作比较,以判断模块对系统性能的影响。 + + + +#### 负载测试 + +开发前期测试。考察软件系统在既定负载下的性能表现指标。指标体现为响应时间、交易容量、并发容量、资源使用率等。 + +- 根据系统详细设计文档,分析系统可能存在的负载点(并发用户数,业务量,数据量),可以按照特性及功能点进行负载分析 +- 固定测试环境,在其它测试角度(负载方面)不变的情况下,变化一个测试角度并持续增加压力,查看系统的性能曲线和处理极限,以及是否有性能瓶颈存在(拐点) + +目的在预定的指标基础上,从多个不同的测试角度去探测分析系统的性能变化情况,获得性能指标,配合性能调优 + +- 确定测试组网模型 +- 设计负载注入用例(系统处理能力) +- 针对不同的负载点,开发负载注入工具 +- 开发性能指标采集工具 + + + +#### 并发测试 + +在开发中后期测试。模拟并发访问,测试多用户并发访问同一个应用、模块、数据时是否产生隐藏的并发问题,如内存泄漏、线程锁、资源争用问题。目的并非为了获得性能指标,而是为了发现并发引起的问题: + +- 设计用户事务并发模型 +- 设计测试用例 +- 设计问题分析方法 + + + +#### 配置测试 + +在开发中后期测试。通过对被测系统的软硬件环境的调整,了解各种不同环境对性能影响的程度,从而找到系统各项资源的最有分配原则。目的是主要用于性能调优,在经过测试获得了基准测试数据后,进行环境调整(包括硬件配置、网络、操作系统、应用服务器、数据库等),再将测试结果与基准数据进行对比,判断调整是否达到最佳状态。 + +- 确定资源调整标准 +- 设计配置测试用例 + + + +#### 强度测试 + +在开发中后期测试。特殊场景分析,构造异常或极端条件(如告警风暴、资源减少增多),查看系统状态。目的是核实测试对象性能行为在异常或极端条件之下的可接受性。 + + + +#### 压力测试 + +在开发中后期测试。测试系统在一定饱和状态下系统能够处理的会话能力,以及是否出现错误。目的是通过测试调优保证系统即使在极端的压力情况下也不会出错甚至系统崩溃。 + + + +#### 稳定性测试 + +在开发中后期测试。测试系统在一定负载下运行长时间后是否会发生问题。测试系统在饱和状态的70%压力下处理会话能力,以及是否出现错误。目的是测试系统在长时间运行的情况下不会出错及性能下降问题 \ No newline at end of file diff --git a/src/Architecture/102.md b/src/Architecture/102.md new file mode 100644 index 0000000..d13a7ec --- /dev/null +++ b/src/Architecture/102.md @@ -0,0 +1,11 @@ +### 规范原则 + +- 接口返回数据即显示:前端仅做渲染逻辑处理 +- 渲染逻辑禁止跨多个接口调用 +- 前端关注交互、渲染逻辑,尽量避免业务逻辑处理的出现 +- 请求响应传输数据格式:JSON,JSON 数据尽量简单轻量,避免多级 JSON 的出现 +- 统一响应格式规范 +- 响应分页格式:使用统一响应格式 +- 下拉框、复选框、单选框:由后端接口统一逻辑判定是否选中,通过 isSelect 标示是否选中 +- Boolean 类型:关于 Boolean 类型,JSON 数据传输中一律使用 1/0 来标示,1 为是 / True,0 为否 / False +- 日期类型:关于日期类型,JSON 数据传输中一律使用字符串,具体日期格式因业务而定 \ No newline at end of file diff --git a/src/Architecture/103.md b/src/Architecture/103.md new file mode 100644 index 0000000..4669146 --- /dev/null +++ b/src/Architecture/103.md @@ -0,0 +1,171 @@ +### 安全性问题 + +安全性问题是一个接口必须要保证的规范。如果接口保证不了安全性,那么接口相当于直接暴露在公网环境中任人蹂躏。 + +#### 调用接口的先决条件-token + +获取token一般会涉及到参数`appid`,`appkey`,`timestamp`,`nonce`,`sign`。我们通过以上几个参数来获取调用系统的凭证: + +- `appid`和`appkey`可以直接通过平台线上申请,也可以线下直接颁发。`appid`是全局唯一的,每个`appid`将对应一个客户,`appkey`需要高度保密 +- `timestamp`是时间戳,使用系统当前的unix时间戳。时间戳的目的就是为了减轻DOS攻击。防止请求被拦截后一直尝试请求接口。服务器端设置时间戳阀值,如果请求时间戳和服务器时间超过阀值,则响应失败 +- `nonce`是随机值。随机值主要是为了增加`sign`的多变性,也可以保护接口的幂等性,相邻的两次请求`nonce`不允许重复,如果重复则认为是重复提交,响应失败 +- `sign`是参数签名,将`appkey`,`timestamp`,`nonce`拼接起来进行md5加密(当然使用其他方式进行不可逆加密也没问题)。 + +`token`,使用参数`appid`,`timestamp`,`nonce`,`sign`来获取token,作为系统调用的唯一凭证。`token`可以设置一次有效(这样安全性更高),也可以设置时效性,这里推荐设置时效性。如果一次有效的话这个接口的请求频率可能会很高。`token`推荐加到请求头上,这样可以跟业务参数完全区分开来。 + + + +#### 使用POST作为接口请求方式 + +一般调用接口最常用的两种方式就是GET和POST。两者的区别也很明显,GET请求会将参数暴露在浏览器URL中,而且对长度也有限制。为了更高的安全性,所有接口都采用POST方式请求。 + + + +#### 客户端IP白名单 + +ip白名单是指将接口的访问权限对部分ip进行开放。这样就能避免其他ip进行访问攻击,设置ip白名单比较麻烦的一点就是当你的客户端进行迁移后,就需要重新联系服务提供者添加新的ip白名单。设置ip白名单的方式很多,除了传统的防火墙之外,spring cloud alibaba提供的组件sentinel也支持白名单设置。为了降低api的复杂度,推荐使用防火墙规则进行白名单设置。 + + + +#### 单个接口针对ip限流 + +限流是为了更好的维护系统稳定性。使用redis进行接口调用次数统计,ip+接口地址作为key,访问次数作为value,每次请求value+1,设置过期时长来限制接口的调用频率。 + + + +#### 记录接口请求日志 + +使用aop全局记录请求日志,快速定位异常请求位置,排查问题原因。 + + + +#### 敏感数据脱敏 + +在接口调用过程中,可能会涉及到订单号等敏感数据,这类数据通常需要脱敏处理,最常用的方式就是加密。加密方式使用安全性比较高的`RSA`非对称加密。非对称加密算法有两个密钥,这两个密钥完全不同但又完全匹配。只有使用匹配的一对公钥和私钥,才能完成对明文的加密和解密过程。 + + + +### 幂等性问题 + +幂等性是指任意多次请求的执行结果和一次请求的执行结果所产生的影响相同。说的直白一点就是查询操作无论查询多少次都不会影响数据本身,因此查询操作本身就是幂等的。但是新增操作,每执行一次数据库就会发生变化,所以它是非幂等的。幂等问题的解决有很多思路,这里讲一种比较严谨的。提供一个生成随机数的接口,随机数全局唯一。调用接口的时候带入随机数。第一次调用,业务处理成功后,将随机数作为key,操作结果作为value,存入redis,同时设置过期时长。第二次调用,查询redis,如果key存在,则证明是重复提交,直接返回错误。 + + + +### 数据规范问题 + +#### 版本控制 + +一套成熟的API文档,一旦发布是不允许随意修改接口的。这时候如果想新增或者修改接口,就需要加入版本控制,版本号可以是整数类型,也可以是浮点数类型。一般接口地址都会带上版本号,http://ip:port//v1/list。 + + + +#### 响应状态码规范 + +一个牛逼的API,还需要提供简单明了的响应值,根据状态码就可以大概知道问题所在。我们采用http的状态码进行数据封装,例如200表示请求成功,4xx表示客户端错误,5xx表示服务器内部发生错误。状态码设计参考如下: + +| 分类 | 描述 | +| :--- | :------------------------------------------- | +| 1xx | 信息,服务器收到请求,需要请求者继续执行操作 | +| 2xx | 成功 | +| 3xx | 重定向,需要进一步的操作以完成请求 | +| 4xx | 客户端错误,请求包含语法错误或无法完成请求 | +| 5xx | 服务端错误 | + +状态码枚举类: + +```java +public enum CodeEnum { + + // 根据业务需求进行添加 + SUCCESS(200,"处理成功"), + ERROR_PATH(404,"请求地址错误"), + ERROR_SERVER(505,"服务器内部发生错误"); + + private int code; + private String message; + + CodeEnum(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} +``` + + + +#### 统一响应数据格式 + +为了方便给客户端响应,响应数据会包含三个属性,状态码(code),信息描述(message),响应数据(data)。客户端根据状态码及信息描述可快速知道接口,如果状态码返回成功,再开始处理数据。响应结果定义及常用方法: + +```java +public class R implements Serializable { + + private static final long serialVersionUID = 793034041048451317L; + + private int code; + private String message; + private Object data = null; + + public int getCode() { + return code; + } + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + public Object getData() { + return data; + } + + /** + * 放入响应枚举 + */ + public R fillCode(CodeEnum codeEnum){ + this.setCode(codeEnum.getCode()); + this.setMessage(codeEnum.getMessage()); + return this; + } + + /** + * 放入响应码及信息 + */ + public R fillCode(int code, String message){ + this.setCode(code); + this.setMessage(message); + return this; + } + + /** + * 处理成功,放入自定义业务数据集合 + */ + public R fillData(Object data) { + this.setCode(CodeEnum.SUCCESS.getCode()); + this.setMessage(CodeEnum.SUCCESS.getMessage()); + this.data = data; + return this; + } +} +``` \ No newline at end of file diff --git a/src/Architecture/1101.md b/src/Architecture/1101.md new file mode 100644 index 0000000..601ecb2 --- /dev/null +++ b/src/Architecture/1101.md @@ -0,0 +1 @@ +我们日常开发中,很多小伙伴容易忽视安全漏洞问题,认为只要正常实现业务逻辑就可以了。其实,**安全性才是最重要的**。本文将跟大家一起学习常见的安全漏洞问题,希望对大家有帮助哈。如果本文有什么错误的话,希望大家提出哈,感谢感谢~ \ No newline at end of file diff --git a/src/Architecture/1102.md b/src/Architecture/1102.md new file mode 100644 index 0000000..53fb197 --- /dev/null +++ b/src/Architecture/1102.md @@ -0,0 +1,53 @@ +### 什么是SQL注入? + +SQL注入是一种代码注入技术,一般被应用于攻击web应用程序。它通过在web应用接口传入一些特殊参数字符,来欺骗应用服务器,执行恶意的SQL命令,以达到非法获取系统信息的目的。它目前是黑客对数据库进行攻击的最常用手段之一。 + + + +### SQL注入是如何攻击的? + +举个常见的**业务场景**:在web表单搜索框输入员工名字,然后后台查询出对应名字的员工。 + +![SQL注入业务场景](images/Architecture/SQL注入业务场景.jpg) + +这种场景下,一般都是前端页面把一个名字参数name传到后台,然后后台通过SQL把结果查询出来 + +```java +name = "田螺"; //前端传过来的 +SQL= "select * from staff where name=" + name; //根据前端传过来的name参数,查询数据库员工表staff +``` + +因为SQL是直接拼接的,如果我们完全信任前端传的参数的话。假如前端传这么一个参数时`'' or '1'='1'`,SQL就变成酱紫的啦。 + +```mysql +select * from staff where name='' or '1'='1'; +``` + +这个SQL会把所有的员工信息全都查出来了,酱紫请求用户已经越权啦。请求者可以获取所有员工的信息,其他用户信息已经暴露了啦。 + + + +### 如何预防SQL注入问题 + +**使用#{}而不是${}** + +在MyBatis中,使用`#{}`而不是`${}`,可以很大程度防止sql注入。 + +> - 因为`#{}`是一个参数占位符,对于字符串类型,会自动加上"",其他类型不加。由于Mybatis采用**预编译**,其后的参数不会再进行SQL编译,所以一定程度上防止SQL注入。 +> - `${}`是一个简单的字符串替换,字符串是什么,就会解析成什么,存在SQL注入风险 + +**不要暴露一些不必要的日志或者安全信息,比如避免直接响应一些sql异常信息。** + +如果SQL发生异常了,不要把这些信息暴露响应给用户,可以自定义异常进行响应 + + + +**不相信任何外部输入参数,过滤参数中含有的一些数据库关键词关键词** + +可以加个参数校验过滤的方法,过滤`union,or`等数据库关键词 + + + +**适当的权限控制** + +在你查询信息时,先校验下当前用户是否有这个权限。如实现代码的时候,可以让用户多传一个企业Id什么的,或者获取当前用户的session信息等,在查询前,先校验一下当前用户是否是这个企业下的等等,是的话才有这个查询员工的权限。 \ No newline at end of file diff --git a/src/Architecture/1103.md b/src/Architecture/1103.md new file mode 100644 index 0000000..ff34a9f --- /dev/null +++ b/src/Architecture/1103.md @@ -0,0 +1,140 @@ +JSON反序列化漏洞——如Fastjson安全漏洞。 + +### 什么是JSON序列化,JSON发序列化 + +- 序列化:把对象转换为字节序列的过程 +- 反序列:把字节序列恢复为Java对象的过程 + +![JSON序列化过程](images/Architecture/JSON序列化过程.jpg) + +**Json序列化**就是将对象转换成Json格式的字符串,**JSON反序列化**就是Json串转换成对象 + + + +### JSON 反序列化漏洞是如何被攻击? + +不安全的反序列化可以导致远程代码执行、重放攻击、注入攻击或特权升级攻击。之前Fastjson频繁爆出安全漏洞,我们现在分析fastjson 1.2.24版本的一个反序列化漏洞吧,这个漏洞比较常见的利用手法就是通过jndi注入的方式实现RCE。 + +我们先来看fastjson一个反序列化的简单例子: + +```java +public class User { + private String name; + + private int age; + + public String getName() { + return name; + } + + public void setName(String name) { + System.out.println("调用了name方法"); + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + System.out.println("调用了age方法"); + this.age = age; + } + + public static void main(String[] args) { + String str = "{\"@type\":\"cn.eovie.bean.User\",\"age\":26,\"name\":\"捡田螺的小男孩\"}"; + User user = JSON.parseObject(str,User.class); + } +} +``` + +运行结果: + +```java +调用了age方法 +调用了name方法 +``` + +加了`@type`属性就能调用对应对象的`setXXX`方法,而`@type`表示指定反序列化成某个类。如果我们能够找到一个类,而这个类的某个`setXXX`方法中通过我们的精心构造能够完成命令执行,即可达到攻击的目的啦。 + +> com.sun.rowset.JdbcRowSetImpl 就是类似这么一个类,它有两个set方法,分别是setAutoCommit和setDataSourceName + +有兴趣的小伙伴,可以看下它的源代码: + +```java + public void setDataSourceName(String var1) throws SQLException { + if (this.getDataSourceName() != null) { + if (!this.getDataSourceName().equals(var1)) { + super.setDataSourceName(var1); + this.conn = null; + this.ps = null; + this.rs = null; + } + } else { + super.setDataSourceName(var1); + } + + } + + public void setAutoCommit(boolean var1) throws SQLException { + if (this.conn != null) { + this.conn.setAutoCommit(var1); + } else { + this.conn = this.connect(); + this.conn.setAutoCommit(var1); + } + + } + + private Connection connect() throws SQLException { + if (this.conn != null) { + return this.conn; + } else if (this.getDataSourceName() != null) { + try { + InitialContext var1 = new InitialContext(); + DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName()); + return this.getUsername() != null && !this.getUsername().equals("") ? var2.getConnection(this.getUsername(), this.getPassword()) : var2.getConnection(); + } catch (NamingException var3) { + throw new SQLException(this.resBundle.handleGetObject("jdbcrowsetimpl.connect").toString()); + } + } else { + return this.getUrl() != null ? DriverManager.getConnection(this.getUrl(), this.getUsername(), this.getPassword()) : null; + } + } +``` + +`setDataSourceName` 简单设置了设置了dataSourceName的值,`setAutoCommit`中有connect操作,connect方法中有典型的jndi的`lookup`方法调用,参数刚好就是在`setDataSourceName`中设置的dataSourceName。 + +因此,有漏洞的反序列代码实现如下即可: + +```java +public class FastjsonTest { + + public static void main(String[] argv){ + testJdbcRowSetImpl(); + } + + public static void testJdbcRowSetImpl(){ + //JDK 8u121以后版本需要设置改系统变量 + System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true"); + //RMI + String payload2 = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://localhost:1099/Exploit\"," + + " \"autoCommit\":true}"; + JSONObject.parseObject(payload2); + } +} +``` + +漏洞复现的流程如下哈: + +![JSON序列化漏洞复现](images/Architecture/JSON序列化漏洞复现.jpg) + +参考的代码来源这里哈,fastjson漏洞代码测试(https://github.com/earayu/fastjson_jndi_poc) + + + +**如何解决json反序列化漏洞问题** + +- 可以升级版本,比如fastjson后面版本,增强AutoType打开时的安全性 fastjson,增加了AutoType黑名单等等,都是为了应对这些安全漏洞 +- 反序列化有fastjson、gson、jackson等等类型,可以替换其他类型 +- 升级+打开safemode \ No newline at end of file diff --git a/src/Architecture/1104.md b/src/Architecture/1104.md new file mode 100644 index 0000000..ac8ac5b --- /dev/null +++ b/src/Architecture/1104.md @@ -0,0 +1,47 @@ +### 什么是XSS? + +XSS 攻击全称跨站脚本攻击(Cross-Site Scripting),这会与层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,因此有人将跨站脚本攻击缩写为XSS。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意攻击用户的特殊目的。XSS攻击一般分三种类型:存储型 、反射型 、DOM型XSS。 + + + +### XSS是如何攻击的? + +拿反射型举个例子吧,流程图如下: + +![XSS攻击-反射案例](images/Architecture/XSS攻击-反射案例.jpg) + +我们搞点简单代码样例吧,首先正常html页面如下: + +```xml + + + +``` + +![XSS攻击-Html](images/Architecture/XSS攻击-Html.jpg) + +- 用户输入搜索信息,点击搜索按钮,就是到达正常服务器的。如果黑客在url后面的参数中加入如下的恶意攻击代码 + + ```java + http://127.0.0.1/search?keyword=" + ``` + +- 当用户打开带有恶意代码的URL的时候,正常服务器会解析出请求参数 name,得到"",拼接到 HTML 中返回给浏览器 + +- 用户浏览器接收到响应后执行解析,其中的恶意代码也会被执行到 + +![XSS攻击-Html结果](images/Architecture/XSS攻击-Html结果.jpg) + +- 这里的链接我写的是百度搜索页,实际上黑客攻击的时候,是引诱用户输入某些重要信息,然后跳到他们自己的服务器,以窃取用户提交的内容信息 + + + +### 如何解决XSS攻击问题 + +- 不相信用户的输入,对输入进行过滤,过滤标签等,只允许合法值 +- HTML 转义 + +![XSS攻击-转义字符](images/Architecture/XSS攻击-转义字符.jpg) + +- 对于链接跳转,如` + +]> +]> +&xxe; +``` + +- 场景2. 攻击者通过将上面的实体行更改为一下内容来探测服务器的专用网络 + +```xml +]> +``` + +- 场景3. 攻击者通过恶意文件执行拒绝服务攻击 + +```xml +]> +``` + + + +### 如何防御XXE + +- 使用开发语言提供的禁用外部实体的方法 +- 过滤用户提交的XML数据,过滤 我开了一家有五十个座位的重庆火锅店,由于用料上等,童叟无欺。平时门庭若市,生意特别红火,而对面二狗家的火锅店却无人问津。二狗为了对付我,想了一个办法,叫了五十个人来我的火锅店坐着却不点菜,让别的客人无法吃饭。 + + + +### 如何应对DDoS攻击? + +- **高防服务器**,即能独立硬防御 50Gbps 以上的服务器,能够帮助网站拒绝服务攻击,定期扫描网络主节点等 +- **黑名单** +- **DDoS 清洗** +- **CDN 加速** \ No newline at end of file diff --git a/src/Architecture/1110.md b/src/Architecture/1110.md new file mode 100644 index 0000000..ac12953 --- /dev/null +++ b/src/Architecture/1110.md @@ -0,0 +1,6 @@ +- Struts 框架漏洞:远程命令执行漏洞和开放重定向漏洞 +- QQ Browser 9.6:API 权限控制问题导致泄露隐私模式 +- Oracle GlassFish Server:REST CSRF +- WebLogic: 未授权命令执行漏洞 +- Hacking Docker:Registry API 未授权访问 +- WordPress 4.7 / 4.7.1:REST API 内容注入漏洞 \ No newline at end of file diff --git a/src/Architecture/1111.md b/src/Architecture/1111.md new file mode 100644 index 0000000..05d399d --- /dev/null +++ b/src/Architecture/1111.md @@ -0,0 +1,27 @@ +### 弱口令 + +- 空口令 +- 口令长度小于8 +- 口令不应该为连续的某个字符(QQQQQQ) +- 账号密码相同(例:root:root) +- 口令与账号相反(例:root:toor) +- 口令纯数字(例:112312324234, 电话号) +- 口令纯字母(例:asdjfhask) +- 口令已数字代替字母(例:hello word, hell0 w0rd) +- 口令采用连续性组合(例:123456,abcdef,654321,fedcba) +- 服务/设备默认出厂口令 + + + +### 证书有效性验证漏洞 + +如果不对证书进行有效性验证,那https就如同虚设啦。 + +- 如果是客户生成的证书,需要跟系统可信根CA形成信任链,不能为了解决ssl证书报错的问题,选择在客户端代码中信任客户端中所有证书的方式 +- 证书快过期时,需要提前更换 + + + +### 未鉴权等权限相关漏洞 + +一些比较重要的接口,一般建议鉴权。比如你查询某账号的转账记录,肯定需要先校验该账号是不是操作人旗下的啦。 \ No newline at end of file diff --git a/src/Architecture/1201.md b/src/Architecture/1201.md new file mode 100644 index 0000000..fe54c62 --- /dev/null +++ b/src/Architecture/1201.md @@ -0,0 +1,22 @@ +**设计难点**:并发量大,应用、数据库都承受不了。另外难控制超卖。 + +**设计要点**: + +- 将请求尽量拦截在系统上游,html尽量静态化,部署到cdn上面。按钮及时设置为不可用,禁止用户重复提交请求 +- 设置页面缓存,针对同一个页面和uid一段时间内返回缓存页面 +- 数据用缓存抗,不直接落到数据库 +- 读数据的时候不做强一致性教研,写数据的时候再做 +- 在每台物理机上也缓存商品信息等等变动不大的相关的数据 +- 像商品中的标题和描述这些本身不变的会在秒杀开始之前全量推送到秒杀机器上并一直缓存直到秒杀结束 +- 像库存这种动态数据会采用被动失效的方式缓存一定时间(一般是数秒),失效后再去Tair缓存拉取最新的数据 +- 如果允许的话,用异步的模式,等缓存都落库之后再返回结果 +- 如果允许的话,增加答题教研等验证措施 + +![秒杀系统](images/Architecture/秒杀系统.png) + +**其它业务和技术保障措施**: + +- **业务隔离**。把秒杀做成一种营销活动,卖家要参加秒杀这种营销活动需要单独报名,从技术上来说,卖家报名后对我们来说就是已知热点,当真正开始时我们可以提前做好预热 +- **系统隔离**。系统隔离更多是运行时的隔离,可以通过分组部署的方式和另外 99% 分开。秒杀还申请了单独的域名,目的也是让请求落到不同的集群中 +- **数据隔离**。秒杀所调用的数据大部分都是热数据,比如会启用单独 cache 集群或 MySQL 数据库来放热点数据,目前也是不想0.01%的数据影响另外99.99% +- **缓存数据库高可用**。主要流量都落在缓存数据库上,需针对缓存数据库的高可用作保障。研究缓存穿透、雪崩等等问题 \ No newline at end of file diff --git a/src/Architecture/1202.md b/src/Architecture/1202.md new file mode 100644 index 0000000..0e7133d --- /dev/null +++ b/src/Architecture/1202.md @@ -0,0 +1,12 @@ +一般在`秒杀时间点`(比如:12点)前几分钟,用户并发量才真正突增,达到秒杀时间点时,并发量会达到顶峰。但由于这类活动是大量用户抢少量商品的场景,必定会出现`狼多肉少`的情况,所以其实绝大部分用户秒杀会失败,只有极少部分用户能够成功。正常情况下,大部分用户会收到商品已经抢完的提醒,收到该提醒后,他们大概率不会在那个活动页面停留了,如此一来,用户并发量又会急剧下降。所以这个峰值持续的时间其实是非常短的,这样就会出现瞬时高并发的情况,下面用一张图直观的感受一下流量的变化: + +![秒杀商品-瞬时高并发](images/Architecture/秒杀商品-瞬时高并发.png) + +像这种瞬时高并发的场景,传统的系统很难应对,我们需要设计一套全新的系统。可以从以下几个方面入手: + +- **页面静态化** +- **CDN加速** +- **缓存** +- **mq异步处理** +- **限流** +- **分布式锁** \ No newline at end of file diff --git a/src/Architecture/1203.md b/src/Architecture/1203.md new file mode 100644 index 0000000..df80ab6 --- /dev/null +++ b/src/Architecture/1203.md @@ -0,0 +1,7 @@ +活动页面是用户流量的第一入口,所以是并发量最大的地方。如果这些流量都能直接访问服务端,恐怕服务端会因为承受不住这么大的压力,而直接挂掉。 + +![秒杀商品-动态秒杀页面](images/Architecture/秒杀商品-动态秒杀页面.png)活动页面绝大多数内容是固定的,比如:商品名称、商品描述、图片等。为了减少不必要的服务端请求,通常情况下,会对活动页面做`静态化`处理。用户浏览商品等常规操作,并不会请求到服务端。只有到了秒杀时间点,并且用户主动点了秒杀按钮才允许访问服务端。 + +![秒杀商品-静态秒杀页面](images/Architecture/秒杀商品-静态秒杀页面.png)这样能过滤大部分无效请求。但只做页面静态化还不够,因为用户分布在全国各地,有些人在北京,有些人在成都,有些人在深圳,地域相差很远,网速各不相同。如何才能让用户最快访问到活动页面呢?这就需要使用CDN,它的全称是Content Delivery Network,即内容分发网络。 + +![秒杀商品-静态秒杀页面CDN](images/Architecture/秒杀商品-静态秒杀页面CDN.png)使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。 \ No newline at end of file diff --git a/src/Architecture/1204.md b/src/Architecture/1204.md new file mode 100644 index 0000000..4d6309f --- /dev/null +++ b/src/Architecture/1204.md @@ -0,0 +1,11 @@ +大部分用户怕错过`秒杀时间点`,一般会提前进入活动页面。此时看到的`秒杀按钮`是置灰,不可点击的。只有到了秒杀时间点那一时刻,秒杀按钮才会自动点亮,变成可点击的。但此时很多用户已经迫不及待了,通过不停刷新页面,争取在第一时间看到秒杀按钮的点亮。 + +从前面得知,该活动页面是静态的。那么我们在静态页面中如何控制秒杀按钮,只在秒杀时间点时才点亮呢?没错,使用js文件控制。为了性能考虑,一般会将css、js和图片等静态资源文件提前缓存到CDN上,让用户能够就近访问秒杀页面。看到这里,有些聪明的小伙伴,可能会问:CDN上的js文件是如何更新的?秒杀开始之前,js标志为false,还有另外一个随机参数。 + +![秒杀商品-秒杀活动开始前](images/Architecture/秒杀商品-秒杀活动开始前.png) + +当秒杀开始的时候系统会生成一个新的js文件,此时标志为true,并且随机参数生成一个新值,然后同步给CDN。由于有了这个随机参数,CDN不会缓存数据,每次都能从CDN中获取最新的js代码。 + +![秒杀商品-秒杀活动开始后](images/Architecture/秒杀商品-秒杀活动开始后.png) + +此外,前端还可以加一个定时器,控制比如:10秒之内,只允许发起一次请求。如果用户点击了一次秒杀按钮,则在10秒之内置灰,不允许再次点击,等到过了时间限制,又允许重新点击该按钮。 \ No newline at end of file diff --git a/src/Architecture/1205.md b/src/Architecture/1205.md new file mode 100644 index 0000000..5ea5859 --- /dev/null +++ b/src/Architecture/1205.md @@ -0,0 +1,7 @@ +在秒杀的过程中,系统一般会先查一下库存是否足够,如果足够才允许下单,写数据库。如果不够,则直接返回该商品已经抢完。由于大量用户抢少量商品,只有极少部分用户能够抢成功,所以绝大部分用户在秒杀时,库存其实是不足的,系统会直接返回该商品已经抢完。这是非常典型的:`读多写少` 的场景。 + +![秒杀商品-读多写少](images/Architecture/秒杀商品-读多写少.png) + +如果有数十万的请求过来,同时通过数据库查缓存是否足够,此时数据库可能会挂掉。因为数据库的连接资源非常有限,比如:mysql,无法同时支持这么多的连接。而应该改用缓存,比如:redis。即便用了redis,也需要部署多个节点。 + +![秒杀商品-Redis缓存](images/Architecture/秒杀商品-Redis缓存.png) \ No newline at end of file diff --git a/src/Architecture/1206.md b/src/Architecture/1206.md new file mode 100644 index 0000000..53f341d --- /dev/null +++ b/src/Architecture/1206.md @@ -0,0 +1,29 @@ +通常情况下,我们需要在redis中保存商品信息,里面包含:商品id、商品名称、规格属性、库存等信息,同时数据库中也要有相关信息,毕竟缓存并不完全可靠。用户在点击秒杀按钮,请求秒杀接口的过程中,需要传入的商品id参数,然后服务端需要校验该商品是否合法。大致流程如下图所示: + +![秒杀商品-大致流程](images/Architecture/秒杀商品-大致流程.png) + +根据商品id,先从缓存中查询商品,如果商品存在,则参与秒杀。如果不存在,则需要从数据库中查询商品,如果存在,则将商品信息放入缓存,然后参与秒杀。如果商品不存在,则直接提示失败。这个过程表面上看起来是OK的,但是如果深入分析一下会发现一些问题。 + + + +### 缓存击穿 + +比如商品A第一次秒杀时,缓存中是没有数据的,但数据库中有。虽说上面有如果从数据库中查到数据,则放入缓存的逻辑。然而,在高并发下,同一时刻会有大量的请求,都在秒杀同一件商品,这些请求同时去查缓存中没有数据,然后又同时访问数据库。结果悲剧了,数据库可能扛不住压力,直接挂掉。如何解决这个问题呢?这就需要加锁,最好使用分布式锁。 + +![秒杀商品-缓存击穿](images/Architecture/秒杀商品-缓存击穿.png)当然,针对这种情况,最好在项目启动之前,先把缓存进行`预热`。即事先把所有的商品,同步到缓存中,这样商品基本都能直接从缓存中获取到,就不会出现缓存击穿的问题了。 + +是不是上面加锁这一步可以不需要了?表面上看起来,确实可以不需要。但如果缓存中设置的过期时间不对,缓存提前过期了,或者缓存被不小心删除了,如果不加速同样可能出现缓存击穿。其实这里加锁,相当于买了一份保险。 + + + +### 缓存穿透 + +如果有大量的请求传入的商品id,在缓存中和数据库中都不存在,这些请求不就每次都会穿透过缓存,而直接访问数据库了。由于前面已经加了锁,所以即使这里的并发量很大,也不会导致数据库直接挂掉。但很显然这些请求的处理性能并不好,有没有更好的解决方案?这时可以想到`布隆过滤器`。 + +![秒杀商品-缓存穿透](images/Architecture/秒杀商品-缓存穿透.png) + +系统根据商品id,先从布隆过滤器中查询该id是否存在,如果存在则允许从缓存中查询数据,如果不存在,则直接返回失败。虽说该方案可以解决缓存穿透问题,但是又会引出另外一个问题:布隆过滤器中的数据如何更缓存中的数据保持一致?这就要求,如果缓存中数据有更新,则要及时同步到布隆过滤器中。如果数据同步失败了,还需要增加重试机制,而且跨数据源,能保证数据的实时一致性吗?显然是不行的。所以布隆过滤器绝大部分使用在缓存数据更新很少的场景中。如果缓存数据更新非常频繁,又该如何处理呢?这时,就需要把不存在的商品id也缓存起来。 + +![秒杀商品-缓存穿透-缓存空商品](images/Architecture/秒杀商品-缓存穿透-缓存空商品.png) + +下次,再有该商品id的请求过来,则也能从缓存中查到数据,只不过该数据比较特殊,表示商品不存在。需要特别注意的是,这种特殊缓存设置的超时时间应该尽量短一点。 \ No newline at end of file diff --git a/src/Architecture/1207.md b/src/Architecture/1207.md new file mode 100644 index 0000000..b37aae5 --- /dev/null +++ b/src/Architecture/1207.md @@ -0,0 +1,132 @@ +对于库存问题看似简单,实则里面还是有些东西。真正的秒杀商品的场景,不是说扣完库存,就完事了,如果用户在一段时间内,还没完成支付,扣减的库存是要加回去的。所以,在这里引出了一个`预扣库存`的概念,预扣库存的主要流程如下: + +![秒杀商品-预扣库存主要流程](images/Architecture/秒杀商品-预扣库存主要流程.png) + +扣减库存中除了上面说到的`预扣库存`和`回退库存`之外,还需要特别注意的是库存不足和库存超卖问题。 + + + +### 数据库扣减库存 + +使用数据库扣减库存,是最简单的实现方案了,假设扣减库存的sql如下: + +```sql +update product set stock=stock-1 where id=123; +``` + +这种写法对于扣减库存是没有问题的,但如何控制库存不足的情况下,不让用户操作呢?这就需要在update之前,先查一下库存是否足够了。伪代码如下: + +```sql +int stock = mapper.getStockById(123); +if(stock > 0) { + int count = mapper.updateStock(123); + if(count > 0) { + addOrder(123); + } +} +``` + +大家有没有发现这段代码的问题?没错,查询操作和更新操作不是原子性的,会导致在并发的场景下,出现库存超卖的情况。有人可能会说,这样好办,加把锁,不就搞定了,比如使用synchronized关键字。确实,可以,但是性能不够好。还有更优雅的处理方案,即基于数据库的乐观锁,这样会少一次数据库查询,而且能够天然的保证数据操作的原子性。只需将上面的sql稍微调整一下: + +```sql +update product set stock=stock-1 where id=product and stock > 0; +``` + +在sql最后加上:`stock > 0`,就能保证不会出现超卖的情况。但需要频繁访问数据库,我们都知道数据库连接是非常昂贵的资源。在高并发的场景下,可能会造成系统雪崩。而且,容易出现多个请求,同时竞争行锁的情况,造成相互等待,从而出现死锁的问题。 + + + +### redis扣减库存 + +redis的`incr`方法是原子性的,可以用该方法扣减库存。伪代码如下: + +```java + boolean exist = redisClient.query(productId,userId); + if(exist) { + return -1; + } + int stock = redisClient.queryStock(productId); + if(stock <=0) { + return 0; + } + redisClient.incrby(productId, -1); + redisClient.add(productId,userId); +return 1; +``` + +代码流程如下: + +- 先判断该用户有没有秒杀过该商品,如果已经秒杀过,则直接返回-1 +- 查询库存,如果库存小于等于0,则直接返回0,表示库存不足 +- 如果库存充足,则扣减库存,然后将本次秒杀记录保存起来。然后返回1,表示成功 + +估计很多小伙伴,一开始都会按这样的思路写代码。但如果仔细想想会发现,这段代码有问题。有什么问题呢?如果在高并发下,有多个请求同时查询库存,当时都大于0。由于查询库存和更新库存非原则操作,则会出现库存为负数的情况,即`库存超卖`。当然有人可能会说,加个`synchronized`不就解决问题?调整后代码如下: + +```java +boolean exist = redisClient.query(productId,userId); +if(exist) { + return -1; +} + +synchronized(this) { + int stock = redisClient.queryStock(productId); + if(stock <=0) { + return 0; + } + redisClient.incrby(productId, -1); + redisClient.add(productId,userId); + } + +return 1; +``` + +加`synchronized`确实能解决库存为负数问题,但是这样会导致接口性能急剧下降,每次查询都需要竞争同一把锁,显然不太合理。为了解决上面的问题,代码优化如下: + +```java +boolean exist = redisClient.query(productId,userId); +if(exist) { + return -1; +} +if(redisClient.incrby(productId, -1)<0) { + return 0; +} +redisClient.add(productId,userId); +return 1; +``` + +该代码主要流程如下: + +- 先判断该用户有没有秒杀过该商品,如果已经秒杀过,则直接返回-1 +- 扣减库存,判断返回值是否小于0,如果小于0,则直接返回0,表示库存不足 +- 如果扣减库存后,返回值大于或等于0,则将本次秒杀记录保存起来。然后返回1,表示成功 + +该方案咋一看,好像没问题。但如果在高并发场景中,有多个请求同时扣减库存,大多数请求的incrby操作之后,结果都会小于0。虽说,库存出现负数,不会出现`超卖的问题`。但由于这里是预减库存,如果负数值负的太多的话,后面万一要回退库存时,就会导致库存不准。那么,有没有更好的方案呢? + + + +### lua脚本扣减库存 + +lua脚本能够保证原子性的,它跟redis一起配合使用,能够完美解决上面的问题。lua脚本有段非常经典的代码: + +```java + StringBuilder lua = new StringBuilder(); + lua.append("if (redis.call('exists', KEYS[1]) == 1) then"); + lua.append(" local stock = tonumber(redis.call('get', KEYS[1]));"); + lua.append(" if (stock == -1) then"); + lua.append(" return 1;"); + lua.append(" end;"); + lua.append(" if (stock > 0) then"); + lua.append(" redis.call('incrby', KEYS[1], -1);"); + lua.append(" return stock;"); + lua.append(" end;"); + lua.append(" return 0;"); + lua.append("end;"); + lua.append("return -1;"); +``` + +该代码的主要流程如下: + +- 先判断商品id是否存在,如果不存在则直接返回 +- 获取该商品id的库存,判断库存如果是-1,则直接返回,表示不限制库存 +- 如果库存大于0,则扣减库存 +- 如果库存等于0,是直接返回,表示库存不足 \ No newline at end of file diff --git a/src/Architecture/1208.md b/src/Architecture/1208.md new file mode 100644 index 0000000..7186167 --- /dev/null +++ b/src/Architecture/1208.md @@ -0,0 +1,113 @@ +之前我提到过,在秒杀的时候,需要先从缓存中查商品是否存在,如果不存在,则会从数据库中查商品。如果数据库中,则将该商品放入缓存中,然后返回。如果数据库中没有,则直接返回失败。 + +大家试想一下,如果在高并发下,有大量的请求都去查一个缓存中不存在的商品,这些请求都会直接打到数据库。数据库由于承受不住压力,而直接挂掉。那么如何解决这个问题呢?这就需要用redis分布式锁了。 + +### setNx加锁 + +使用redis的分布式锁,首先想到的是`setNx`命令。 + +```java +if (jedis.setnx(lockKey, val) == 1) { + jedis.expire(lockKey, timeout); +} +``` + +用该命令其实可以加锁,但和后面的设置超时时间是分开的,并非原子操作。假如加锁成功了,但是设置超时时间失败了,该lockKey就变成永不失效的了。在高并发场景中,该问题会导致非常严重的后果。那么,有没有保证原子性的加锁命令呢? + + + +### set加锁 + +使用redis的set命令,它可以指定多个参数。 + +```java +String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime); +if ("OK".equals(result)) { + return true; +} +return false; +``` + +其中: + +- lockKey:锁的标识 +- requestId:请求id +- NX:只在键不存在时,才对键进行设置操作。 +- PX:设置键的过期时间为 millisecond 毫秒。 +- expireTime:过期时间 + +由于该命令只有一步,所以它是原子操作。 + + + +### 释放锁 + +接下来,有些朋友可能会问:在加锁时,既然已经有了lockKey锁标识,为什么要需要记录requestId呢?因为requestId是在释放锁的时候用的。 + +```java +if (jedis.get(lockKey).equals(requestId)) { + jedis.del(lockKey); + return true; +} +return false; +``` + +在释放锁的时候,只能释放自己加的锁,不允许释放别人加的锁。这里为什么要用requestId,用userId不行吗? + +答:如果用userId的话,假设本次请求流程走完了,准备删除锁。此时,巧合锁到了过期时间失效了。而另外一个请求,巧合使用的相同userId加锁,会成功。而本次请求删除锁的时候,删除的其实是别人的锁了。 + +当然使用lua脚本也能避免该问题: + +```java +if redis.call('get', KEYS[1]) == ARGV[1] then + return redis.call('del', KEYS[1]) +else + return 0 +end +``` + +它能保证查询锁是否存在和删除锁是原子操作。 + + + +### 自旋锁 + +上面的加锁方法看起来好像没有问题,但如果你仔细想想,如果有1万的请求同时去竞争那把锁,可能只有一个请求是成功的,其余的9999个请求都会失败。 + +在秒杀场景下,会有什么问题?答:每1万个请求,有1个成功。再1万个请求,有1个成功。如此下去,直到库存不足。这就变成均匀分布的秒杀了,跟我们想象中的不一样。 + +如何解决这个问题呢?答:使用自旋锁。 + +```java +try { + Long start = System.currentTimeMillis(); + while(true) { + String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime); + if ("OK".equals(result)) { + return true; + } + + long time = System.currentTimeMillis() - start; + if (time>=timeout) { + return false; + } + try { + Thread.sleep(50); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + +} finally{ + unlock(lockKey,requestId); +} +return false; +``` + +在规定的时间,比如500毫秒内,自旋不断尝试加锁,如果成功则直接返回。如果失败,则休眠50毫秒,再发起新一轮的尝试。如果到了超时时间,还未加锁成功,则直接返回失败。 + + + +### redisson + +除了上面的问题之外,使用redis分布式锁,还有锁竞争问题、续期问题、锁重入问题、多个redis实例加锁问题等。这些问题使用redisson可以解决,由于篇幅的原因,在这里先保留一点悬念,有疑问的私聊给我。后面会出一个专题介绍分布式锁,敬请期待。 \ No newline at end of file diff --git a/src/Architecture/1209.md b/src/Architecture/1209.md new file mode 100644 index 0000000..d10ad6f --- /dev/null +++ b/src/Architecture/1209.md @@ -0,0 +1,55 @@ +我们都知道在真实的秒杀场景中,有三个核心流程: + +![秒杀商品-三个核心流程](images/Architecture/秒杀商品-三个核心流程.png) + +而这三个核心流程中,真正并发量大的是秒杀功能,下单和支付功能实际并发量很小。所以,我们在设计秒杀系统时,有必要把下单和支付功能从秒杀的主流程中拆分出来,特别是下单功能要做成mq异步处理的。而支付功能,比如支付宝支付,是业务场景本身保证的异步。于是,秒杀后下单的流程变成如下: + +![秒杀商品-下单的流程](images/Architecture/秒杀商品-下单的流程.png) + +如果使用mq,需要关注以下几个问题: + + + +### 消息丢失问题 + +秒杀成功了,往mq发送下单消息的时候,有可能会失败。原因有很多,比如:网络问题、broker挂了、mq服务端磁盘问题等。这些情况,都可能会造成消息丢失。那么,如何防止消息丢失呢?答:加一张消息发送表。 + +![秒杀商品-消息丢失问题-加消息发送表](images/Architecture/秒杀商品-消息丢失问题-加消息发送表.png) + +在生产者发送mq消息之前,先把该条消息写入消息发送表,初始状态是待处理,然后再发送mq消息。消费者消费消息时,处理完业务逻辑之后,再回调生产者的一个接口,修改消息状态为已处理。如果生产者把消息写入消息发送表之后,再发送mq消息到mq服务端的过程中失败了,造成了消息丢失。这时候,要如何处理呢?答:使用job,增加重试机制。 + +![秒杀商品-消息丢失问题-加Job](images/Architecture/秒杀商品-消息丢失问题-加Job.png) + +用job每隔一段时间去查询消息发送表中状态为待处理的数据,然后重新发送mq消息。 + + + +### 重复消费问题 + +本来消费者消费消息时,在ack应答的时候,如果网络超时,本身就可能会消费重复的消息。但由于消息发送者增加了重试机制,会导致消费者重复消息的概率增大。那么,如何解决重复消息问题呢?答:加一张消息处理表。 + +![秒杀商品-消息丢失问题-加消息处理表](images/Architecture/秒杀商品-消息丢失问题-加消息处理表.png) + +消费者读到消息之后,先判断一下消息处理表,是否存在该消息,如果存在,表示是重复消费,则直接返回。如果不存在,则进行下单操作,接着将该消息写入消息处理表中,再返回。有个比较关键的点是:下单和写消息处理表,要放在同一个事务中,保证原子操作。 + + + +### 垃圾消息问题 + +这套方案表面上看起来没有问题,但如果出现了消息消费失败的情况。比如:由于某些原因,消息消费者下单一直失败,一直不能回调状态变更接口,这样job会不停的重试发消息。最后,会产生大量的垃圾消息。那么,如何解决这个问题呢? + +![秒杀商品-消息丢失问题-加Job优化](images/Architecture/秒杀商品-消息丢失问题-加Job优化.png) + +每次在job重试时,需要先判断一下消息发送表中该消息的发送次数是否达到最大限制,如果达到了,则直接返回。如果没有达到,则将次数加1,然后发送消息。这样如果出现异常,只会产生少量的垃圾消息,不会影响到正常的业务。 + + + +### 延迟消费问题 + +通常情况下,如果用户秒杀成功了,下单之后,在15分钟之内还未完成支付的话,该订单会被自动取消,回退库存。那么,在15分钟内未完成支付,订单被自动取消的功能,要如何实现呢?我们首先想到的可能是job,因为它比较简单。但job有个问题,需要每隔一段时间处理一次,实时性不太好。还有更好的方案?答:使用延迟队列。我们都知道rocketmq,自带了延迟队列的功能。 + +![秒杀商品-延迟消费](images/Architecture/秒杀商品-延迟消费.png) + +下单时消息生产者会先生成订单,此时状态为待支付,然后会向延迟队列中发一条消息。达到了延迟时间,消息消费者读取消息之后,会查询该订单的状态是否为待支付。如果是待支付状态,则会更新订单状态为取消状态。如果不是待支付状态,说明该订单已经支付过了,则直接返回。还有个关键点,用户完成支付之后,会修改订单状态为已支付。 + +![秒杀商品-增加已支付](images/Architecture/秒杀商品-增加已支付.png) \ No newline at end of file diff --git a/src/Architecture/1210.md b/src/Architecture/1210.md new file mode 100644 index 0000000..1345e56 --- /dev/null +++ b/src/Architecture/1210.md @@ -0,0 +1,66 @@ +通过秒杀活动,如果我们运气爆棚,可能会用非常低的价格买到不错的商品(这种概率堪比买福利彩票中大奖)。但有些高手,并不会像我们一样老老实实,通过秒杀页面点击秒杀按钮,抢购商品。他们可能在自己的服务器上,模拟正常用户登录系统,跳过秒杀页面,直接调用秒杀接口。如果是我们手动操作,一般情况下,一秒钟只能点击一次秒杀按钮。 + +![秒杀商品-正常用户请求](images/Architecture/秒杀商品-正常用户请求.png) + +但是如果是服务器,一秒钟可以请求成上千接口。 + +![秒杀商品-非法用户请求](images/Architecture/秒杀商品-非法用户请求.png) + +这种差距实在太明显了,如果不做任何限制,绝大部分商品可能是被机器抢到,而非正常的用户,有点不太公平。所以,我们有必要识别这些非法请求,做一些限制。那么,我们该如何现在这些非法请求呢?目前有两种常用的限流方式: + +- 基于nginx限流 +- 基于redis限流 + + + +### 对同一用户限流 + +为了防止某个用户,请求接口次数过于频繁,可以只针对该用户做限制。 + +![秒杀商品-对同一用户限流](images/Architecture/秒杀商品-对同一用户限流.png) + +限制同一个用户id,比如每分钟只能请求5次接口。 + + + +### 对同一ip限流 + +有时候只对某个用户限流是不够的,有些高手可以模拟多个用户请求,这种nginx就没法识别。这时需要加同一ip限流功能。 + +![秒杀商品-对同一IP限流](images/Architecture/秒杀商品-对同一IP限流.png) + +限制同一个ip,比如每分钟只能请求5次接口。但这种限流方式可能会有误杀的情况,比如同一个公司或网吧的出口ip是相同的,如果里面有多个正常用户同时发起请求,有些用户可能会被限制住。 + + + +### 对接口限流 + +别以为限制了用户和ip就万事大吉,有些高手甚至可以使用代理,每次都请求都换一个ip。这时可以限制请求的接口总次数。 + +![秒杀商品-对接口限流](images/Architecture/秒杀商品-对接口限流.png) + +在高并发场景下,这种限制对于系统的稳定性是非常有必要的。但可能由于有些非法请求次数太多,达到了该接口的请求上限,而影响其他的正常用户访问该接口。看起来有点得不偿失。 + + + +### 加验证码 + +相对于上面三种方式,加验证码的方式可能更精准一些,同样能限制用户的访问频次,但好处是不会存在误杀的情况。 + +![秒杀商品-加验证码](images/Architecture/秒杀商品-加验证码.png) + +通常情况下,用户在请求之前,需要先输入验证码。用户发起请求之后,服务端会去校验该验证码是否正确。只有正确才允许进行下一步操作,否则直接返回,并且提示验证码错误。此外,验证码一般是一次性的,同一个验证码只允许使用一次,不允许重复使用。普通验证码,由于生成的数字或者图案比较简单,可能会被破解。优点是生成速度比较快,缺点是有安全隐患。还有一个验证码叫做:`移动滑块`,它生成速度比较慢,但比较安全,是目前各大互联网公司的首选。 + + + +### 提高业务门槛 + +上面说的加验证码虽然可以限制非法用户请求,但是有些影响用户体验。用户点击秒杀按钮前,还要先输入验证码,流程显得有点繁琐,秒杀功能的流程不是应该越简单越好吗? + +其实,有时候达到某个目的,不一定非要通过技术手段,通过业务手段也一样。 + +12306刚开始的时候,全国人民都在同一时刻抢火车票,由于并发量太大,系统经常挂。后来,重构优化之后,将购买周期放长了,可以提前20天购买火车票,并且可以在9点、10、11点、12点等整点购买火车票。调整业务之后(当然技术也有很多调整),将之前集中的请求,分散开了,一下子降低了用户并发量。 + +回到这里,我们通过提高业务门槛,比如只有会员才能参与秒杀活动,普通注册用户没有权限。或者,只有等级到达3级以上的普通用户,才有资格参加该活动。 + +这样简单的提高一点门槛,即使是黄牛党也束手无策,他们总不可能为了参加一次秒杀活动,还另外花钱充值会员吧? \ No newline at end of file diff --git a/src/Architecture/1301.md b/src/Architecture/1301.md new file mode 100644 index 0000000..2bd6253 --- /dev/null +++ b/src/Architecture/1301.md @@ -0,0 +1,81 @@ +当存储IPv4地址时,应该使用32位的无符号整数(UNSIGNED INT)来存储IP地址,而不是使用字符串。相对字符串存储,使用无符号整数来存储有如下的好处: + +- 节省空间,不管是数据存储空间,还是索引存储空间 +- 便于使用范围查询(BETWEEN...AND),且效率更高 + +通常,在保存IPv4地址时,一个IPv4最小需要7个字符,最大需要15个字符,所以,使用`VARCHAR(15)`即可。MySQL在保存变长的字符串时,还需要额外的一个字节来保存此字符串的长度。而如果使用无符号整数来存储,只需要4个字节即可。 + +使用无符号整数来存储也有缺点: + +- 不便于阅读 +- 需要手动转换 + +对于转换来说,MySQL提供了相应的函数来把字符串格式的IP转换成整数`INET_ATON`,以及把整数格式的IP转换成字符串的`INET_NTOA`。如下所示: + +```sql +mysql> select inet_aton('192.168.0.1'); ++--------------------------+ +| inet_aton('192.168.0.1') | ++--------------------------+ +| 3232235521 | ++--------------------------+ +1 row in set (0.00 sec) + +mysql> select inet_ntoa(3232235521); ++-----------------------+ +| inet_ntoa(3232235521) | ++-----------------------+ +| 192.168.0.1 | ++-----------------------+ +1 row in set (0.00 sec) +``` + +对于IPv6来说,使用`VARBINARY`同样可获得相同的好处,同时MySQL也提供了相应的转换函数,即`INET6_ATON`和`INET6_NTOA`。 + +对于转换字符串IPv4和数值类型,可以放在应用层,下面是使用java代码来对二者转换: + +```java +public class IpLongUtils { + /** + * 把字符串IP转换成long + * + * @param ipStr 字符串IP + * @return IP对应的long值 + */ + public static long ip2Long(String ipStr) { + String[] ip = ipStr.split("\\."); + return (Long.valueOf(ip[0]) << 24) + (Long.valueOf(ip[1]) << 16) + + (Long.valueOf(ip[2]) << 8) + Long.valueOf(ip[3]); + } + + /** + * 把IP的long值转换成字符串 + * + * @param ipLong IP的long值 + * @return long值对应的字符串 + */ + public static String long2Ip(long ipLong) { + StringBuilder ip = new StringBuilder(); + ip.append(ipLong >>> 24).append("."); + ip.append((ipLong >>> 16) & 0xFF).append("."); + ip.append((ipLong >>> 8) & 0xFF).append("."); + ip.append(ipLong & 0xFF); + return ip.toString(); + } + + public static void main(String[] args) { + System.out.println(ip2Long("192.168.0.1")); + System.out.println(long2Ip(3232235521L)); + System.out.println(ip2Long("10.0.0.1")); + } + +} +``` + +输出结果为: + +```properties +3232235521 +192.168.0.1 +167772161 +``` \ No newline at end of file diff --git a/src/Architecture/1302.md b/src/Architecture/1302.md new file mode 100644 index 0000000..f647a96 --- /dev/null +++ b/src/Architecture/1302.md @@ -0,0 +1,7 @@ +公认方案: + +- **分布式ID生成器产生ID** +- **ID转62进制字符串** +- **记录数据库,根据业务要求确定过期时间,可以保留部分永久链接** + +主要难点在于分布式ID生成。鉴于短链一般没有严格递增的需求,可以使用预先分发一个号段,然后生成的方式。看了下新浪微博的短链接,8位,理论上可以保存超过200万亿对关系,具体怎么存储的还有待研究。 \ No newline at end of file diff --git a/src/Architecture/1303.md b/src/Architecture/1303.md new file mode 100644 index 0000000..60c8ef1 --- /dev/null +++ b/src/Architecture/1303.md @@ -0,0 +1,18 @@ +红包系统其实很像秒杀系统,只不过同一个秒杀的总量不大,但是全局的并发量非常大,如春晚可能几百万人同时抢红包。 + +**技术难点**: + +- 主要在数据库,减库存的时候会抢锁 +- 由于业务需求不同,没办法异步,也不能超卖,事务更加严格 + +**不能采用的方式**: + +- 乐观锁:手慢会失败,DB 面临更大压力,所以不能采用 +- 直接用缓存顶,涉及到钱,一旦缓存挂掉就完了 + +**建议方式**: + +- 接入层垂直切分,根据红包ID,发红包、抢红包、拆红包、查详情详情等都在同一台机器上处理,互不影响,分而治之 +- 请求进行排队,到数据库的时候是串行的,就不涉及抢锁的问题了 +- 为了防止队列太长过载导致队列被降级,直接打到数据库上,所以数据库前面再加上一个缓存,用CAS自增控制并发,太高的并发直接返回失败 +- 红包冷热数据分离,按时间分表 \ No newline at end of file diff --git a/src/Architecture/1304.md b/src/Architecture/1304.md new file mode 100644 index 0000000..e50a1f5 --- /dev/null +++ b/src/Architecture/1304.md @@ -0,0 +1,5 @@ +任务轮询或任务轮询+抢占排队方案 + +- 每个服务器首次启动时加入队列 +- 每次任务运行首先判断自己是否是当前可运行任务,如果是便运行 +- 如果不是当前运行的任务,检查自己是否在队列中,如果在,便退出,如果不在队列中,进入队列 \ No newline at end of file diff --git a/src/Architecture/1305.md b/src/Architecture/1305.md new file mode 100644 index 0000000..e8991dd --- /dev/null +++ b/src/Architecture/1305.md @@ -0,0 +1,8 @@ +**主要难点**:关系复杂,数据量大。一个人可以关注非常多的用户,一个大 V 也有可能有几千万的粉丝。 + +**基本方案**: + +- 推模式:推模式就是,用户A关注了用户 B,用户 B 每发送一个动态,后台遍历用户B的粉丝,往他们粉丝的 feed 里面推送一条动态 +- 拉模式:推模式相反,拉模式则是,用户每次刷新 feed 第一页,都去遍历关注的人,把最新的动态拉取回来 + +一般采用推拉结合的方式,用户发送状态之后,先推送给粉丝里面在线的用户,然后不在线的那部分等到上线的时候再来拉取。另外冷热数据分离,用户关系在缓存里面可以设置一个过期时间,比如七天。七天没上线的可能就很少用这个 APP。 \ No newline at end of file diff --git a/src/Architecture/1401.md b/src/Architecture/1401.md new file mode 100644 index 0000000..4c829cf --- /dev/null +++ b/src/Architecture/1401.md @@ -0,0 +1,2 @@ +- **热点数据缓存**:如报表、明星出轨、对象缓存、全页缓存都可以提升热点数据的访问速度 +- **中间数据缓存**:如导入导出计算中的中间状态数据缓存,以防内存溢出和提升了计算获取数据的速度 \ No newline at end of file diff --git a/src/Architecture/1402.md b/src/Architecture/1402.md new file mode 100644 index 0000000..1979297 --- /dev/null +++ b/src/Architecture/1402.md @@ -0,0 +1,18 @@ +String 类型setnx方法,只有不存在时才能添加成功,返回true。 + +```java +public static boolean getLock(String key, long expireTime) { + Long flag = jedis.setnx(key, "1"); + if (flag == 1) { + jedis.expire(key, expireTime); + } + + return flag == 1; + // NX 不存在则操作,EX 设置有效期单位是秒 + // return "OK".equals(jedis.set(key, requestId, "NX", "EX", expireTime)); +} + +public static void releaseLock(String key) { + jedis.del(key); +} +``` \ No newline at end of file diff --git a/src/Architecture/1403.md b/src/Architecture/1403.md new file mode 100644 index 0000000..88c4a31 --- /dev/null +++ b/src/Architecture/1403.md @@ -0,0 +1,4 @@ +**利用int类型的incrby的原子性** + +- 分库分表ID:一次性拿一号段 +- 订单ID:一次性拿一个号段 \ No newline at end of file diff --git a/src/Architecture/1404.md b/src/Architecture/1404.md new file mode 100644 index 0000000..b5aafda --- /dev/null +++ b/src/Architecture/1404.md @@ -0,0 +1,3 @@ +**int类型,incr方法** + +例如:文章的阅读量、微博点赞数、允许一定的延迟,先写入Redis再定时同步到数据库 \ No newline at end of file diff --git a/src/Architecture/1405.md b/src/Architecture/1405.md new file mode 100644 index 0000000..873ba4a --- /dev/null +++ b/src/Architecture/1405.md @@ -0,0 +1,3 @@ +**int类型,incr方法** + +以访问者的ip和其他信息作为key,访问一次增加一次计数,超过次数则返回false。 \ No newline at end of file diff --git a/src/Architecture/1406.md b/src/Architecture/1406.md new file mode 100644 index 0000000..1c58a3d --- /dev/null +++ b/src/Architecture/1406.md @@ -0,0 +1,33 @@ +String类型的bitcount(1.6.6的bitmap数据结构介绍)。字符是以8位二进制存储的。 + +```shell +set k1 a +setbit k1 6 1 +setbit k1 7 0 +get k1 + +# 6 7 代表的a的二进制位的修改 +# a 对应的ASCII码是97,转换为二进制数据是01100001 +# b 对应的ASCII码是98,转换为二进制数据是01100010 +``` + +在线用户统计,留存用户统计: + +```shell +setbit onlineusers 01 +setbit onlineusers 11 +setbit onlineusers 20 +``` + +支持按位与、按位或等等操作: + +- `BITOPANDdestkeykey[key...]`:对一个或多个 key 求逻辑并,并将结果保存到 destkey +- `BITOPORdestkeykey[key...]`:对一个或多个 key 求逻辑或,并将结果保存到 destkey +- `BITOPXORdestkeykey[key...]`:对一个或多个 key 求逻辑异或,并将结果保存到 destkey +- `BITOPNOTdestkeykey`:对给定 key 求逻辑非,并将结果保存到 destkey + +计算出7天都在线的用户: + +```shell +BITOP "AND" "7_days_both_online_users" "day_1_online_users" "day_2_online_users" ... "day_7_online_users" +``` \ No newline at end of file diff --git a/src/Architecture/1407.md b/src/Architecture/1407.md new file mode 100644 index 0000000..89a983f --- /dev/null +++ b/src/Architecture/1407.md @@ -0,0 +1,12 @@ +String 或hash。所有String可以做的hash都可以做。 + +![1586782173682](images/Architecture/20200413205303434.png) + +- key:用户id +- field:商品id +- value:商品数量 +- +1:hincr +- -1:hdecr +- 删除:hdel +- 全选:hgetall +- 商品数:hlen \ No newline at end of file diff --git a/src/Architecture/1408.md b/src/Architecture/1408.md new file mode 100644 index 0000000..9c1efe3 --- /dev/null +++ b/src/Architecture/1408.md @@ -0,0 +1,7 @@ +用户消息时间线TimeLine。list双向链表,直接作为timeline就好了。插入有序。Timeline的实现一般有推模式、拉模式、推拉结合这几种。 + +- 推模式:某人发布内容之后推送给所有粉丝,空间换时间,瓶颈在写入 +- 拉模式:粉丝从自己的关注列表中读取内容,时间换空间,瓶颈在读取 +- 推拉结合:某人发布内容后推送给`活跃粉丝`,不活跃粉丝则使用拉取 + +目前只讨论推模式,考虑单个feed内容实体存入散列(hashes)、每个用户的timeline列表存入列表(lists)。 \ No newline at end of file diff --git a/src/Architecture/1409.md b/src/Architecture/1409.md new file mode 100644 index 0000000..231096f --- /dev/null +++ b/src/Architecture/1409.md @@ -0,0 +1,4 @@ +List提供了两个阻塞的弹出操作:`blpop/brpop`,可以设置超时时间: + +- `blpop key1 timeout`:移除并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 +- `brpop key1 timeout` 移除并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 \ No newline at end of file diff --git a/src/Architecture/1410.md b/src/Architecture/1410.md new file mode 100644 index 0000000..5fcf1c6 --- /dev/null +++ b/src/Architecture/1410.md @@ -0,0 +1 @@ +自带一个随机获得值:`spop myset`。 \ No newline at end of file diff --git a/src/Architecture/1411.md b/src/Architecture/1411.md new file mode 100644 index 0000000..e456651 --- /dev/null +++ b/src/Architecture/1411.md @@ -0,0 +1,10 @@ +![1586782271388](images/Architecture/20200413205334747.png) + + +假如上面的微博ID是`t1001`,用户ID是`u3001`,用 `like:t1001` 来维护 `t1001` 这条微博的所有点赞用户: + +- 点赞了这条微博:`sadd like:t1001 u3001` +- 取消点赞:`srem like:t1001 u3001` +- 是否点赞:`sismember like:t1001 u3001` +- 点赞的所有用户:`smembers like:t1001` +- 点赞数:`scard like:t1001` \ No newline at end of file diff --git a/src/Architecture/1412.md b/src/Architecture/1412.md new file mode 100644 index 0000000..fa528e5 --- /dev/null +++ b/src/Architecture/1412.md @@ -0,0 +1,7 @@ +![1586782231684](images/Architecture/20200413205314496.png) + +用 `tags:i5001` 来维护商品所有的标签。 + +- `sadd tags:i5001 画面清晰细腻` +- `sadd tags:i5001 真彩清晰显示屏` +- `sadd tags:i5001 流程至极` \ No newline at end of file diff --git a/src/Architecture/1413.md b/src/Architecture/1413.md new file mode 100644 index 0000000..d7a80f0 --- /dev/null +++ b/src/Architecture/1413.md @@ -0,0 +1,16 @@ +- 获取差集:`sdiff set1 set2` +- 获取交集(intersection ):`sinter set1 set2` +- 获取并集:`sunion set1 set2` + +![1586782246941](images/Architecture/20200413205324331.png) + +假如:iPhone11 上市了 + +- `sadd brand:apple iPhone11` +- `sadd brand:ios iPhone11` +- `sad screensize:6.0-6.24 iPhone11` +- `sad screentype:lcd iPhone 11` + +筛选商品"苹果的、ios的、屏幕在6.0-6.24之间的,屏幕材质是LCD屏幕": + +- `sinter brand:apple brand:ios screensize:6.0-6.24 screentype:lcd` \ No newline at end of file diff --git a/src/Architecture/1414.md b/src/Architecture/1414.md new file mode 100644 index 0000000..a3e3e33 --- /dev/null +++ b/src/Architecture/1414.md @@ -0,0 +1,12 @@ +follow 关注 fans 粉丝 + +- 相互关注: + - sadd 1:follow 2 + - sadd 2:fans 1 + - sadd 1:fans 2 + - sadd 2:follow 1 +- 我关注的人也关注了他(取交集): + - sinter 1:follow 2:fans +- 可能认识的人: + - 用户1可能认识的人(差集):sdiff 2:follow 1:follow + - 用户2可能认识的人:sdiff 1:follow 2:follow \ No newline at end of file diff --git a/src/Architecture/1415.md b/src/Architecture/1415.md new file mode 100644 index 0000000..fe99d15 --- /dev/null +++ b/src/Architecture/1415.md @@ -0,0 +1,5 @@ +id 为6001 的新闻点击数加1:zincrby hotNews:20190926 1 n6001 + +获取今天点击最多的15条:zrevrange hotNews:20190926 0 15 withscores + +![1586782291610](images/Architecture/20200413205344663.png) \ No newline at end of file diff --git a/src/Architecture/1501.md b/src/Architecture/1501.md new file mode 100644 index 0000000..82b6dbf --- /dev/null +++ b/src/Architecture/1501.md @@ -0,0 +1,22 @@ +**微信支付结果通知场景** + +- 微信官方文档上提到微信支付通知结果可能会推送多次,需要开发者自行保证幂等性。第一次我们可以直接修改订单状态(如支付中 -> 支付成功),第二次就根据订单状态来判断,如果不是支付中,则不进行订单处理逻辑。 + + + +**插入数据库场景** + +- 每次插入数据时,先检查下数据库中是否有这条数据的主键 id,如果有,则进行更新操作。 + + + +**写 Redis 场景** + +- Redis 的 `Set` 操作天然幂等性,所以不用考虑 Redis 写数据的问题。 + + + +**其他场景方案** + +- 生产者发送每条数据时,增加一个全局唯一 id,类似订单 id。每次消费时,先去 Redis 查下是否有这个 id,如果没有,则进行正常处理消息,且将 id 存到 Redis。如果查到有这个 id,说明之前消费过,则不要进行重复处理这条消息 +- 不同业务场景,可能会有不同的幂等性方案,大家选择合适的即可,上面的几种方案只是提供常见的解决思路。 \ No newline at end of file diff --git a/src/Architecture/1502.md b/src/Architecture/1502.md new file mode 100644 index 0000000..7419235 --- /dev/null +++ b/src/Architecture/1502.md @@ -0,0 +1,57 @@ +### 生产者存放消息的过程中丢失消息 + +![生产者存放消息的过程中丢失消息](images/Architecture/生产者存放消息的过程中丢失消息.jpg) + +**解决方案** + +- 事务机制(不推荐,异步方式) + +对于 RabbitMQ 来说,生产者发送数据之前开启 RabbitMQ 的**事务机制**`channel.txselect` ,如果消息没有进队列,则生产者受到异常报错,并进行回滚 `channel.txRollback`,然后重试发送消息;如果收到了消息,则可以提交事务 `channel.txCommit`。但这是一个同步的操作,会影响性能。 + +- confirm 机制(推荐,异步方式) + +我们可以采用另外一种模式:`confirm` 模式来解决同步机制的性能问题。每次生产者发送的消息都会分配一个唯一的 id,如果写入到了 RabbitMQ 队列中,则 RabbitMQ 会回传一个 `ack` 消息,说明这个消息接收成功。如果 RabbitMQ 没能处理这个消息,则回调 `nack` 接口。说明需要重试发送消息。 + +也可以自定义超时时间 + 消息 id 来实现超时等待后重试机制。但可能出现的问题是调用 ack 接口时失败了,所以会出现消息被发送两次的问题,这个时候就需要保证消费者消费消息的幂等性。 + + + +`事务模式` 和 `confirm` 模式的区别: + +- 事务机制是同步的,提交事务后悔被**阻塞**直到提交事务完成后。 +- confirm 模式异步接收通知,但可能**接收不到通知**。需要考虑接收不到通知的场景。 + + + +### 消息队列丢失消息 + +![消息队列丢失消息](images/Architecture/消息队列丢失消息.png) + +消息队列的消息可以放到内存中,或将内存中的消息转到硬盘(比如数据库)中,一般都是内存和硬盘中都存有消息。如果只是放在内存中,那么当机器重启了,消息就全部丢失了。如果是硬盘中,则可能存在一种极端情况,就是将内存中的数据转换到硬盘的期间中,消息队列出问题了,未能将消息持久化到硬盘。 + +**解决方案** + +- 创建 `Queue` 的时候将其设置为持久化。 +- 发送消息的时候将消息的 `deliveryMode` 设置为 2 。 +- 开启生产者 `confirm` 模式,可以重试发送消息。 + + + +### 消费者丢失消息 + +![消费者丢失消息](images/Architecture/消费者丢失消息.png) + +消费者刚拿到数据,还没开始处理消息,结果进程因为异常退出了,消费者没有机会再次拿到消息。 + +**解决方案** + +- 关闭 RabbitMQ 的自动 `ack`,每次生产者将消息写入消息队列后,就自动回传一个 `ack` 给生产者。 +- 消费者处理完消息再主动 `ack`,告诉消息队列我处理完了。 + +**问题:** 那这种主动 `ack` 有什么漏洞了?如果 主动 `ack` 的时候挂了,怎么办? + +则可能会被再次消费,这个时候就需要幂等处理了。 + +**问题:** 如果这条消息一直被重复消费怎么办? + +则需要有加上重试次数的监测,如果超过一定次数则将消息丢失,记录到异常表或发送异常通知给值班人员。 \ No newline at end of file diff --git a/src/Architecture/1503.md b/src/Architecture/1503.md new file mode 100644 index 0000000..b1d41ef --- /dev/null +++ b/src/Architecture/1503.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待,有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/Architecture/1504.md b/src/Architecture/1504.md new file mode 100644 index 0000000..b1d41ef --- /dev/null +++ b/src/Architecture/1504.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待,有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/Architecture/1505.md b/src/Architecture/1505.md new file mode 100644 index 0000000..b1d41ef --- /dev/null +++ b/src/Architecture/1505.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待,有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/Architecture/1506.md b/src/Architecture/1506.md new file mode 100644 index 0000000..b1d41ef --- /dev/null +++ b/src/Architecture/1506.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待,有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/Architecture/1507.md b/src/Architecture/1507.md new file mode 100644 index 0000000..b1d41ef --- /dev/null +++ b/src/Architecture/1507.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待,有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/Architecture/1508.md b/src/Architecture/1508.md new file mode 100644 index 0000000..b1d41ef --- /dev/null +++ b/src/Architecture/1508.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待,有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/Architecture/1509.md b/src/Architecture/1509.md new file mode 100644 index 0000000..b1d41ef --- /dev/null +++ b/src/Architecture/1509.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待,有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/Architecture/1510.md b/src/Architecture/1510.md new file mode 100644 index 0000000..b1d41ef --- /dev/null +++ b/src/Architecture/1510.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待,有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/Architecture/2.md b/src/Architecture/2.md new file mode 100644 index 0000000..8d20bf1 --- /dev/null +++ b/src/Architecture/2.md @@ -0,0 +1,14 @@ +互联网早期,一般的网站应用流量较小,只需一个应用,将所有功能代码都部署在一起就可以,这样可以减少开发、部署和维护的成本。比如说一个电商系统,里面会包含很多用户管理,商品管理,订单管理,物流管理等等很多模块,我们会把它们做成一个web项目,然后部署到一台tomcat服务器上。 + +![单体应用架构](images/Architecture/单体应用架构.png) + +**优点** + +- 项目架构简单,小型项目的话, 开发成本低 +- 项目部署在一个节点上, 维护方便 + +**缺点** + +- 全部功能集成在一个工程中,对于大型项目来讲不易开发和维护 +- 项目模块之间紧密耦合,单点容错率低 +- 无法针对不同模块进行针对性优化和水平扩展 \ No newline at end of file diff --git a/src/Architecture/201.md b/src/Architecture/201.md new file mode 100644 index 0000000..33d7f88 --- /dev/null +++ b/src/Architecture/201.md @@ -0,0 +1,20 @@ +### 机房共用注册中心 + +所有机房共用一个服务注册中心,所有的请求由它统一分发,应用指向同一个数据库主库。 + +> 要突破单机房的容量限制,最直观的解决办法就是再建新的机房,机房之间通过专线连成同一个内部网络。应用可以部署一部分节点到第二个机房,数据库也可以将主备库交叉部署到不同的机房。这一阶段,只是解决了机房容量不足的问题,两个机房逻辑上仍是一个整体。 + +缺点: + +> 1. 服务层逻辑上是无差别的应用节点,**每一次 RPC 调用都有一半的概率跨机房**; +> 2. 每个特定的数据库主库只能位于一个机房,所以宏观上也一定有一半的数据库访问是跨机房的。 + + + +### 机房独占注册中心 + +每个机房独占一个服务注册中心,所有的请求独立分发,应用指向同一个数据库主库。 + +> 改进后的同城多机房架构,依靠不同服务注册中心,将应用层逻辑隔离开。只要一笔请求进入一个机房,应用层就一定会在一个机房内处理完。当然,由于数据库主库只在其中一边,所以这个架构仍然不解决一半数据访问跨机房的问题。 + +> 这个架构下,只要在入口处调节进入两个机房的请求比例,就可以精确控制两个机房的负载比例。基于这个能力,可以实现全站蓝绿发布。 \ No newline at end of file diff --git a/src/Architecture/202.md b/src/Architecture/202.md new file mode 100644 index 0000000..8d2d2d3 --- /dev/null +++ b/src/Architecture/202.md @@ -0,0 +1,29 @@ +> - 城市 1:idc1(registry1 + leader) + idc2(registry2 + replica1)。所有的服务都访问 leader 数据库 +> - 城市 2:idc3(registry3 + replica2) 另一个城市为备份的中心,访问replica,隔离对 leader 的依赖 + +两地三中心的两种形态: + +- 同城热备,异地冷备(蚂蚁就是采用这种方案,通常每个 idc 平摊流量) +- 同城灾备,异地灾备(一个中心是活的,另有一个同城灾备,一个异地灾备) + +### “ 双活 ” 或 “ 多活 ” 数据中心 + +多个或两个数据中心都处于运行当中,运行相同的应用,具备同样的数据,能够提供跨中心业务负载均衡运行能力,实现持续的应用可用性和灾难备份能力,所以称为 “双活 ” 和 “ 多活 ”。 + + + +### 传统数据中心和灾备中心 + +生产数据中心投入运行,灾备 数据中心处在不工作状态,只有当灾难发生时,生产数据中心瘫痪,灾备中心才启动。 + + + +异地灾备机房距离数据库主节点距离过远、访问耗时过长,异地备节点数据又不是强一致的,**所以无法直接提供在线服务**。 + + + +在扩展能力上,由于跨地区的备份中心不承载核心业务,不能解决核心业务跨地区扩展的问题;在成本上,灾备系统仅在容灾时使用,资源利用率低,成本较高;在容灾能力上,由于灾备系统冷备等待,容灾时可用性低,切换风险较大。 + + + +两地三中心看起来很美好,其实无法解决立刻切换的问题-**异地延迟无法消除**。 \ No newline at end of file diff --git a/src/Architecture/3.md b/src/Architecture/3.md new file mode 100644 index 0000000..6b06e2d --- /dev/null +++ b/src/Architecture/3.md @@ -0,0 +1,19 @@ +随着访问量的逐渐增大,单一应用只能依靠增加节点来应对,但是这时候会发现并不是所有的模块都会有比较大的访问量。还是以上面的电商为例子, 用户访问量的增加可能影响的只是用户和订单模块, 但是对消息模块的影响就比较小. 那么此时我们希望只多增加几个订单模块, 而不增加消息模块. 此时单体应用就做不到了, 垂直应用就应运而生了。所谓的垂直应用架构,就是将原来的一个应用拆成互不相干的几个应用,以提升效率。比如我们可以将上面电商的单体应用拆分成: + +- 电商系统(用户管理 商品管理 订单管理) +- 后台系统(用户管理 订单管理 客户管理) +- CMS系统(广告管理 营销管理) + +这样拆分完毕之后,一旦用户访问量变大,只需要增加电商系统的节点就可以了,而无需增加后台和CMS的节点。 + +![垂直应用架构](images/Architecture/垂直应用架构.png) + +**优点** + +- 系统拆分实现了流量分担,解决了并发问题,而且可以针对不同模块进行优化和水扩展 +- 一个系统的问题不会影响到其他系统,提高容错率 + +**缺点** + +- 系统之间相互独立, 无法进行相互调用 +- 系统之间相互独立, 会有重复的开发任务 \ No newline at end of file diff --git a/src/Architecture/301.md b/src/Architecture/301.md new file mode 100644 index 0000000..4200303 --- /dev/null +++ b/src/Architecture/301.md @@ -0,0 +1,20 @@ +`OAuth2.0` 的授权简单理解其实就是获取令牌(`token`)的过程,`OAuth` 协议定义了四种获得令牌的授权方式(`authorization grant` )如下: + +- 授权码(`authorization-code`) +- 隐藏式(`implicit`) +- 密码式(`password`) +- 客户端凭证(`client credentials`) + +但值得注意的是,不管我们使用哪一种授权方式,在三方应用申请令牌之前,都必须在系统中去申请身份唯一标识:客户端 ID(`client ID`)和 客户端密钥(`client secret`)。这样做可以保证 `token` 不被恶意使用。 + + + +下面我们会分析每种授权方式的原理,在进入正题前,先了解 `OAuth2.0` 授权过程中几个重要的参数: + +- `response_type`:code 表示要求返回授权码,token 表示直接返回令牌 +- `client_id`:客户端身份标识 +- `client_secret`:客户端密钥 +- `redirect_uri`:重定向地址 +- `scope`:表示授权的范围,`read`只读权限,`all`读写权限 +- `grant_type`:表示授权的方式,`AUTHORIZATION_CODE`(授权码)、`password`(密码)、`client_credentials`(凭证式)、`refresh_token` 更新令牌 +- `state`:应用程序传递的一个随机数,用来防止`CSRF` \ No newline at end of file diff --git a/src/Architecture/302.md b/src/Architecture/302.md new file mode 100644 index 0000000..5bdff75 --- /dev/null +++ b/src/Architecture/302.md @@ -0,0 +1,62 @@ +授权码模式(Authorization Code Grant)。 + + ![授权码模式](images/Architecture/授权码模式.png) + +- 第一步:用户访问页面 +- 第二步:访问的页面将请求重定向到认证服务器 +- 第三步:认证服务器向用户展示授权页面,等待用户授权 +- 第四步:用户授权,认证服务器生成一个code和带上client_id发送给应用服务器。然后,应用服务器拿到code,并用client_id去后台查询对应的client_secret +- 第五步:将code、client_id、client_secret传给认证服务器换取access_token和 refresh_token +- 第六步:将access_token和refresh_token传给应用服务器 +- 第七步:验证token,访问真正的资源页面 + + ![授权码模式优缺点](images/Architecture/授权码模式优缺点.png) + + + +**掘金授权案例** + +`OAuth2.0`四种授权中授权码方式是最为复杂,但也是安全系数最高的,比较常用的一种方式。这种方式适用于兼具前后端的`Web`项目,因为有些项目只有后端或只有前端,并不适用授权码模式。下图我们以用`WX`登录掘金为例,详细看一下授权码方式的整体流程。 + +![OAuth2.0-授权码](images/Architecture/OAuth2.0-授权码.png) + +用户选择`WX`登录掘金,掘金会向`WX`发起授权请求,接下来 `WX`询问用户是否同意授权(常见的弹窗授权)。其中 `response_type` 为 `code` 要求返回授权码,`scope` 参数表示本次授权范围为只读权限,`redirect_uri` 重定向地址。 + +```javascript +https://wx.com/oauth/authorize? + response_type=code& + client_id=CLIENT_ID& + redirect_uri=http://juejin.im/callback& + scope=read& + state=10001 +``` + +用户同意授权后,`WX` 根据 `redirect_uri`重定向并带上授权码。 + +```javascript +http://juejin.im/callback?code=AUTHORIZATION_CODE +``` + +当掘金拿到授权码(code)时,带授权码和密匙等参数向`WX`申请令牌。`grant_type`表示本次授权为授权码方式 `authorization_code` ,获取令牌要带上客户端密匙 `client_secret`,和上一步得到的授权码 `code`。 + +```javascript +https://wx.com/oauth/token? + client_id=CLIENT_ID& + client_secret=CLIENT_SECRET& + grant_type=authorization_code& + code=AUTHORIZATION_CODE& + redirect_uri=http://juejin.im/callback +``` + +最后 `WX` 收到请求后向 `redirect_uri` 地址发送 `JSON` 数据,其中的`access_token` 就是令牌。 + +```javascript + { + "access_token":"ACCESS_TOKEN", + "token_type":"bearer", + "expires_in":2592000, + "refresh_token":"REFRESH_TOKEN", + "scope":"read", + ...... +} +``` \ No newline at end of file diff --git a/src/Architecture/303.md b/src/Architecture/303.md new file mode 100644 index 0000000..d35cc4a --- /dev/null +++ b/src/Architecture/303.md @@ -0,0 +1,10 @@ +简化模式(Implicit Grant)。 + +![简化模式](images/Architecture/简化模式.png) + +- 第一步:用户访问页面时,重定向到认证服务器 +- 第二步:认证服务器给用户一个认证页面,等待用户授权 +- 第三步:用户授权,认证服务器想应用页面返回Token +- 第四步:验证Token,访问真正的资源页面 + +![简化模式优缺点](images/Architecture/简化模式优缺点.png) \ No newline at end of file diff --git a/src/Architecture/304.md b/src/Architecture/304.md new file mode 100644 index 0000000..fd3cf7d --- /dev/null +++ b/src/Architecture/304.md @@ -0,0 +1,13 @@ +密码模式(Resource Owner Password Credentials Grant)。 + +![密码模式](images/Architecture/密码模式.png) + +- 第一步:用户访问用页面时,输入第三方认证所需要的信息(QQ/微信账号密码) +- 第二步:应用页面那种这个信息去认证服务器授权 +- 第三步:认证服务器授权通过,拿到token,访问真正的资源页面 + +**优点**:不需要多次请求转发,额外开销,同时可以获取更多的用户信息。 + +**缺点**:局限性,认证服务器和应用方必须有超高的信赖。 + +**应用场景**:自家公司搭建的认证服务器。 \ No newline at end of file diff --git a/src/Architecture/305.md b/src/Architecture/305.md new file mode 100644 index 0000000..0f1cbcc --- /dev/null +++ b/src/Architecture/305.md @@ -0,0 +1,10 @@ +客户端模式(Client Credentials Grant)。 + +![客户端模式](images/Architecture/客户端模式.png) + +- 第一步:用户访问应用客户端 +- 第二步:通过客户端定义的验证方法,拿到token,无需授权 +- 第三步:访问资源服务器A +- 第四步:拿到一次token就可以畅通无阻的访问其他的资源页面。 + +这是一种最简单的模式,只要client请求,我们就将AccessToken发送给它。这种模式是最方便但最不安全的模式。因此这就要求我们对client完全的信任,而client本身也是安全的。因此这种模式一般用来提供给我们完全信任的服务器端服务。在这个过程中不需要用户的参与。 \ No newline at end of file diff --git a/src/Architecture/306.md b/src/Architecture/306.md new file mode 100644 index 0000000..2f60cb9 --- /dev/null +++ b/src/Architecture/306.md @@ -0,0 +1,9 @@ +上边提到有一些`Web`应用是没有后端的, 属于纯前端应用,无法用上边的授权码模式。令牌的申请与存储都需要在前端完成,跳过了授权码这一步。前端应用直接获取 `token`,`response_type` 设置为 `token`,要求直接返回令牌,跳过授权码,`WX`授权通过后重定向到指定 `redirect_uri` 。 + +```javascript +https://wx.com/oauth/authorize? + response_type=token& + client_id=CLIENT_ID& + redirect_uri=http://juejin.im/callback& + scope=read +``` \ No newline at end of file diff --git a/src/Architecture/307.md b/src/Architecture/307.md new file mode 100644 index 0000000..a5acc1e --- /dev/null +++ b/src/Architecture/307.md @@ -0,0 +1,11 @@ +密码模式比较好理解,用户在掘金直接输入自己的`WX`用户名和密码,掘金拿着信息直接去`WX`申请令牌,请求响应的 `JSON`结果中返回 `token`。`grant_type` 为 `password` 表示密码式授权。 + +```javascript +https://wx.com/token? + grant_type=password& + username=USERNAME& + password=PASSWORD& + client_id=CLIENT_ID +``` + +这种授权方式缺点是显而易见的,非常的危险,如果采取此方式授权,该应用一定是可以高度信任的。 \ No newline at end of file diff --git a/src/Architecture/308.md b/src/Architecture/308.md new file mode 100644 index 0000000..5fad798 --- /dev/null +++ b/src/Architecture/308.md @@ -0,0 +1,8 @@ +凭证式和密码式很相似,主要适用于那些没有前端的命令行应用,可以用最简单的方式获取令牌,在请求响应的 `JSON` 结果中返回 `token`。`grant_type` 为 `client_credentials` 表示凭证式授权,`client_id` 和 `client_secret` 用来识别身份。 + +```javascript +https://wx.com/token? + grant_type=client_credentials& + client_id=CLIENT_ID& + client_secret=CLIENT_SECRET +``` \ No newline at end of file diff --git a/src/Architecture/309.md b/src/Architecture/309.md new file mode 100644 index 0000000..15f8224 --- /dev/null +++ b/src/Architecture/309.md @@ -0,0 +1,19 @@ +**问题一:令牌怎么用?** + +拿到令牌可以调用 `WX` API 请求数据了,那令牌该怎么用呢?每个到达`WX`的请求都必须带上 `token`,将 `token` 放在 `http` 请求头部的一个`Authorization`字段里。如果使用`postman` 模拟请求,要在`Authorization` -> `Bearer Token` 放入 `token`,**注意**:低版本`postman` 没有这个选项。 + +![OAuth2.0-令牌怎么用](images/Architecture/OAuth2.0-令牌怎么用.png) + + + +**问题二:令牌过期怎么办?** + +`token`是有时效性的,一旦过期就需要重新获取,但是重走一遍授权流程,不仅麻烦而且用户体验也不好,那如何让更新令牌变得优雅一点呢?一般在颁发令牌时会一次发两个令牌,一个令牌用来请求`API`,另一个负责更新令牌 `refresh_token`。`grant_type` 为 `refresh_token` 请求为更新令牌,参数 `refresh_token` 是用于更新令牌的令牌。 + +```javascript +https://wx.com/oauth/token? + grant_type=refresh_token& + client_id=CLIENT_ID& + client_secret=CLIENT_SECRET& + refresh_token=REFRESH_TOKEN +``` \ No newline at end of file diff --git a/src/Architecture/4.md b/src/Architecture/4.md new file mode 100644 index 0000000..71be049 --- /dev/null +++ b/src/Architecture/4.md @@ -0,0 +1,13 @@ +即分布式架构当垂直应用越来越多,重复的业务代码就会越来越多。这时候,我们就思考可不可以将重复的代码抽取出来,做成统一的业务层作为独立的服务,然后由前端控制层调用不同的业务层服务呢? + +这就产生了新的分布式系统架构。它将把工程拆分成表现层和服务层两个部分,服务层中包含业务逻辑。表现层只需要处理和页面的交互,业务逻辑都是调用服务层的服务来实现。 + +![分布式架构](images/Architecture/分布式架构.png) + +**优点** + +- 抽取公共的功能为服务层,提高代码复用性 + +**缺点** + +- 系统间耦合度变高,调用关系错综复杂,难以维护 \ No newline at end of file diff --git a/src/Architecture/401.md b/src/Architecture/401.md new file mode 100644 index 0000000..d502f4a --- /dev/null +++ b/src/Architecture/401.md @@ -0,0 +1,8 @@ +- 失败次数超过3次,启用图片验证码 +- 失败次数超过10次,启用手机验证码 +- 启用HTTPS解决中间人攻击 +- 敏感数据进行加密传输 +- 操作日志 +- 异常操作或登录体系 +- 拒绝弱密码 +- 防止用户名被遍历 \ No newline at end of file diff --git a/src/Architecture/402.md b/src/Architecture/402.md new file mode 100644 index 0000000..1c75346 --- /dev/null +++ b/src/Architecture/402.md @@ -0,0 +1,23 @@ +### 账号注册流程 + +在判断账号是否注册时,为了防止恶意攻击,通过手动或自动化程序测试账号是否注册,这里应该做风险控制,如连续3次账号未注册,后续每次输入账号都需要验证(如输入验证码,滑动验证等)才会继续流程。 + +![账号注册流程](images/Architecture/账号注册流程.png) + + + +### 账号登录主流程 + +账号可能是手机号、邮箱号或其他,大部分App均支持手机号验证码登录,这里也分析此流程。第三方账号登录一般情况下有两种情况: + +- 主流社交账号如微信、QQ、微博、Facebook等的登录,对于已绑定的账号,直接唤起相应App进行授权登录,对于未绑定的账户,则还需要进行绑定 + +- 同一公司体系下产品的账号,如腾讯系的腾讯视频、王者荣耀等,无需注册,使用一套账号(微信、QQ)授权登录 + + ![账号登录流程](images/Architecture/账号登录流程.png) + + + +### 找回密码流程 + +![找回密码流程](images/Architecture/找回密码流程.png) \ No newline at end of file diff --git a/src/Architecture/403.md b/src/Architecture/403.md new file mode 100644 index 0000000..a69b6e6 --- /dev/null +++ b/src/Architecture/403.md @@ -0,0 +1,125 @@ +一般使用 **https 协议 + 非对称加密算法(如 RSA)**来传输用户密码,为了更加安全,可以在前端构造一下随机因子。使用 **BCrypt + 盐存储用户密码**。在感知到暴力破解危害的时候,**「开启短信验证、图形验证码、账号暂时锁定」**等防御机制来抵御暴力破解。 + +### 传输密码 + +#### https协议 + +**http 的三大风险** + +为什么要使用 https 协议呢?**「http 它不香」**吗? 因为 http 是明文信息传输的。如果在茫茫的网络海洋,使用 http 协议,有以下三大风险: + +- 窃听/嗅探风险:第三方可以截获通信数据 +- 数据篡改风险:第三方获取到通信数据后,会进行恶意修改 +- 身份伪造风险:第三方可以冒充他人身份参与通信 + +如果传输不重要的信息还好,但是传输用户密码这些敏感信息,那可不得了。所以一般都要使用**「https 协议」**传输用户密码信息。 + + + +**https 原理** + +https 原理是什么呢?为什么它能解决 http 的三大风险呢? + +**https = http + SSL/TLS**, SSL/TLS 是传输层加密协议,它提供内容加密、身份认证、数据完整性校验,以解决数据传输的安全性问题。 + + + +**https一定安全吗?** + +https 的数据传输过程,数据都是密文的,那么,使用了 https 协议传输密码信息,一定是安全的吗?其实**「不然」** + +- 比如,https 完全就是建立在证书可信的基础上的呢。但是如果遇到中间人伪造证书,一旦客户端通过验证,安全性顿时就没了哦!平时各种钓鱼不可描述的网站,很可能就是黑客在诱导用户安装它们的伪造证书 +- 通过伪造证书,https 也是可能被抓包的 + + + +#### 对称加密算法 + +既然使用了 https 协议传输用户密码,还是不一定安全,那么就给用户密码加密再传输。加密算法有对称加密和非对称加密两大类。对称加密:加密和解密使用**「相同密钥」**的加密算法。 + +![img](images/Architecture/2cabf15de992c630b80b55b7734744bf.png) + +常用的对称加密算法主要有以下几种: + +![img](images/Architecture/cdefa098def4fa1cb6c181f700df4c49.png) + +如果使用对称加密算法,需要**考虑密钥如何给到对方**,如果密钥还是网络传输给对方,传输过程,被中间人拿到的话,也是有风险的哦。 + + + +#### 非对称加密算法 + +非对称加密算法需要两个密钥(公开密钥和私有密钥)。公钥与私钥是成对存在的,如果用公钥对数据进行加密,只有对应的私钥才能解密。 + +![img](images/Architecture/468036d6bd7316bc39d8c783af042fc8.png) + +常用的非对称加密算法主要有以下几种:![img](images/Architecture/788b54bf0bb97d401f13a0fdc20bc9c1.png) + +如果使用非对称加密算法,也需要考虑**「密钥公钥如何给到对方」**,如果公钥还是网络传输给对方,传输过程,被中间人拿到的话,会有什么问题呢?**「他们是不是可以伪造公钥,把伪造的公钥给客户端,然后,用自己的私钥等公钥加密的数据发过来?」** + +我们直接**「登录一下百度」**,抓下接口请求,验证一发大厂是怎么加密的。可以发现有获取公钥接口,如下: + +![img](images/Architecture/1a9f1463d439bc07a6b44df1ce973916.png) + +再看下登录接口,发现就是 RSA 算法,RSA 就是**「非对称加密算法」**。其实百度前端是用了 JavaScript 库**「jsencrypt」**,在 github 的 star 还挺多的。 + +![img](images/Architecture/dc291356663fc69dd4e8f7cfe7be63b6.png) + +因此,我们可以用**「https + 非对称加密算法(如 RSA)」** 传输用户密码。 + + + +### 存储密码 + +假设密码已经安全到达服务端啦,那么,如何存储用户的密码呢?一定不能明文存储密码到数据库哦!可以用**「哈希摘要算法加密密码」**,再保存到数据库。 + +**哈希摘要算法**:只能从明文生成一个对应的哈希值,不能反过来根据哈希值得到对应的明文。 + +#### MD5摘要算法 + +MD5 是一种非常经典的哈希摘要算法,被广泛应用于数据完整性校验、数据(消息)摘要、数据加密等。但是仅仅使用 MD5 对密码进行摘要,并不安全。在 MD5 免费破解网站一输入,马上就可以看到原密码了。 + +试想一下,如果黑客构建一个超大的数据库,把所有 20 位数字以内的数字和字母组合的密码全部计算 MD5 哈希值出来,并且把密码和它们对应的哈希值存到里面去(这就是**「彩虹表」**)。在破解密码的时候,只需要查一下这个彩虹表就完事了。所以**「单单 MD5 对密码取哈希值存储」**,已经不安全啦。 + + + +#### MD5+盐摘要算法 + +在密码学中,是指通过在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这种过程称之为“加盐”。用户密码+盐之后,进行哈希散列,再保存到数据库。这样可以有效应对彩虹表破解法。但是呢,使用加盐,需要注意以下几点: + +- 不能在代码中写死盐,且盐需要有一定的长度(盐写死太简单的话,黑客可能注册几个账号反推出来) +- 每一个密码都有独立的盐,并且盐要长一点,比如超过 20 位。(盐太短,加上原始密码太短,容易破解) +- 最好是随机的值,并且是全球唯一的,意味着全球不可能有现成的彩虹表给你用 + + + +#### Bcrypt + +即使是加了盐,密码仍有可能被暴力破解。因此,我们可以采取更**「慢一点」**的算法,让黑客破解密码付出更大的代价,甚至迫使他们放弃。提升密码存储安全的利器——Bcrypt。 + +实际上,Spring Security 已经废弃了 MessageDigestPasswordEncoder,推荐使用BCryptPasswordEncoder,也就是BCrypt来进行密码哈希。BCrypt 生而为保存密码设计的算法,相比 MD5 要慢很多。看个例子: + +```java +public class BCryptTest { + public static void main(String[] args) { + String password = "123456"; + long md5Begin = System.currentTimeMillis(); + DigestUtils.md5Hex(password); + long md5End = System.currentTimeMillis(); + System.out.println("md5 time:"+(md5End - md5Begin)); + long bcrytBegin = System.currentTimeMillis(); + BCrypt.hashpw(password, BCrypt.gensalt(10)); + long bcrytEnd = System.currentTimeMillis(); + System.out.println("bcrypt Time:" + (bcrytEnd- bcrytBegin)); + } +} +``` + +运行结果: + +```java +md5 time:47 +bcrypt Time:1597 +``` + +粗略对比发现,BCrypt 比 MD5 慢几十倍,黑客想暴力破解的话,就需要花费几十倍的代价。因此一般情况,建议使用 Bcrypt 来存储用户的密码。 \ No newline at end of file diff --git a/src/Architecture/5.md b/src/Architecture/5.md new file mode 100644 index 0000000..2b7fcfb --- /dev/null +++ b/src/Architecture/5.md @@ -0,0 +1,12 @@ +在分布式架构下,当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心对集群进行实时管理。此时,用于资源调度和治理中心(SOA Service Oriented Architecture,面向服务的架构)是关键。 + +![SOA架构](images/Architecture/SOA架构.png) + +**优点** + +- 使用注册中心解决了服务间调用关系的自动调节 + +**缺点** + +- 服务间会有依赖关系,一旦某个环节出错会影响较大( 服务雪崩 ) +- 服务关心复杂,运维、测试部署困难 \ No newline at end of file diff --git a/src/Architecture/501.md b/src/Architecture/501.md new file mode 100644 index 0000000..83fbcb4 --- /dev/null +++ b/src/Architecture/501.md @@ -0,0 +1,16 @@ +下述分析的几种权限管理其实并无优劣之分。权限管理作为系统的基石,应依据系统目标用户特点、后续发展方向、维护成本等方面进行综合评估,找到最适合系统的模式即可。 + +- 用户管理核心是解决用户与权限的问题 +- 角色可理解为一类用户,或者一堆权限的集合,链接了用户与权限的关系 +- 权限可以分为功能权限和数据范围 +- 复杂的继承关系,数据范围依赖用户组织架构树,功能权限依赖角色树,将用户放置于组织架构树的不同节点上,并赋予角色,即解决了功能权限和数据范围的问题 + + + +**权限设计=功能权限+数据权限** + + + +参考文档 + +- https://www.cnblogs.com/jpfss/p/11677430.html \ No newline at end of file diff --git a/src/Architecture/502.md b/src/Architecture/502.md new file mode 100644 index 0000000..076ca76 --- /dev/null +++ b/src/Architecture/502.md @@ -0,0 +1,76 @@ +### 用户-权限 + +用户直接与权限映射,这种设计的优势在于简洁直观,适合用户数量不多,功能较为简单的系统,它的劣势也是非常的明显当用户量增多时,维护成本较高,可扩展性差。 + +![用户-权限](images/Architecture/用户-权限.png) + +系统页面Demo: + +![用户-权限Demo](images/Architecture/用户-权限Demo.png) + + + +### 用户-角色-权限 + +若系统用户和功能增多,为每一个用户匹配单独的权限,会变得非常的繁琐,因此权限分门别类,形成“权限包”。从用户的角度,将用户分类,同一类用户固定为相同的角色,赋予相同的权限,会让操作变得简单很多。 + +![用户-角色-权限](images/Architecture/用户-角色-权限.png) + +系统页面Demo: + +![用户-角色-权限Demo用户管理](images/Architecture/用户-角色-权限Demo用户管理.png) + +![用户-角色-权限Demo角色管理](images/Architecture/用户-角色-权限Demo角色管理.png) + + + +### 组织-用户-角色-权限 + +对于管理性后台,往往人员是职级区分的,比如用户王五为销售组长,其组员赵六和孙七,王五需要看到赵六和孙七的销售额数据和可以进行赵六和孙七的所有操作,而赵六仅能看到自己的销售额数据,进行和自己相关的操作。这个事例中引入了两个新的概念: + +- **用户的权限可以细分为功能权限和数据范围权限** +- **数据范围和功能权限都有了继承的层级概念** + +所谓功能权限大家比较好理解,比如能否看到某个页面,能否点击某个按钮。而数据权限略抽象些,比如在业绩报表模块,从功能权限角度,可以决定用户能否打开这个报表页面,但是不同用户进来看到不同的数据(王五需要看到赵六和孙七的销售额数据,而赵六仅能看到自己的销售额数据,看不到孙七的),则是由数据范围来控制的。 + +![组织-用户-角色-权限](images/Architecture/组织-用户-角色-权限.png) + + + +#### 数据范围的继承 + +我们可以将用户进行分级管理,比如建立多层级的组织架构树,将不同用户放置于组织架构的不同根节点上,来实现多层级用户的建立和管理。 + +- 如果用户的层级如果比较简单(不多于三级),可以将层级关系融入到角色之中。比如用户分为三级:管理员-组长-组员,管理员能看到全部的数据范围和拥有全部的功能权限,而组长能查看组员的数据范围和拥有部分功能权限(比如无法编辑用户),而组员的数据范围仅仅为自己负责的数据和拥有部分功能权限。 + + 我们可以在组长这个角色下,允许其绑定组员,针对不同的角色设置不同的数据范围读取方式,管理员可以读取全部数据范围,组长需要读取其组员的,组员只能读取自己的。大家有兴趣可以去了解下RBAC0/1模型 + + ![组织-用户-角色-权限数据范围](images/Architecture/组织-用户-角色-权限数据范围.png) + +- 而对于用户层级较多的情况,建议采用多层级的组织架构的管理模式,先建立公司的组织部门,再将人置于组织架构树的不同节点之下。以用户在组织节点的位置,以及是否为某个节点组织的负责人,来确定其数据范围。 + + + +#### 功能权限的继承 + +一般是将角色进行分级,有了所谓的角色树的概念: + +![功能权限的继承](images/Architecture/功能权限的继承.png) + +由此,我们就得到了自由度更高但是逻辑更复杂的权限管理: + +![功能权限的继承层级](images/Architecture/功能权限的继承层级.png) + +涉及到组织架构树和角色树,需要考虑到的场景更多,这些细节要根据实际的业务场景来制定方案。比如: + +- 组织有成立和解散的时间,员工也存在转岗换组织部门的情况,因此要考虑引入时间轴的概念。增加很多的校验逻辑,比如需要增加员工入职、离职时间,且员工在该部门任职的时间不能早于部门成立的时间等等 +- 同一员工能否兼岗,允许在多个组织下存在 +- 角色上是否会有互斥情况存在(RBAC-2模型),比如实际业务中,发钞和验钞的工作不允许同一个人做,因此在功能设计时要考虑角色之间的互斥性,通过为用户配置角色来实现用户与权限的映射关系,不同权限间是存在优先级的,比如刚刚的例子,互斥关系为最高优先级 + +实体关系图 : + +![功能权限的实体关系图](images/Architecture/功能权限的实体关系图.png) + +系统页面Demo: + +![功能权限的Demo](images/Architecture/功能权限的Demo.png) \ No newline at end of file diff --git a/src/Architecture/503.md b/src/Architecture/503.md new file mode 100644 index 0000000..7cec464 --- /dev/null +++ b/src/Architecture/503.md @@ -0,0 +1,41 @@ +RBAC是一套成熟的权限模型。在传统权限模型中,我们直接把权限赋予用户。而在RBAC中,增加了“角色”的概念,我们首先把权限赋予角色,再把角色赋予用户。这样,由于增加了角色,授权会更加灵活方便。在RBAC中,根据权限的复杂程度,又可分为RBAC0、RBAC1、RBAC2、RBAC3。其中,RBAC0是基础,RBAC1、RBAC2、RBAC3都是以RBAC0为基础的升级。我们可以根据自家产品权限的复杂程度,选取适合的权限模型。 + +![RBAC](images/Architecture/RBAC.png) + +### 基本模型RBAC0 + +RBAC0是基础,很多产品只需基于RBAC0就可以搭建权限模型了。在这个模型中,我们把权限赋予角色,再把角色赋予用户。用户和角色,角色和权限都是多对多的关系。用户拥有的权限等于他所有的角色持有权限之和。 + +![RBAC0](images/Architecture/RBAC0.png) + + + +### 角色分层模型RBAC1 + +RBAC1建立在RBAC0基础之上,在角色中引入了继承的概念。简单理解就是,给角色可以分成几个等级,每个等级权限不同,从而实现更细粒度的权限管理。 + +![RBAC1](images/Architecture/RBAC1.png) + + + +### 角色限制模型RBAC2 + +RBAC2同样建立在RBAC0基础之上,仅是对用户、角色和权限三者之间增加了一些限制。这些限制可以分成两类,即静态职责分离SSD(Static Separation of Duty)和动态职责分离DSD(Dynamic Separation of Duty)。具体限制如下图: + +![RBAC2](images/Architecture/RBAC2.png) + + + +### 统一模型RBAC3 + +RBAC3是RBAC1和RBAC2的合集,所以RBAC3既有角色分层,也包括可以增加各种限制。 + +![RBAC3](images/Architecture/RBAC3.png) + + + +### 延展用户组 + +基于RBAC模型,还可以适当延展,使其更适合我们的产品。譬如增加用户组概念,直接给用户组分配角色,再把用户加入用户组。这样用户除了拥有自身的权限外,还拥有了所属用户组的所有权限。 + +![RBAC用户组](images/Architecture/RBAC用户组.png) \ No newline at end of file diff --git a/src/Architecture/6.md b/src/Architecture/6.md new file mode 100644 index 0000000..72b2fea --- /dev/null +++ b/src/Architecture/6.md @@ -0,0 +1,918 @@ +## + +https://juejin.cn/user/4177799914474653/posts + +https://www.cnblogs.com/jiujuan/p/13280473.html + +微服务架构在某种程度上是面向服务的架构SOA继续发展的下一步,它更加强调服务的"彻底拆分"。 + +![微服务架构](images/Architecture/微服务架构.png) + +**优点** + +- 更好的开发规模 +- 更快的开发速度 +- 支持迭代开发或现代化增量开发 +- 充分利用现代软件开发生态系统的优势(云、容器、 DevOps、Serverless) +- 支持水平缩放和细粒度缩放 +- 小体量,较低了开发人员的认知复杂性 + +**缺点** + +- 更高数量级的活动组件(服务、数据库、进程、容器、框架) +- 复杂性从代码转移到基础设施 +- RPC 调用和网络通信的大量增加 +- 整个系统的安全性管理更具有挑战性 +- 整个系统的设计变得更加困难 +- 引入了分布式系统的复杂性 + + + +### 微服务定义 + +![微服务定义](images/Architecture/微服务定义.jpg) + +- **一组小的服务** + + 原来的单块服务都是业务能力大而全的打包在一个单块中,微服务主张把这些单块服务进行拆分,形成一个个小的独立的服务。这里有个最大的特点是“小”,那么纠结要小到什么程度才为之小,很多同学都会纠结这个小的点,因为这个小并没有特别和明确的规定,所以这也就引申出了现在很多DDD领域驱动设计来指引微服务的拆分,但基本上一个微服务能让一个开发人员能够独立的理解,基本上就称为一个微服务,具体有多少行代码并不是很关键。 + +- **独立的进程** + + 微服务是运行在独立的进程当中,例如java程序部署在tomcat,也可以部署在容器docker中,容易本身也是一种进程,所以微服务可以以进程的方式去扩展。 + +- **轻量级的通讯** + + 微服务主张使用轻量级去构建通讯机制,例如http,固定消息格式和减少消息格式,服务之间不耦合,让通讯尽量轻量。 + +- **基于业务能力** + + 微服务是基于业务能力进行构建,例如有用户服务,登陆服务,商品服务,基于这些业务能力去构建这些微服务。 + +- **独立部署** + + 微服务被拆分开后,每个团队独立维护自己的微服务,开发,迭代自己的微服务,是可以独立的去部署,团队之间是不需要特别的去协调,这些对业务开发维护可以做到更加的敏捷,轻量,快速。 + +- **无集中式管理** + + 原来单体服务是需要整个技术团队是需要独立的架构团队去管理,统一架构,统一技术栈,统一存储,微服务就不太一样,微服务主张每个团队根据自己的技术需要,选择自己最熟悉,最高效解决问题的技术栈,甚至选择不同存储方式。 + + + +### 康威定律 + +> 康威法则设计系统的组织,其产生的设计和架构,等价组织的组织架构 + + + +**单块应用时代** + +![康威定律-单块应用](images/Architecture/康威定律-单块应用.jpg) + +几个团队共同去对一个单块应用去开发和维护时,如果一个团队对这个单块应用进行改造引入一些新的功能或技术的时候,往往需要其他的团队协作和配合,连同做集成测试才能交付这个应用,这个时候,不仅仅是沟通协调成本高,团队和团队之间往往容易产生摩擦。**也就是说,多团队之间和单应用产生不匹配,违反康威法则**。怎么解决,微服务是一个解决的手段: + +![康威定律-微服务解决方案](images/Architecture/康威定律-微服务解决方案.jpg) + +我们把单块的应用拆分成诺干个独立的应用,每个团队负责自己的服务,相互之间不干扰,当团队A服务的服务进行修改不需要其他的团队来配合,或者说这种配合沟通成本比较少,一般只发生在双方边界交集的地方,那么这个时候发现多团队和微服务之间架构的关系可以映射起来,它符合了康威法则,整体研发效率更高效。 + + + +### 微服务利弊 + +![微服务利弊](images/Architecture/微服务利弊.jpg) + +- **利** + + - **强模块化边界** + + 我们知道做软件架构,软件设计,模块化是非常重要的一点,一开始我们写程序做软件,我们采用类的方式来做模块化,后面开始采用组件或类库的方式做模块化,可以做到工程上的重用和分享给其他团队来使用。微服务在组件的层次上面又高了一层,以服务的方式来做模块化,每个团队独立开始和维护自己的服务,有明显的一个边界,开发完一个服务其他团队可以直接调用这个服务,不需要像组件通过jar或源码的方式去进行分享,所以微服务的边界是比较清晰的。 + + - **可独立部署** + + 可独立部署是微服务最显著的一个特性,每个团队可以根据自己的业务需求,当产品经理或业务方把需求提过来,可以根据需要独立开发和部署服务,一般来说不需要太过依赖其他团队去协同,这个对比单块应用,单块引用在这个方面需求很多团队来协助和帮忙。 + + - **技术多样性** + + 微服务是分散式治理,没有集中治理,每个团队可以根据团队自己的实际情况和业务的实际情况去选择适合自己的技术栈,有些团队可能擅长Java开发,有些团队可能更偏向前端,更适合用nodejs去开发服务,不过这个不是越多越好,技术栈的引入也是有成本 + +- **弊** + + - **分布式复杂性** + + 在原来单块应用就是一个应用,一个对单块应用的架构比较熟悉的人可以对整个单块应用有一个很好的把控。但是到了分布式系统,微服务化了以后可能涉及到的服务有好几十个,一些大公司可能涉及到的服务上百个,服务与服务之间是通过相互沟通来实现业务,那么这个时候整个系统就变成非常复杂,一般的开发人员或一个团队都无法理解整个系统是如何工作的,这个就是分布式带来的复杂性。 + + - **最终一致性** + + 微服务的数据是分散式治理的,每个团队都有自己的数据源和数据拷贝,比方说团队A有订单数据,B团队也有订单数据,团队A修改了订单数据是否应该同步给团队B的数据呢,这里就涉及到数据一致性问题,如果没有很好的解决一致性问题,就可能造成数据的不一致,这个在业务上是不可以接受的。 + + - **运维复杂性** + + 以往的运维需要管理的是机器+单块的应用,分布式系统和单块应用不一样的是,分布式系统需要很多的服务,服务与服务之间相互协同,那么对分布式系统的资源,容量规划,对监控,对整个系统的可靠性稳定性都非常具备挑战的。 + + - **测试复杂性** + + 对测试人员来说,在单块应用上,一个测试团队只需要测试一个单块应用就可以了,到了分布式系统,各个服务是分布在各个团队的,这个对测试团队来说要求就很好,做集成测试的时候需要很多的团队相互配合去联合做集成测试。 + + + +### 微服务分层 + +**BFF是什么?** + +BFF即 Backend For Frontend(服务于前端的后端),也就是服务器设计 API 时会考虑前端的使用,并在服务端直接进行业务逻辑的处理,又称为用户体验适配器。BFF 只是一种逻辑分层,而非一种技术,虽然 BFF 是一个新名词,但它的理念由来已久。 + + + +一般将微服务整个体系大的方向划分为2层,见下图: + +![微服务分层](images/Architecture/微服务分层.jpg) + +在最上层不属于微服务有很多的连接方式,有PC,有H5,有APP等等,在下层,包含了2个层,它们一起组成我们的微服务或SOA,微服务加单的划分为2层,最底下的基础服务层。 + +- **微服务基础服务层** + + 基础服务一般属于互联网平台基础性的支撑服务,比方说,电商网站的基础服务有订单服务,商品服务,用户服务等,这些都属于比较基础和原子性,下沉一个公司的基础设施的低层,向下承接存储,向上提供业务能力,有些公司叫(基础服务,中间层服务,公共服务),netflix成为中间层服务。我们暂且统称为基础服务。 + +- **微服务聚合服务层** + + 已经有了基础服务能提供业务能力,为什么还需要聚合服务,因为我们有不同的接入端,如app和H5,pc等等,它们看似调用大致相同的数据,但其实存在很多差异,例如PC需要展示更多信息,APP需要做信息裁剪等等。一般低层服务都是比较通用的,基础服务应该对外输出相对统一的服务,在抽象上做得比较好。但是对不同的外界app和pc的接入,我们需要作出不同的适配,这个时候需要有一个层去做出聚合裁剪的工作。例如一个商品详情在pc端展示和app端的展示,pc可能会展示更多的信息,而app则需要对信息作出一些裁剪,如果基础服务直接开放接口给到pc和app,那么基础服务也需要去做成各种设配,这个很不利于基础服务的抽象,所以我们在基础层之上加入聚合服务层,这个层可以针对pc和app做成适当的设配进行相应的裁剪。 + + ![聚合服务](images/Architecture/聚合服务.jpg) + + 除了裁剪,还有一个更重要的原因,假定PC端想获取“我的订单”的一个列表,那么Pc端必须知道和调用基础服务的几个模块(用户服务,订单服务,商品服务),pc端发起几次请求之后,在这个几个请求的数据进行汇总,这样不仅性能低下网络开销也比较大,还有pc端要承接数据聚合的这么一个工作,会让pc端变成更为复杂。如果在中间加多一个层为聚合服务层,即对网络开销进行减少,因为微服务内部是通过内网进行数据传输,也让pc端的业务变得比较简单。 + + ![微服务-聚合服务](images/Architecture/微服务-聚合服务.jpg) + + 这个层在各个公司有不同叫法,有叫 聚合服务,边界服务,设配服务 netflix叫边界服务,因为它处在公司微服务和外部的边界之上。这个的划分只是一个逻辑划分,在物理上或者在微服务上这两个层级其实在部署和调用没有差别。 + + + +**代码分层设计** + +![分层设计](images/Architecture/分层设计.png) + + + +### 技术架构体系 + +![微服务技术架构体系](images/Architecture/微服务技术架构体系.jpg) + +- **接入层** + + 接入层负责把外部的流量接入到内部平台系统中来,涉及到更多是基础设施,由运维团队进行负责。 + +- **基础设施层** + + 基础设施层主要是由运维团队来进行维护,设计由计算,也计算资源的分配,网络,存储,监控,安全等等 + +- **网关层** + + 流量接进来之后,会先经过一个网关层,网关在微服务起到举足轻重的作用,主要起到反向路由,限流熔断,安全,鉴权等等的跨横切面的功能,这个层在微服务中起到核心的层次。 + +- **业务服务层** + + 整个业务服务按照逻辑划分为两次,分别是聚合层和基础服务层,聚合层对基础层进行聚合和裁剪,对外部提供业务能力。当然这个视每个公司不同情况而定,此层再划分两层是属于逻辑划分。 + +- **支撑服务层** + + 微服务并不是单单把业务服务启动起来就完毕,微服务在治理的过程中还需要更多的支持,所以由了支撑服务层。支持服务包含了注册发现,集中配置,容错限流,日志聚合,监控告警,后台服务,后台服务涉及到例如MQ,Job,数据访问,这些都是后台服务的内容。 + +- **平台服务层** + + 在微服务逐步完善的过程中,各个团队的都引入一个新的平台服务,例如由容器,镜像的管理,容器的服务编排等等,很多公司先后的引入容器化和容器编排来解决运维管理和发布微服务的难题,docker + keburnetes,确实是被微服务越来越接受。另外,通过CICD支撑起来的devops也是构建在平台服务层的这个能力。由于这个平台服务层的逐步完善也在慢慢解放运维人员一开始对微服务各种治理的不适。 + + + +### 服务发现机制 + +**第一种 传统Lb模式** + +![传统Lb模式](images/Architecture/传统Lb模式.jpg) + +这个模式有一个独立的Lb,例如可以硬件F5做负载均衡器,也可以用软件,例如nginx来做负载均衡器,一般来说生产者上线后,会想运维申请一个域名,将域名配置到负载均衡器上,生产者的服务会部署多份,Lb具有负载均衡的功能。消费方想要去进行消费,会通过dns做域名解析,dns会解析到Lb上面,Lb会负载均衡到后台的生产者服务。这种做法是最传统的做法,也是最简单,消费者接入成本低,但是生产者发布服务需要运维的介入。还有一点问题就是Lb成为整个服务中转中心,如何确保这个Lb为高可用,另外还有一点,就是消费者调用生产者必须穿透Lb,这当中可能会有一些性能开销。 + + + +**第二种 进程内Lb模式** + +![进程内Lb模式](images/Architecture/进程内Lb模式.jpg) + +这种做法把传统的Lb转移到进程内,生产者会把自己的信息注册到一个注册中心,并且定期发送心跳建立生产者和注册中心的连接。消费者去监听注册中心,从注册中心获取生产者的列表,Lb存在消费者的进程内,消费者直接使用内部Lb去调用生产者,消费者的Lb会定期去同步注册中心的服务信息。这种做法的好处是没有中间的一跳,不存在集中式Lb的性能短板,也不存在Lb可能存在的单点问题。但是在多语言中,必须每个语言都维护自己的一个Lb,我们熟知的Dubbo就是采用这种进程内Lb模式。 + + + +**第三种 主机独立Lb模式** + +![主机独立Lb模式](images/Architecture/主机独立Lb模式.jpg) + +主机独立Lb模式是在前面传统Lb和进程内Lb的模式上做了折中,它把一个Lb以一个独立进程的方式部署在一台独立主机上,既不是集中式Lb也不是进程内Lb,这种方式跟第二种有一些类似,生产者一样注册到注册中心,主机上的Lb也会定时同步注册中心的注册信息,把注册信息放在本地进程中进行负载均衡,这种方式Lb既不存在消费者的进程内,可以让消费者更专注于业务,还可以免去集中式Lb每次调用都必须进行中转一跳的网络开销,并且也可以支持多语言跟消费者语言脱离关系。不过这种模式可能在运维的成本会比较高,运维需要关注每一台机器的LB。 + + + +### API网关 + +![微服务-API网关-案例](images/Architecture/微服务-API网关-案例.jpg) + +![微服务-API网关-定义](images/Architecture/微服务-API网关-定义.jpg) + +让客户看公司的服务会认为是一个整体的服务。这个就是我们的网关所起到的作用,能够屏蔽我们内部的细节,统一输出对外的接口。 + +![微服务-API网关-架构](images/Architecture/微服务-API网关-架构.jpg) + +从这张图上看到有四个层次,最上层是我们用户层,第二层是我们的负载均衡器,第三层就是我们的网关,最后是我们内部的微服务,在接入网关的时候为什么需要在上面需要一个负载均衡器,因为我们想让网关无状态,无状态的网关有一个好处,可以部署很多,不会有单点,即使挂了一台,其他的网关还在,这个对整个系统的稳定性起来非常重要的作用。一般的系统会有一个LB,然后对应多个网关。网关能起到的作用很多: + +- 最重要的一个重要反向路由,当外面的请求进来之后,怎么找到内部具体的微服务,这个是网关起来重要职责,将外部的调用转化为内部的服务服务,这个就是反向路由 +- 第二个是认证安全,网关像是一个门卫,有一些访问是正常的访问,有一些是恶意的访问,例如说爬虫,甚至是一些黑客行为,网关需要将其拦截在外部- 第三个重要职责是限流熔断,比方说,有一个门,外面有流量进来,正常来说流量是比较稳定的,但也有可能有突发流量,有可能网站在搞促销,这个时候可能就有流量的洪峰闯进来,如果说内部没有好的限流熔断措施,可能造成内部整个服务的服务器瘫痪,网关就要承担限流熔断的职责。 +- 最后一个功能,网关要承担日志监控的职责,外部的访问所有的流量都要经过网关,那么可以在网关上可以对所有的流量做访问的审计,把它作为日志保存起来,另外可以通过分析日志,知道性能的调用情况,能够对整个流量情况进行监控 + + + +### 路由发现体系 + +![Netflix的路由发现体系](images/Architecture/Netflix的路由发现体系.jpg) + +在Netflix的微服务架构中,有两个非常重要的支撑服务 + +- Netflix的大名鼎鼎的注册中心组件叫Eureka +- 另一个Netflix也是大名鼎鼎的网关组件叫Zuul + +Netflix在内部微服务上也是两层的逻辑划分,低层是基础服务(Netflix叫中间层服务),上一层叫聚合服务层,(Netflix叫边界服务),内部服务的发现也是通过注册中心Eureka,基础服务向Eureka进行服务注册,聚合服务通过Eureka进行服务发现,并把聚合层生产者缓存在本身,就可以进行直接的服务调用。 + +网关层是处在外部调用和聚合服务之间的层,网关层可以看作是一个超级的客户端,它一样可以作为微服务的一个组件,也会同步Eureka注册中心的路由表,外部服务请求进来后,网关根据路由表找到对应的聚合服务进行调用。 + +另外注册中心和网关还可以对整个调用进行治理,比方说对服务的调用进行安全管控,哪些服务是是有严格的安全要求,不允许随便进行调用,哪些服务可以通过网关放出去,这些能力可以通过网关和注册中心进行实现。这些就是服务治理相关的能力。 + + + +### 配置中心 + +![配置中心](images/Architecture/配置中心.jpg) + +配置中心可以简单的理解为一个服务模块,开发人员或运维人员可以通过界面对配种中心进行配置,下面相关的微服务连接到配置中心上面就可以实时连接获取到配置中心上面修改的参数。更新的方式一般有两种 + +- pull模式,服务定时去拉取配置中心的数据 +- push模式,服务一直连接到配置中心上,一旦配置有变成,配种中心将把变更的参数推送到对应的微服务上 + +这两种做法其实各有利弊 + +- pull可以保证一定可以拉取得到数据,pull一般采用定时拉取的方式,即使某一次出现网络没有拉取得到数据,那在下一次定时器也将可以拉取得到数据,最终保证能更新得到配置 +- push也有好处,避免pull定时器获取存在时延,基本可以做到准实时的更新,但push也存在问题,如果有网络抖动,某一次push没有推送成功,将丢失这次配置的更新 + +目前比较流行的配种中心开源组件有springcloud-Config,百度的disconf,阿里的diamond,还有携程的apollo,杨波老师之前是在携程工作过,所以主推的是apollo这套系统。 + +![Apollo配置中心](images/Architecture/Apollo配置中心.jpg) + +也是一个服务器,也带有对应的客户端,它的特色在于客户端,客户端有一个缓存机制,每次拉取成功后,会把数据保存在缓存机制中,甚至爬客户端的缓存丢失,客户端还可以将缓存sync在本地文件缓存,这样的设计非常的巧妙,就算apollo的配置中心挂掉了,或者客户端的服务重启了,但是因为本地缓存还存在,还可以使用本地缓存继续对外提供服务,从这点来看apollo的配置中心在高可用上考虑还是比较周到的。 + +另外一点,配置中心有两种获取配置数据的方式,一种pull,一种push,两者各有有点,apollo把两者的优点进行了结合,开发或运维人员在配置中心进行修改,配置中心服务将实时将修改推送push到apollo的客户端,但考虑到可能由于某些网络抖动没有推送成功,客户端还具备了定时向apollo服务端拉取pull数据的功能,就算推送没成功,但是只要一定时间周期,客户端还是会主动去拉取同步数据,保证能把最终配置同步到服务中。这个也是apollo在高可用方面上非常有特色的设计。 + + + +### 微服务治理 + +![微服务治理](images/Architecture/微服务治理.jpg) + +- **服务注册发现** + + 微服务当中有很多服务,几十个上百个,它们当中有错中复杂的依赖关系,这个时候就存在服务的消费者怎么发现生产者,这个就是服务注册发现需要解决的问题。 + +- **服务的负载均衡** + + 为了应对大的流量,我们的服务提供方一般都是大规模部署,这个时候就存在服务的负载均衡的问题,另外我们的服务需要路由,这个能力非常重要,如果我们需要灰度发布或者蓝绿发布的机制,那么需要考虑软路由的机制。 + +- **监控-日志** + + 日志对于我们后期排错找出问题,定位问题是非常关键,我们一套好的监控治理框架需要集成日志服务 + +- **监控-metrics** + + 当我们需要对服务的调用量进行监控,对服务延迟出错数有一个好的监控手段,这就是me监控环境 + +- **监控-调用链埋点** + + 微服务有错综复杂的调用关系,就像一个网状一般,如果没有好的调用链监控,开发人员很容易迷失在当中,出问题很难定位,有了好的调用链监控会帮助我们快速定位问题,更好的理解整套微服务系统。 + +- **限流熔断** + + 微服务是一个分布式系统,如果没有好的限流熔断措施,当一个服务出现故障或者出现延迟,会造成整个系统瘫痪。 + +- **安全-访问控制** + + 有些服务并不希望所有的人都能去调用到,涉及到一些敏感信息,比例跟钱相关的信息,那么我们需要安全和访问的控制策略,来限制对这些服务的访问。 + +- **rpc & rest** + + rpc和rest根据之前的对比,两者各有优劣,如果一个微服务框架中能支持这两个调用,能兼容更多的技术栈,会更加的灵活 + +- **序列化** + + 序列化中,有高性能但对开发人员不优化的二进制序列化,也有对开发人员相当友好的但性能未必最佳的文本式序列化,这个需要根据场景进行灵活的配置,消息系列化协议 + +- **代码生成** + + 现在在大规模开发的情况下,比较推从一个契约驱动开发的方法,开发人员先定立契约,代码自动生成的方式生成对应的代码脚手架,这个在大规模开发的时候更能确保代码的一致和规整 + +- **统一异常处理** + + 我们希望服务治理的环节能集成统一的服务异常处理的能力,这样的化异常能够达到更加标准化,出现问题能更好定位好属于什么类型的问题。如果说没有这样的一个环节,大家各自的玩法不一样,抛的异常各异,出现问题难以定位和无法标准化友好输出。 + +- **文档** + + 微服务最终是要给消费者去使用,暴露出去的API如果没有好的文档,只提供出一些代码,接入方接入的成本会变成比较高,好的文档体系是各方协调和效率的保证。 + +- **集中配置中心** + + 微服务框架需要集成集中式的配置能力,避免各个服务间各自配置,增快参数调整的速度和规范统一格式。 + +- **后台集成MQ,Cache,DB** + + 微服务治理的核心思路就是把上面讲到的各个环节沉淀下来,变成平台和框架的一部分,开发人员可以更加专注业务逻辑的实现,在实现业务逻辑的时候不需要去关注外部环节的,从而提升开发的效率,治理环节沉淀在框架之中有专门的平台架构团队去进行管控。 + + + +### 微服务分层监控 + +**分层监控** + +![微服务分层监控](images/Architecture/微服务分层监控.jpg) + +- **基础设施监控** + + 一般是由运维人员进行负责,涉及到的方面比较接近硬件体系,例如网络,交换机,路由器等低层设备,这些设备的可靠性稳定性就直接影响到上层服务应用的稳定性,所以需要对网络的流量,丢包情况,错包情况,连接数等等这些基础设施的核心指标进行监控。 + +- **系统层监控** + + 涵盖了物理机,虚拟机,操作系统这些都是属于系统级别监控的方面,对几个核心指标监控,如cpu使用率,内存占用率,磁盘IO和网络带宽情况。 + +- **应用层监控** + + 涉及到方面就跟服务紧密相关,例如对url访问的性能,访问的调用数,访问的延迟,还有对服务提供性能进行监控,服务的错误率,对sql也需要进行监控,查看是否有慢sql,对与cache来说,需要监控缓存的命中率和性能,每个服务的响应时间和qps等等。 + +- **业务监控** + + 比方说一个典型的交易网站,需要关注它的用户登录情况,注册情况,下单情况,支付情况,这些直接影响到实际触发的业务交易情况,这个监控可以提供给运营和公司高管他们需需要关注的数据,直接可能对公司战略产生影响。 + +- **端用户体验监控** + + 一个应用程序可能通过app,h5,pc端的方式交付到用户的手上,用户通过浏览器,客户端打开练到到我们的服务,那么在用户端用户的体验是怎么样,用户端的性能是怎么样,有没有产生错误,这些信息也是需要进行监控并记录下来,如果没有监控,有可能用户的因为某些原因出错或者性能问题造成体验非常的差,而我们并没有感知,这里面包括了,监控用户端的使用性能,返回码,在哪些城市地区他们的使用情况是怎么样,还有运营商的情况,包括电信,联通用户的连接情况。我们需要进一步去知道是否有哪些渠道哪些用户接入的时候存在着问题,包括我们还需要知道客户端使用的操作系统浏览器的版本。 + + + +**监控点** + +可以通过以下几点进行监控: + +- 日志监控 +- Metrics监控 +- 调用链监控 +- 报警系统 +- 健康检查 + +![微服务监控点](images/Architecture/微服务监控点.jpg) + + + +**典型主流的监控架构** + +![典型主流的监控架构](images/Architecture/典型主流的监控架构.jpg) + +在微服务运行的体系下,我们一般把监控的agent分散到各个服务身边,agent分别是收集机器和服务的metrics,发送到后台监控系统,一般来说,我们的服务量非常大,在收集的过程中,会加入队列,一般来说用kafka,用消息队列有个好处就是两边可以进行解耦,还好就是可以起到庞大的日志进行一个缓存的地带,并在mq可以做到高可用,保证消息不会丢失。 + +日志收集目前比较流行的是ELK的一套解决方案,(Elasticsearch,Logstash,Kibana),Elasticsearch 分布式搜索引擎,Logstash 是一个日志收集的agent,Kibana 是一个查询的日志界面。 + +metrice会采用一个时间序列的数据库,influxDB是最近比较主流时间数据库。 + +微服务的agent例如springboot也提供了健康检查的端点,可以检查cpu使用情况,内存使用情况,jvm使用情况,这些需要一个健康检查机制,能够定期对服务的健康和机器的健康进行check,比较常见的是nagios,zabbix等,这些开源平台能够定期去检查到各个微服务的检查程序并能够进行告警给相关人员,在服务未奔溃之前就可以进行提前的预先接入。 + + + +### 调用链 + +微服务是一个分布式非常复杂系统,如果没有一套调用链监控,如果服务之间依赖出现问题就很难进行调位。 + +目前个大主流互联网公司中,ali有非常出现的鹰眼系统,点评也有一套很出名的调用链监控系统CAT。调用链监控其实最早是google提出来的,2010年google发表了一篇调用链的论文,论文以它内部的调用链系统dapper命名,这个论文中讲解调用链在google使用的经验和原理,大致的原理如下图: + +![Dapper](images/Architecture/Dapper.jpg) + +在外界对微服务进行一个请求开始进入我们的微服务体系时,会生成一个Root Span,当web服务去调用后面的服务svc1时又会生成一个span,调用DB也会生成一个span,每一个应用调度都会生成一个新的span,这个是span是整个调用链形成的关键,span中有一些关键的信息,有traceId,spanId。RootSpan是比较特殊的,在启动的时候会生成spanId还会生成TraceId,其他的span会生成自己的spanId,为了维护好调用链上下文的调用关系,span会去记录调用它的链路,以parent spanId记录下来,这样的话父子之间的关系就可以记录下来,每个调用都会把第一个链路traceId也记录下来,这样,当我们把这些span都存在起来,就可以通过分析手段,把整个调用链的关系还原出来。 + +这里可以采用ELK的方式去记录和展示调用链监控日志,当我们一条调用为一行记录存储下来: + +![调用行为记录](images/Architecture/调用行为记录.jpg) + +通过traceId 和 parentSpanId 就可以串联起来为一个整体的链路,并可以从这个链路去分析错误或者调用延时和调用次数等等。 + +![调用行为还原](images/Architecture/调用行为还原.jpg) + +目前市面主流的调用链选型有 zipkin,pinpoint,cat,skywalking,他们之间各有一些偏重点,值得一说的是skywalking国人出品的一款新的调用链工具,采用开源的基于字节码注入的调用链分析,接入段无代码入侵,而且开源支持多种插件,UI在几款工具来说比较功能比较强大,而且ui也比较赏心悦目,目前已经加入了apache孵化器。 + +**skywalking优势** + +- 首先在实现方式上,skywalking基本对于代码做到了无入侵,采用java探针和字节码增强的方式,而在cat还采用了代码埋点,而zipkin采用了拦截请求,pinpoint也是使用java探针和字节码增强 +- 其次在分析的颗粒度上,skywaling是方法级,而zipkin是接口级,其他两款也是方法级 +- 在数据存储上,skywalking可以采用日志体系中比较出名的ES,其他几款,zipkin也可以使用ES,pinpoint使用Hbase,cat使用mysql或HDFS,相对复杂,如果公司对ES熟悉的人才比较有保证,选择熟悉存储方案也是考虑技术选型的重点 +- 还有就是性能影响,根据网上的一些性能报告,虽然未必百分百准备,但也具备参考价值,skywalking的探针对吞吐量的影响在4者中间是最效的,经过对skywalking的一些压测也大致证明 + +下面是网上摘录的几款调用链选型对比: + +**基本原理** + +| 类别 | Zipkin | Pinpoint | SkyWalking CAT | +| -------- | ------------------------------------------ | -------------------- | -------------------- | +| 实现方式 | 拦截请求,发送(HTTP,mq)数据至zipkin服务 | java探针,字节码增强 | java探针,字节码增强 | + +**接入** + +| 类别 | Zipkin | Pinpoint | SkyWalking | CAT | +| ---------------------- | --------------------------------------- | ----------------- | --------------- | -------- | +| 接入方式」 | 基于linkerd或者sleuth方式,引入配置即可 | javaagent字节码」 | javaagent字节码 | 代码侵入 | +| agent到collector的协议 | http,MQ | thrift | gRPC | http/tcp | +| OpenTracing | √ | × | √ | × | + +**分析** + +| 类别 | Zipkin | Pinpoint | SkyWalking | CAT | +| ------------ | ------ | -------- | ---------- | ------ | +| 颗粒度 | 接口级 | 方法级 | 方法级 | 代码级 | +| 全局调用统计 | × | √ | √ | √ | +| traceid查询 | √ | × | √ | × | +| 报警 | × | √ | √ | √ | +| JVM监控 | × | × | √ | √ | + +**页面UI展示** + +| 类别 | Zipkin | Pinpoint | SkyWalking | CAT | +| ------ | ------ | ---------- | ---------- | ---------- | +| 健壮度 | \*\* | \*\*\*\*\* | \*\*\*\* | \*\*\*\*\* | + +**数据存储** + +| 类别 | Zipkin | Pinpoint | SkyWalking | CAT | +| -------- | ------------------------ | -------- | ---------- | ---------- | +| 数据存储 | ES,mysql,Cassandra,内存 | Hbase | ES,H2 | mysql,hdfs | + + + +### 流量治理 + +**熔断** + +如果说房子里面安装了电路熔断器,当你使用超大功率的电路时,有熔断设配帮你保护不至于出问题的时候把问题扩大化。 + +**隔离** + +我们知道计算资源都是有限的,cpu,内存,队列,线程池都是资源,他们都是限定的资源数,如果不进行隔离,一个服务的调用可能要消耗很多的线程资源,把其他服务的资源都给占用了,那么可能出现应为一个服务的问题连带效应造成其他服务不能进行访问。 + +**限流** + +让大流量的访问冲进去我们的服务时,我们需要一定的限流措施,比方说我们规则一定时间内只允许一定的访问数从我们的资源过,如果再大的化系统会出现问题,那么就需要限流保护。 + +**降级** + +如果说系统后题无法提供足够的支撑能力,那么需要一个降级能力,保护系统不会被进一步恶化,而且可以对用户提供比较友好的柔性方案,例如告知用户暂时无法访问,请在一段时候后重试等等。 + + + +**Hystrix** + +Hystrix就把上面说的 熔断,隔离,限流,降级封装在这么一个组件里面 下图是Hystrix内部设计和调用流程 + +![Hystrix调用流程](images/Architecture/Hystrix调用流程.jpg) + +大致的工作流如下: + +- 构建一个HystrixCommand对象,用于封装请求,并在构造方法配置请求被执行需要的参数 +- 执行命令,Hystrix提供了几种执行命令的方法,比较常用到的是synchrous和asynchrous +- 判断电路是否被打开,如果被打开,直接进入fallback方法 +- 判断线程池/队列/信号量是否已经满,如果满了,直接进入fallback方法 +- 执行run方法,一般是HystrixCommand.run(),进入实际的业务调用,执行超时或者执行失败抛出未提前预计的异常时,直接进入fallback方法 +- 无论中间走到哪一步都会进行上报metrics,统计出熔断器的监控指标 +- fallback方法也分实现和备用的环节 +- 最后是返回请求响应 + + + +### 设计模式 + +#### 独享数据库(Database per Microservice) + +当一家公司将大型单体系统替换成一组微服务,首先要面临的最重要决策是关于数据库。单体架构会使用大型中央数据库。即使转移到微服务架构许多架构师仍倾向于保持数据库不变。虽然有一些短期收益,但它却是反模式的,特别是在大规模系统中,微服务将在数据库层严重耦合,整个迁移到微服务的目标都将面临失败(例如,团队授权、独立开发等问题)。 + +更好的方法是为每个微服务提供自己的数据存储,这样服务之间在数据库层就不存在强耦合。这里我使用数据库这一术语来表示逻辑上的数据隔离,也就是说微服务可以共享物理数据库,但应该使用分开的数据结构、集合或者表,这还将有助于确保微服务是按照领域驱动设计的方法正确拆分的。 + +![微服务-独享数据库](images/Architecture/微服务-独享数据库.png) + +优点 + +- 数据由服务完全所有 +- 服务的开发团队之间耦合度降低 + +缺点 + +- 服务间的数据共享变得更有挑战性 +- 在应用范围的保证 ACID 事务变得困难许多 +- 细心设计如何拆分单体数据库是一项极具挑战的任务 + +何时使用独享数据库 + +- 在大型企业应用程序中 +- 当团队需要完全把控微服务以实现开发规模扩展和速度提升 + +何时不宜使用独享数据库 + +- 在小规模应用中 +- 如果是单个团队开发所有微服务 + +可用技术示例 + +所有 SQL、 NoSQL 数据库都提供数据的逻辑分离(例如,单独的表、集合、结构、数据库)。 + + + +#### 事件源(Event Sourcing) + +在微服务架构中,特别使用独享数据库时,微服务之间需要进行数据交换。对于弹性高可伸缩的和可容错的系统,它们应该通过交换事件进行异步通信。在这种情况,您可能希望进行类似更新数据库并发送消息这样的原子操作,如果在大数据量的分布式场景使用关系数据库,您将无法使用两阶段锁协议(2PL),因为它无法伸缩。而 NoSQL 数据库因为大多不支持两阶段锁协议甚至无法实现分布式事务。 + +在这些场景,可以基于事件的架构使用事件源模式。在传统数据库中,直接存储的是业务实体的当前“状态”,而在事件源中任何“状态”更新事件或其他重要事件都会被存储起来,而不是直接存储实体本身。这意味着业务实体的所有更改将被保存为一系列不可变的事件。因为数据是作为一系列事件存储的,而非直接更新存储,所以各项服务可以通过重放事件存储中的事件来计算出所需的数据状态。 + +![微服务-事件源](images/Architecture/微服务-事件源.png) + +优点 + +- 为高可伸缩系统提供原子性操作。 +- 自动记录实体变更历史,包括时序回溯功能。 +- 松耦合和事件驱动的微服务。 + +缺点 + +- 从事件存储中读取实体成为新的挑战,通常需要额外的数据存储(CQRS 模式) +- 系统整体复杂性增加了,通常需要领域驱动设计 +- 系统需要处理事件重复(幂等)或丢失 +- 变更事件结构成为新的挑战 + +何时使用事件源 + +- 使用关系数据库的、高可伸缩的事务型系统 +- 使用 NoSQL 数据库的事务型系统 +- 弹性高可伸缩微服务架构 +- 典型的消息驱动或事件驱动系统(电子商务、预订和预约系统) + +何时不宜使用事件源 + +- 使用 SQL 数据库的低可伸缩性事务型系统 +- 在服务可以同步交换数据(例如,通过 API)的简单微服务架构中 + + + +#### 命令和查询职责分离(CQRS) + +如果我们使用事件源,那么从事件存储中读取数据就变得困难了。要从数据存储中获取实体,我们需要处理所有的实体事件。有时我们对读写操作还会有不同的一致性和吞吐量要求。 + +这种情况,我们可以使用 CQRS 模式。在该模式中,系统的数据修改部分(命令)与数据读取部分(查询)是分离的。而 CQRS 模式有两种容易令人混淆的模式,分别是简单的和高级的。 + +在其简单形式中,不同实体或 ORM 模型被用于读写操作,如下所示: + +![微服务-简单CQRS](images/Architecture/微服务-简单CQRS.png) + +它有助于强化单一职责原则和分离关注点,从而实现更简洁的设计。 + +在其高级形式中,会有不同的数据存储用于读写操作。高级的 CQRS 通常结合事件源模式。根据不同情况,会使用不同类型的写数据存储和读数据存储。写数据存储是“记录的系统”,也就是整个系统的核心源头。 + +![微服务-高级CQRS](images/Architecture/微服务-高级CQRS.png) + +对于读频繁的应用程序或微服务架构,OLTP 数据库(任何提供 ACID 事务保证的关系或非关系数据库)或分布式消息系统都可以被用作写存储。对于写频繁的应用程序(写操作高可伸缩性和大吞吐量),需要使用写可水平伸缩的数据库(如全球托管的公共云数据库)。标准化的数据则保存在写数据存储中。 + +对搜索(例如 Apache Solr、Elasticsearch)或读操作(KV 数据库、文档数据库)进行优化的非关系数据库常被用作读存储。许多情况会在需要 SQL 查询的地方使用读可伸缩的关系数据库。非标准化和特殊优化过的数据则保存在读存储中。 + +数据是从写存储异步复制到读存储中的,所以读存储和写存储之间会有延迟,但最终是一致的。 + +优点 + +- 在事件驱动的微服务中数据读取速度更快 +- 数据的高可用性 +- 读写系统可独立扩展 + +缺点 + +- 读数据存储是弱一致性的(最终一致性) +- 整个系统的复杂性增加了,混乱的 CQRS 会显着危害整个项目 + +何时使用 CQRS + +- 在高可扩展的微服务架构中使用事件源 +- 在复杂领域模型中,读操作需要同时查询多个数据存储 +- 在读写操作负载差异明显的系统中 + +何时不宜使用 CQRS + +- 在没有必要存储大量事件的微服务架构中,用事件存储快照来计算实体状态是一个更好的选择 +- 在读写操作负载相近的系统中 + + + +#### Saga + +如果微服务使用独享数据库,那么通过分布式事务管理一致性是一个巨大的挑战。你无法使用传统的两阶段提交协议,因为它要么不可伸缩(关系数据库),要么不被支持(多数非关系数据库)。 + +但您还是可以在微服务架构中使用 Saga 模式实现分布式事务。Saga 是 1987 年开发的一种古老模式,是关系数据库中关于大事务的一个替代概念。但这种模式的一种现代变种对分布式事务也非常有效。Saga 模式是一个本地事务序列,其每个事务在一个单独的微服务内更新数据存储并发布一个事件或消息。Saga 中的首个事务是由外部请求(事件或动作)初始化的,一旦本地事务完成(数据已保存在数据存储且消息或事件已发布),那么发布消息或事件则会触发 Saga 中的下一个本地事务。 + +![微服务-Saga](images/Architecture/微服务-Saga.png) + +如果本地事务失败,Saga 将执行一系列补偿事务来回滚前面本地事务的更改。 + +Saga 事务协调管理主要有两种形式: + +- 事件编排 Choreography:分散协调,每个微服务生产并监听其他微服务的事件或消息然后决定是否执行某个动作 +- 命令编排 Orchestration:集中协调,由一个协调器告诉参与的微服务哪个本地事务需要执行 + +优点 + +- 为高可伸缩或松耦合的、事件驱动的微服务架构提供一致性事务 +- 为使用了不支持 2PC 的非关系数据库的微服务架构提供一致性事务 + +缺点 + +- 需要处理瞬时故障,并且提供等幂性 +- 难以调试,而且复杂性随着微服务数量增加而增加 + +何时使用 Saga + +- 在使用了事件源的高可伸缩、松耦合的微服务中 +- 在使用了分布式非关系数据库的系统中 + +何时不宜使用 Saga + +- 使用关系数据库的低可伸缩性事务型系统 +- 在服务间存在循环依赖的系统中 + + + +#### 面向前端的后端 (BFF) + +在现代商业应用开发,特别是微服务架构中,前后端应用是分离和独立的服务,它们通过 API 或 GraphQL 连接。如果应用程序还有移动 App 客户端,那么 Web 端和移动客户端使用相同的后端微服务就会出现问题。因为移动客户端和 Web 客户端有不同的屏幕尺寸、显示屏、性能、能耗和网络带宽,它们的 API 需求不同。 + +面向前端的后端模式适用于需要为特殊 UI 定制单独后端的场景。它还提供了其他优势,比如作为下游微服务的封装,从而减少 UI 和下游微服务之间的频繁通信。此外,在高安全要求的场景中,BFF 为部署在 DMZ 网络中的下游微服务提供了更高的安全性。 + +![微服务-BFF](images/Architecture/微服务-BFF.png) + +优点 + +- 分离 BFF 之间的关注点,使得我们可以为具体的 UI 优化他们 +- 提供更高的安全性 +- 减少 UI 和下游微服务之间频繁的通信 + +缺点 + +- BFF 之间代码重复 +- 大量的 BFF 用于其他用户界面(例如,智能电视,Web,移动端,PC 桌面版) +- 需要仔细的设计和实现,BFF 不应该包含任何业务逻辑,而应只包含特定客户端逻辑和行为 + +何时使用 BFF + +- 如果应用程序有多个含不同 API 需求的 UI +- 出于安全需要,UI 和下游微服务之间需要额外的层 +- 如果在 UI 开发中使用微前端 + +何时不宜使用 BFF + +- 如果应用程序虽有多个 UI,但使用的 API 相同 +- 如果核心微服务不是部署在 DMZ 网络中 + +可用技术示例 + +任何后端框架(Node.js,Spring,Django,Laravel,Flask,Play,…)都能支持。 + + + +#### API网关 + +在微服务架构中,UI 通常连接多个微服务。如果微服务是细粒度的(FaaS) ,那么客户端可能需要连接非常多的微服务,这将变得繁杂和具有挑战性。此外,这些服务包括它们的 API 还将不断进化。大型企业还希望能有其他横切关注点(SSL 终止、身份验证、授权、节流、日志记录等)。 + +一个解决这些问题的可行方法是使用 API 网关。API 网关位于客户端 APP 和后端微服务之间充当 facade,它可以是反向代理,将客户端请求路由到适当的后端微服务。它还支持将客户端请求扇出到多个微服务,然后将响应聚合后返回给客户端。它还支持必要的横切关注点。 + +![微服务-API网关](images/Architecture/微服务-API网关.png) + +优点 + +- 在前端和后端服务之间提供松耦合 +- 减少客户端和微服务之间的调用次数 +- 通过 SSL 终端、身份验证和授权实现高安全性 +- 集中管理的横切关注点,例如,日志记录和监视、节流、负载平衡 + +缺点 + +- 可能导致微服务架构中的单点故障 +- 额外的网络调用带来的延迟增加 +- 如果不进行扩展,它们很容易成为整个企业应用的瓶颈 +- 额外的维护和开发费用 + +何时使用 API 网关 + +- 在复杂的微服务架构中,它几乎是必须的 +- 在大型企业中,API 网关是中心化安全性和横切关注点的必要工具 + +何时不宜使用 API 网关 + +- 在安全和集中管理不是最优先要素的私人项目或小公司中 +- 如果微服务的数量相当少 + + + +#### Strangler + +如果想在运行中的项目中使用微服务架构,我们需要将遗留的或现有的单体应用迁移到微服务。将现有的大型在线单体应用程序迁移到微服务是相当有挑战性的,因为这可能破坏应用程序的可用性。 + +一个解决方案是使用 Strangler 模式。Strangler 模式意味着通过使用新的微服务逐步替换特定功能,将单体应用程序增量地迁移到微服务架构。此外,新功能只在微服务中添加,而不再添加到遗留的单体应用中。然后配置一个 Facade (API 网关)来路由遗留单体应用和微服务间的请求。当某个功能从单体应用迁移到微服务,Facade 就会拦截客户端请求并路由到新的微服务。一旦迁移了所有的功能,遗留单体应用程序就会被“扼杀(Strangler)”,即退役。 + +![微服务-Strangler](images/Architecture/微服务-Strangler.png) + +优点 + +- 安全的迁移单体应用程序到微服务 +- 可以并行地迁移已有功能和开发新功能 +- 迁移过程可以更好把控节奏 + +缺点 + +- 在现有的单体应用服务和新的微服务之间共享数据存储变得具有挑战性 +- 添加 Facade (API 网关)将增加系统延迟 +- 端到端测试变得困难 + +何时使用 Strangler + +- 将大型后端单体应用程序的增量迁移到微服务 + +何时不宜使用 Strangler + +- 如果后端单体应用很小,那么全量替换会更好 +- 如果无法拦截客户端对遗留的单体应用程序的请求 + + + +#### 断路器 + +在微服务架构中,微服务通过同步调用其他服务来满足业务需求。服务调用会由于瞬时故障(网络连接缓慢、超时或暂时不可用) 导致失败,这种情况重试可以解决问题。然而,如果出现了严重问题(微服务完全失败),那么微服务将长时间不可用,这时重试没有意义且浪费宝贵的资源(线程被阻塞,CPU 周期被浪费)。此外,一个服务的故障还会引发整个应用系统的级联故障。这时快速失败是一种更好的方法。 + +在这种情况,可以使用断路器模式挽救。一个微服务通过代理请求另一个微服务,其工作原理类似于电气断路器,代理通过统计最近发生的故障数量,并使用它来决定是继续请求还是简单的直接返回异常。 + +![微服务-断路器](images/Architecture/微服务-断路器.png) + +断路器可以有以下三种状态: + +- 关闭:断路器将请求路由到微服务,并统计给定时段内的故障数量,如果超过阈值,它就会触发并进入打开状态 +- 打开:来自微服务的请求会快速失败并返回异常。在超时后,断路器进入半开启状态 +- 半开:只有有限数量的微服务请求被允许通过并进行调用。如果这些请求成功,断路器将进入闭合状态。如果任何请求失败,断路器则会进入开启状态 + +优点 + +- 提高微服务架构的容错性和弹性 +- 阻止引发其他微服务的级联故障 + +缺点 + +- 需要复杂的异常处理 +- 日志和监控 +- 应该支持人工复位 + +何时使用断路器 + +- 在微服务间使用同步通信的紧耦合的微服务架构中 +- 如果微服务依赖多个其他微服务 + +何时不宜使用断路器 + +- 松耦合、事件驱动的微服务架构 +- 如果微服务不依赖于其他微服务 + + + +#### 外部化配置 + +每个业务应用都有许多用于各种基础设施的配置参数(例如,数据库、网络、连接的服务地址、凭据、证书路径)。此外在企业应用程序通常部署在各种运行环境(Local、 Dev、 Prod)中,实现这些的一个方法是通过内部配置。这是一个致命糟糕实践,它会导致严重的安全风险,因为生产凭证很容易遭到破坏。此外,配置参数的任何更改都需要重新构建应用程序,这在在微服务架构中会更加严峻,因为我们可能拥有数百个服务。 + +更好的方法是将所有配置外部化,使得构建过程与运行环境分离,生产的配置文件只在运行时或通过环境变量使用,从而最小化了安全风险。 + +优点 + +- 生产配置不属于代码库,因而最小化了安全漏洞 +- 修改配置参数不需要重新构建应用程序 + +缺点 + +- 我们需要选择一个支持外部化配置的框架 + +何时使用外部化配置 + +- 任何重要的生产应用程序都必须使用外部化配置 + +何时不宜使用外部化配置 + +- 在验证概念的开发中 + + + +#### 消费端驱动的契约测试 + +在微服务架构中,通常有许多有不同团队开发的微服务。这些微型服务协同工作来满足业务需求(例如,客户请求),并相互进行同步或异步通信。消费端微服务的集成测试具有挑战性,通常用 TestDouble 以获得更快、更低成本的测试运行。但是 TestDouble 通常并不能代表真正的微服务提供者,而且如果微服务提供者更改了它的 API 或 消息,那么 TestDouble 将无法确认这些。另一种选择是进行端到端测试,尽管它在生产之前是强制性的,但却是脆弱的、缓慢的、昂贵的且不能替代集成测试(Test Pyramid)。 + +在这方面消费端驱动的契约测试可以帮助我们。在这里,负责消费端微服务的团队针对特定的服务端微服务,编写一套包含了其请求和预期响应(同步)或消息(异步)的测试套件,这些测试套件称为显式的约定。对于微服务服务端,将其消费端所有约定的测试套件都添加到其自动化测试中。当特定服务端微服务的自动化测试执行时,它将一起运行自己的测试和约定的测试并进行验证。通过这种方式,契约测试可以自动的帮助维护微服务通信的完整性。 + +优点 + +- 如果提供程序意外更改 API 或消息,可以被快速的自动发现 +- 更少意外、更健壮,特别是包含大量微服务的企业应用程序 +- 改善团队自主性 + +缺点 + +- 需要额外的工作来开发和集成微服务服务端的契约测试,因为他们可能使用完全不同的测试工具 +- 如果契约测试与真实服务情况不匹配,将可能导致生产故障 + +何时使用需求驱动的契约测试 + +- 在大型企业业务应用程序中,通常由不同的团队开发不同服务 + +何时不宜使用消费端驱动的契约测试 + +- 所有微服务由同一团队负责开发的小型简单的应用程序 +- 如果服务端微服务是相对稳定的,并且不处在活跃的开发状态 + + + +### 关键设计 + +#### 监控-发现故障的征兆 + +![监控-发现故障的征兆](images/Architecture/监控-发现故障的征兆.jpg) + + + +#### 定位问题-链路跟踪 + +![定位问题-链路跟踪](images/Architecture/定位问题-链路跟踪.png) + +![定位问题-taceId](images/Architecture/定位问题-taceId.png) + +要实现链路跟踪,每次服务调用会在HTTP的HEADERS中记录至少记录四项数据: + +- traceId:traceId标识一个用户请求的调用链路。具有相同traceId的调用属于同一条链路 +- spanId:标识一次服务调用的ID,即链路跟踪的节点ID +- parentId:父节点的spanId +- requestTime & responseTime:请求时间和响应时间 + + + +#### 分析问题-日志分析 + +![分析问题-日志分析](images/Architecture/分析问题-日志分析.png) + +一般使用ELK日志分析组件。ELK是Elasticsearch、Logstash和Kibana三个组件的缩写。 + +- Elasticsearch:搜索引擎,同时也是日志的存储。 +- Logstash:日志采集器,它接收日志输入,对日志进行一些预处理,然后输出到Elasticsearch。 +- Kibana:UI组件,通过Elasticsearch的API查找数据并展示给用户。 + +最后还有一个小问题是如何将日志发送到Logstash。一种方案是在日志输出的时候直接调用Logstash接口将日志发送过去。这样一来又(咦,为啥要用“又”)要修改代码……于是小明选用了另一种方案:日志仍然输出到文件,每个服务里再部署个Agent扫描日志文件然后输出给Logstash。 + + + +#### 网关-权限控制,服务治理 + +![网关-权限控制,服务治理](images/Architecture/网关-权限控制,服务治理.png) + + + +#### 服务注册于发现-动态扩容 + +![服务注册于发现-动态扩容](images/Architecture/服务注册于发现-动态扩容.png) + + + +#### 熔断、服务降级、限流 + +**熔断** + +当一个服务因为各种原因停止响应时,调用方通常会等待一段时间,然后超时或者收到错误返回。如果调用链路比较长,可能会导致请求堆积,整条链路占用大量资源一直在等待下游响应。所以当多次访问一个服务失败时,应熔断,标记该服务已停止工作,直接返回错误。直至该服务恢复正常后再重新建立连接。 + +![熔断](images/Architecture/熔断.png) + + + +**服务降级** + +当下游服务停止工作后,如果该服务并非核心业务,则上游服务应该降级,以保证核心业务不中断。比如网上超市下单界面有一个推荐商品凑单的功能,当推荐模块挂了后,下单功能不能一起挂掉,只需要暂时关闭推荐功能即可。 + + + +**限流** + +一个服务挂掉后,上游服务或者用户一般会习惯性地重试访问。这导致一旦服务恢复正常,很可能因为瞬间网络流量过大又立刻挂掉,在棺材里重复着仰卧起坐。因此服务需要能够自我保护——限流。限流策略有很多,最简单的比如当单位时间内请求数过多时,丢弃多余的请求。另外,也可以考虑分区限流。仅拒绝来自产生大量请求的服务的请求。例如商品服务和订单服务都需要访问促销服务,商品服务由于代码问题发起了大量请求,促销服务则只限制来自商品服务的请求,来自订单服务的请求则正常响应。 + +![限流](images/Architecture/限流.png) + + + +#### 测试 + +![三种测试](images/Architecture/三种测试.png) + +![Mock-Server](images/Architecture/Mock-Server.png) \ No newline at end of file diff --git a/src/Architecture/601.md b/src/Architecture/601.md new file mode 100644 index 0000000..c23d237 --- /dev/null +++ b/src/Architecture/601.md @@ -0,0 +1,45 @@ +### 业务关系 + +订单系统与各业务系统的关系: + +![订单系统](images/Architecture/订单系统.jpg) + +- **对外系统** + + 所有给企业外部用户使用的系统都在这一层,包括官网、普通用户使用的C端,还包括给商户使用的商家后台和在各个销售渠道进行分销的系统,比如与银行信用卡中心合作、微信合作在合作商的平台露出本企业的产品。这类系统站在与客户接触的最前线,是公司实现商业模式的桥头堡。 + +- **管理中后台** + + 每个C端的业务形态都会有一个对应的系统模块,如负责管理平台交易的订单系统,管理优惠信息的促销系统,管理平台所有产品的产品系统,以及管理所有对外系统显示内容的内容系统等。 + +- **公共服务系统** + + 随着企业的发展,信息化建设到达一定程度后,企业需要将通用功能服务化、平台化,以保证应用架构的合理性,提升服务效率。这类系统主要给其他应用系统提供基础服务能力支持。 + + + +### 上下游关系 + +![订单上下游关系](images/Architecture/订单上下游关系.jpg) + +由此可见,订单系统对上接收用户信息,将用户信息转化为产品订单,同时管理并跟踪订单信息和数据,承载了公司整个交易线的重要对客环节。对下则衔接产品系统、促销系统、仓储系统、会员系统、支付系统等,对整个电商平台起着承上启下的作用。 + + + +### 业务架构 + +![订单业务架构](images/Architecture/订单业务架构.jpg) + +- **订单服务** + + 该模块的主要功能是用户日常使用的服务和页面,主要有订单列表、订单详情、在线下单等,还包括为公共业务模块提供的多维度订单数据服务。 + +- **订单逻辑** + + 订单系统的核心,起着至关重要的作用,在订单系统负责管理订单创建、订单支付、订单生产、订单确认、订单完成、取消订单等订单流程。还涉及到复杂的订单状态规则、订单金额计算规则以及增减库存规则等。在4节核心功能设计中会重点来说。 + +- **底层服务** + + 信息化建设达到一定程度的企业,一般会将公司公共服务模块化,比如:产品,会构建对应的产品系统,代码、数据库,接口等相对独立。但是,这也带来了一个问题,比如:订单创建的场景下需要获取的信息分散在各个系统。 + + 如果需要从各个公共服务系统调用:一是会花费大量时间,二是代码的维护成本非常高。因此,订单系统接入所需的公共服务模块接口,在订单系统即可完成对接公共系统的服务。 \ No newline at end of file diff --git a/src/Architecture/602.md b/src/Architecture/602.md new file mode 100644 index 0000000..7df13fc --- /dev/null +++ b/src/Architecture/602.md @@ -0,0 +1,27 @@ +### 订单流程 + +订单流程主要是订单产生到交易结束的整个流程,按照现在电子商城(E-mall),仓库管理(WMS),物流管理系统(TMS)的流转过程主要如下图: + +![订单流程](images/Architecture/订单流程.png) + + + +### 正向流程 + +**订单创建>订单支付>订单生产>订单确认>订单完成** + + + +### 逆向流程 + +![订单逆向流程](images/Architecture/订单逆向流程.jpg) + +上面说到逆向流程是各种修改订单、取消订单、退款、退货等操作,需要梳理清楚这些流程与正向流程的关系,才能理清订单系统完整的订单流程。 + +- **订单修改**:可梳理订单内信息,根据信息关联程度及业务诉求,设定订单的可修改范围是什么,比如:客户下单后,想修改收货人地址及电话。此时只需对相应数据进行更新即可。 + +- **订单取消**:用户提交订单后没有进行支付操作,此时用户原则上属于取消订单,因为还未付款,则比较简单,只需要将原本提交订单时扣减的库存补回,促销优惠中使用的优惠券,权益等视平台规则,进行相应补回。 + +- **退款**:用户支付成功后,客户发出退款的诉求后,需商户进行退款审核,双方达成一致后,系统应以退款单的形式完成退款,关联原订单数据。因商品无变化,所以不需考虑与库存系统的交互,仅需考虑促销系统及支付系统交互即可。 + +- **退货**:用户支付成功后,客户发出退货的诉求后,需商户进行退款审核,双方达成一致后,需对库存系统进行补回,支付系统、促销系统以退款单形式完成退款。最后,在退款/退货流程中,需结合平台业务场景,考虑优惠分摊的逻辑,在发生退款/退货时,优惠该如何退回的处理规则和流程。 \ No newline at end of file diff --git a/src/Architecture/603.md b/src/Architecture/603.md new file mode 100644 index 0000000..ecf1d1c --- /dev/null +++ b/src/Architecture/603.md @@ -0,0 +1,207 @@ +### 订单信息 + +![订单详细信息](images/Architecture/订单详细信息.png) + + + +### 订单单号 + +订单单号是订单信息中的主Key,代表了该订单的唯一性,并且使用在仓库管理系统中,WMS作为拆分合并订单中与电子商城中的订单关联的Key值。订单单号一般组成方式有以下两种: + +- **日期时间+随机数字** + - 初期业务量不多的时候20-26位足够应付 + - **yyyyMMddHHmmss(年月日时分秒) + 6位随机码** + - 6位随机码表示一秒钟可能生成的订单数上,存在一百万分之一的随机并发相同导致下单失败,因此在初期业务每秒下单量不高的时候选择这种简单的方法足够满足需求 + +- **日期时间+自增** + - 不会产生随机数生成冲突 + - 注意防治被查看到销售量需要将数字加密设置 + + + +### 倒计时时间 + +订单里面显示倒计时有: + +- **下单未支付** + + - 商品下单后开始倒计时,一定时间内如果还未下单则超时关闭订单 + - 普通商品一般采取3天时间,特价商品根据情况一般采取的是30分钟,快消品一般采用的15分钟 + +- **已发货确认收货倒计时** + + 商品一般是发货开始后开始倒计时10天时间,O2O商品应该是送达即收货。 + + - 满1天记录1天 XX天hh小时mm分钟 + - 小于1天小时则hh小时mm分钟ss秒 + + 防止发货时间过长,发货后用户可以采用一次延长收货,商家/平台端则可以多次**延长收货**。 + + + +### 扣减库存 + +用户下单后,系统需要生成订单,此时需要先获取下单中涉及的商品信息,然后获取该商品所涉及到的优惠信息,如果商品不参与优惠信息,则无此环节。扣减库存规则是指订单中的商品,何时从仓储系统中对相应商品库存进行扣除。方式各有优缺点,需结合实际场景进行考虑,如:秒杀、抢购、促销活动等,可使用下单减库存的方式。而对于产品库存量大,并发流量没有那么强的产品使用付款减库存的方式。 + + + +**秒杀场景下如何扣减库存?** + +- **采用下单减库存** + + 因秒杀场景下,大部分用户都是想直接购买商品的,可以直接用下单减库存。大量用户和恶意用户都是同时进行的,区别是正常用户会直接购买商品,恶意用户虽然在竞争抢购的名额,但是获取到的资格和普通用户一样,所以下单减库存在秒杀场景下,恶意用户下单并不能造成之前说的缺点。而且下单直接扣减库存,这个方案更简单,在第一步就扣减库存了。 + +- **Redis 缓存** + + 查询缓存要比查询数据库快,所以将库存数放在缓存中,直接在缓存中扣减库存。如果并发很高,还可以采取分布式锁的方案。 + +- **限流** + + 秒杀场景中,对请求做了很多限流操作,如前端页面的限流和后端令牌桶限流,真正到扣减库存时,请求数很少了。 + + + +#### 下单减库存 + +即用户下单成功时减少库存数量。 + +**优势**:用户体验友好,系统逻辑简洁。 + +**缺点**:会导致恶意下单或下单后却不买,使得真正有需求的用户无法购买,影响真实销量。 + + + +**解决办法** + +- **设置订单有效时间**:若订单创建成功N分钟不付款,则订单取消,库存回滚 +- **限购**:用各种条件来限制买家的购买件数,比如一个账号、一个ip,只能买一件 +- **风控**:从技术角度进行判断,屏蔽恶意账号,禁止恶意账号购买 + + + +#### 付款减库存 + +即用户支付完成并反馈给平台后再减少库存数量。 + +**优势**:减少无效订单带来的资源损耗。 + +**缺点**:因第三方支付返回结果存在时差,同一时间多个用户同时付款成功,会导致下单数目超过库存,商家库存不足容易引发断货和投诉,成本增加。 + + + +**解决办法** + +- 付款前再次校验库存,如确认订单要付款时再验证一次,并友好提示用户库存不足 +- 增加提示信息:在商品详情页,订单步骤页面提示不及时付款,不能保证有库存等 + + + +#### 预扣库存 + +下单页面显示最新的库存,下单后保留这个库存一段时间(比如10分钟),超过保留时间后,库存释放。若保留时间过后再支付,如果没有库存,则支付失败。 + +**优势**:结合下单减库存的优点,实时减库存,且缓解恶意买家大量下单的问题,保留时间内未支付,则释放库存。 + +**缺点**:保留时间内,恶意买家大量下单将库存用完。并发量很高的时候,依然会出现下单数超过库存数。 + + + +### 恶意下单 + +如何解决恶意买家下单的问题?这里的恶意买家指短时间内大量下单,将库存用完的买家。 + +- **限制用户下单数量** + + **优点**:限制恶意买家下单 + + **缺点**:用户想要多买几件,被限制了,会降低销售量 + +- **标识恶意买家** + + 通过标识用户设备id或会员id,将用户加入黑名单,不足之处是有些用户是模拟的,识别不出来是不是真正的恶意买家。 + + + +### 支付失败 + +如何解决下单成功而支付失败(库存不足)的问题? + +- **备用库存** + + **优点**:缓解部分用户支付失败的问题。 + + **缺点**:备用库存只能缓解问题,不能从根本上解决问题。另外备用库存针对普通商品可以,针对特殊商品这种库存少的,备用库存量也不会很大,还是会出现大量用户下单成功却因库存不足而支付失败的问题。 + + + +### 库存超卖 + +如何解决高并发下库存超卖的场景?库存超卖最简单的解释就是多成交了订单而发不了货。 + +**场景**:用户 A 和 B 成功下单,在支付时扣减库存,当前库存数为 10。因 A 和 B 查询库存时,都还有库存数,所以 A 和 B 都可以付款。 + +A 和 B 同时支付,A 和 B 支付完成后,可以看做两个请求`回调`后台系统扣减库存,有两个线程处理请求,两个线程查询出来的库存数 `inventory = 10`。 + +![库存超卖](images/Architecture/库存超卖.png) + +A 线程更新最终库存数 :lastInventory = inventory - 1 = 9, + +B 线程更新库存数: lastInventory = inventory - 1 = 9。 + +而实际最终的库存应是 8 才对,这样就出现库存超卖的情况,而发不出货。那如何解决库存超卖的情况呢?以下方案都是基于数据库层面的。 + +- **方案一:SQL语句直接更新库存,而不是先查询出来,然后赋值** + + ```mysql + UPDATE [库存表] SET 库存数 - 1 + ``` + +- **方案二:SQL语句更新库存时,如果扣减库存后,库存数为负数,直接抛异常,利用事务的原子性进行自动回滚。** + +- **方案三:利用SQL语句更新库存,防止库存为负数** + + ```mysql + UPDATE [库存表] SET 库存数 - 1 WHERE 库存数 - 1 > 0 + ``` + + 如果影响条数大于1,则表示扣减库存成功,否则不更新库存,并退款。 + + + +### 订单拆分 + +用户支付完订单后,需要获取订单的支付信息,包括支付流水号、支付时间等。支付完订单接着就是等商家发货,但在发货过程中,根据平台业务模式的不同,可能会涉及到订单的拆分。订单拆分一般分两种: + +- 一种是用户挑选的商品来自于不同渠道(自营与商家,商家与商家) +- 另一种是在SKU层面上拆分订单:不同仓库,不同运输要求的SKU,包裹重量体积限制等因素需要将订单拆分 + + + +### 异步处理 + +随着公司的发展你可能会发现你项目的**请求链路越来越长**,例如刚开始的电商项目,可以就是粗暴的扣库存、下单。慢慢地又加上积分服务、短信服务等。这一路同步调用下来客户可能等急了,这时候就是消息队列登场的好时机。 + +**调用链路长、响应就慢了**,并且相对于扣库存和下单,积分和短信没必要这么的 “及时”。因此只需要在下单结束那个流程,扔个消息到消息队列中就可以直接返回响应了。而且积分服务和短信服务可以并行的消费这条消息。可以看出消息队列可以**减少请求的等待,还能让服务异步并发处理,提升系统总体性能**。 + +![订单服务-异步处理](images/Architecture/订单服务-异步处理.png) + + + +### 服务解耦 + +上面我们说到加了积分服务和短信服务,这时候可能又要来个营销服务,之后领导又说想做个大数据,又来个数据分析服务等等。所以一般会选用消息队列来解决系统之间耦合的问题,订单服务把订单相关消息塞到消息队列中,下游系统谁要谁就订阅这个主题。 + +![订单服务-服务解耦](images/Architecture/订单服务-服务解耦.jpg) + + + +### 流量控制 + +后端服务相对而言都是比较弱的,因为业务较重,处理时间较长。如秒杀活动爆发式流量打过来可能就顶不住了,因此需要引入一个中间件来做缓冲,基于消息队列实现削峰填谷功效。 + +- 网关的请求先放入消息队列中,后端服务尽自己最大能力去消息队列中消费请求。超时的请求可以直接返回错误 +- 当然还有一些服务特别是某些后台任务,不需要及时地响应,并且业务处理复杂且流程长,那么过来的请求先放入消息队列中,后端服务按照自己的节奏处理 + +上面两种情况分别对应着生产者生产过快和消费者消费过慢两种情况,消息队列都能在其中发挥很好的缓冲效果。 + +![订单服务-流量控制](images/Architecture/订单服务-流量控制.jpg) \ No newline at end of file diff --git a/src/Architecture/604.md b/src/Architecture/604.md new file mode 100644 index 0000000..8fff6a9 --- /dev/null +++ b/src/Architecture/604.md @@ -0,0 +1,255 @@ +### 超时关闭 + +下单后发布延迟消息至MQ,等延迟时间到后,MQ会通知应用该消息,然后检查是否已被支付,未被支付则关闭超时订单。 + + + +### 重复支付 + +![重复支付-下单流程](images/Architecture/重复支付-下单流程.png) + +如图是一个简化的下单流程,首先是提交订单,然后是支付。支付的话,一般是走支付网关(支付中心),然后支付中心与第三方支付渠道(微信、支付宝、银联)交互,支付成功以后,异步通知支付中心,支付中心更新自身支付订单状态,再通知业务应用,各业务再更新各自订单状态。 + +这个过程中经常可能遇到的问题是掉单,无论是超时未收到回调通知也好,还是程序自身报错也好,总之由于各种各样的原因,没有如期收到通知并正确的处理后续逻辑等等,都会造成用户支付成功了,但是服务端这边订单状态没更新,这个时候有可能产生投诉,或者用户重复支付。 + +由于③⑤造成的掉单称之为外部掉单,由④⑥造成的掉单我们称之为内部掉单。为了防止掉单,这里可以这样处理: + +- 支付订单增加一个中间状态“支付中”,当同一个订单去支付的时候,先检查有没有状态为“支付中”的支付流水,当然支付(prepay)的时候要加个锁。支付完成以后更新支付流水状态的时候再讲其改成“支付成功”状态 +- 支付中心这边要自己定义一个超时时间(比如:30秒),在此时间范围内如果没有收到支付成功回调,则应调用接口主动查询支付结果,比如10s、20s、30s查一次,如果在最大查询次数内没有查到结果,应做异常处理 +- 支付中心收到支付结果以后,将结果同步给业务系统,可以发MQ,也可以直接调用,直接调用的话要加重试(比如:SpringBoot Retry) +- 无论是支付中心,还是业务应用,在接收支付结果通知时都要考虑接口幂等性,消息只处理一次,其余的忽略 +- 业务应用也应做超时主动查询支付结果 + +对于上面说的超时主动查询可以在发起支付的时候将这些支付订单放到一张表中,用定时任务去扫。 + +为了防止订单重复提交,可以这样处理: + +**创建订单的时候,用订单信息计算一个哈希值,判断redis中是否有key,有则不允许重复提交,没有则生成一个新key,放到redis中设置个过期时间,然后创建订单。其实就是在一段时间内不可重复相同的操作。** + +附上微信支付最佳实践: + +![微信支付最佳实践](images/Architecture/微信支付最佳实践.png) + + + +### 支付对账 + +![对账业务流程](images/Architecture/对账业务流程.png) + + + +### 支付掉单 + +一个最常见的支付平台架构关系如下所示: + +![支付系统异常处理-支付平台](images/Architecture/支付系统异常处理-支付平台.jpg) + +上图我们是站在第三方支付公司支付角度,如果是自己公司的内部支付系统,那么外部商户这一块其实就是公司内部一些系统,比如说订单系统,而外部支付渠道其实就是第三方支付公司。我们以携程为例,在其上面发起一笔订单支付,将会经过三个系统: + +- 携程创建订单,向第三方支付公司发起支付请求 +- 第三方支付公司创建订单,并向工行发起支付请求 +- 工行完成扣款操作,返回第三方支付公司 +- 第三方支付完成订单更新并返回携程 +- 携程变更订单状态 + +上面的流程,简单如下图所示: + +![支付系统异常处理-携程](images/Architecture/支付系统异常处理-携程.jpg) + +在这个过程就可能会碰到,用户工行卡已经扣款,但是携程订单却还是待支付,我们通常将这种情况称为「掉单」。上述掉单的场景,多数是因为「③、⑤」环节信息丢失导致,这种掉单我们将其称为「外部掉单」。还有一种极少数的情况,收到 「③、⑤」环节返回信息,但是在「④、⑥」环节内部系统更新订单状态失败,从而导致丢失支付成功的信息,这类掉单由于是内部问题,我们通常将其称之为「内部掉单」。 + + + +#### 外部掉单 + +外部掉单是因为没有收到对端返回信息,这种情况极有可能是网络问题,也有可能对端处理逻辑太慢,导致我方请求超时,直接断开了网络请求。 + +**① 增加超时时间** + +适当的增加超时时间,在增加网络超时时间之后,可能还需要调整整个链路的超时时间,不然有可能导致整个链路内部超时从而引起内部掉单。 + +**注意**:对接外部渠道,一定要「设置网络连接超时时间与读取超时时间」。 + +**② 接收异步通知** + +接收渠道异步回执通知信息,一般来说,现在支付渠道接口都可以上送一个异步回调地址,当渠道端处理成功,将会把成功信息通知到这个回调地址上。这种情况下,只需要接收通知信息,然后解析,再更新内部订单状态。 + +![支付系统异常处理-支付异步通知](images/Architecture/支付系统异常处理-支付异步通知.jpg) + +**注意** + +- 对于异步请求信息,一定需要对通知内容进行签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失 +- 异步通知将会发送多次,所以异步通知处理需要幂等 + +**③ 掉单查询** + +有的渠道可能没有提供异步通知的功能,只提供了订单查询的接口,这种情况下,只能使用定时掉单查询解决。可以将这类超时未知的订单的单独保存到掉单表,然后定时向渠道端查询订单的状态。若查询成功或者明确失败(比如订单不存在等),可以更新订单状态,并且删除掉单表记录;若查询依旧未知,这时我们需要等待下次查询的结果。 + +![支付系统异常处理-定时查询](images/Architecture/支付系统异常处理-定时查询.jpg) + +**注意**:有些情况下,有可能无法查询返回订单的状态,所以需要设置订单查询的最大次数,防止无限查询浪费性能。 + +**④ 对账** + +最后,极少数的情况下,订单查询与异步通知都无法获取的支付结果,这就只能进行对账处理。如果第二天渠道端给的对账文件有这一笔支付结果,那么可以根据这个记录更新直接更新内部支付记录。 + +**注意**:稳妥一点,可以先发起查询,然后根据查询结果更新订单记录。不过有些极端情况,查询无法获取结果,那么直接更新内部记录即可。那如果第二天也没有这笔记录的结果,这种情况下,我们可以认为这笔是失败的。如果用户被扣款,渠道端内部将会发起退款,将支付金额返回给用户。所以这种情况可以无需处理。 + + + +#### 内部掉单 + +**① 支付公司内部订单关系** + +如下图所示,第三方支付公司内部表通常为支付订单与渠道订单这样一种 1 比 N 的关系: + +![支付系统异常处理-支付订单渠道1N](images/Architecture/支付系统异常处理-支付订单渠道1N.jpg) + +**渠道订单**代表着第三方支付公司与外部渠道的关系,其实对**外部渠道系统**来讲,第三方支付公司就是一个外部商户。如果使用上图 1 对1 的订单关系,当第一次支付支付失败,外部商户可能会再次使用相同订单号对第三方支付公司发起支付。 + +![支付系统异常处理-支付订单渠道11](images/Architecture/支付系统异常处理-支付订单渠道11.jpg) + +如果第三方支付公司也拿相同的内部订单去请求外部渠道系统,有可能外部渠道系统并不支持同一订单号再次请求。但是现实的情况,很多外部商户并不是那么容易更换生成新的订单号,所以一般第三方支付公司都需要支持同一外部商户订单号在未成功的情况下,支持重复支付。在这种情况下,就需要我们上面的 1:N 的订单关系图了。 + + + +**② 内部掉单异常的原因** + +当收到外部渠道系统的成功的返回信息,成功更新了渠道订单表的记录。但是由于渠道订单表与支付订单表可能不是同一个数据库,也有可能两者并不在同一个应用中,这就有可能导致更新支付订单表的更新失败。 + +![支付系统异常处理-内部掉单](images/Architecture/支付系统异常处理-内部掉单.jpg) + +由于支付订单是表保存着外部商户订单与内部订单关系,支付订单未成功,所以外部商户也无法查询得到成功的支付结果。 + +此时渠道订单表已经成功,所以上面外部掉单的方法并不适用内部掉单。 + + + +**内部掉单异常解决办法:** + +- **分布式事务** + + 内部掉单异常,说白就是因为支付订单表与渠道订单表无法使用数据库事务保证两者同时更新成功或失败。 + +- **异步补偿更新** + + 当发生内部掉单的情况,即更新支付订单失败等情况,可以将这里支付订单保存(无法保证绝对成功)到一张内部掉单表。所以还需要定时查询,查询一段时间内支付订单未成功,而渠道订单表已成功的支付订单记录,然后也将其插入到内部掉单表。另一个系统应用,只需要定时扫描内部掉单表,将支付订单成功,然后再删除内部掉单记录即可。 + +**注意**:当支付订单表数据量很大后,定时查询可能会慢,为了防止影响主库,所以这类查询可以在备库进行。 + + + +#### 解决方案 + +支付掉单、卡单是支付过程中经常会碰到的事,可以采用异步补偿的方案,解决该问题。异步补偿方案可以采用如下两种: + +- 定时轮询补偿方案 +- 延迟消息补偿方案 + +定时轮询补偿方案实现起来比较简单,但是时效性稍差。而延迟消息补偿方案总体来说比较优秀,但是实现起来比较复杂。如果没有自定义的延迟时间的需求,可以直接采用 RocketMQ 延迟消息,简单快捷。另外**延迟队列**使用场景还是比较多,不仅仅能用在掉单补偿上,还可以用于支付关单等场景。所以有能力开发的团队,可以开发一个通用的延迟队列。 + + + +**方案一:定时轮询补偿方案** + +**① 整体流程** + +该方案主要采用定时任务,批量查询掉单记录,从而驱动查询具体支付结果,然后更新内部订单。整体方案流程图如下: + +![支付掉单-定时任务补偿](images/Architecture/支付掉单-定时任务补偿.jpg) + +前三步流程没什么好说的,正常的支付流程,咱们针对后面几步具体详细说下。 + +第三步调用支付通道之后,如果支付通道端返回**支付受理成功或者支付处理中**,我们就需要调用第四步,将这类订单插入掉单表。如果支付直接成功了,那就正常流程返回即可。 + +> 复习一下,网关类支付,比如支付宝、微信支付、网银支付,这种支付模式,支付通道仅仅返回支付受理成功,具体支付结果需要接收支付通道端的支付通知,这类支付我们将其称为异步支付。相应的还有同步支付,比如银行卡支付,微信、支付宝代扣类支付,这类支付,同步就能返回支付结果。 + +第五步,补单应用将会定时查询数据库,批量查询掉单记录。 + +第六步,补单应用使用线程池,多线程异步的方式发起掉单查询。 + +第七步,调用支付通道支付查询接口。 + +重点来了,如果第七步支付结果查询为以下状态: + +- **支付结果为扣款成功** +- **支付结果为明确失败** +- **掉单记录查询达到最大次数** + +**第八步就会删除掉单记录。** + +最后,如果掉单查询依旧还是处理中,那么经过一定的延时之后,重复第五步,再次重新掉单补偿,直到成功或者查询到达最大次数。 + +**② 相关问题** + +**为什么需要新建一张掉单表?不能直接使用支付订单表,查询未成功的订单吗?** + +这个问题,实际上确实可以直接使用的支付订单表,然后批量查询当天未成功的订单,补单程序发起支付查询。那为什么需要新建一张掉单表?主要是因为数据库查询效率问题,因为支付订单表每天都会大量记录新增,随着时间,这张表记录将会越来越多,越来越大。 + +**支付记录越多,批量范围查询效率就会变低,查询速度将会变慢**。所以为了查询效率,新建一张掉单表。这张表里仅记录支付未成功的订单,所以数据量就会很小,那么查询效率就会很高。另外,掉单表里的记录,不会被永久保存,只是临时性。当支付结果查询成功,或者支付结果明确失败,再或者查询次数到达规定最大次数,就会删除掉单记录。 + +**这就是第八步为什么需要删除掉单表的原因。** + +如果需要保存每次掉单表查询详情,那么这里建议再新增一张掉单查询记录表,保存每一次的查询记录。针对这个方案,如果还有其他问题,欢迎留言。 + +**③ 方案优缺点** + +定时轮询补偿方案,最大的优点可能就是系统架构方案比较简单,比较容易实施。那么这个方案的缺点主要在于**定时任务**上。定时任务轮询方案天然会存在以下不足: + +- **轮询效率稍低** +- 每次查询数据库,已经被执行过记录,仍然会被扫描(补单程序将会根据一定策略决定是否发起支付通道查询),有**重复计算**的嫌疑 +- **时效性不够好**,如果每小时轮询一次,最差的情况下,时间误差会达到1小时 +- 如果为了解决时效性问题,增加定时任务查询效率,那么 1 中查询效率跟 2 的重复计算问题将会更加明显 + + + +**方案二:延迟消息补偿方案** + +下面介绍另外一种掉单补偿方案,延迟消息补偿方案,这个方案整体流程与定时任务方案类似,最大区别可能在于,从一种**拉模式**变成一种**推模式**。 + +**① 整体流程** + +整体方案流程图如下: + +![支付掉单-延迟消息补偿方案](images/Architecture/支付掉单-延迟消息补偿方案.jpg) + +这个方案主要流程跟定时方案类似,主要区别在于第四步,第五步,第八步。 + +第四步的流程从插入掉单表变更为往**延迟队列发送掉单消息**。 + +第五步,补单程序接收掉单消息,然后触发支付掉单查询。 + +第八步,如果第七步支付结果查询为以下状态: + +- 支付结果为扣款成功 +- 支付结果为明确失败 +- 掉单记录查询达到最大次数 + +补单程序将会告知延迟队列消费成功,延迟队列将会删除这条掉单消息。其他状态将会告知消费失效,延迟队列将会在一定延时之后,再次发送掉单消息,然后继续重复第五步。 + +**② 延迟队列** + +这里的延迟队列需要自己实现,复杂度还是比较高的,这里给大家推荐几种实现方案: + +第一种,基于 **Redis SortedSet** 实现延迟队列。可以参考一下有赞的实现方案https://tech.youzan.com/queuing_delay/ + +第二种,基于时间轮算法(**TimingWheel**)实现延迟队列,具体可以参考 Kafka 延时队列。 + +第三种,基于 **RocketMQ** 延迟消息。 + +前两种方案说起来还需要再开发,所以还是比较复杂的。这里重点说下第三种方案,该方案是 **RocketMQ** 已经支持的特性,开箱即用,使用起来还是比较简单的。RocketMQ 延迟消息支持 18 个等级,分别如下: + +```properties +1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h +``` + +消息发送方可以通过Message.setDelayTimeLevel方式指定延迟等级,对应上方的延迟时间。消息消费方,如果消费失败,默认将会在消息发送方的的延迟等级基础上加 1。如果消息消费方需要指定其他的延迟等级,可以使用ConsumeConcurrentlyContext.setDelayLevelWhenNextConsume方式。RocketMQ 延迟消息,支持的特性还是比较基础、简单,不支持自定义延迟时间。不过对于掉单补偿的这个场景刚好够用,但是如果需要自定义延迟的,那还是得采用其他的方案。 + +**③ 方案优缺点** + +延迟消息的方案相对于定时轮询方案来讲: + +- 无需再查询全部订单,效率高 +- 时效性较好 + +不过延迟消息这种方案,需要基于**延迟队列**,实现起来比较复杂,目前开源实现也比较少。 \ No newline at end of file diff --git a/src/Architecture/605.md b/src/Architecture/605.md new file mode 100644 index 0000000..b5bf1b1 --- /dev/null +++ b/src/Architecture/605.md @@ -0,0 +1,253 @@ +### 前提条件 + +#### 公众号 + +微信公众号大体上可以分为服务号和订阅号。微信支付接入需要**已经完成微信认证的服务号**。如果是小程序的话,也需要完成**微信认证**。公众号可以关联同一主体的10个小程序,不同主体的3个小程序,如果是和公众号同一主体的小程序并且公众号已经完成认证,则直接可以在公众号后台的`小程序管理`中,进行快速注册并认证,这样就无需重复支付微信认证所需的`300`RMB了。 + +![微信支付-公众号](images/Architecture/微信支付-公众号.png) + + + +#### 微信商户平台 + +微信认证完成后,在公众号后台的 `微信支付` 中开通微信支付功能。提交微信支付申请后,3-5个工作日内,会进行审核,审核通过后会往你填写的邮箱里发送一份包含商户号信息的邮件,同时会往你填写的对公账户中打几毛钱的汇款,需要你查看具体金额后在商户平台中验证。 + +商户分为普通商户和服务商商户,千万不要申请错了。普通商户是可以进行交易,但是不能拓展商户。服务商可以拓展商户,但是不能交易。服务商就是提供统一的支付入口,它需要绑定具体的普通商户,微信支付时会在支付接口中携带普通商户参数,支付成功后金额会直接到具体的普通商户账户上。 + +![微信支付-微信商户平台](images/Architecture/微信支付-微信商户平台.png) + +申请时直接申请**普通商户**就可以了。 + + + +#### 绑定商户 + +微信支付发起依赖于公众号、小程序等应用与商户号的绑定关系。因此在进行开发前,需要将商户与具体应用进行绑定。如果商户和需要绑定的AppID是同一主体,只需要以下步骤即可完成绑定。 + +- 在商户平台-产品中心-AppID账户管理中关联AppID,输入AppId申请绑定 +- 在公众号或小程序后台微信支付-商户号管理中进行确认。 + +![微信支付-绑定商户](images/Architecture/微信支付-绑定商户.png) + +如果商户和需要绑定的AppID是不同主体,步骤和上述一样,除了输入AppId之外,还需要填入AppId的认证信息。 + +![微信支付-新增授权](images/Architecture/微信支付-新增授权.png) + + + +### 相关配置 + +#### 支付产品类型 + +- **付款码支付** + + 用户打开微信钱包-付款码的界面,商户扫码后提交完成支付。 + +- **JSAPI支付** + + 用户通过微信扫码,关注公众号等方式进入商家H5页面,并在微信内调用JSSDK完成支付。 + +- **Native支付** + + 用户打开微信扫一扫,扫描商户的二维码后完成支付。 + +- **APP支付** + + 商户APP中集成微信SDK,用户点击后跳转到微信内完成支付。 + +- **H5支付** + + 用户在微信以外的手机浏览器请求微信支付的场景唤起微信支付。 + +- **小程序支付** + + 用户在微信小程序中使用微信支付的场景。 + +- **刷脸支付** + + 无需掏出手机,刷脸完成支付,适合线下各种场景。 + + + +在商户平台-产品中心-我的产品中申请开通支付产品。 + +![微信支付-产品大全](images/Architecture/微信支付-产品大全.png) + + + +#### 支付授权目录配置 + +在商户平台-产品中心-开发配置中进行支付授权目录的配置(即你开发的下单接口地址),需要注意的是授权目录最多可以配置**五个**,在开发过程中请合理定义支付接口。 + +![微信支付-开发配置](images/Architecture/微信支付-开发配置.png) + + + +#### 配置商户密钥 + +在商户平台-账户中心-API安全中设置API密钥。 + +![微信支付-API秘钥](images/Architecture/微信支付-API秘钥.png) + +第一次设置时,需要安装操作证书,傻瓜式安装,按照提示一步一步操作就可以。API密钥需要一个**32位**的随机字符串,记得**不要随意更改API密钥**。 + +![微信支付-设置API秘钥](images/Architecture/微信支付-设置API秘钥.png) + +在微信API v3版本中,除了要配置API密钥外,还需要配置APIv3密钥和申请CA颁发的API证书。 + +- API v3密钥主要用于平台证书解密、回调信息解密 +- API证书用于调用更高级别的api接口,包含退款、红包等接口 + +**如果使用开源的微信开发包,请了解是否支持v3版本**。 + + + +#### 配置服务器 + +在公众号后台-开发-基本配置-服务器配置中启用并填写服务器信息。 + +![微信支付-服务器配置](images/Architecture/微信支付-服务器配置.png) + + + +#### 白名单配置 + +在公众号后台-开发-基本配置-公众号开发信息中配置开发者密钥,同时填写IP白名单。 + +![微信支付-白名单配置](images/Architecture/微信支付-白名单配置.png) + + + +#### JS接口安全域名 + +在公众号后台-公众号设置-功能设置中设置JS接口安全域名。 + +![微信支付-JS接口安全域名](images/Architecture/微信支付-JS接口安全域名.png) + +上面的配置是基于公众号支付配置的,小程序支付没有这么麻烦,小程序支付不用配置支付授权目录和授权域名。 + +| | JSAPI | 小程序 | +| :------- | :--------- | :----- | +| 支付协议 | HTTP/HTTPS | HTTPS | +| 支付目录 | 有 | 无 | +| 授权域名 | 有 | 无 | + + + +### 支付流程 + +由于微信升级了API接口,在API v3接口中,需要加载申请的API证书,微信已经封装了相关jar包,并且提供了加载示例,具体可参考“https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_3.shtml”,这里就不再赘述。我们以API v2为例详细学习一下微信接入的主要流程(因为API v3的一些接口还在持续升级,v2接口相对完整)。 + +![微信支付-支付流程](images/Architecture/微信支付-支付流程.png) + +上面的这张图片来自微信开发文档,我们详细分析一下支付流程。 + + + +#### 微信下单接口 + +用户通过微信客户端发起支付,在商戶后台生成订单,然后调用微信下单接口,生成预支付订单,返回订单号!下单接口涉及到的主要参数,只列举重要的几个参数: + +| 请求参数 | 是否必传 | 类型 | 描述 | +| :----------- | :------- | :----- | :------------------------ | +| appid | 是 | String | 公众号appid | +| mch_id | 是 | String | 商户号 | +| nonce_str | 是 | String | 随机字符串,32位以内 | +| sign | 是 | String | 签名,默认使用MD5进行加密 | +| out_trade_no | 是 | String | 系统内部订单号 | +| total_fee | 是 | Int | 订单总金额,单位是分 | +| notify_url | 是 | String | 支付结果通知接口 | + +`sign` 的签名也比较通用,涉及了一个保证签名不可预测的`nonce_str: + +- 将所有发送的非空参数使用字典排序生成键值对(key1=value1&key2=value2) +- 将商户平台密钥拼接在上述字符串的最后("String"+&key=密钥) +- 将上述字符串采用MD5加密 + + + +#### 支付 + +拉起微信支付,输入密码,完成支付。这一步需要在H5网页中执行JS调起支付。需要以下参数,因此在预付订单返回时,需要将下列参数封装后响应给页面,由页面完成支付。 + +| 参数名 | 是否必传 | 类型 | 描述 | +| :-------- | :------- | :----- | :------------------------------ | +| appId | 是 | String | 公众号id | +| timeStamp | 是 | String | 当前时间戳 | +| nonceStr | 是 | String | 随机字符串 | +| package | 是 | String | 预支付订单,格式为prepay_id=*** | +| signType | 是 | String | 签名类型,默认MD5 | +| paySign | 是 | String | 签名 | + + + +签名和下单接口的签名方式一样。 + +JS伪代码如下: + +```javascript +function onBridgeReady(){ + WeixinJSBridge.invoke( + 'getBrandWCPayRequest', { + // 公众号ID,由商户传入 + "appId":"wx2421b1c4370ec43b", + // 时间戳,自1970年以来的秒数 + "timeStamp":"1395712654", + // 随机串 + "nonceStr":"e61463f8efa94090b1f366cccfbbb444", + "package":"prepay_id=u802345jgfjsdfgsdg888", + // 微信签名方式 + "signType":"MD5", + // 微信签名 + "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" + }, + function(res){ + if(res.err_msg == "get_brand_wcpay_request:ok" ){ + // 使用以上方式判断前端返回,微信团队郑重提示: + // res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。 + } + }); +} +if (typeof WeixinJSBridge == "undefined"){ + if( document.addEventListener ){ + document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); + }else if (document.attachEvent){ + document.attachEvent('WeixinJSBridgeReady', onBridgeReady); + document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); + } +}else{ + onBridgeReady(); +} +``` + +注意伪代码中的这句话`// res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。`为什么这么说呢,我举个例子应该就明白了。假如你去超市买东西,是不是你说支付成功了你就可以把东西带走呢?肯定不是,是当商家收到钱后才算你支付成功,你才可以把东西带走。也就是说,这里提示的成功并不能说一定支付成功了,具体是否成功,微信平台会以异步的方式给你进行通知。 + + + +#### 异步通知 + +异步通知是比较重要的一步,在这里你可以根据通知结果处理你的业务逻辑。但是,可能会由于网络波动等原因通知不到,或者说微信接收到的响应不符合API的规定,微信会持续发起多次通知(请在回调通知接口中合理处理,**避免重复通知造成业务重复处理**),直到成功为止,通知频率为`15s`/`15s`/`30s`/`3m`/`10m`/`20m`/`30m`/`30m`/`30m`/`60m`/`3h`/`3h`/`3h`/`6h`/`6h` - 总计 `24h4m`)。但是微信不保证通知最终一定会成功。异步通知**响应参数**如下: + +| 参数名 | 是否必传 | 类型 | 描述 | +| :---------- | :------- | :----- | :--------------------------- | +| return_code | 是 | String | 返回状态码,`SUCCESS`/`FAIL` | +| return_msg | 否 | String | 返回信息 | + +如果微信一直通知不成功怎么?还是刚才那个例子,你明明支付成功了,但是商家却一直说她没收到钱,这时候你怎么办?肯定是去看一下她的手机是否真的没有收到钱!这里也一样。 + + + +#### 支付状态查询 + +![微信支付-支付状态查询](images/Architecture/微信支付-支付状态查询.png) + +- 商户APP或者前端页面收到支付返回时,商户需要调用商户查单接口确认订单状态,并把查询结果展示给用户 +- 商户后台需要准确、高效地处理微信支付发送的异步支付结果通知,并按接口规范把处理结果返回给微信支付 +- 商户后台未收到异步支付结果通知时,商户应该主动调用 `微信支付查单接口`,同步订单状态 +- 商户在T+1日从微信支付侧获取T日的交易账单,并与商户系统中的订单核对。如出现订单在微信支付侧成功,但是在商户侧未成功的情况,商户需要给用户补发货或者退款处理 + + + +**总结** + +本文主要以公众号支付为例,总结了接入微信支付需要的相关配置和支付流程。其他支付像APP支付也是开发中比较常见的应用场景,APP支付需要在 `微信开放平台` 去创建应用来接入微信支付。除此之外,微信支付API在向v3平滑升级,有些接口也还没有升级完成,升级完的接口相较于v2发生了一些数据格式方面的变化。如果引用第三方开发包进行开发,需要注意接口对应的版本。 diff --git a/src/Architecture/606.md b/src/Architecture/606.md new file mode 100644 index 0000000..ab0d55d --- /dev/null +++ b/src/Architecture/606.md @@ -0,0 +1,9 @@ +系统A是一个电商系统,目前是一台机器部署,系统中有一个用户下订单的接口,但是用户下订单之前一定要去检查一下库存,确保库存足够了才会给用户下单。由于系统有一定的并发,所以会预先将商品的库存保存在redis中,用户下单的时候会更新redis的库存。此时系统架构如下: + +![库存超卖-问题](images/Architecture/库存超卖-问题.png) + +但是这样一来会**产生一个问题**:假如某个时刻,redis里面的某个商品库存为1,此时两个请求同时到来,其中一个请求执行到上图的第3步,更新数据库的库存为0,但是第4步还没有执行。而另外一个请求执行到了第2步,发现库存还是1,就继续执行第3步。这样的结果,是导致卖出了2个商品,然而其实库存只有1个。这就是典型的`库存超卖`问题。 + +**解决方案**:此时,我们很容易想到解决方案:用锁把2、3、4步锁住,让它们执行完之后,另一个线程才能进来执行第2步。 + +![库存超卖-解决方案](images/Architecture/库存超卖-解决方案.jpg) \ No newline at end of file diff --git a/src/Architecture/7.md b/src/Architecture/7.md new file mode 100644 index 0000000..4055076 --- /dev/null +++ b/src/Architecture/7.md @@ -0,0 +1,34 @@ +Serverless的基础是云技术,它是云技术发展到一定阶段而出现的一种革命性的高端架构。Serverless并不是说不需要服务器,而是指不需要开发者去关心底层服务器的状态、资源和扩容等,开发者只需要关注于业务逻辑实现。架构上,我们可以把serverless分为FaaS和BaaS: + +![Serverless](images/Architecture/Serverless.jpg) + +- **FaaS(函数即服务)**:用于创建、运行、管理函数服务的计算平台,它支持多种开发语言,比如java、nodejs、dart等,这有利于不同端测的开发同学介入开发。FaaS是基于事件驱动的思想,只有当一个函数被事件触发时才会占用服务器资源执行,不然都是无需占用服务器资源的 +- **BaaS(后端即服务)**:提供了用于函数调用的第三方基础服务,比如身份校验、日志、数据库等,它是有服务商直接提供,开发者无需关系实现,直接调用即可 + + + +**优点** + +- 降低创业公司启动成本 +- 减少运营成本 +- 降低开发成本 +- 实现快速上线 +- 系统安全性更高 +- 能适应微服务架构和扩展性能力强 + +**缺点** + +- 不适合长时间运行应用 +- 完全会依赖于第三方服务 +- 缺乏调式和开发工具,排查问题困难 +- 无法用于高并发运用 + + + +**应用场景** + +- 发送通知 +- WebHook +- 数据统计分析 +- Trigger及定时任务 +- Chat 机器人 \ No newline at end of file diff --git a/src/Architecture/701.md b/src/Architecture/701.md new file mode 100644 index 0000000..fd7ff02 --- /dev/null +++ b/src/Architecture/701.md @@ -0,0 +1 @@ +先来看看什么是数据脱敏?数据脱敏也叫数据的去隐私化,在我们给定脱敏规则和策略的情况下,对敏感数据比如 `手机号`、`银行卡号` 等信息,进行转换或者修改的一种技术手段,防止敏感数据直接在不可靠的环境下使用。像政府、医疗行业、金融机构、移动运营商是比较早开始应用数据脱敏的,因为他们所掌握的都是用户最核心的私密数据,如果泄露后果是不可估量的。数据脱敏的应用在生活中是比较常见的,比如我们在淘宝买东西订单详情中,商家账户信息会被用 `*` 遮挡,保障了商户隐私不泄露,这就是一种数据脱敏方式。数据脱敏又分为静态数据脱敏(`SDM`)和 动态数据脱敏(`DDM`)。 \ No newline at end of file diff --git a/src/Architecture/702.md b/src/Architecture/702.md new file mode 100644 index 0000000..08a58e1 --- /dev/null +++ b/src/Architecture/702.md @@ -0,0 +1,9 @@ +静态数据脱敏(`SDM`):适用于将数据抽取出生产环境脱敏后分发至测试、开发、培训、数据分析等场景。 + +有时我们可能需要将生产环境的数据 `copy` 到测试、开发库中,以此来排查问题或进行数据分析,但出于安全考虑又不能将敏感数据存储于非生产环境,此时就要把敏感数据从生产环境脱敏完毕之后再在非生产环境使用。 + +这样脱敏后的数据与生产环境隔离,满足业务需要的同时又保障了生产数据的安全。 + +![数据脱敏过程](images/Architecture/数据脱敏过程.png) + +如图所示,将用户的真实 `姓名`、`手机号`、`身份证`、`银行卡号` 通过 `替换`、`无效化`、`乱序`、`对称加密` 等方案进行脱敏改造。 \ No newline at end of file diff --git a/src/Architecture/703.md b/src/Architecture/703.md new file mode 100644 index 0000000..4bac812 --- /dev/null +++ b/src/Architecture/703.md @@ -0,0 +1,3 @@ +动态数据脱敏(`DDM`):一般用在生产环境,访问敏感数据时实时进行脱敏,因为有时在不同情况下对于同一敏感数据的读取,需要做不同级别的脱敏处理,例如:不同角色、不同权限所执行的脱敏方案会不同。 + +**注意**:在抹去数据中的敏感内容同时,也需要保持原有的数据特征、业务规则和数据关联性,保证我们在开发、测试以及数据分析类业务不会受到脱敏的影响,使脱敏前后的数据一致性和有效性。**总之一句话:你爱怎么脱就怎么脱,别影响我使用就行**。 \ No newline at end of file diff --git a/src/Architecture/704.md b/src/Architecture/704.md new file mode 100644 index 0000000..8e74928 --- /dev/null +++ b/src/Architecture/704.md @@ -0,0 +1,59 @@ +### 无效化 + +无效化方案在处理待脱敏的数据时,通过对字段数据值进行 `截断`、`加密`、`隐藏` 等方式让敏感数据脱敏,使其不再具有利用价值。一般采用特殊字符(`*`等)代替真值,这种隐藏敏感数据的方法简单,但缺点是用户无法得知原数据的格式,如果想要获取完整信息,要让用户授权查询。 + +![截断方式](images/Architecture/截断方式.png) + +比如我们将身份证号用 * 替换真实数字就变成了 "220724 \*\*\*\*\*\* 3523",非常简单。 + +![隐藏方式](images/Architecture/隐藏方式.png) + + + +### 随机值 + +随机值替换,字母变为随机字母,数字变为随机数字,文字随机替换文字的方式来改变敏感数据,这种方案的优点在于可以在一定程度上保留原有数据的格式,往往这种方法用户不易察觉的。 + +我们看到 `name` 和 `idnumber` 字段进行了随机化脱敏,而名字姓、氏随机化稍有特殊,需要有对应姓氏字典数据支持。 + +![随机值](images/Architecture/随机值.png) + + + +### 数据替换 + +数据替换与前边的无效化方式比较相似,不同的是这里不以特殊字符进行遮挡,而是用一个设定的虚拟值替换真值。比如说我们将手机号统一设置成 “13651300000”。 + +![数据替换](images/Architecture/数据替换.png) + + + +### 对称加密 + +对称加密是一种特殊的可逆脱敏方法,通过加密密钥和算法对敏感数据进行加密,密文格式与原始数据在逻辑规则上一致,通过密钥解密可以恢复原始数据,要注意的就是密钥的安全性。 + +![对称加密](images/Architecture/对称加密.png) + + + +### 平均值 + +平均值方案经常用在统计场景,针对数值型数据,我们先计算它们的均值,然后使脱敏后的值在均值附近随机分布,从而保持数据的总和不变。 + +![原始数据](images/Architecture/原始数据.png) + +对价格字段 `price` 做平均值处理后,字段总金额不变,但脱敏后的字段值都在均值 60 附近。 + +![平均值](images/Architecture/平均值.png) + + + +### 偏移和取整 + +这种方式通过随机移位改变数字数据,偏移取整在保持了数据的安全性的同时保证了范围的大致真实性,比之前几种方案更接近真实数据,在大数据分析场景中意义比较大。 + +比如下边的日期字段`create_time`中 `2020-12-08 15:12:25` 变为 `2018-01-02 15:00:00`。 + +![取整](images/Architecture/取整.png) + +数据脱敏规则在实际应用中往往都是多种方案配合使用,以此来达到更高的安全级别。 \ No newline at end of file diff --git a/src/Architecture/8.md b/src/Architecture/8.md new file mode 100644 index 0000000..b477380 --- /dev/null +++ b/src/Architecture/8.md @@ -0,0 +1,63 @@ +### 三种服务发现模式 + +服务发现和负载均衡并不是新问题,业界其实已经探索和总结出一些常用的模式,这些模式的核心其实是代理 (Proxy,如下图所示),以及代理在架构中所处的位置。 + +![三种服务发现模式](images/Architecture/三种服务发现模式.png) + +在服务消费方和服务提供方之间增加一层代理,由代理负责服务发现和负载均衡功能,消费方通过代理间接访问目标服务。根据代理在架构上所处的位置不同,当前业界主要有三种不同的服务发现模式。 + + + +#### 模式一:传统集中式代理 + +![模式一:传统集中式代理](images/Architecture/模式一:传统集中式代理.png) + +这是最简单和传统做法,在服务消费者和生产者之间,代理作为独立一层集中部署,由独立团队 (一般是运维或框架) 负责治理和运维。常用的集中式代理有硬件负载均衡器 (如 F5),或者软件负载均衡器 (如 Nginx),F5(4 层负载)+Nginx(7 层负载) 这种软硬结合两层代理也是业内常见做法,兼顾配置的灵活性 (Nginx 比 F5 易于配置)。 + +这种方式通常在 DNS 域名服务器的配合下实现服务发现,服务注册 (建立服务域名和 IP 地址之间的映射关系) 一般由运维人员在代理上手工配置,服务消费方仅依赖服务域名,这个域名指向代理,由代理解析目标地址并做负载均衡和调用。 + +国外知名电商网站 eBay,虽然体量巨大,但其内部的服务发现机制仍然是基于这种传统的集中代理模式,国内公司如携程,也是采用这种模式。 + + + +#### 模式二:客户端嵌入式代理 + +![模式二:客户端嵌入式代理](images/Architecture/模式二:客户端嵌入式代理.png) + +这是很多互联网公司比较流行的一种做法,代理 (包括服务发现和负载均衡逻辑) 以客户库的形式嵌入在应用程序中。这种模式一般需要独立的服务注册中心组件配合,服务启动时自动注册到注册中心并定期报心跳,客户端代理则发现服务并做负载均衡。 + +Netflix 开源的 Eureka(注册中心)[附录 1] 和 Ribbon(客户端代理)[附录 2] 是这种模式的典型案例,国内阿里开源的 Dubbo 也是采用这种模式。 + + + +#### 模式三:主机独立进程代理 + +这种做法是上面两种模式的一个折中,代理既不是独立集中部署,也不嵌入在客户应用程序中,而是作为独立进程部署在每一个主机上,一个主机上的多个消费者应用可以共用这个代理,实现服务发现和负载均衡,如下图所示。这个模式一般也需要独立的服务注册中心组件配合,作用同模式二。 + +![模式三:主机独立进程代理](images/Architecture/模式三:主机独立进程代理.png) + + + +### 服务网格Service Mesh + +所谓的 Service Mesh,其实本质上就是上面提到的模式三:主机独立进程模式。 + +![服务网格ServiceMesh](images/Architecture/服务网格ServiceMesh.png) + +**Service Mesh特点** + +- 是一个基础设施 +- 轻量级网络代理,应用程序间通讯的中间层 +- 应用程序无感知,对应用程序透明无侵入 +- 解耦应用程序的重试/超时、监控、追踪和服务发现等控制层面的东西 + + + +**Service Mesh开源实现** + +- 第一代Service Mesh + - Linkerd:使用Scala编写,是业界第一个开源的Service Mesh方案 + - Envoy:基于C++ 11编写,无论是理论上还是实际上,Envoy 性能都比 Linkderd 更好 +- 第二代Service Mesh:主要改进集中在更加强大的控制面功能(与之对应的 sidecar proxy 被称之为数据面) + - Istio:是 Google 和 IBM 两位巨人联合 Lyft 的合作开源项目。是当前最主流的Service Mesh方案 + - Conduit:各方面的设计理念与 Istio 非常类似。但是作者抛弃了 Linkerd, 使用Rust重新编写了sidecar, 叫做 Conduit Data Plane, 控制面则由Go编写的 Conduit Control Plane接管 \ No newline at end of file diff --git a/src/Architecture/801.md b/src/Architecture/801.md new file mode 100644 index 0000000..0271c08 --- /dev/null +++ b/src/Architecture/801.md @@ -0,0 +1,14 @@ +自Redis 3.2开始,Redis基于geohash和有序集合提供了地理位置相关功能。 Redis Geo模块包含了以下6个命令: + +- **GEOADD**: 将给定的位置对象(纬度、经度、名字)添加到指定的key; +- GEOPOS: 从key里面返回所有给定位置对象的位置(经度和纬度); +- GEODIST: 返回两个给定位置之间的距离; +- GEOHASH: 返回一个或多个位置对象的Geohash表示; +- **GEORADIUS**: 以给定的经纬度为中心,返回目标集合中与中心的距离不超过给定最大距离的所有位置对象; +- GEORADIUSBYMEMBER: 以给定的位置对象为中心,返回与其距离不超过给定最大距离的所有位置对象。 + +其中,组合使用GEOADD和GEORADIUS可实现“附近的人”中“增”和“查”的基本功能。要实现微信中“附近的人”功能,可直接使用GEORADIUSBYMEMBER命令。其中“给定的位置对象”即为用户本人,搜索的对象为其他用户。不过本质上,GEORADIUSBYMEMBER = GEOPOS + GEORADIUS,即先查找用户位置再通过该位置搜索附近满足位置相互距离条件的其他用户对象。以下会从源码角度入手对GEOADD和GEORADIUS命令进行分析,剖析其算法原理。 + +> Redis geo操作中只包含了“增”和“查”的操作,并没有专门的“删除”命令。主要是因为Redis内部使用有序集合(zset)保存位置对象,可用zrem进行删除。 + +> 在Redis源码geo.c的文件注释中,只说明了该文件为GEOADD、GEORADIUS和GEORADIUSBYMEMBER的实现文件(其实在也实现了另三个命令)。从侧面看出其他三个命令为辅助命令。 \ No newline at end of file diff --git a/src/Architecture/802.md b/src/Architecture/802.md new file mode 100644 index 0000000..f7d1c88 --- /dev/null +++ b/src/Architecture/802.md @@ -0,0 +1,26 @@ +**使用方式** + +```shell +GEOADD key longitude latitude member [longitude latitude member ...] +``` + +将给定的位置对象(纬度、经度、名字)添加到指定的key。其中,key为集合名称,member为该经纬度所对应的对象。在实际运用中,当所需存储的对象数量过多时,可通过设置多key(如一个省一个key)的方式对对象集合变相做sharding,避免单集合数量过多。成功插入后的返回值: + +``` +(integer) N +``` + +其中N为成功插入的个数。通过源码分析可以看出Redis内部使用有序集合(zset)保存位置对象,有序集合中每个元素都是一个带位置的对象,元素的score值为其经纬度对应的52位的geohash值。 + +> double类型精度为52位; +> geohash是以base32的方式编码,52bits最高可存储10位geohash值,对应地理区域大小为0.6\*0.6米的格子。换句话说经Redis geo转换过的位置理论上会有约0.3\*1.414=0.424米的误差。 + + + +**算法小结** + +简单总结下GEOADD命令都干了啥: + +- 参数提取和校验 +- 将入参经纬度转换为52位的geohash值(score) +- 调用ZADD命令将member及其对应的score存入集合key中 \ No newline at end of file diff --git a/src/Architecture/803.md b/src/Architecture/803.md new file mode 100644 index 0000000..3332604 --- /dev/null +++ b/src/Architecture/803.md @@ -0,0 +1,53 @@ +**使用方式** + +``` +GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count] [STORE key] [STORedisT key] +``` + +以给定的经纬度为中心,返回目标集合中与中心的距离不超过给定最大距离的所有位置对象。 + +范围单位:`m | km | ft | mi --> 米 | 千米 | 英尺 | 英里` + +额外参数: + +- WITHDIST:在返回位置对象的同时,将位置对象与中心之间的距离也一并返回。距离的单位和用户给定的范围单位保持一致 +- WITHCOORD:将位置对象的经度和维度也一并返回 +- WITHHASH:以 52 位有符号整数的形式,返回位置对象经过原始 geohash 编码的有序集合分值。这个选项主要用于底层应用或者调试,实际中的作用并不大 +- ASC|DESC:从近到远返回位置对象元素 | 从远到近返回位置对象元素 +- COUNT count:选取前N个匹配位置对象元素。(不设置则返回所有元素) +- STORE key:将返回结果的地理位置信息保存到指定key +- STORedisT key:将返回结果离中心点的距离保存到指定key + +由于 STORE 和 STORedisT 两个选项的存在,GEORADIUS 和 GEORADIUSBYMEMBER 命令在技术上会被标记为写入命令,从而只会查询(写入)主实例,QPS过高时容易造成主实例读写压力过大。 为解决这个问题,在 Redis 3.2.10 和 Redis 4.0.0 中,分别新增了 GEORADIUS_RO 和 GEORADIUSBYMEMBER_RO两个只读命令。 + 不过,在实际开发中笔者发现 在java package `Redis.clients.jedis.params.geo` 的 GeoRadiusParam 参数类中并不包含 STORE 和 STORedisT 两个参数选项,在调用georadius时是否真的只查询了主实例,还是进行了只读封装。感兴趣的朋友可以自己研究下。成功查询后的返回值: +不带WITH限定,返回一个member list,如: + +``` +["member1","member2","member3"] +``` + +带WITH限定,member list中每个member也是一个嵌套list,如: + +``` +[ + ["member1", distance1, [longitude1, latitude1]] + ["member2", distance2, [longitude2, latitude2]] +] +``` + + + +**算法小结** + +抛开众多可选参数不谈,简单总结下GEORADIUS命令是怎么利用geohash获取目标位置对象的: + +- 参数提取和校验 +- 利用中心点和输入半径计算待查区域范围。这个范围参数包括满足条件的最高的geohash网格等级(精度) 以及 对应的能够覆盖目标区域的九宫格位置 +- 对九宫格进行遍历,根据每个geohash网格的范围框选出位置对象。进一步找出与中心点距离小于输入半径的对象,进行返回 + +直接描述不太好理解,我们通过如下两张图在对算法进行简单的演示: + +![georadius](images/Architecture/georadius.jpg) ![georadius-range](images/Architecture/georadius-range.jpg) + +令左图的中心为搜索中心,绿色圆形区域为目标区域,所有点为待搜索的位置对象,红色点则为满足条件的位置对象。 + 在实际搜索时,首先会根据搜索半径计算geohash网格等级(即右图中网格大小等级),并确定九宫格位置(即红色九宫格位置信息);再依次查找计算九宫格中的点(蓝点和红点)与中心点的距离,最终筛选出距离范围内的点(红点)。 \ No newline at end of file diff --git a/src/Architecture/901.md b/src/Architecture/901.md new file mode 100644 index 0000000..afd6fd0 --- /dev/null +++ b/src/Architecture/901.md @@ -0,0 +1,17 @@ +常见的场景如下: + +- 给一个 userId ,判断用户登陆状态 +- 两亿用户最近 7 天的签到情况,统计 7 天内连续签到的用户总数 +- 统计每天的新增与第二天的留存用户数 +- 统计网站的对访客(Unique Visitor,UV)量 +- 最新评论列表 +- 根据播放量音乐榜单 + +通常情况下,我们面临的用户数量以及访问量都是巨大的,比如百万、千万级别的用户数量,或者千万级别、甚至亿级别的访问信息。所以,我们必须要选择能够非常高效地统计大量数据(例如亿级)的集合类型。 + +**如何选择合适的数据集合,我们首先要了解常用的统计模式,并运用合理的数据来解决实际问题。**四种统计类型: + +- 二值状态统计 +- 聚合统计 +- 排序统计 +- 基数统计 \ No newline at end of file diff --git a/src/Architecture/902.md b/src/Architecture/902.md new file mode 100644 index 0000000..4c2e372 --- /dev/null +++ b/src/Architecture/902.md @@ -0,0 +1,148 @@ +**什么是二值状态统计呀?** + +也就是集合中的元素的值只有 0 和 1 两种,在签到打卡和用户是否登陆的场景中,只需记录`签到(1)`或 `未签到(0)`,`已登录(1)`或`未登陆(0)`。假如我们在判断用户是否登陆的场景中使用 Redis 的 String 类型实现(**key -> userId,value -> 0 表示下线,1 - 登陆**),假如存储 100 万个用户的登陆状态,如果以字符串的形式存储,就需要存储 100 万个字符串了,内存开销太大。 + + + +**为什么String类型内存开销大?** + +String 类型除了记录实际数据以外,还需要额外的内存记录数据长度、空间使用等信息。当保存的数据包含字符串,String 类型就使用简单动态字符串(SDS)结构体来保存,如下图所示: + +![SDS](images/Architecture/SDS.png) + +- **len**:占 4 个字节,表示 buf 的已用长度 +- **alloc**:占 4 个字节,表示 buf 实际分配的长度,通常 > len +- **buf**:字节数组,保存实际的数据,Redis 自动在数组最后加上一个 “\0”,额外占用一个字节的开销 + +所以,在 SDS 中除了 buf 保存实际的数据, len 与 alloc 就是额外的开销。另外,还有一个 **RedisObject 结构的开销**,因为 Redis 的数据类型有很多,而且,不同数据类型都有些相同的元数据要记录(比如最后一次访问的时间、被引用的次数等)。所以,Redis 会用一个 RedisObject 结构体来统一记录这些元数据,同时指向实际数据。 + +![RedisObject](images/Architecture/RedisObject.png) + +对于二值状态场景,我们就可以利用 Bitmap 来实现。比如登陆状态我们用一个 bit 位表示,一亿个用户也只占用 一亿 个 bit 位内存 ≈ (100000000 / 8/ 1024/1024)12 MB。 + +``` +大概的空间占用计算公式是:($offset/8/1024/1024) MB +``` + + + +**什么是 Bitmap 呢?** + +Bitmap 的底层数据结构用的是 String 类型的 SDS 数据结构来保存位数组,Redis 把每个字节数组的 8 个 bit 位利用起来,每个 bit 位 表示一个元素的二值状态(不是 0 就是 1)。可以将 Bitmap 看成是一个 bit 为单位的数组,数组的每个单元只能存储 0 或者 1,数组的下标在 Bitmap 中叫做 offset 偏移量。为了直观展示,我们可以理解成 buf 数组的每个字节用一行表示,每一行有 8 个 bit 位,8 个格子分别表示这个字节中的 8 个 bit 位,如下图所示: + +![Bitmap](images/Architecture/Bitmap.png) + +**8 个 bit 组成一个 Byte,所以 Bitmap 会极大地节省存储空间。** 这就是 Bitmap 的优势。 + +当遇到的统计场景只需要统计数据的二值状态,比如用户是否存在、 ip 是否是黑名单、以及签到打卡统计等场景就可以考虑使用 Bitmap。只需要一个 bit 位就能表示 0 和 1。在统计海量数据的时候将大大减少内存占用。 + + + +### 判断用户登陆态 + +怎么用 Bitmap 来判断海量用户中某个用户是否在线呢?Bitmap 提供了 `GETBIT、SETBIT` 操作,通过一个偏移值 offset 对 bit 数组的 offset 位置的 bit 位进行读写操作,需要注意的是 offset 从 0 开始。 + +只需要一个 key = login_status 表示存储用户登陆状态集合数据, 将用户 ID 作为 offset,在线就设置为 1,下线设置 0。通过 `GETBIT`判断对应的用户是否在线。50000 万 用户只需要 6 MB 的空间。 + +- **SETBIT 命令** + + ``` + SETBIT + ``` + + 设置或者清空 key 的 value 在 offset 处的 bit 值(只能是 0 或者 1)。 + +- **GETBIT 命令** + + ``` + GETBIT + ``` + + 获取 key 的 value 在 offset 处的 bit 位的值,当 key 不存在时,返回 0。 + + + +假如我们要判断 ID = 10086 的用户的登陆情况: + +- 第一步,执行以下指令,表示用户已登录。 + + ``` + SETBIT login_status 10086 1 + ``` + +- 第二步,检查该用户是否登陆,返回值 1 表示已登录。 + + ``` + GETBIT login_status 10086 + ``` + +- 第三步,登出,将 offset 对应的 value 设置成 0。 + + ``` + SETBIT login_status 10086 0 + ``` + + + +### 用户每个月的签到情况 + +在签到统计中,每个用户每天的签到用 1 个 bit 位表示,一年的签到只需要 365 个 bit 位。一个月最多只有 31 天,只需要 31 个 bit 位即可。 + +比如统计编号 89757 的用户在 2021 年 5 月份的打卡情况要如何进行?key 可以设计成 `uid:sign:{userId}:{yyyyMM}`,月份的每一天的值 - 1 可以作为 offset(因为 offset 从 0 开始,所以 `offset = 日期 - 1`)。 + +- 第一步,执行下面指令表示记录用户在 2021 年 5 月 16 号打卡。 + + ``` + SETBIT uid:sign:89757:202105 15 1 + ``` + +- 第二步,判断编号 89757 用户在 2021 年 5 月 16 号是否打卡。 + + ``` + GETBIT uid:sign:89757:202105 15 + ``` + +- 第三步,统计该用户在 5 月份的打卡次数,使用 `BITCOUNT` 指令。该指令用于统计给定的 bit 数组中,值 = 1 的 bit 位的数量。 + + ``` + BITCOUNT uid:sign:89757:202105 + ``` + +这样我们就可以实现用户每个月的打卡情况了,是不是很赞。 + + + +**如何统计这个月首次打卡时间呢?** + +Redis 提供了 `BITPOS key bitValue [start] [end]`指令,返回数据表示 Bitmap 中第一个值为 `bitValue` 的 offset 位置。在默认情况下, 命令将检测整个位图, 用户可以通过可选的 `start` 参数和 `end` 参数指定要检测的范围。所以我们可以通过执行以下指令来获取 userID = 89757 在 2021 年 5 月份**首次打卡**日期: + +``` +BITPOS uid:sign:89757:202105 1 +``` + +需要注意的是,我们需要将返回的 value + 1 ,因为 offset 从 0 开始。 + + + +### 连续签到用户总数 + +在记录了一个亿的用户连续 7 天的打卡数据,如何统计出这连续 7 天连续打卡用户总数呢? + +我们把每天的日期作为 Bitmap 的 key,userId 作为 offset,若是打卡则将 offset 位置的 bit 设置成 1。key 对应的集合的每个 bit 位的数据则是一个用户在该日期的打卡记录。一共有 7 个这样的 Bitmap,如果我们能对这 7 个 Bitmap 的对应的 bit 位做 『与』运算。同样的 UserID offset 都是一样的,当一个 userID 在 7 个 Bitmap 对应对应的 offset 位置的 bit = 1 就说明该用户 7 天连续打卡。结果保存到一个新 Bitmap 中,我们再通过 `BITCOUNT` 统计 bit = 1 的个数便得到了连续打卡 7 天的用户总数了。 + +Redis 提供了 `BITOP operation destkey key [key ...]`这个指令用于对一个或者多个 键 = key 的 Bitmap 进行位元操作。 + +`opration` 可以是 `and`、`OR`、`NOT`、`XOR`。当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 `0` 。空的 `key` 也被看作是包含 `0` 的字符串序列。便于理解,如下图所示: + +![BITOP](images/Architecture/BITOP.png) + +3 个 Bitmap,对应的 bit 位做「与」操作,结果保存到新的 Bitmap 中。操作指令表示将 三个 bitmap 进行 AND 操作,并将结果保存到 destmap 中。接着对 destmap 执行 BITCOUNT 统计。 + +``` +// 与操作 +BITOP AND destmap bitmap:01 bitmap:02 bitmap:03 +// 统计 bit 位 = 1 的个数 +BITCOUNT destmap +``` + +简单计算下 一个一亿个位的 Bitmap占用的内存开销,大约占 12 MB 的内存(10^8/8/1024/1024),7 天的 Bitmap 的内存开销约为 84 MB。同时我们最好给 Bitmap 设置过期时间,让 Redis 删除过期的打卡数据,节省内存。 diff --git a/src/Architecture/903.md b/src/Architecture/903.md new file mode 100644 index 0000000..b1db7dc --- /dev/null +++ b/src/Architecture/903.md @@ -0,0 +1,76 @@ +基数统计:统计一个集合中不重复元素的个数,常见于计算独立用户数(UV)。 + +实现基数统计最直接的方法,就是采用集合(Set)这种数据结构,当一个元素从未出现过时,便在集合中增加一个元素;如果出现过,那么集合仍保持不变。当页面访问量巨大,就需要一个超大的 Set 集合来统计,将会浪费大量空间。 + +另外,这样的数据也不需要很精确,到底有没有更好的方案呢?这个问题问得好,Redis 提供了 `HyperLogLog` 数据结构就是用来解决种种场景的统计问题。`HyperLogLog` 是一种不精确的去重基数方案,它的统计规则是基于概率实现的,标准误差 0.81%,这样的精度足以满足 UV 统计需求了。 + + + +### 网站的 UV + +#### Set方案 + +一个用户一天内多次访问一个网站只能算作一次,所以很容易就想到通过 Redis 的 Set 集合来实现。用户编号 89757 访问 「Redis 为什么这么快 」时,我们将这个信息放到 Set 中。 + +```shell +SADD Redis为什么这么快:uv 89757 +``` + +当用户编号 89757 多次访问「Redis 为什么这么快」页面,Set 的去重功能能保证不会重复记录同一个用户 ID。通过 `SCARD` 命令,统计「Redis 为什么这么快」页面 UV。指令返回一个集合的元素个数(也就是用户 ID)。 + +``` +SCARD Redis为什么这么快:uv +``` + + + +#### Hash方案 + +可以利用 Hash 类型实现,将用户 ID 作为 Hash 集合的 key,访问页面则执行 HSET 命令将 value 设置成 1。即使用户重复访问,重复执行命令,也只会把这个 userId 的值设置成 “1"。最后,利用 `HLEN` 命令统计 Hash 集合中的元素个数就是 UV。如下: + +``` +HSET redis集群:uv userId:89757 1 +// 统计 UV +HLEN redis集群 +``` + + + +#### HyperLogLog方案 + +Set 虽好,如果文章非常火爆达到千万级别,一个 Set 就保存了千万个用户的 ID,页面多了消耗的内存也太大了。同理,Hash数据类型也是如此。咋办呢? + +利用 Redis 提供的 `HyperLogLog` 高级数据结构(不要只知道 Redis 的五种基础数据类型了)。这是一种用于基数统计的数据集合类型,即使数据量很大,计算基数需要的空间也是固定的。每个 `HyperLogLog` 最多只需要花费 12KB 内存就可以计算 2 的 64 次方个元素的基数。Redis 对 `HyperLogLog` 的存储进行了优化,在计数比较小的时候,存储空间采用系数矩阵,占用空间很小。只有在计数很大,稀疏矩阵占用的空间超过了阈值才会转变成稠密矩阵,占用 12KB 空间。 + +- **PFADD**:将访问页面的每个用户 ID 添加到 `HyperLogLog` 中。 + + ``` + PFADD Redis主从同步原理:uv userID1 userID 2 useID3 + ``` + +- **PFCOUNT**:利用 `PFCOUNT` 获取 「Redis主从同步原理」页面的 UV值。 + + ``` + PFCOUNT Redis主从同步原理:uv + ``` + +- **PFMERGE**:将多个 `HyperLogLog` 合并在一起形成一个新的 `HyperLogLog` 值。 + + ``` + PFMERGE destkey sourcekey [sourcekey ...] + ``` + + **使用场景** + + 比如在网站中我们有两个内容差不多的页面,运营说需要这两个页面的数据进行合并。其中页面的 UV 访问量也需要合并,那这个时候 `PFMERGE` 就可以派上用场了,也就是**同样的用户访问这两个页面则只算做一次**。 + + 如下所示:Redis、MySQL 两个 Bitmap 集合分别保存了两个页面用户访问数据。 + + ``` + PFADD Redis数据 user1 user2 user3 + PFADD MySQL数据 user1 user2 user4 + PFMERGE 数据库 Redis数据 MySQL数据 + PFCOUNT 数据库 // 返回值 = 4 + ``` + + 将多个 HyperLogLog 合并(merge)为一个 HyperLogLog , 合并后的 HyperLogLog 的基数接近于所有输入HyperLogLog 的可见集合(observed set)的**并集**。user1、user2 都访问了 Redis 和 MySQL,只算访问了一次。 \ No newline at end of file diff --git a/src/Architecture/904.md b/src/Architecture/904.md new file mode 100644 index 0000000..f54afc5 --- /dev/null +++ b/src/Architecture/904.md @@ -0,0 +1,108 @@ +Redis的4个集合类型中(List、Set、Hash、Sorted Set),List和Sorted Set就是有序的。 + +- List:按照元素插入 List 的顺序排序,使用场景通常可以作为 消息队列、最新列表、排行榜 +- Sorted Set:根据元素的score权重排序,我们可以自己决定每个元素的权重值。使用场景(排行榜,比如按照播放量、点赞数) + + + +### 最新评论列表 + +**可以利用List插入的顺序排序实现评论列表**。比如微信公众号的后台回复列表(不要杠,举例子),每一公众号对应一个 List,这个List保存该公众号的所有的用户评论。每当一个用户评论,则利用`LPUSH key value [value ...]`插入到List队头。 + +``` +LPUSH 码哥字节 1 2 3 4 5 6 +``` + +接着再用 `LRANGE key star stop` 获取列表指定区间内的元素。 + +``` +> LRANGE 码哥字节 0 4 +1) "6" +2) "5" +3) "4" +4) "3" +5) "2" +``` + +**注意**:并不是所有最新列表都能用 List 实现,对于因为对于频繁更新的列表,list类型的分页可能导致列表元素重复或漏掉。比如当前评论列表 `List ={A, B, C, D}`,左边表示最新的评论,D 是最早的评论。 + +``` +LPUSH 码哥字节 D C B A +``` + +展示第一页最新 2 个评论,获取到 A、B: + +``` +LRANGE 码哥字节 0 1 +1) "A" +2) "B" +``` + +按照我们想要的逻辑来说,第二页可通过 `LRANGE 码哥字节 2 3` 获取 C,D。如果在展示第二页之前,产生新评论 E,评论 E 通过 `LPUSH 码哥字节 E` 插入到 List 队头,List = {E, A, B, C, D }。现在执行 `LRANGE 码哥字节 2 3` 获取第二页评论发现, B 又出现了。 + +``` +LRANGE 码哥字节 2 3 +1) "B" +2) "C" +``` + +出现这种情况的原因在于 List 是利用元素所在的位置排序,一旦有新元素插入,`List = {E,A,B,C,D}`。原先的数据在 List 的位置都往后移动一位,导致读取都旧元素。 + +![List最新列表](images/Architecture/List最新列表.png) + + + +**小结** + +只有不需要分页(比如每次都只取列表的前 5 个元素)或者更新频率低(比如每天凌晨统计更新一次)的列表才适合用 List 类型实现。对于需要分页并且会频繁更新的列表,需用使用有序集合 Sorted Set 类型实现。另外,需要通过时间范围查找的最新列表,List 类型也实现不了,需要通过有序集合 Sorted Set 类型实现,如以成交时间范围作为条件来查询的订单列表。 + + + +### 排行榜 + +对于最新列表的场景,List 和 Sorted Set 都能实现,为啥还用 List 呢?直接使用 Sorted Set 不是更好,它还能设置 score 权重排序更加灵活。原因是 Sorted Set 类型占用的内存容量是 List 类型的数倍之多,对于列表数量不多的情况,可以用 Sorted Set 类型来实现。 + +比如要一周音乐榜单,我们需要实时更新播放量,并且需要分页展示。除此以外,排序是根据播放量来决定的,这个时候 List 就无法满足了。我们可以将音乐 ID 保存到 Sorted Set 集合中,`score` 设置成每首歌的播放量,该音乐每播放一次则设置 score = score +1。 + +- **ZADD** + + 比如我们将《青花瓷》和《花田错》播放量添加到 musicTop 集合中: + + ``` + ZADD musicTop 100000000 青花瓷 8999999 花田错 + ``` + +- **ZINCRBY** + + 《青花瓷》每播放一次就通过 `ZINCRBY`指令将 score + 1。 + + ``` + > ZINCRBY musicTop 1 青花瓷 + 100000001 + ``` + +- **ZRANGEBYSCORE** + + 最后我们需要获取 musicTop **前十**播放量音乐榜单,目前最大播放量是 N ,可通过如下指令获取: + + ``` + ZRANGEBYSCORE musicTop N-9 N WITHSCORES + ``` + + **注意**:可是这个 N 我们怎么获取呀? + +- **ZREVRANGE** + + 可通过 `ZREVRANGE key start stop [WITHSCORES]`指令。其中元素的排序按 `score` 值递减(从大到小)来排列。具有相同 `score` 值的成员按字典序的逆序(reverse lexicographical order)排列。 + + ``` + > ZREVRANGE musicTop 0 0 WITHSCORES + 1) "青花瓷" + 2) 100000000 + ``` + + + +**小结** + +即使集合中的元素频繁更新,Sorted Set 也能通过 `ZRANGEBYSCORE`命令准确地获取到按序排列的数据。**在面对需要展示最新列表、排行榜等场景时,如果数据更新频繁或者需要分页显示,建议优先考虑使用 Sorted Set。** \ No newline at end of file diff --git a/src/Architecture/905.md b/src/Architecture/905.md new file mode 100644 index 0000000..a7638bb --- /dev/null +++ b/src/Architecture/905.md @@ -0,0 +1,62 @@ +指的就是统计多个集合元素的聚合结果,比如说: + +- 统计多个元素的共有数据(交集) +- 统计两个集合其中的一个独有元素(差集统计) +- 统计多个集合的所有元素(并集统计) + +什么样的场景会用到交集、差集、并集呢? + +Redis 的 Set 类型支持集合内的增删改查,底层使用了 Hash 数据结构,无论是 add、remove 都是 O(1) 时间复杂度。并且支持多个集合间的交集、并集、差集操作,利用这些集合操作,解决上边提到的统计问题。 + +### 交集-共同好友 + +比如 QQ 中的共同好友正是聚合统计中的交集。我们将账号作为 Key,该账号的好友作为 Set 集合的 value。模拟两个用户的好友集合: + +``` +SADD user:码哥字节 R大 Linux大神 PHP之父 +SADD user:大佬 Linux大神 Python大神 C++菜鸡 +``` + +![交集-共同好友](images/Architecture/交集-共同好友.png)交集 + +统计两个用户的共同好友只需要两个 Set 集合的交集,如下命令: + +``` +SINTERSTORE user:共同好友 user:码哥字节 user:大佬 +``` + +命令的执行后,「user:码哥字节」、「user:大佬」两个集合的交集数据存储到 user:共同好友这个集合中。 + + + +### 差集-每日新增好友数 + +比如,统计某个 App 每日新增注册用户量,只需要对近两天的总注册用户量集合取差集即可。如2021-06-01 的总注册用户量存放在 `key = user:20210601` set 集合中,2021-06-02 的总用户量存放在 `key = user:20210602` 的集合中。 + +![差集-每日新增好友数](images/Architecture/差集-每日新增好友数.png) + +如下指令,执行差集计算并将结果存放到 `user:new` 集合中。 + +``` +SDIFFSTORE user:new user:20210602 user:20210601 +``` + +执行完毕,此时的 user:new 集合将是 2021/06/02 日新增用户量。除此之外,QQ 上有个可能认识的人功能,也可以使用差集实现,就是把你朋友的好友集合减去你们共同的好友即是可能认识的人。 + + + +### 并集-总共新增好友 + +还是差集的例子,统计 2021/06/01 和 2021/06/02 两天总共新增的用户量,只需要对两个集合执行并集。 + +``` +SUNIONSTORE userid:new user:20210602 user:20210601 +``` + +此时新的集合 userid:new 则是两日新增的好友。 + + + +**小结** + +Set 的差集、并集和交集的计算复杂度较高,在数据量较大的情况下,如果直接执行这些计算,会导致 Redis 实例阻塞。所以,可以专门部署一个集群用于统计,让它专门负责聚合计算,或者是把数据读取到客户端,在客户端来完成聚合统计,这样就可以规避由于阻塞导致其他服务无法响应。 \ No newline at end of file diff --git a/src/Architecture/README.md b/src/Architecture/README.md new file mode 100644 index 0000000..de0c72e --- /dev/null +++ b/src/Architecture/README.md @@ -0,0 +1,5 @@ +
Architecture
+ +Introduction:收纳技术相关的 `架构` 等总结! + +## 🚀点击左侧菜单栏开始吧! \ No newline at end of file diff --git a/src/Architecture/_sidebar.md b/src/Architecture/_sidebar.md new file mode 100644 index 0000000..bd5bbc0 --- /dev/null +++ b/src/Architecture/_sidebar.md @@ -0,0 +1,108 @@ +* 🏁 架构演进 + * [✍ 软件架构模式](src/Architecture/1 "软件架构模式") + * [✍ 单体应用架构(Monoliths)](src/Architecture/2 "单体应用架构(Monoliths)") + * [✍ 垂直应用架构(Vertical)](src/Architecture/3 "垂直应用架构(Vertical)") + * [✍ 分布式架构(Distributed)](src/Architecture/4 "分布式架构(Distributed)") + * [✍ 面向服务化架构(SOA)](src/Architecture/5 "面向服务化架构(SOA)") + * [✍ 微服务架构(Micro Service)](src/Architecture/6 "微服务架构(Micro Service)") + * [✍ 无服务器架构(Serverless)](src/Architecture/7 "无服务器架构(Serverless)") + * [✍ 服务网格(Service Mesh)](src/Architecture/8 "服务网格(Service Mesh)") +* 🏁 架构规范 + * [✍ 指标](src/Architecture/101 "指标") + * [✍ 前后端分离](src/Architecture/102 "前后端分离") + * [✍ API接口设计](src/Architecture/103 "API接口设计") +* 🏁 多数据中心 + * [✍ 同城多机房](src/Architecture/201 "同城多机房") + * [✍ 两地三中心](src/Architecture/202 "两地三中心") +* [🏁 OAuth2.0](src/Architecture/301 "OAuth2.0") + * [✍ 授权码模式](src/Architecture/302 "授权码模式") + * [✍ 简化模式](src/Architecture/303 "简化模式") + * [✍ 密码模式](src/Architecture/304 "密码模式") + * [✍ 客户端模式](src/Architecture/305 "客户端模式") + * [✍ 隐藏式](src/Architecture/306 "隐藏式") + * [✍ 密码式](src/Architecture/307 "密码式") + * [✍ 凭证式](src/Architecture/308 "凭证式") + * [✍ 常见问题](src/Architecture/309 "常见问题") +* 🏁 用户体系 + * [✍ 登录安全规则](src/Architecture/401 "登录安全规则") + * [✍ 注册登录流程](src/Architecture/402 "注册登录流程") + * [✍ 密码设计](src/Architecture/403 "密码设计") +* [🏁 权限设计](src/Architecture/501 "权限设计") + * [✍ 权限模型](src/Architecture/502 "权限模型") + * [✍ RBAC](src/Architecture/503 "RBAC") +* 🏁 订单支付 + * [✍ 系统设计](src/Architecture/601 "系统设计") + * [✍ 流程设计](src/Architecture/602 "流程设计") + * [✍ 关键设计](src/Architecture/603 "关键设计") + * [✍ 异常设计](src/Architecture/604 "异常设计") + * [✍ 微信支付](src/Architecture/605 "微信支付") + * [✍ 库存超卖问题](src/Architecture/606 "库存超卖问题") +* [🏁 数据脱敏](src/Architecture/701 "数据脱敏") + * [✍ 静态数据脱敏](src/Architecture/702 "静态数据脱敏") + * [✍ 动态数据脱敏](src/Architecture/703 "动态数据脱敏") + * [✍ 数据脱敏方案](src/Architecture/704 "数据脱敏方案") +* 🏁 附近的人 + * [✍ 操作命令](src/Architecture/801 "操作命令") + * [✍ GEOADD](src/Architecture/802 "GEOADD") + * [✍ GEORADIUS](src/Architecture/803 "GEORADIUS") +* [🏁 亿级数据统计](src/Architecture/901 "亿级数据统计") + * [✍ 二值统计](src/Architecture/902 "二值统计") + * [✍ 基数统计](src/Architecture/903 "基数统计") + * [✍ 排序统计](src/Architecture/904 "排序统计") + * [✍ 聚合统计](src/Architecture/905 "聚合统计") +* 🏁 短信服务 + * [✍ 短信防刷](src/Architecture/1001 "短信防刷") +* [🏁 安全漏洞](src/Architecture/1101 "安全漏洞") + * [✍ SQL注入](src/Architecture/1102 "SQL注入") + * [✍ JSON反序列化漏洞](src/Architecture/1103 "JSON反序列化漏洞") + * [✍ XSS攻击](src/Architecture/1104 "XSS攻击") + * [✍ CSRF攻击](src/Architecture/1105 "CSRF攻击") + * [✍ 文件上传下载漏洞](src/Architecture/1106 "文件上传下载漏洞") + * [✍ 敏感数据泄露](src/Architecture/1107 "敏感数据泄露") + * [✍ XXE 漏洞](src/Architecture/1108 "XXE 漏洞") + * [✍ DDoS 攻击](src/Architecture/1109 "DDoS 攻击") + * [✍ 框架或应用漏洞](src/Architecture/1110 "框架或应用漏洞") + * [✍ 其它漏洞](src/Architecture/1111 "其它漏洞") +* [🏁 秒杀商品](src/Architecture/1201 "秒杀商品") + * [✍ 瞬时高并发](src/Architecture/1202 "瞬时高并发") + * [✍ 页面静态化](src/Architecture/1203 "页面静态化") + * [✍ 秒杀按钮](src/Architecture/1204 "秒杀按钮") + * [✍ 读多写少](src/Architecture/1205 "读多写少") + * [✍ 缓存问题](src/Architecture/1206 "缓存问题") + * [✍ 库存问题](src/Architecture/1207 "库存问题") + * [✍ 分布式锁](src/Architecture/1208 "分布式锁") + * [✍ mq异步处理](src/Architecture/1209 "mq异步处理") + * [✍ 如何限流](src/Architecture/1210 "如何限流") +* 🏁 其它设计 + * [✍ IP地址存储](src/Architecture/1301 "IP地址存储") + * [✍ 短链接](src/Architecture/1302 "短链接") + * [✍ 红包系统](src/Architecture/1303 "红包系统") + * [✍ 分布式定时任务](src/Architecture/1304 "分布式定时任务") + * [✍ 微博推送](src/Architecture/1305 "微博推送") +* 🏁 Redis应用场景 + * [✍ 数据缓存](src/Architecture/1401 "数据缓存") + * [✍ 分布式锁](src/Architecture/1402 "分布式锁") + * [✍ 全局ID](src/Architecture/1403 "全局ID") + * [✍ 计数器](src/Architecture/1404 "计数器") + * [✍ 限流](src/Architecture/1405 "限流") + * [✍ 位统计](src/Architecture/1406 "位统计") + * [✍ 购物车](src/Architecture/1407 "购物车") + * [✍ 时间线TimeLine](src/Architecture/1408 "时间线TimeLine") + * [✍ 消息队列](src/Architecture/1409 "消息队列") + * [✍ 抽奖](src/Architecture/1410 "抽奖") + * [✍ 点赞、签到、打卡](src/Architecture/1411 "点赞、签到、打卡") + * [✍ 商品标签](src/Architecture/1412 "商品标签") + * [✍ 商品筛选](src/Architecture/1413 "商品筛选") + * [✍ 用户关注、推荐模型](src/Architecture/1414 "用户关注、推荐模型") + * [✍ 排行榜](src/Architecture/1415 "排行榜") +* 🏁 分布式问题场景 + * [✍ 消息队列 —— 幂等问题](src/Architecture/1501 "消息队列 —— 幂等问题") + * [✍ 消息队列 —— 消息丢失](src/Architecture/1502 "消息队列 —— 消息丢失") + * [✍ 消息队列 —— 消息乱序](src/Architecture/1503 "消息队列 —— 消息乱序") + * [✍ 消息队列 —— 消息积压](src/Architecture/1504 "消息队列 —— 消息积压") + * [✍ 消息队列 —— 消息过期失效](src/Architecture/1505 "消息队列 —— 消息过期失效") + * [✍ 消息队列 —— 队列写满](src/Architecture/1506 "消息队列 —— 队列写满") + * [✍ Redis —— 数据丢失](src/Architecture/1507 "Redis —— 数据丢失") + * [✍ 分库分表 —— 扩容](src/Architecture/1508 "分库分表 —— 扩容") + * [✍ 分库分表 —— 唯一ID](src/Architecture/1509 "分库分表 —— 唯一ID") + * [✍ 分布式事务](src/Architecture/1510 "分布式事务") \ No newline at end of file diff --git a/src/Architecture/images/Architecture/1a9f1463d439bc07a6b44df1ce973916.png b/src/Architecture/images/Architecture/1a9f1463d439bc07a6b44df1ce973916.png new file mode 100644 index 0000000..9b367d2 Binary files /dev/null and b/src/Architecture/images/Architecture/1a9f1463d439bc07a6b44df1ce973916.png differ diff --git a/src/Architecture/images/Architecture/20200413205303434.png b/src/Architecture/images/Architecture/20200413205303434.png new file mode 100644 index 0000000..6706c54 Binary files /dev/null and b/src/Architecture/images/Architecture/20200413205303434.png differ diff --git a/src/Architecture/images/Architecture/20200413205314496.png b/src/Architecture/images/Architecture/20200413205314496.png new file mode 100644 index 0000000..8cf80ef Binary files /dev/null and b/src/Architecture/images/Architecture/20200413205314496.png differ diff --git a/src/Architecture/images/Architecture/20200413205324331.png b/src/Architecture/images/Architecture/20200413205324331.png new file mode 100644 index 0000000..48597a3 Binary files /dev/null and b/src/Architecture/images/Architecture/20200413205324331.png differ diff --git a/src/Architecture/images/Architecture/20200413205334747.png b/src/Architecture/images/Architecture/20200413205334747.png new file mode 100644 index 0000000..3660a32 Binary files /dev/null and b/src/Architecture/images/Architecture/20200413205334747.png differ diff --git a/src/Architecture/images/Architecture/20200413205344663.png b/src/Architecture/images/Architecture/20200413205344663.png new file mode 100644 index 0000000..e4be9b3 Binary files /dev/null and b/src/Architecture/images/Architecture/20200413205344663.png differ diff --git a/src/Architecture/images/Architecture/2cabf15de992c630b80b55b7734744bf.png b/src/Architecture/images/Architecture/2cabf15de992c630b80b55b7734744bf.png new file mode 100644 index 0000000..f0882bb Binary files /dev/null and b/src/Architecture/images/Architecture/2cabf15de992c630b80b55b7734744bf.png differ diff --git a/src/Architecture/images/Architecture/468036d6bd7316bc39d8c783af042fc8.png b/src/Architecture/images/Architecture/468036d6bd7316bc39d8c783af042fc8.png new file mode 100644 index 0000000..9b8b607 Binary files /dev/null and b/src/Architecture/images/Architecture/468036d6bd7316bc39d8c783af042fc8.png differ diff --git a/src/Architecture/images/Architecture/788b54bf0bb97d401f13a0fdc20bc9c1.png b/src/Architecture/images/Architecture/788b54bf0bb97d401f13a0fdc20bc9c1.png new file mode 100644 index 0000000..151fa6b Binary files /dev/null and b/src/Architecture/images/Architecture/788b54bf0bb97d401f13a0fdc20bc9c1.png differ diff --git a/src/Architecture/images/Architecture/Apollo配置中心.jpg b/src/Architecture/images/Architecture/Apollo配置中心.jpg new file mode 100644 index 0000000..92af044 Binary files /dev/null and b/src/Architecture/images/Architecture/Apollo配置中心.jpg differ diff --git a/src/Architecture/images/Architecture/BITOP.png b/src/Architecture/images/Architecture/BITOP.png new file mode 100644 index 0000000..c32dc26 Binary files /dev/null and b/src/Architecture/images/Architecture/BITOP.png differ diff --git a/src/Architecture/images/Architecture/Bitmap.png b/src/Architecture/images/Architecture/Bitmap.png new file mode 100644 index 0000000..475ecfb Binary files /dev/null and b/src/Architecture/images/Architecture/Bitmap.png differ diff --git a/src/Architecture/images/Architecture/Blackboard-pattern.png b/src/Architecture/images/Architecture/Blackboard-pattern.png new file mode 100644 index 0000000..df2ad44 Binary files /dev/null and b/src/Architecture/images/Architecture/Blackboard-pattern.png differ diff --git a/src/Architecture/images/Architecture/Broker-pattern.png b/src/Architecture/images/Architecture/Broker-pattern.png new file mode 100644 index 0000000..7dc50ba Binary files /dev/null and b/src/Architecture/images/Architecture/Broker-pattern.png differ diff --git a/src/Architecture/images/Architecture/CSRF攻击案例.jpg b/src/Architecture/images/Architecture/CSRF攻击案例.jpg new file mode 100644 index 0000000..60ccab0 Binary files /dev/null and b/src/Architecture/images/Architecture/CSRF攻击案例.jpg differ diff --git a/src/Architecture/images/Architecture/Client-server-pattern.png b/src/Architecture/images/Architecture/Client-server-pattern.png new file mode 100644 index 0000000..b8e4f7c Binary files /dev/null and b/src/Architecture/images/Architecture/Client-server-pattern.png differ diff --git a/src/Architecture/images/Architecture/Dapper.jpg b/src/Architecture/images/Architecture/Dapper.jpg new file mode 100644 index 0000000..467fe3d Binary files /dev/null and b/src/Architecture/images/Architecture/Dapper.jpg differ diff --git a/src/Architecture/images/Architecture/Event-bus-pattern.png b/src/Architecture/images/Architecture/Event-bus-pattern.png new file mode 100644 index 0000000..77a9d4e Binary files /dev/null and b/src/Architecture/images/Architecture/Event-bus-pattern.png differ diff --git a/src/Architecture/images/Architecture/Hystrix调用流程.jpg b/src/Architecture/images/Architecture/Hystrix调用流程.jpg new file mode 100644 index 0000000..def4835 Binary files /dev/null and b/src/Architecture/images/Architecture/Hystrix调用流程.jpg differ diff --git a/src/Architecture/images/Architecture/Interpreter-pattern.png b/src/Architecture/images/Architecture/Interpreter-pattern.png new file mode 100644 index 0000000..759d520 Binary files /dev/null and b/src/Architecture/images/Architecture/Interpreter-pattern.png differ diff --git a/src/Architecture/images/Architecture/JSON序列化漏洞复现.jpg b/src/Architecture/images/Architecture/JSON序列化漏洞复现.jpg new file mode 100644 index 0000000..a9d1bc2 Binary files /dev/null and b/src/Architecture/images/Architecture/JSON序列化漏洞复现.jpg differ diff --git a/src/Architecture/images/Architecture/JSON序列化过程.jpg b/src/Architecture/images/Architecture/JSON序列化过程.jpg new file mode 100644 index 0000000..9437b2b Binary files /dev/null and b/src/Architecture/images/Architecture/JSON序列化过程.jpg differ diff --git a/src/Architecture/images/Architecture/Layered-pattern.png b/src/Architecture/images/Architecture/Layered-pattern.png new file mode 100644 index 0000000..a13c995 Binary files /dev/null and b/src/Architecture/images/Architecture/Layered-pattern.png differ diff --git a/src/Architecture/images/Architecture/List最新列表.png b/src/Architecture/images/Architecture/List最新列表.png new file mode 100644 index 0000000..d1aa2ef Binary files /dev/null and b/src/Architecture/images/Architecture/List最新列表.png differ diff --git a/src/Architecture/images/Architecture/Master-slave-pattern.png b/src/Architecture/images/Architecture/Master-slave-pattern.png new file mode 100644 index 0000000..bb64d68 Binary files /dev/null and b/src/Architecture/images/Architecture/Master-slave-pattern.png differ diff --git a/src/Architecture/images/Architecture/Mock-Server.png b/src/Architecture/images/Architecture/Mock-Server.png new file mode 100644 index 0000000..f6114f0 Binary files /dev/null and b/src/Architecture/images/Architecture/Mock-Server.png differ diff --git a/src/Architecture/images/Architecture/Model-view-controller-pattern.png b/src/Architecture/images/Architecture/Model-view-controller-pattern.png new file mode 100644 index 0000000..e5ac760 Binary files /dev/null and b/src/Architecture/images/Architecture/Model-view-controller-pattern.png differ diff --git a/src/Architecture/images/Architecture/Netflix的路由发现体系.jpg b/src/Architecture/images/Architecture/Netflix的路由发现体系.jpg new file mode 100644 index 0000000..3f5ddae Binary files /dev/null and b/src/Architecture/images/Architecture/Netflix的路由发现体系.jpg differ diff --git a/src/Architecture/images/Architecture/OAuth2.0-令牌怎么用.png b/src/Architecture/images/Architecture/OAuth2.0-令牌怎么用.png new file mode 100644 index 0000000..0dd9d54 Binary files /dev/null and b/src/Architecture/images/Architecture/OAuth2.0-令牌怎么用.png differ diff --git a/src/Architecture/images/Architecture/OAuth2.0-授权码.png b/src/Architecture/images/Architecture/OAuth2.0-授权码.png new file mode 100644 index 0000000..b6be7f2 Binary files /dev/null and b/src/Architecture/images/Architecture/OAuth2.0-授权码.png differ diff --git a/src/Architecture/images/Architecture/Peer-to-peer-pattern.png b/src/Architecture/images/Architecture/Peer-to-peer-pattern.png new file mode 100644 index 0000000..b5e52dd Binary files /dev/null and b/src/Architecture/images/Architecture/Peer-to-peer-pattern.png differ diff --git a/src/Architecture/images/Architecture/Pipe-filter-pattern.png b/src/Architecture/images/Architecture/Pipe-filter-pattern.png new file mode 100644 index 0000000..5ddc937 Binary files /dev/null and b/src/Architecture/images/Architecture/Pipe-filter-pattern.png differ diff --git a/src/Architecture/images/Architecture/RBAC.png b/src/Architecture/images/Architecture/RBAC.png new file mode 100644 index 0000000..598a8d2 Binary files /dev/null and b/src/Architecture/images/Architecture/RBAC.png differ diff --git a/src/Architecture/images/Architecture/RBAC0.png b/src/Architecture/images/Architecture/RBAC0.png new file mode 100644 index 0000000..0288068 Binary files /dev/null and b/src/Architecture/images/Architecture/RBAC0.png differ diff --git a/src/Architecture/images/Architecture/RBAC1.png b/src/Architecture/images/Architecture/RBAC1.png new file mode 100644 index 0000000..58397c4 Binary files /dev/null and b/src/Architecture/images/Architecture/RBAC1.png differ diff --git a/src/Architecture/images/Architecture/RBAC2.png b/src/Architecture/images/Architecture/RBAC2.png new file mode 100644 index 0000000..3b98ad7 Binary files /dev/null and b/src/Architecture/images/Architecture/RBAC2.png differ diff --git a/src/Architecture/images/Architecture/RBAC3.png b/src/Architecture/images/Architecture/RBAC3.png new file mode 100644 index 0000000..ef95d1e Binary files /dev/null and b/src/Architecture/images/Architecture/RBAC3.png differ diff --git a/src/Architecture/images/Architecture/RBAC用户组.png b/src/Architecture/images/Architecture/RBAC用户组.png new file mode 100644 index 0000000..b6c9d22 Binary files /dev/null and b/src/Architecture/images/Architecture/RBAC用户组.png differ diff --git a/src/Architecture/images/Architecture/RedisObject.png b/src/Architecture/images/Architecture/RedisObject.png new file mode 100644 index 0000000..7eb7431 Binary files /dev/null and b/src/Architecture/images/Architecture/RedisObject.png differ diff --git a/src/Architecture/images/Architecture/SDS.png b/src/Architecture/images/Architecture/SDS.png new file mode 100644 index 0000000..31200cc Binary files /dev/null and b/src/Architecture/images/Architecture/SDS.png differ diff --git a/src/Architecture/images/Architecture/SOA架构.png b/src/Architecture/images/Architecture/SOA架构.png new file mode 100644 index 0000000..7af6046 Binary files /dev/null and b/src/Architecture/images/Architecture/SOA架构.png differ diff --git a/src/Architecture/images/Architecture/SQL注入业务场景.jpg b/src/Architecture/images/Architecture/SQL注入业务场景.jpg new file mode 100644 index 0000000..506aa0c Binary files /dev/null and b/src/Architecture/images/Architecture/SQL注入业务场景.jpg differ diff --git a/src/Architecture/images/Architecture/Serverless.jpg b/src/Architecture/images/Architecture/Serverless.jpg new file mode 100644 index 0000000..2ff98d5 Binary files /dev/null and b/src/Architecture/images/Architecture/Serverless.jpg differ diff --git a/src/Architecture/images/Architecture/XSS攻击-Html.jpg b/src/Architecture/images/Architecture/XSS攻击-Html.jpg new file mode 100644 index 0000000..a5cebb4 Binary files /dev/null and b/src/Architecture/images/Architecture/XSS攻击-Html.jpg differ diff --git a/src/Architecture/images/Architecture/XSS攻击-Html结果.jpg b/src/Architecture/images/Architecture/XSS攻击-Html结果.jpg new file mode 100644 index 0000000..3ec1ff6 Binary files /dev/null and b/src/Architecture/images/Architecture/XSS攻击-Html结果.jpg differ diff --git a/src/Architecture/images/Architecture/XSS攻击-反射案例.jpg b/src/Architecture/images/Architecture/XSS攻击-反射案例.jpg new file mode 100644 index 0000000..25cf0f3 Binary files /dev/null and b/src/Architecture/images/Architecture/XSS攻击-反射案例.jpg differ diff --git a/src/Architecture/images/Architecture/XSS攻击-转义字符.jpg b/src/Architecture/images/Architecture/XSS攻击-转义字符.jpg new file mode 100644 index 0000000..bce2ea2 Binary files /dev/null and b/src/Architecture/images/Architecture/XSS攻击-转义字符.jpg differ diff --git a/src/Architecture/images/Architecture/cdefa098def4fa1cb6c181f700df4c49.png b/src/Architecture/images/Architecture/cdefa098def4fa1cb6c181f700df4c49.png new file mode 100644 index 0000000..d65ec5b Binary files /dev/null and b/src/Architecture/images/Architecture/cdefa098def4fa1cb6c181f700df4c49.png differ diff --git a/src/Architecture/images/Architecture/dc291356663fc69dd4e8f7cfe7be63b6.png b/src/Architecture/images/Architecture/dc291356663fc69dd4e8f7cfe7be63b6.png new file mode 100644 index 0000000..472bce1 Binary files /dev/null and b/src/Architecture/images/Architecture/dc291356663fc69dd4e8f7cfe7be63b6.png differ diff --git a/src/Architecture/images/Architecture/georadius-range.jpg b/src/Architecture/images/Architecture/georadius-range.jpg new file mode 100644 index 0000000..7a0c3a7 Binary files /dev/null and b/src/Architecture/images/Architecture/georadius-range.jpg differ diff --git a/src/Architecture/images/Architecture/georadius.jpg b/src/Architecture/images/Architecture/georadius.jpg new file mode 100644 index 0000000..c66a730 Binary files /dev/null and b/src/Architecture/images/Architecture/georadius.jpg differ diff --git a/src/Architecture/images/Architecture/三种服务发现模式.png b/src/Architecture/images/Architecture/三种服务发现模式.png new file mode 100644 index 0000000..e8e32af Binary files /dev/null and b/src/Architecture/images/Architecture/三种服务发现模式.png differ diff --git a/src/Architecture/images/Architecture/三种测试.png b/src/Architecture/images/Architecture/三种测试.png new file mode 100644 index 0000000..eef8487 Binary files /dev/null and b/src/Architecture/images/Architecture/三种测试.png differ diff --git a/src/Architecture/images/Architecture/主机独立Lb模式.jpg b/src/Architecture/images/Architecture/主机独立Lb模式.jpg new file mode 100644 index 0000000..0f66714 Binary files /dev/null and b/src/Architecture/images/Architecture/主机独立Lb模式.jpg differ diff --git a/src/Architecture/images/Architecture/交集-共同好友.png b/src/Architecture/images/Architecture/交集-共同好友.png new file mode 100644 index 0000000..93de67b Binary files /dev/null and b/src/Architecture/images/Architecture/交集-共同好友.png differ diff --git a/src/Architecture/images/Architecture/传统Lb模式.jpg b/src/Architecture/images/Architecture/传统Lb模式.jpg new file mode 100644 index 0000000..bc646e8 Binary files /dev/null and b/src/Architecture/images/Architecture/传统Lb模式.jpg differ diff --git a/src/Architecture/images/Architecture/典型主流的监控架构.jpg b/src/Architecture/images/Architecture/典型主流的监控架构.jpg new file mode 100644 index 0000000..471d7bd Binary files /dev/null and b/src/Architecture/images/Architecture/典型主流的监控架构.jpg differ diff --git a/src/Architecture/images/Architecture/分层设计.png b/src/Architecture/images/Architecture/分层设计.png new file mode 100644 index 0000000..1173dfe Binary files /dev/null and b/src/Architecture/images/Architecture/分层设计.png differ diff --git a/src/Architecture/images/Architecture/分布式架构.png b/src/Architecture/images/Architecture/分布式架构.png new file mode 100644 index 0000000..806d385 Binary files /dev/null and b/src/Architecture/images/Architecture/分布式架构.png differ diff --git a/src/Architecture/images/Architecture/分析问题-日志分析.png b/src/Architecture/images/Architecture/分析问题-日志分析.png new file mode 100644 index 0000000..af38cb4 Binary files /dev/null and b/src/Architecture/images/Architecture/分析问题-日志分析.png differ diff --git a/src/Architecture/images/Architecture/功能权限的Demo.png b/src/Architecture/images/Architecture/功能权限的Demo.png new file mode 100644 index 0000000..3ce8d8f Binary files /dev/null and b/src/Architecture/images/Architecture/功能权限的Demo.png differ diff --git a/src/Architecture/images/Architecture/功能权限的实体关系图.png b/src/Architecture/images/Architecture/功能权限的实体关系图.png new file mode 100644 index 0000000..baef7de Binary files /dev/null and b/src/Architecture/images/Architecture/功能权限的实体关系图.png differ diff --git a/src/Architecture/images/Architecture/功能权限的继承.png b/src/Architecture/images/Architecture/功能权限的继承.png new file mode 100644 index 0000000..7882c0d Binary files /dev/null and b/src/Architecture/images/Architecture/功能权限的继承.png differ diff --git a/src/Architecture/images/Architecture/功能权限的继承层级.png b/src/Architecture/images/Architecture/功能权限的继承层级.png new file mode 100644 index 0000000..00b8485 Binary files /dev/null and b/src/Architecture/images/Architecture/功能权限的继承层级.png differ diff --git a/src/Architecture/images/Architecture/单体应用架构.png b/src/Architecture/images/Architecture/单体应用架构.png new file mode 100644 index 0000000..28b7855 Binary files /dev/null and b/src/Architecture/images/Architecture/单体应用架构.png differ diff --git a/src/Architecture/images/Architecture/原始数据.png b/src/Architecture/images/Architecture/原始数据.png new file mode 100644 index 0000000..0b4168c Binary files /dev/null and b/src/Architecture/images/Architecture/原始数据.png differ diff --git a/src/Architecture/images/Architecture/取整.png b/src/Architecture/images/Architecture/取整.png new file mode 100644 index 0000000..fb27061 Binary files /dev/null and b/src/Architecture/images/Architecture/取整.png differ diff --git a/src/Architecture/images/Architecture/垂直应用架构.png b/src/Architecture/images/Architecture/垂直应用架构.png new file mode 100644 index 0000000..740316c Binary files /dev/null and b/src/Architecture/images/Architecture/垂直应用架构.png differ diff --git a/src/Architecture/images/Architecture/定位问题-taceId.png b/src/Architecture/images/Architecture/定位问题-taceId.png new file mode 100644 index 0000000..6025d74 Binary files /dev/null and b/src/Architecture/images/Architecture/定位问题-taceId.png differ diff --git a/src/Architecture/images/Architecture/定位问题-链路跟踪.png b/src/Architecture/images/Architecture/定位问题-链路跟踪.png new file mode 100644 index 0000000..18d2cb5 Binary files /dev/null and b/src/Architecture/images/Architecture/定位问题-链路跟踪.png differ diff --git a/src/Architecture/images/Architecture/客户端模式.png b/src/Architecture/images/Architecture/客户端模式.png new file mode 100644 index 0000000..1f067c7 Binary files /dev/null and b/src/Architecture/images/Architecture/客户端模式.png differ diff --git a/src/Architecture/images/Architecture/密码模式.png b/src/Architecture/images/Architecture/密码模式.png new file mode 100644 index 0000000..9652f6d Binary files /dev/null and b/src/Architecture/images/Architecture/密码模式.png differ diff --git a/src/Architecture/images/Architecture/对称加密.png b/src/Architecture/images/Architecture/对称加密.png new file mode 100644 index 0000000..f32548e Binary files /dev/null and b/src/Architecture/images/Architecture/对称加密.png differ diff --git a/src/Architecture/images/Architecture/对账业务流程.png b/src/Architecture/images/Architecture/对账业务流程.png new file mode 100644 index 0000000..204d9ca Binary files /dev/null and b/src/Architecture/images/Architecture/对账业务流程.png differ diff --git a/src/Architecture/images/Architecture/差集-每日新增好友数.png b/src/Architecture/images/Architecture/差集-每日新增好友数.png new file mode 100644 index 0000000..9e3d6ba Binary files /dev/null and b/src/Architecture/images/Architecture/差集-每日新增好友数.png differ diff --git a/src/Architecture/images/Architecture/平均值.png b/src/Architecture/images/Architecture/平均值.png new file mode 100644 index 0000000..187c25e Binary files /dev/null and b/src/Architecture/images/Architecture/平均值.png differ diff --git a/src/Architecture/images/Architecture/库存超卖-解决方案.jpg b/src/Architecture/images/Architecture/库存超卖-解决方案.jpg new file mode 100644 index 0000000..4127911 Binary files /dev/null and b/src/Architecture/images/Architecture/库存超卖-解决方案.jpg differ diff --git a/src/Architecture/images/Architecture/库存超卖-问题.png b/src/Architecture/images/Architecture/库存超卖-问题.png new file mode 100644 index 0000000..ff8acaf Binary files /dev/null and b/src/Architecture/images/Architecture/库存超卖-问题.png differ diff --git a/src/Architecture/images/Architecture/库存超卖.png b/src/Architecture/images/Architecture/库存超卖.png new file mode 100644 index 0000000..667b989 Binary files /dev/null and b/src/Architecture/images/Architecture/库存超卖.png differ diff --git a/src/Architecture/images/Architecture/康威定律-单块应用.jpg b/src/Architecture/images/Architecture/康威定律-单块应用.jpg new file mode 100644 index 0000000..5214857 Binary files /dev/null and b/src/Architecture/images/Architecture/康威定律-单块应用.jpg differ diff --git a/src/Architecture/images/Architecture/康威定律-微服务解决方案.jpg b/src/Architecture/images/Architecture/康威定律-微服务解决方案.jpg new file mode 100644 index 0000000..afe58e9 Binary files /dev/null and b/src/Architecture/images/Architecture/康威定律-微服务解决方案.jpg differ diff --git a/src/Architecture/images/Architecture/微信支付-API秘钥.png b/src/Architecture/images/Architecture/微信支付-API秘钥.png new file mode 100644 index 0000000..2b2b904 Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-API秘钥.png differ diff --git a/src/Architecture/images/Architecture/微信支付-JS接口安全域名.png b/src/Architecture/images/Architecture/微信支付-JS接口安全域名.png new file mode 100644 index 0000000..829418e Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-JS接口安全域名.png differ diff --git a/src/Architecture/images/Architecture/微信支付-产品大全.png b/src/Architecture/images/Architecture/微信支付-产品大全.png new file mode 100644 index 0000000..ba942ef Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-产品大全.png differ diff --git a/src/Architecture/images/Architecture/微信支付-公众号.png b/src/Architecture/images/Architecture/微信支付-公众号.png new file mode 100644 index 0000000..245e5fc Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-公众号.png differ diff --git a/src/Architecture/images/Architecture/微信支付-开发配置.png b/src/Architecture/images/Architecture/微信支付-开发配置.png new file mode 100644 index 0000000..6d40dec Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-开发配置.png differ diff --git a/src/Architecture/images/Architecture/微信支付-微信商户平台.png b/src/Architecture/images/Architecture/微信支付-微信商户平台.png new file mode 100644 index 0000000..d3ba1d2 Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-微信商户平台.png differ diff --git a/src/Architecture/images/Architecture/微信支付-支付流程.png b/src/Architecture/images/Architecture/微信支付-支付流程.png new file mode 100644 index 0000000..c74d547 Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-支付流程.png differ diff --git a/src/Architecture/images/Architecture/微信支付-支付状态查询.png b/src/Architecture/images/Architecture/微信支付-支付状态查询.png new file mode 100644 index 0000000..a8446b5 Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-支付状态查询.png differ diff --git a/src/Architecture/images/Architecture/微信支付-新增授权.png b/src/Architecture/images/Architecture/微信支付-新增授权.png new file mode 100644 index 0000000..f739b6b Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-新增授权.png differ diff --git a/src/Architecture/images/Architecture/微信支付-服务器配置.png b/src/Architecture/images/Architecture/微信支付-服务器配置.png new file mode 100644 index 0000000..b927d2c Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-服务器配置.png differ diff --git a/src/Architecture/images/Architecture/微信支付-白名单配置.png b/src/Architecture/images/Architecture/微信支付-白名单配置.png new file mode 100644 index 0000000..9bfbd6f Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-白名单配置.png differ diff --git a/src/Architecture/images/Architecture/微信支付-绑定商户.png b/src/Architecture/images/Architecture/微信支付-绑定商户.png new file mode 100644 index 0000000..c2c258f Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-绑定商户.png differ diff --git a/src/Architecture/images/Architecture/微信支付-设置API秘钥.png b/src/Architecture/images/Architecture/微信支付-设置API秘钥.png new file mode 100644 index 0000000..f980ffb Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付-设置API秘钥.png differ diff --git a/src/Architecture/images/Architecture/微信支付最佳实践.png b/src/Architecture/images/Architecture/微信支付最佳实践.png new file mode 100644 index 0000000..8f73d86 Binary files /dev/null and b/src/Architecture/images/Architecture/微信支付最佳实践.png differ diff --git a/src/Architecture/images/Architecture/微服务-API网关-定义.jpg b/src/Architecture/images/Architecture/微服务-API网关-定义.jpg new file mode 100644 index 0000000..691b0aa Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-API网关-定义.jpg differ diff --git a/src/Architecture/images/Architecture/微服务-API网关-架构.jpg b/src/Architecture/images/Architecture/微服务-API网关-架构.jpg new file mode 100644 index 0000000..925c8d1 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-API网关-架构.jpg differ diff --git a/src/Architecture/images/Architecture/微服务-API网关-案例.jpg b/src/Architecture/images/Architecture/微服务-API网关-案例.jpg new file mode 100644 index 0000000..096e9e3 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-API网关-案例.jpg differ diff --git a/src/Architecture/images/Architecture/微服务-API网关.png b/src/Architecture/images/Architecture/微服务-API网关.png new file mode 100644 index 0000000..acd0117 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-API网关.png differ diff --git a/src/Architecture/images/Architecture/微服务-BFF.png b/src/Architecture/images/Architecture/微服务-BFF.png new file mode 100644 index 0000000..4a31d83 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-BFF.png differ diff --git a/src/Architecture/images/Architecture/微服务-Saga.png b/src/Architecture/images/Architecture/微服务-Saga.png new file mode 100644 index 0000000..4a31d83 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-Saga.png differ diff --git a/src/Architecture/images/Architecture/微服务-Strangler.png b/src/Architecture/images/Architecture/微服务-Strangler.png new file mode 100644 index 0000000..01d894d Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-Strangler.png differ diff --git a/src/Architecture/images/Architecture/微服务-事件源.png b/src/Architecture/images/Architecture/微服务-事件源.png new file mode 100644 index 0000000..42511ab Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-事件源.png differ diff --git a/src/Architecture/images/Architecture/微服务-断路器.png b/src/Architecture/images/Architecture/微服务-断路器.png new file mode 100644 index 0000000..e0447fc Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-断路器.png differ diff --git a/src/Architecture/images/Architecture/微服务-独享数据库.png b/src/Architecture/images/Architecture/微服务-独享数据库.png new file mode 100644 index 0000000..79135f6 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-独享数据库.png differ diff --git a/src/Architecture/images/Architecture/微服务-简单CQRS.png b/src/Architecture/images/Architecture/微服务-简单CQRS.png new file mode 100644 index 0000000..b6c2c78 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-简单CQRS.png differ diff --git a/src/Architecture/images/Architecture/微服务-聚合服务.jpg b/src/Architecture/images/Architecture/微服务-聚合服务.jpg new file mode 100644 index 0000000..ed90777 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-聚合服务.jpg differ diff --git a/src/Architecture/images/Architecture/微服务-高级CQRS.png b/src/Architecture/images/Architecture/微服务-高级CQRS.png new file mode 100644 index 0000000..1c1883d Binary files /dev/null and b/src/Architecture/images/Architecture/微服务-高级CQRS.png differ diff --git a/src/Architecture/images/Architecture/微服务分层.jpg b/src/Architecture/images/Architecture/微服务分层.jpg new file mode 100644 index 0000000..4a55950 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务分层.jpg differ diff --git a/src/Architecture/images/Architecture/微服务分层监控.jpg b/src/Architecture/images/Architecture/微服务分层监控.jpg new file mode 100644 index 0000000..7f45700 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务分层监控.jpg differ diff --git a/src/Architecture/images/Architecture/微服务利弊.jpg b/src/Architecture/images/Architecture/微服务利弊.jpg new file mode 100644 index 0000000..97fda1a Binary files /dev/null and b/src/Architecture/images/Architecture/微服务利弊.jpg differ diff --git a/src/Architecture/images/Architecture/微服务定义.jpg b/src/Architecture/images/Architecture/微服务定义.jpg new file mode 100644 index 0000000..eb6903a Binary files /dev/null and b/src/Architecture/images/Architecture/微服务定义.jpg differ diff --git a/src/Architecture/images/Architecture/微服务技术架构体系.jpg b/src/Architecture/images/Architecture/微服务技术架构体系.jpg new file mode 100644 index 0000000..7c9d32e Binary files /dev/null and b/src/Architecture/images/Architecture/微服务技术架构体系.jpg differ diff --git a/src/Architecture/images/Architecture/微服务架构.png b/src/Architecture/images/Architecture/微服务架构.png new file mode 100644 index 0000000..8f43f9f Binary files /dev/null and b/src/Architecture/images/Architecture/微服务架构.png differ diff --git a/src/Architecture/images/Architecture/微服务治理.jpg b/src/Architecture/images/Architecture/微服务治理.jpg new file mode 100644 index 0000000..bc9f234 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务治理.jpg differ diff --git a/src/Architecture/images/Architecture/微服务监控点.jpg b/src/Architecture/images/Architecture/微服务监控点.jpg new file mode 100644 index 0000000..79a3b97 Binary files /dev/null and b/src/Architecture/images/Architecture/微服务监控点.jpg differ diff --git a/src/Architecture/images/Architecture/截断方式.png b/src/Architecture/images/Architecture/截断方式.png new file mode 100644 index 0000000..bd509ad Binary files /dev/null and b/src/Architecture/images/Architecture/截断方式.png differ diff --git a/src/Architecture/images/Architecture/找回密码流程.png b/src/Architecture/images/Architecture/找回密码流程.png new file mode 100644 index 0000000..b15ae58 Binary files /dev/null and b/src/Architecture/images/Architecture/找回密码流程.png differ diff --git a/src/Architecture/images/Architecture/授权码模式.png b/src/Architecture/images/Architecture/授权码模式.png new file mode 100644 index 0000000..d99956b Binary files /dev/null and b/src/Architecture/images/Architecture/授权码模式.png differ diff --git a/src/Architecture/images/Architecture/授权码模式优缺点.png b/src/Architecture/images/Architecture/授权码模式优缺点.png new file mode 100644 index 0000000..2054771 Binary files /dev/null and b/src/Architecture/images/Architecture/授权码模式优缺点.png differ diff --git a/src/Architecture/images/Architecture/支付掉单-定时任务补偿.jpg b/src/Architecture/images/Architecture/支付掉单-定时任务补偿.jpg new file mode 100644 index 0000000..61b2c1c Binary files /dev/null and b/src/Architecture/images/Architecture/支付掉单-定时任务补偿.jpg differ diff --git a/src/Architecture/images/Architecture/支付掉单-延迟消息补偿方案.jpg b/src/Architecture/images/Architecture/支付掉单-延迟消息补偿方案.jpg new file mode 100644 index 0000000..66934c0 Binary files /dev/null and b/src/Architecture/images/Architecture/支付掉单-延迟消息补偿方案.jpg differ diff --git a/src/Architecture/images/Architecture/支付系统异常处理-内部掉单.jpg b/src/Architecture/images/Architecture/支付系统异常处理-内部掉单.jpg new file mode 100644 index 0000000..ac1fad6 Binary files /dev/null and b/src/Architecture/images/Architecture/支付系统异常处理-内部掉单.jpg differ diff --git a/src/Architecture/images/Architecture/支付系统异常处理-定时查询.jpg b/src/Architecture/images/Architecture/支付系统异常处理-定时查询.jpg new file mode 100644 index 0000000..22c5874 Binary files /dev/null and b/src/Architecture/images/Architecture/支付系统异常处理-定时查询.jpg differ diff --git a/src/Architecture/images/Architecture/支付系统异常处理-携程.jpg b/src/Architecture/images/Architecture/支付系统异常处理-携程.jpg new file mode 100644 index 0000000..291fbda Binary files /dev/null and b/src/Architecture/images/Architecture/支付系统异常处理-携程.jpg differ diff --git a/src/Architecture/images/Architecture/支付系统异常处理-支付平台.jpg b/src/Architecture/images/Architecture/支付系统异常处理-支付平台.jpg new file mode 100644 index 0000000..d34377f Binary files /dev/null and b/src/Architecture/images/Architecture/支付系统异常处理-支付平台.jpg differ diff --git a/src/Architecture/images/Architecture/支付系统异常处理-支付异步通知.jpg b/src/Architecture/images/Architecture/支付系统异常处理-支付异步通知.jpg new file mode 100644 index 0000000..229444a Binary files /dev/null and b/src/Architecture/images/Architecture/支付系统异常处理-支付异步通知.jpg differ diff --git a/src/Architecture/images/Architecture/支付系统异常处理-支付订单渠道11.jpg b/src/Architecture/images/Architecture/支付系统异常处理-支付订单渠道11.jpg new file mode 100644 index 0000000..143edfe Binary files /dev/null and b/src/Architecture/images/Architecture/支付系统异常处理-支付订单渠道11.jpg differ diff --git a/src/Architecture/images/Architecture/支付系统异常处理-支付订单渠道1N.jpg b/src/Architecture/images/Architecture/支付系统异常处理-支付订单渠道1N.jpg new file mode 100644 index 0000000..11262e7 Binary files /dev/null and b/src/Architecture/images/Architecture/支付系统异常处理-支付订单渠道1N.jpg differ diff --git a/src/Architecture/images/Architecture/数据替换.png b/src/Architecture/images/Architecture/数据替换.png new file mode 100644 index 0000000..ba7db6f Binary files /dev/null and b/src/Architecture/images/Architecture/数据替换.png differ diff --git a/src/Architecture/images/Architecture/数据脱敏过程.png b/src/Architecture/images/Architecture/数据脱敏过程.png new file mode 100644 index 0000000..b7453f1 Binary files /dev/null and b/src/Architecture/images/Architecture/数据脱敏过程.png differ diff --git a/src/Architecture/images/Architecture/文件下载漏洞.jpg b/src/Architecture/images/Architecture/文件下载漏洞.jpg new file mode 100644 index 0000000..2fe360f Binary files /dev/null and b/src/Architecture/images/Architecture/文件下载漏洞.jpg differ diff --git a/src/Architecture/images/Architecture/服务注册于发现-动态扩容.png b/src/Architecture/images/Architecture/服务注册于发现-动态扩容.png new file mode 100644 index 0000000..19756d1 Binary files /dev/null and b/src/Architecture/images/Architecture/服务注册于发现-动态扩容.png differ diff --git a/src/Architecture/images/Architecture/服务网格ServiceMesh.png b/src/Architecture/images/Architecture/服务网格ServiceMesh.png new file mode 100644 index 0000000..e28e982 Binary files /dev/null and b/src/Architecture/images/Architecture/服务网格ServiceMesh.png differ diff --git a/src/Architecture/images/Architecture/模式一:传统集中式代理.png b/src/Architecture/images/Architecture/模式一:传统集中式代理.png new file mode 100644 index 0000000..c898f04 Binary files /dev/null and b/src/Architecture/images/Architecture/模式一:传统集中式代理.png differ diff --git a/src/Architecture/images/Architecture/模式三:主机独立进程代理.png b/src/Architecture/images/Architecture/模式三:主机独立进程代理.png new file mode 100644 index 0000000..ab3d267 Binary files /dev/null and b/src/Architecture/images/Architecture/模式三:主机独立进程代理.png differ diff --git a/src/Architecture/images/Architecture/模式二:客户端嵌入式代理.png b/src/Architecture/images/Architecture/模式二:客户端嵌入式代理.png new file mode 100644 index 0000000..63b09f8 Binary files /dev/null and b/src/Architecture/images/Architecture/模式二:客户端嵌入式代理.png differ diff --git a/src/Architecture/images/Architecture/消息队列丢失消息.png b/src/Architecture/images/Architecture/消息队列丢失消息.png new file mode 100644 index 0000000..3a0fdc1 Binary files /dev/null and b/src/Architecture/images/Architecture/消息队列丢失消息.png differ diff --git a/src/Architecture/images/Architecture/消费者丢失消息.png b/src/Architecture/images/Architecture/消费者丢失消息.png new file mode 100644 index 0000000..c18e8fb Binary files /dev/null and b/src/Architecture/images/Architecture/消费者丢失消息.png differ diff --git a/src/Architecture/images/Architecture/熔断.png b/src/Architecture/images/Architecture/熔断.png new file mode 100644 index 0000000..afe0624 Binary files /dev/null and b/src/Architecture/images/Architecture/熔断.png differ diff --git a/src/Architecture/images/Architecture/生产者存放消息的过程中丢失消息.jpg b/src/Architecture/images/Architecture/生产者存放消息的过程中丢失消息.jpg new file mode 100644 index 0000000..7997539 Binary files /dev/null and b/src/Architecture/images/Architecture/生产者存放消息的过程中丢失消息.jpg differ diff --git a/src/Architecture/images/Architecture/用户-权限.png b/src/Architecture/images/Architecture/用户-权限.png new file mode 100644 index 0000000..d16d68d Binary files /dev/null and b/src/Architecture/images/Architecture/用户-权限.png differ diff --git a/src/Architecture/images/Architecture/用户-权限Demo.png b/src/Architecture/images/Architecture/用户-权限Demo.png new file mode 100644 index 0000000..bf1f1df Binary files /dev/null and b/src/Architecture/images/Architecture/用户-权限Demo.png differ diff --git a/src/Architecture/images/Architecture/用户-角色-权限.png b/src/Architecture/images/Architecture/用户-角色-权限.png new file mode 100644 index 0000000..ef477b5 Binary files /dev/null and b/src/Architecture/images/Architecture/用户-角色-权限.png differ diff --git a/src/Architecture/images/Architecture/用户-角色-权限Demo用户管理.png b/src/Architecture/images/Architecture/用户-角色-权限Demo用户管理.png new file mode 100644 index 0000000..a26f031 Binary files /dev/null and b/src/Architecture/images/Architecture/用户-角色-权限Demo用户管理.png differ diff --git a/src/Architecture/images/Architecture/用户-角色-权限Demo角色管理.png b/src/Architecture/images/Architecture/用户-角色-权限Demo角色管理.png new file mode 100644 index 0000000..feb5487 Binary files /dev/null and b/src/Architecture/images/Architecture/用户-角色-权限Demo角色管理.png differ diff --git a/src/Architecture/images/Architecture/监控-发现故障的征兆.jpg b/src/Architecture/images/Architecture/监控-发现故障的征兆.jpg new file mode 100644 index 0000000..6edc82f Binary files /dev/null and b/src/Architecture/images/Architecture/监控-发现故障的征兆.jpg differ diff --git a/src/Architecture/images/Architecture/秒杀商品-Redis缓存.png b/src/Architecture/images/Architecture/秒杀商品-Redis缓存.png new file mode 100644 index 0000000..40359ab Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-Redis缓存.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-三个核心流程.png b/src/Architecture/images/Architecture/秒杀商品-三个核心流程.png new file mode 100644 index 0000000..4c09821 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-三个核心流程.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-下单的流程.png b/src/Architecture/images/Architecture/秒杀商品-下单的流程.png new file mode 100644 index 0000000..90199d8 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-下单的流程.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-加验证码.png b/src/Architecture/images/Architecture/秒杀商品-加验证码.png new file mode 100644 index 0000000..b2bff04 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-加验证码.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-动态秒杀页面.png b/src/Architecture/images/Architecture/秒杀商品-动态秒杀页面.png new file mode 100644 index 0000000..79dd187 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-动态秒杀页面.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-增加已支付.png b/src/Architecture/images/Architecture/秒杀商品-增加已支付.png new file mode 100644 index 0000000..99dd83c Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-增加已支付.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-大致流程.png b/src/Architecture/images/Architecture/秒杀商品-大致流程.png new file mode 100644 index 0000000..df328ee Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-大致流程.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-对同一IP限流.png b/src/Architecture/images/Architecture/秒杀商品-对同一IP限流.png new file mode 100644 index 0000000..d2b0e26 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-对同一IP限流.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-对同一用户限流.png b/src/Architecture/images/Architecture/秒杀商品-对同一用户限流.png new file mode 100644 index 0000000..f0af642 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-对同一用户限流.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-对接口限流.png b/src/Architecture/images/Architecture/秒杀商品-对接口限流.png new file mode 100644 index 0000000..20062e3 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-对接口限流.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-延迟消费.png b/src/Architecture/images/Architecture/秒杀商品-延迟消费.png new file mode 100644 index 0000000..9ae441e Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-延迟消费.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-正常用户请求.png b/src/Architecture/images/Architecture/秒杀商品-正常用户请求.png new file mode 100644 index 0000000..c95f597 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-正常用户请求.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加Job.png b/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加Job.png new file mode 100644 index 0000000..8805aa1 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加Job.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加Job优化.png b/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加Job优化.png new file mode 100644 index 0000000..c52d4a8 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加Job优化.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加消息发送表.png b/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加消息发送表.png new file mode 100644 index 0000000..c525514 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加消息发送表.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加消息处理表.png b/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加消息处理表.png new file mode 100644 index 0000000..cedc8e8 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-消息丢失问题-加消息处理表.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-瞬时高并发.png b/src/Architecture/images/Architecture/秒杀商品-瞬时高并发.png new file mode 100644 index 0000000..490762e Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-瞬时高并发.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-秒杀活动开始前.png b/src/Architecture/images/Architecture/秒杀商品-秒杀活动开始前.png new file mode 100644 index 0000000..c527444 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-秒杀活动开始前.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-秒杀活动开始后.png b/src/Architecture/images/Architecture/秒杀商品-秒杀活动开始后.png new file mode 100644 index 0000000..efc79a4 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-秒杀活动开始后.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-缓存击穿.png b/src/Architecture/images/Architecture/秒杀商品-缓存击穿.png new file mode 100644 index 0000000..cd588f7 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-缓存击穿.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-缓存穿透-缓存空商品.png b/src/Architecture/images/Architecture/秒杀商品-缓存穿透-缓存空商品.png new file mode 100644 index 0000000..ec0a3da Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-缓存穿透-缓存空商品.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-缓存穿透.png b/src/Architecture/images/Architecture/秒杀商品-缓存穿透.png new file mode 100644 index 0000000..0161e85 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-缓存穿透.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-读多写少.png b/src/Architecture/images/Architecture/秒杀商品-读多写少.png new file mode 100644 index 0000000..03b8a6d Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-读多写少.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-静态秒杀页面.png b/src/Architecture/images/Architecture/秒杀商品-静态秒杀页面.png new file mode 100644 index 0000000..1dd1aea Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-静态秒杀页面.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-静态秒杀页面CDN.png b/src/Architecture/images/Architecture/秒杀商品-静态秒杀页面CDN.png new file mode 100644 index 0000000..e1471ea Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-静态秒杀页面CDN.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-非法用户请求.png b/src/Architecture/images/Architecture/秒杀商品-非法用户请求.png new file mode 100644 index 0000000..5be5016 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-非法用户请求.png differ diff --git a/src/Architecture/images/Architecture/秒杀商品-预扣库存主要流程.png b/src/Architecture/images/Architecture/秒杀商品-预扣库存主要流程.png new file mode 100644 index 0000000..b7abc6d Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀商品-预扣库存主要流程.png differ diff --git a/src/Architecture/images/Architecture/秒杀系统.png b/src/Architecture/images/Architecture/秒杀系统.png new file mode 100644 index 0000000..99f8a81 Binary files /dev/null and b/src/Architecture/images/Architecture/秒杀系统.png differ diff --git a/src/Architecture/images/Architecture/简化模式.png b/src/Architecture/images/Architecture/简化模式.png new file mode 100644 index 0000000..9652f6d Binary files /dev/null and b/src/Architecture/images/Architecture/简化模式.png differ diff --git a/src/Architecture/images/Architecture/简化模式优缺点.png b/src/Architecture/images/Architecture/简化模式优缺点.png new file mode 100644 index 0000000..4661453 Binary files /dev/null and b/src/Architecture/images/Architecture/简化模式优缺点.png differ diff --git a/src/Architecture/images/Architecture/组织-用户-角色-权限.png b/src/Architecture/images/Architecture/组织-用户-角色-权限.png new file mode 100644 index 0000000..00b8485 Binary files /dev/null and b/src/Architecture/images/Architecture/组织-用户-角色-权限.png differ diff --git a/src/Architecture/images/Architecture/组织-用户-角色-权限数据范围.png b/src/Architecture/images/Architecture/组织-用户-角色-权限数据范围.png new file mode 100644 index 0000000..fd599ae Binary files /dev/null and b/src/Architecture/images/Architecture/组织-用户-角色-权限数据范围.png differ diff --git a/src/Architecture/images/Architecture/网关-权限控制,服务治理.png b/src/Architecture/images/Architecture/网关-权限控制,服务治理.png new file mode 100644 index 0000000..b6caf2d Binary files /dev/null and b/src/Architecture/images/Architecture/网关-权限控制,服务治理.png differ diff --git a/src/Architecture/images/Architecture/聚合服务.jpg b/src/Architecture/images/Architecture/聚合服务.jpg new file mode 100644 index 0000000..555dac3 Binary files /dev/null and b/src/Architecture/images/Architecture/聚合服务.jpg differ diff --git a/src/Architecture/images/Architecture/订单上下游关系.jpg b/src/Architecture/images/Architecture/订单上下游关系.jpg new file mode 100644 index 0000000..2280255 Binary files /dev/null and b/src/Architecture/images/Architecture/订单上下游关系.jpg differ diff --git a/src/Architecture/images/Architecture/订单业务架构.jpg b/src/Architecture/images/Architecture/订单业务架构.jpg new file mode 100644 index 0000000..28447b8 Binary files /dev/null and b/src/Architecture/images/Architecture/订单业务架构.jpg differ diff --git a/src/Architecture/images/Architecture/订单服务-异步处理.png b/src/Architecture/images/Architecture/订单服务-异步处理.png new file mode 100644 index 0000000..c83422a Binary files /dev/null and b/src/Architecture/images/Architecture/订单服务-异步处理.png differ diff --git a/src/Architecture/images/Architecture/订单服务-服务解耦.jpg b/src/Architecture/images/Architecture/订单服务-服务解耦.jpg new file mode 100644 index 0000000..95e294f Binary files /dev/null and b/src/Architecture/images/Architecture/订单服务-服务解耦.jpg differ diff --git a/src/Architecture/images/Architecture/订单服务-流量控制.jpg b/src/Architecture/images/Architecture/订单服务-流量控制.jpg new file mode 100644 index 0000000..fcc08b0 Binary files /dev/null and b/src/Architecture/images/Architecture/订单服务-流量控制.jpg differ diff --git a/src/Architecture/images/Architecture/订单流程.png b/src/Architecture/images/Architecture/订单流程.png new file mode 100644 index 0000000..25b477b Binary files /dev/null and b/src/Architecture/images/Architecture/订单流程.png differ diff --git a/src/Architecture/images/Architecture/订单系统.jpg b/src/Architecture/images/Architecture/订单系统.jpg new file mode 100644 index 0000000..262592f Binary files /dev/null and b/src/Architecture/images/Architecture/订单系统.jpg differ diff --git a/src/Architecture/images/Architecture/订单详细信息.png b/src/Architecture/images/Architecture/订单详细信息.png new file mode 100644 index 0000000..a4c7d94 Binary files /dev/null and b/src/Architecture/images/Architecture/订单详细信息.png differ diff --git a/src/Architecture/images/Architecture/订单逆向流程.jpg b/src/Architecture/images/Architecture/订单逆向流程.jpg new file mode 100644 index 0000000..2c97976 Binary files /dev/null and b/src/Architecture/images/Architecture/订单逆向流程.jpg differ diff --git a/src/Architecture/images/Architecture/调用行为记录.jpg b/src/Architecture/images/Architecture/调用行为记录.jpg new file mode 100644 index 0000000..47cc4f7 Binary files /dev/null and b/src/Architecture/images/Architecture/调用行为记录.jpg differ diff --git a/src/Architecture/images/Architecture/调用行为还原.jpg b/src/Architecture/images/Architecture/调用行为还原.jpg new file mode 100644 index 0000000..9a4aef1 Binary files /dev/null and b/src/Architecture/images/Architecture/调用行为还原.jpg differ diff --git a/src/Architecture/images/Architecture/账号注册流程.png b/src/Architecture/images/Architecture/账号注册流程.png new file mode 100644 index 0000000..5e97b41 Binary files /dev/null and b/src/Architecture/images/Architecture/账号注册流程.png differ diff --git a/src/Architecture/images/Architecture/账号登录流程.png b/src/Architecture/images/Architecture/账号登录流程.png new file mode 100644 index 0000000..6cf3f71 Binary files /dev/null and b/src/Architecture/images/Architecture/账号登录流程.png differ diff --git a/src/Architecture/images/Architecture/软件架构模式.png b/src/Architecture/images/Architecture/软件架构模式.png new file mode 100644 index 0000000..90777bd Binary files /dev/null and b/src/Architecture/images/Architecture/软件架构模式.png differ diff --git a/src/Architecture/images/Architecture/进程内Lb模式.jpg b/src/Architecture/images/Architecture/进程内Lb模式.jpg new file mode 100644 index 0000000..6f04d08 Binary files /dev/null and b/src/Architecture/images/Architecture/进程内Lb模式.jpg differ diff --git a/src/Architecture/images/Architecture/配置中心.jpg b/src/Architecture/images/Architecture/配置中心.jpg new file mode 100644 index 0000000..16930d4 Binary files /dev/null and b/src/Architecture/images/Architecture/配置中心.jpg differ diff --git a/src/Architecture/images/Architecture/重复支付-下单流程.png b/src/Architecture/images/Architecture/重复支付-下单流程.png new file mode 100644 index 0000000..d895dd5 Binary files /dev/null and b/src/Architecture/images/Architecture/重复支付-下单流程.png differ diff --git a/src/Architecture/images/Architecture/限流.png b/src/Architecture/images/Architecture/限流.png new file mode 100644 index 0000000..fe8ed50 Binary files /dev/null and b/src/Architecture/images/Architecture/限流.png differ diff --git a/src/Architecture/images/Architecture/随机值.png b/src/Architecture/images/Architecture/随机值.png new file mode 100644 index 0000000..27a0648 Binary files /dev/null and b/src/Architecture/images/Architecture/随机值.png differ diff --git a/src/Architecture/images/Architecture/隐藏方式.png b/src/Architecture/images/Architecture/隐藏方式.png new file mode 100644 index 0000000..5370719 Binary files /dev/null and b/src/Architecture/images/Architecture/隐藏方式.png differ diff --git a/src/BigData/1.md b/src/BigData/1.md new file mode 100644 index 0000000..c418e7f --- /dev/null +++ b/src/BigData/1.md @@ -0,0 +1 @@ +![Hadoop生态架构图](images/BigData/Hadoop生态架构图.png) \ No newline at end of file diff --git a/src/BigData/101.md b/src/BigData/101.md new file mode 100644 index 0000000..6f619b3 --- /dev/null +++ b/src/BigData/101.md @@ -0,0 +1,73 @@ +Flume是一个分布式、可靠、和高可用的海量日志采集、聚合和传输的系统。支持在日志系统中定制各类数据发送方,用于收集数据。同时,Flume提供对数据进行简单处理,并写到各种数据接受方(比如文本、HDFS、Hbase等)的能力 。 + +### 应用架构 + +![Flume复杂应用](images/BigData/Flume复杂应用.png)# + + + +### 安装使用 + +第一步:在apache-flume-1.7.0-bin\conf目录下创建一个example.conf配置文件。然后把官文档中的案例内容复制到example.conf文件中,如下内容: + +```properties +# example.conf: A single-node Flume configuration + +# Name the components on this agent +a1.sources = r1 +a1.sinks = k1 +a1.channels = c1 + +# Describe/configure the source +a1.sources.r1.type = netcat +a1.sources.r1.bind = localhost +a1.sources.r1.port = 44444 + +# Describe the sink +a1.sinks.k1.type = logger + +# Use a channel which buffers events in memory +a1.channels.c1.type = memory +a1.channels.c1.capacity = 1000 +a1.channels.c1.transactionCapacity = 100 + +# Bind the source and sink to the channel +a1.sources.r1.channels = c1 +a1.sinks.k1.channel = c1 +``` + +第二步:进入到解压flume目录中执行命令,文档中的执行命令如下: + +```shell +[root@mini3 apache-flume-1.7.0-bin]# bin/flume-ng agent --conf conf --conf-file conf/example.conf --name a1 -Dflume.root.logger=INFO,console +``` + +**参数的简要说明**:指明conf文件路径、指明conf文件、指定agent、指明log打印信息级别和位置。执行效果: + +```shell +Info: Including Hive libraries found via () for Hive access ++ exec /usr/local/jdk1.7.0_65/bin/java -Xmx20m -Dflume.root.logger=INFO,console -cp '/usr/local/apache-flume-1.7.0-bin/conf:/usr/local/apache-flume-1.7.0-bin/lib/*:/lib/*' -Djava.library.path= org.apache.flume.node.Application --conf-file example.conf --name a1 +...... +2018-01-31 18:14:45,870 (lifecycleSupervisor-1-4) [INFO - org.apache.flume.source.NetcatSource.start(NetcatSource.java:155)] Source starting +2018-01-31 18:14:45,894 (lifecycleSupervisor-1-4) [INFO - org.apache.flume.source.NetcatSource.start(NetcatSource.java:169)] Created serverSocket:sun.nio.ch.ServerSocketChannelImpl[/127.0.0.1:44444] +``` + +如上打印日志,启动成功。 + +第三步:通过telnet客户端进行测试。另开一个终端命令行:输入命令 + +```shell +telnet localhost 44444 +``` + +连接成功后即可进行模拟通信,即经过44444端口发送消息,让flume监听到。执行结果如下: + +![Flume-telnet](images/BigData/Flume-telnet.jpg) + +flume后台监听打印: + +```shell +2018-01-31 18:15:48,913 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{} body: 6E 69 68 61 6F 0D nihao. } +``` + +注:如果不能使用telnet,通过yum安装即可。 \ No newline at end of file diff --git a/src/BigData/102.md b/src/BigData/102.md new file mode 100644 index 0000000..1e5c3c4 --- /dev/null +++ b/src/BigData/102.md @@ -0,0 +1,550 @@ +Kafka是最初由Linkedin公司开发,是一个分布式、分区的、多副本的、多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常见可以用于web/nginx日志、访问日志,消息服务等等,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。主要应用场景是:日志收集系统和消息系统。Kafka主要设计目标如下: + +- 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问性能 +- 高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒100K条消息的传输 +- 支持Kafka Server间的消息分区,及分布式消费,同时保证每个partition内的消息顺序传输 +- 同时支持离线数据处理和实时数据处理 +- Scale out:支持在线水平扩展 + +消息传递模式:**点对点传递模式、发布-订阅模式**。大部分消息系统选用发布-订阅模式。**Kafka就是一种发布-订阅模式**。 + + + +### Kafka架构 + +![Kafka架构](images/BigData/Kafka架构.png) + +kafka支持消息持久化,消费端是主动拉取数据,消费状态和订阅关系由客户端负责维护,**消息消费完后,不会立即删除,会保留历史消息**。因此支持多订阅时,消息只会存储一份就可以。 + +- **broker**:kafka集群中包含一个或者多个服务实例(节点),这种服务实例被称为broker(一个broker就是一个节点/一个服务器) +- **topic**:每条发布到kafka集群的消息都属于某个类别,这个类别就叫做topic +- **partition**:partition是一个物理上的概念,每个topic包含一个或者多个partition +- **segment**:一个partition当中存在多个segment文件段,每个segment分为两部分,.log文件和 .index 文件,其中 .index 文件是索引文件,主要用于快速查询, .log 文件当中数据的偏移量位置 +- **producer**:消息的生产者,负责发布消息到 kafka 的 broker 中 +- **consumer**:消息的消费者,向 kafka 的 broker 中读取消息的客户端 +- **consumer group**:消费者组,每一个 consumer 属于一个特定的 consumer group(可以为每个consumer指定 groupName) +- **.log**:存放数据文件 +- **.index**:存放.log文件的索引数据 + + + +### Kafka优点 + +- **解耦** + + 在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。 + +- **冗余(副本)** + + 有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。 + +- **扩展性** + + 因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改变代码、不需要调节参数。扩展就像调大电力按钮一样简单。 + +- **灵活性&峰值处理能力** + + 在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。 + +- **可恢复性** + + 系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。 + +- **顺序保证** + + 在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。Kafka保证一个Partition内的消息的有序性。 + +- **缓冲** + + 在任何重要的系统中,都会有需要不同的处理时间的元素。例如,加载一张图片比应用过滤器花费更少的时间。消息队列通过一个缓冲层来帮助任务最高效率的执行———写入队列的处理会尽可能的快速。该缓冲有助于控制和优化数据流经过系统的速度。 + +- **异步通信** + + 很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。 + + + +### 主要组件 + +#### broker + +Kafka 服务器,负责消息存储和转发;一个 broker 就代表一个 kafka 节点。**一个 broker 可以包含多个 topic**。 + + + +#### topic(主题) + +- kafka将消息以topic为单位进行归类 +- topic特指kafka处理的消息源(feeds of messages)的不同分类 +- topic是一种分类或者发布的一些列记录的名义上的名字。kafka主题始终是支持多用户订阅的;也就是说,一 个主题可以有零个,一个或者多个消费者订阅写入的数据 +- 在kafka集群中,可以有无数的主题 +- 生产者和消费者消费数据一般以主题为单位。更细粒度可以到分区级别 + +kafka学习了数据库里面的设计,在里面设计了topic(主题),这个东西类似于关系型数据库的表 + +![kafka-topic](images/BigData/kafka-topic.jpg) + +此时我需要获取数据,那就直接监听TopicA即可。 + + + +#### partition(分区) + +kafka当中,topic是消息的归类,一个topic可以有多个分区(partition),每个分区保存部分topic的数据,所有的partition当中的数据全部合并起来,就是一个topic当中的所有的数据。一个broker服务下,可以创建多个分区,broker数与分区数没有关系; 在kafka中,每一个分区会有一个编号:编号从0开始。**每一个分区内的数据是有序的,但全局的数据不能保证是有序的。**(有序是指生产什么样顺序,消费时也是什么样的顺序) + +kafka还有一个概念叫Partition(分区),分区具体在服务器上面表现起初就是一个目录,一个主题下面有多个分区,这些分区会存储到不同的服务器上面,或者说,其实就是在不同的主机上建了不同的目录。这些分区主要的信息就存在了.log文件里面。跟数据库里面的分区差不多,是为了提高性能。 + +![kafka-partition](images/BigData/kafka-partition.jpg) + +至于为什么提高了性能,很简单,多个分区多个线程,多个线程并行处理肯定会比单线程好得多 + +Topic和partition像是HBASE里的table和region的概念,table只是一个逻辑上的概念,真正存储数据的是region,这些region会分布式地存储在各个服务器上面,对应于kafka,也是一样,**Topic也是逻辑概念**,而partition就是分布式存储单元。这个设计是保证了海量数据处理的基础。我们可以对比一下,如果HDFS没有block的设计,一个100T的文件也只能单独放在一个服务器上面,那就直接占满整个服务器了,引入block后,大文件可以分散存储在不同的服务器上。 + +注意: + +1.分区会有单点故障问题,所以我们会为每个分区设置副本数 + +2.分区的编号是从0开始的 + + + +topic 的分区,一个 topic 可以包含多个 partition,topic 消息保存在各个 partition 上;由于一个 topic 能被分到多个分区上,给 kafka 提供给了并行的处理能力,这也正是 kafka 高吞吐的原因之一。 + +partition 物理上由多个 segment 文件组成,每个 segment 大小相等,**顺序读写(这也是 kafka 比较快的原因之一,不需要随机写)**。每个 Segment 数据文件以该段中最小的 offset ,文件扩展名为.log。当查找 offset 的 Message 的时候,通过二分查找快找到 Message 所处于的 Segment 中。 + +![kafka-partition](images/BigData/kafka-partition.png) + + + +#### offset + +- 消息在日志中的位置,可以理解是消息在 partition 上的偏移量,也是代表该消息的**唯一序号**。 +- 同时也是主从之间的需要同步的信息 + +![kafka-offset](images/BigData/kafka-offset.png) + + + +#### producer(生产者) + +producer主要是用于生产消息,是kafka当中的消息生产者,生产的消息通过topic进行归类,保存到kafka的broker里面。往消息系统里面发送数据的就是生产者。 + +![kafka-producer](images/BigData/kafka-producer.jpg) + + + +#### consumer(消费者) + +consumer是kafka当中的消费者,主要用于消费kafka当中的数据,消费者一定是归属于某个消费组中的。从kafka里读取数据的就是消费者: + +![kafka-consumer](images/BigData/kafka-consume.jpg) + + + +#### consumer group(消费者组) + +消费者组由一个或者多个消费者组成,**同一个组中的消费者对于同一条消息只消费一次**。每个消费者都属于某个消费者组,如果不指定,那么所有的消费者都属于默认的组。每个消费者组都有一个ID,即group ID。组内的所有消费者协调在一起来消费一个订阅主题( topic)的所有分区(partition)。当然,**每个分区只能由同一个消费组内的一个消费者(consumer)来消费**,可以由不同的**消费组**来消费。partition数量决定了每个consumer group中并发消费者的最大数量。如下图: + +![consumer_group示例](images/BigData/consumer_group示例.png) + +如上面左图所示,如果只有两个分区,即使一个组内的消费者有4个,也会有两个空闲的。如上面右图所示,有4个分区,每个消费者消费一个分区,并发量达到最大4。在来看如下一幅图: + +![consumer_group示例2](images/BigData/consumer_group示例2.png) + +如上图所示,不同的消费者组消费同一个topic,这个topic有4个分区,分布在两个节点上。左边的 消费组1有两个消费者,每个消费者就要消费两个分区才能把消息完整的消费完,右边的 消费组2有四个消费者,每个消费者消费一个分区即可。 + + + +**总结下kafka中分区与消费组的关系**: + +消费组:由一个或者多个消费者组成,同一个组中的消费者对于同一条消息只消费一次。 + +某一个主题下的分区数,对于消费该主题的同一个消费组下的消费者数量,应该小于等于该主题下的分区数。 + +如:某一个主题有4个分区,那么消费组中的消费者应该小于等于4,而且最好与分区数成整数倍 1 2 4 这样。同一个分区下的数据,在同一时刻,不能同一个消费组的不同消费者消费。 + +总结:**分区数越多,同一时间可以有越多的消费者来进行消费,消费数据的速度就会越快,提高消费的性能**。 + + + +#### partition replicas(分区副本) + +kafka 中的分区副本如下图所示: + +![kafka分区副本](images/BigData/kafka分区副本.png) + +**副本数**(replication-factor):控制消息保存在几个broker(服务器)上,一般情况下副本数等于broker的个数。 + +一个broker服务下,不可以创建多个副本因子。**创建主题时,副本因子应该小于等于可用的broker数**。副本因子操作以分区为单位的。每个分区都有各自的主副本和从副本;主副本叫做leader,从副本叫做 follower(在有多个副本的情况下,kafka会为同一个分区下的所有分区,设定角色关系:一个leader和N个 follower),**处于同步状态的副本叫做in-sync-replicas(ISR)**。 + + + +#### segment文件 + +一个partition当中由多个segment文件组成,每个segment文件,包含两部分,一个是 .log 文件,另外一个是 .index 文件,其中 .log 文件包含了我们发送的数据存储,.index 文件,记录的是我们.log文件的数据索引值,便于我们加快数据查询速度。 + + + +#### message物理结构 + +生产者发送到kafka的每条消息,都被kafka包装成了一个message。message 的物理结构如下图所示: + +![message物理结构](images/BigData/message物理结构.png) + +所以生产者发送给kafka的消息并不是直接存储起来,而是经过kafka的包装,每条消息都是上图这个结构,只有最后一个字段才是真正生产者发送的消息数据。 + + + +#### zookeeper + +管理 kafka 集群,负责存储了集群 broker、topic、partition 等 meta 数据存储,同时也负责 broker 故障发现,partition leader 选举,负载均衡等功能。 + +![kafka-zookeeper](images/BigData/kafka-zookeeper.png) + + + +### 消息传递 + +#### 点对点消息传递模式 + +在点对点消息系统中,消息持久化到一个队列中。此时,将有一个或多个消费者消费队列中的数据。但是一条消息只能被消费一次。当一个消费者消费了队列中的某条数据之后,该条数据则从消息队列中删除。该模式即使有多个消费者同时消费数据,也能保证数据处理的顺序。这种架构描述示意图如下: + +![Kafka点对点消息传递模式](images/BigData/Kafka点对点消息传递模式.png) + +**生产者发送一条消息到queue,只有一个消费者能收到**。 + + + +#### 发布-订阅消息传递模式 + +在发布-订阅消息系统中,消息被持久化到一个topic中。与点对点消息系统不同的是,消费者可以订阅一个或多个topic,消费者可以消费该topic中所有的数据,同一条数据可以被多个消费者消费,数据被消费后不会立马删除。在发布-订阅消息系统中,消息的生产者称为发布者,消费者称为订阅者。该模式的示例图如下: + +![Kafka发布-订阅消息传递模式](images/BigData/Kafka发布-订阅消息传递模式.png) + +**发布者发送到topic的消息,只有订阅了topic的订阅者才会收到消息**。 + + + +### 服务治理 + +既然 Kafka 是分布式的发布/订阅系统,这样如果做的集群之间数据同步和一致性,kafka 是不是肯定不会丢消息呢?以及宕机的时候如果进行 Leader 选举呢? + + + +#### 数据同步 + +在 Kafka 中的 Partition 有一个 leader 与多个 follower,producer 往某个 Partition 中写入数据是,只会往 leader 中写入数据,然后数据才会被复制进其他的 Replica 中。而每一个 follower 可以理解成一个消费者,定期去 leader 去拉去消息。而只有数据同步了后,kafka 才会给生产者返回一个 ACK 告知消息已经存储落地了。 + + + +#### ISR + +在 Kafka 中,为了保证性能,Kafka 不会采用强一致性的方式来同步主从的数据。而是维护了一个:in-sync Replica 的列表,Leader 不需要等待所有 Follower 都完成同步,只要在 ISR 中的 Follower 完成数据同步就可以发送 ack 给生产者即可认为消息同步完成。同时如果发现 ISR 里面某一个 follower 落后太多的话,就会把它剔除。 + +具体流程如下: + +![Kafka服务治理-ISR-1](images/BigData/Kafka服务治理-ISR-1.png) + +![Kafka服务治理-ISR-2](images/BigData/Kafka服务治理-ISR-2.png) + +![Kafka服务治理-ISR-3](images/BigData/Kafka服务治理-ISR-3.png) + +![Kafka服务治理-ISR-4](images/BigData/Kafka服务治理-ISR-4.png) + +**上述的做法并无法保证 kafka 一定不丢消息。**虽然 Kafka 通过多副本机制中最大限度保证消息不会丢失,但是如果数据已经写入系统 page cache 中但是还没来得及刷入磁盘,此时突然机器宕机或者掉电,那消息自然而然的就会丢失。 + + + +#### Kafka故障恢复 + +![Kafka服务治理-故障恢复](images/BigData/Kafka服务治理-故障恢复.png) + +Kafka 通过 Zookeeper 连坐集群的管理,所以这里的选举机制采用的是 Zab(zookeeper 使用)。 + +- 生产者发生消息给 leader,这个时候 leader 完成数据存储,突然发生故障,没有给 producer 返回 ack +- 通过 ZK 选举,其中一个 follower 成为 leader,这个时候 producer 重新请求新的 leader,并存储数据 + + + +### 数据不丢失机制 + +#### 生产者生产数据不丢失 + +**发送消息方式** + +生产者发送给kafka数据,可以采用**同步方式**或**异步方式**: + +- **同步方式** + + 发送一批数据给kafka后,等待kafka返回结果: + + - 生产者等待10s,如果broker没有给出ack响应,就认为失败 + - 生产者重试3次,如果还没有响应,就报错 + +- **异步方式** + + 发送一批数据给kafka,只是提供一个回调函数: + + - 先将数据保存在生产者端的buffer中。buffer大小是2万条 + - 满足数据阈值或者数量阈值其中的一个条件就可以发送数据 + - 发送一批数据的大小是500条 + +注意:如果broker迟迟不给ack,而buffer又满了,开发者可以设置是否直接清空buffer中的数据。 + + + +**ack机制(确认机制)** + +生产者数据发送出去,需要服务端返回一个确认码,即ack响应码;ack的响应有三个状态值: + +- 0:生产者只负责发送数据,不关心数据是否丢失,丢失的数据,需要再次发送 + +- 1:partition的leader收到数据,不管follow是否同步完数据,响应的状态码为1 + +- -1:所有的从节点都收到数据,响应的状态码为-1 + +**注意**:如果broker端一直不返回ack状态,producer永远不知道是否成功;producer可以设置一个超时时间10s,超过时间认为失败。 + + + +#### broker中数据不丢失 + +在broker中,保证数据不丢失主要是通过副本因子(冗余),防止数据丢失。 + + + +#### 消费者消费数据不丢失 + +在消费者消费数据的时候,只要每个消费者记录好offset值即可,就能保证数据不丢失。也就是需要我们自己维护偏移量(offset),可保存在 Redis 中。 + + + +### 常见问题 + +**问题一:Kafka性能好在什么地方?** + +- **顺序写磁盘** + + 操作系统每次从磁盘读写数据的时候,需要先寻址,也就是先要找到数据在磁盘上的物理位置,然后再进行数据读写,如果是机械硬盘,寻址就需要较长的时间。 kafka的设计中,数据其实是存储在磁盘上面,一般来说,会把数据存储在内存上面性能才会好。但是kafka用的是顺序写,追加数据是追加到末尾,磁盘顺序写的性能极高,在磁盘个数一定,转数达到一定的情况下,基本和内存速度一致。随机写的话是在文件的某个位置修改数据,性能会较低。 + +- **Page Cache** + + Kafka 在 OS 系统方面使用了 Page Cache 而不是我们平常所用的 Buffer。Page Cache 其实不陌生,也不是什么新鲜事物 + + ![Kafka-PageCache](images/BigData/Kafka-PageCache.png) + + 我们在 linux 上查看内存的时候,经常可以看到 buff/cache,两者都是用来加速 IO 读写用的,而 cache 是作用于读,也就是说,磁盘的内容可以读到 cache 里面这样,应用程序读磁盘就非常快;而 buff 是作用于写,我们开发写磁盘都是,一般如果写入一个 buff 里面再 flush 就非常快。而 kafka 正是把这两者发挥了极致: + + Kafka 虽然是 scala 写的,但是依旧在 Java 的虚拟机上运行,尽管如此,它尽量避开了 JVM 的限制,它利用了 Page cache 来存储,这样躲开了数据在 JVM 因为 GC 而发生的 STD。另一方面也是 Page Cache 使得它实现了零拷贝,具体下面会讲。 + +- **零拷贝** + + 先来看看非零拷贝的情况: + + ![kafka-零拷贝](images/BigData/kafka-零拷贝.jpg) + + 可以看到数据的拷贝从内存拷贝到kafka服务进程那块,又拷贝到socket缓存那块,整个过程耗费的时间比较高,kafka利用了Linux的sendFile技术(NIO),省去了进程切换和一次数据拷贝,让性能变得更好。 + + ![kafka-零拷贝优化](images/BigData/kafka-零拷贝优化.jpg) + + **传统的一次应用程请求数据的过程** + + ![kafka-传统数据请求](images/BigData/kafka-传统数据请求.png) + + 这里大致可以发传统的方式发生了 4 次拷贝,2 次 DMA 和 2 次 CPU,而 CPU 发生了 4 次的切换。(DMA 简单理解就是,在进行 I/O 设备和内存的数据传输的时候,数据搬运的工作全部交给 DMA 控制器,而 CPU 不再参与任何与数据搬运相关的事情) + + **零拷贝的方式** + + ![kafka-零拷贝的方式](images/BigData/kafka-零拷贝的方式.png) + + 通过优化我们可以发现,CPU 只发生了 2 次的上下文切换和 3 次数据拷贝。(linux 系统提供了系统事故调用函数“ sendfile()”,这样系统调用,可以直接把内核缓冲区里的数据拷贝到 socket 缓冲区里,不再拷贝到用户态) + +- **分区分段** + + 我们上面也介绍过了,kafka 采取了分区的模式,而每一个分区又对应到一个物理分段,而查找的时候可以根据二分查找快速定位。这样不仅提供了数据读的查询效率,也提供了并行操作的方式。 + +- **数据压缩** + + Kafka 对数据提供了:Gzip 和 Snappy 压缩协议等压缩协议,对消息结构体进行了压缩,一方面减少了带宽,也减少了数据传输的消耗。 + + + +**问题二:日志如何分段存储?** + +Kafka规定了一个分区内的.log文件最大为1G,做这个限制目的是为了方便把.log加载到内存去操作 + +```shell +00000000000000000000.index +00000000000000000000.log +00000000000000000000.timeindex + +00000000000005367851.index +00000000000005367851.log +00000000000005367851.timeindex + +00000000000009936472.index +00000000000009936472.log +00000000000009936472.timeindex +``` + +这个9936472之类的数字,就是代表了这个日志段文件里包含的起始offset,也就说明这个分区里至少都写入了接近1000万条数据了。Kafka broker有一个参数,log.segment.bytes,限定了每个日志段文件的大小,最大就是1GB,一个日志段文件满了,就自动开一个新的日志段文件来写入,避免单个文件过大,影响文件的读写性能,这个过程叫做log rolling,正在被写入的那个日志段文件,叫做active log segment。如果大家有看前面的两篇有关于HDFS的文章时,就会发现NameNode的edits log也会做出限制,所以这些框架都是会考虑到这些问题。 + + + +**问题三:Kafka如何网络设计?** + +kafka的网络设计和Kafka的调优有关,这也是为什么它能支持高并发的原因: + +![Kafka的网络设计](images/BigData/Kafka的网络设计.jpg) + +首先客户端发送请求全部会先发送给一个Acceptor,broker里面会存在3个线程(默认是3个),这3个线程都是叫做processor,Acceptor不会对客户端的请求做任何的处理,直接封装成一个个socketChannel发送给这些processor形成一个队列,发送的方式是轮询,就是先给第一个processor发送,然后再给第二个,第三个,然后又回到第一个。消费者线程去消费这些socketChannel时,会获取一个个request请求,这些request请求中就会伴随着数据。 + +线程池里面默认有8个线程,这些线程是用来处理request的,解析请求,如果request是写请求,就写到磁盘里。读的话返回结果。 processor会从response中读取响应数据,然后再返回给客户端。这就是Kafka的网络三层架构。 + +所以如果我们需要对kafka进行增强调优,增加processor并增加线程池里面的处理线程,就可以达到效果。request和response那一块部分其实就是起到了一个缓存的效果,是考虑到processor们生成请求太快,线程数不够不能及时处理的问题。所以这就是一个加强版的reactor网络线程模型。 + + + +### 安装Kafka + +第一步:安装 JDK + +第二步:安装 Zookeeper + +第三步:下载Kafka:https://www.apache.org/dyn/closer.cgi?path=/kafka/2.8.0/kafka-2.8.0-src.tgz + +第四步:安装Kafka: + +```javascript + tar -xzvf kafka_2.12-2.0.0.tgz +``` + +第五步:配置环境变量: + +```javascript + export ZK=/usr/local/src/apache-zookeeper-3.7.0-bin + export PATH=$PATH:$ZK/bin + export KAFKA=/usr/local/src/kafka + export PATH=$PATH:$KAFKA/bin +``` + +第六步:启动Kafka: + +```javascript + nohup kafka-server-start.sh 自己的配置文件路径/server.properties & +``` + +![启动Kafka日志](images/BigData/启动Kafka日志.png) + + + +### Spring Boot案例 + +第一步:添加依赖 + +```xml + + org.springframework.kafka + spring-kafka + +``` + +第二步:配置文件application.yml + +```yaml +kafka: + bootstrap: + servers: localhost:9092 + topic: + user: topic-user + group: + id: group-user +``` + +第三步:创建kafka生产者类 + +```java +/** + * Kafka消息生产类 + */ +@Log +@Component +public class KafkaProducer { + @Resource + private KafkaTemplate kafkaTemplate; + @Value("${kafka.topic.user}") + private String topicUser;// topic名称 + /** + * 发送用户消息 + * @param user 用户信息 + */ + public void sendUserMessage(User user) { + GsonBuilder builder = new GsonBuilder(); + builder.setPrettyPrinting(); + builder.setDateFormat("yyyy-MM-dd HH:mm:ss"); + String message = builder.create().toJson(user); + kafkaTemplate.send(topicUser, message); + log.info("\n生产消息至Kafka\n" + message); + } +} + +/** + * 测试控制器 + */ +@RestController +@RequestMapping("/kafka") +public class KafkaController { + @Autowired + private User user; + @Autowired + private KafkaProducer kafkaProducer; + @RequestMapping("/createMsg") + public void createMsg() { + kafkaProducer.sendUserMessage(user); + } +} +``` + +第四步:创建kafka消费者类,并通过控制器调用 + +```java +public class KafkaConsumerDemo { + + @Value("${kafka.topic.user}") + private String topicUser;// topic名称 + + public void consume() { + Properties props = new Properties(); + // 必须设置的属性 + props.put("bootstrap.servers", "127.0.0.1:9092"); + props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); + props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); + props.put("group.id", "group-user"); + // 自动提交offset,每1s提交一次(提交后的消息不再消费,避免重复消费问题) + props.put("enable.auto.commit", "true");// 自动提交offset:true【PS:只有当消息提交后,此消息才不会被再次接受到】 + props.put("auto.commit.interval.ms", "1000");// 自动提交的间隔 + /** + * 消费方式配置 + * earliest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费 + * latest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据 + * none: topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常 + */ + props.put("auto.offset.reset", "earliest "); + // 拉取消息设置,每次poll操作最多拉取多少条消息(一般不主动设置,取默认的就好) + props.put("max.poll.records", "100 "); + + //根据上面的配置,新增消费者对象 + KafkaConsumer consumer = new KafkaConsumer<>(props); + // 订阅topic-user topic + consumer.subscribe(Collections.singletonList(topicUser)); + while (true) { + // 从服务器开始拉取数据 + ConsumerRecords records = consumer.poll(Duration.ofMillis(100)); + records.forEach(record -> { + System.out.printf("成功消费消息:topic = %s ,partition = %d,offset = %d, key = %s, value = %s%n", + record.topic(), record.partition(), record.offset(), record.key(), record.value()); + }); + } + } +} +``` \ No newline at end of file diff --git a/src/BigData/201.md b/src/BigData/201.md new file mode 100644 index 0000000..324cf04 --- /dev/null +++ b/src/BigData/201.md @@ -0,0 +1,173 @@ +HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建大规模结构化的存储集群。HBase的目标是存储并处理大型数据,具体来说是仅需使用普通的硬件配置,就能够处理由成千上万的行和列所组成的大型数据。与MapReduce的离线批处理计算框架不同,HBase是一个可以随机访问的存储和检索数据平台,弥补了HDFS不能随机访问数据的缺陷,适合实时性要求不是非常高的业务场景。HBase存储的都是Byte数组,它不介意数据类型,允许动态、灵活的数据模型。 + +![HBase](images/BigData/HBase.jpg) + +上图描述了Hadoop 2.0生态系统中的各层结构。其中HBase位于结构化存储层,HDFS为HBase提供了高可靠性的底层存储支持, MapReduce为HBase提供了高性能的批处理能力,Zookeeper为HBase提供了稳定服务和failover机制,Pig和Hive为HBase提供了进行数据统计处理的高层语言支持,Sqoop则为HBase提供了便捷的RDBMS数据导入功能,使业务数据从传统数据库向HBase迁移变的非常方便。 + + + +HBase是基于列存储、构建在HDFS上的分布式存储系统,其主要功能是存储海量结构化数据。HBase构建在HDFS之上,因此HBase也是通过增加廉价的PC机提高系统运行和存储的能力。HBase中存储的表有如下特点: + +- 大表:一个表可以有数十亿行,上百万列 +- 无模式:每行都有一个可排序主键和任意多的列,列可以根据需要动态的增加,同一张表中不同的行可以有截然不同的列 +- 面向列:面向列(族)的存储和权限控制,列(族)独立检索 +- 稀疏:对于空(null)的列,并不占用存储空间,表可以设计的非常稀疏 +- 数据多版本:每个单元中的数据可以有多个版本,默认情况下版本号自动分配,是单元格插入时的时间戳 +- 数据类型单一:Hbase中的数据都是字符串,没有类型 + + + +### 基本架构 + +![HBase基本架构](images/BigData/HBase基本架构.jpg) + +由上图可知,hbase包括Clinet、HMaster、HRegionServer、ZooKeeper组件: + +- Client + + Client主要通过ZooKeeper与Hbaser和HRegionServer通信,对于管理操作:client向master发起请求,对于数据读写操作:client向regionserver发起请求 + +- ZooKeeper + + zk负责存储root表的地址,也负责存储当前服务的master地址,regsion server也会将自身的信息注册到zk中,以便master能够感知region server的状态,zk也会协调active master,也就是可以提供一个选举master leader,也会协调各个region server的容灾流程 + +- HMaster + + master可以启动多个master,master主要负责table和region的管理工作,响应用户对表的CRUD操作,管理region server的负载均衡,调整region 的分布和分配,当region server停机后,负责对失效的regionn进行迁移操作 + +- HRegionServer + + region server主要负责响应用户的IO请求,并把IO请求转换为读写HDFS的操作 + + + +### 使用场景 + +**适用场景** + +- 存在高并发读写 +- 表结构的列族经常需要调整 +- 存储结构化或半结构化数据 +- 高并发的key-value存储 +- key随机写入,有序存储 +- 针对每个key保存一个固定大小的集合 多版本 + + + +**不适用场景** + +- 由于hbase只能提供行锁,它对分布式事务支持不好 +- 对于查询操作中的join、group by 性能很差 +- 查询如果不使用row-key,性能会很差,因为此时会进行全表扫描,建立二级索引或多级索引需要同时维护一张索引表 +- 高并发的随机读支持有限 + + + +### SpringBoot案例 + +**第一步:引入相关依赖** + +```xml + + org.springframework.data + spring-data-hadoop-hbase + 2.5.0.RELEASE + + + org.apache.hbase + hbase-client + 1.1.2 + + + org.springframework.data + spring-data-hadoop + 2.5.0.RELEASE + +``` + +**第二步:增加配置** + +官方提供的方式是通过xml方式,简单改写后如下: + +```java +@Configuration +public class HBaseConfiguration { + + @Value("${hbase.zookeeper.quorum}") + private String zookeeperQuorum; + + @Value("${hbase.zookeeper.property.clientPort}") + private String clientPort; + + @Value("${zookeeper.znode.parent}") + private String znodeParent; + + @Bean + public HbaseTemplate hbaseTemplate() { + org.apache.hadoop.conf.Configuration conf = new org.apache.hadoop.conf.Configuration(); + conf.set("hbase.zookeeper.quorum", zookeeperQuorum); + conf.set("hbase.zookeeper.property.clientPort", clientPort); + conf.set("zookeeper.znode.parent", znodeParent); + return new HbaseTemplate(conf); + } +} +``` + +application.yml + +```yml +hbase: + zookeeper: + quorum: hbase1.xxx.org,hbase2.xxx.org,hbase3.xxx.org + property: + clientPort: 2181 + +zookeeper: + znode: + parent: /hbase +``` + +**第三步:在service类注入HBaseTemplate** + +```java +@Service +@Slf4j +public class HBaseService { + + @Autowired + private HbaseTemplate hbaseTemplate; + + public List getRowKeyAndColumn(String tableName, String startRowkey, String stopRowkey, String column, String qualifier) { + FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL); + if (StringUtils.isNotBlank(column)) { + log.debug("{}", column); + filterList.addFilter(new FamilyFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes(column)))); + } + if (StringUtils.isNotBlank(qualifier)) { + log.debug("{}", qualifier); + filterList.addFilter(new QualifierFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes(qualifier)))); + } + Scan scan = new Scan(); + if (filterList.getFilters().size() > 0) { + scan.setFilter(filterList); + } + scan.setStartRow(Bytes.toBytes(startRowkey)); + scan.setStopRow(Bytes.toBytes(stopRowkey)); + + return hbaseTemplate.find(tableName, scan, (rowMapper, rowNum) -> rowMapper); + } + + public List getListRowkeyData(String tableName, List rowKeys, String familyColumn, String column) { + return rowKeys.stream().map(rk -> { + if (StringUtils.isNotBlank(familyColumn)) { + if (StringUtils.isNotBlank(column)) { + return hbaseTemplate.get(tableName, rk, familyColumn, column, (rowMapper, rowNum) -> rowMapper); + } else { + return hbaseTemplate.get(tableName, rk, familyColumn, (rowMapper, rowNum) -> rowMapper); + } + } + return hbaseTemplate.get(tableName, rk, (rowMapper, rowNum) -> rowMapper); + }).collect(Collectors.toList()); + } +} +``` \ No newline at end of file diff --git a/src/BigData/202.md b/src/BigData/202.md new file mode 100644 index 0000000..be45b43 --- /dev/null +++ b/src/BigData/202.md @@ -0,0 +1,270 @@ +随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。HDFS只是分布式文件管理系统中的一种。 + +HDFS(Hadoop Distributed File System),它是一个文件系统,用于存储文件,通过目录树来定位文件;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。 + +**使用场景**:适合一次写入,多次读出的场景,且不支持文件的修改。适合用来做数据分析,并不适合用来做网盘应用。 + + + +**HDFS优缺点** + +- 优点 + - 高容错性 + - 数据自动保存多个副本。它通过增加副本的形式,提高容错性 + - 某一个副本丢失以后,它可以自动恢复 + - 适合处理大数据 + - 可构建在廉价机器上,通过多副本机制,提高可靠性 + +- 缺点 + - 不适合低延时数据访问,比如毫秒级的存储数据 + - 无法高效的对大量小文件进行存储 + - 不支持并发写入、文件随机修改 + + + +### HDFS组成架构 + +![HDFS组成架构1](images/BigData/HDFS组成架构1.png) + +![HDFS组成架构2](images/BigData/HDFS组成架构2.png) + + + +**HDFS文件块大小** + +HDFS 中的文件在物理上是分块存储(Block),块的大小可以通过配置参数(dfs.blocksize)来规定,默认大小在Hadoop2.x 版本中是 128M,老版本中是 64M。 + +如果寻址时间为 100ms,即查找目标 Block 的时间是 100ms。寻址时间与传输时间的比例为 100 : 1为最佳状态,因此传输时间为 1ms。目前磁盘的传输速率大概在 100MB/s,取个整大概就是 128MB。 + + + +**客户端操作** + +```java +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.*; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.net.URI; + +public class HdfsClient { + + FileSystem fileSystem = null; + + @Before + public void init() { + try { + fileSystem = FileSystem.get(URI.create("hdfs://hadoop102:9000"), new Configuration(), "djm"); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * 上传文件 + */ + @Test + public void put() { + try { + fileSystem.copyFromLocalFile(new Path("C:\\Users\\Administrator\\Desktop\\Hadoop 入门.md"), new Path("/")); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 下载文件 + */ + @Test + public void download() { + try { + // useRawLocalFileSystem表示是否开启文件校验 + fileSystem.copyToLocalFile(false, new Path("/Hadoop 入门.md"), + new Path("C:\\Users\\Administrator\\Desktop\\Hadoop 入门1.md"), true); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 删除文件 + */ + @Test + public void delete() { + try { + // recursive表示是否递归删除 + fileSystem.delete(new Path("/Hadoop 入门.md"), true); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 文件重命名 + */ + @Test + public void rename() { + try { + fileSystem.rename(new Path("/tmp"), new Path("/temp")); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 查看文件信息 + */ + @Test + public void ls() { + try { + RemoteIterator listFiles = fileSystem.listFiles(new Path("/etc"), true); + while (listFiles.hasNext()) { + LocatedFileStatus fileStatus = listFiles.next(); + if (fileStatus.isFile()) { + // 仅输出文件信息 + System.out.print(fileStatus.getPath().getName() + " " + + fileStatus.getLen() + " " + fileStatus.getPermission() + " " + fileStatus.getGroup() + " "); + // 获取文件块信息 + BlockLocation[] blockLocations = fileStatus.getBlockLocations(); + for (BlockLocation blockLocation : blockLocations) { + // 获取节点信息 + String[] hosts = blockLocation.getHosts(); + for (String host : hosts) { + System.out.print(host + " "); + } + } + System.out.println(); + } + + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + @After + public void exit() { + try { + fileSystem.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} +``` + + + +### HDFS写数据流程 + +**剖析文件写入** + +![HDFS剖析文件写入](images/BigData/HDFS剖析文件写入.png) + +- 客户端通过 Distributed FileSystem 模块向 NameNode 请求上传文件,NameNode 检查目标文件是否已存在,父目录是否存在 +- NameNode 返回是否可以上传 +- 客户端请求第一个 Block 上传到哪几个 DataNode +- NameNode 返回三个节点,分别是 dn1、dn2、dn3 +- 客户端通过 FSDataOutputStream 模块请求 dn1 上传数据,dn1 收到请求会继续调用 dn2,然后 dn2 调用 dn3,将这个通信管道建立完成 +- 按倒序逐级响应客户端 +- 客户端开始往 dn1 上传第一个 Block(先从磁盘读取数据放到一个本地内存缓存),以 Packet 为单位,dn1 收到一个Packet 就会传给 dn2,dn2 传给 dn3;dn1 每传一个 packet 会放入一个应答队列等待应答 +- 当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器 + + + +**网络拓扑-节点距离计算** + +在HDFS写数据过程中,NameNode会选择距离待上传数据最近距离的DataNode接收数据。那么这个最近距离怎么计算呢? + +![HDFS网络拓扑-节点距离计算](images/BigData/HDFS网络拓扑-节点距离计算.png) + + + +**机架感知** + +![HDFS机架感知](images/BigData/HDFS机架感知.png) + + + +### HDFS读数据流程 + +![HDFS读数据流程](images/BigData/HDFS读数据流程.png) + +- 客户端通过 Distributed FileSystem 向 NameNode 请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址 +- 根据就近原则挑选一台 DataNode,请求读取数据 +- DataNode 开始传输数据给客户端 +- 客户端以 Packet 为单位接收,先在本地缓存,然后写入目标文件 + + + +### DataNode + +**DataNode工作机制** + +![HDFSDataNode工作机制](images/BigData/HDFSDataNode工作机制.png) + +- 一个数据块在 DataNode 上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳 +- DataNode 启动后向 NameNode 注册,通过后,周期性(1小时)的向 NameNode 上报所有的块信息 +- 心跳是每 3 秒一次,心跳返回结果带有 NameNode 给该 DataNode 的命令如复制块数据到另一台机器,或删除某个数据块,如果超过 10 分钟没有收到某个 DataNode 的心跳,则认为该节点不可用 +- 集群运行中可以安全加入和退出一些机器 + + + +**数据完整性** + +![HDFS数据完整性](images/BigData/HDFS数据完整性.png) + +- 当 DataNode 读取 Block 的时候,它会计算 CheckSum +- 如果计算后的 CheckSum,与 Block 创建时值不一样,说明 Block 已经损坏 +- Client 读取其他 DataNode 上的 Block +- 在其文件创建后周期验证 + + + +### 掉线时限参数设置 + +![HDFS掉线时限参数设置](images/BigData/HDFS掉线时限参数设置.png) + +[hdfs-site.xml] + +```xml + + dfs.namenode.heartbeat.recheck-interval + 300000 + 毫秒 + + + dfs.heartbeat.interval + 3 + +1.2.3.4.5.6.7.8.9.10. +``` + + + +### 服役新数据节点 + +将 hadoop102 上的 java、hadoop、profile 发送到新主机,source 一下 profile,直接启动即可加入集群。 + + + +### HDFS 2.X新特性 + +**集群间数据拷贝** + +采用 distcp 命令实现两个 Hadoop 集群之间的递归数据复制 + +```shell +[djm@hadoop102 hadoop-2.7.2]$ hadoop distcp hdfs://haoop102:9000/user/djm/hello.txt hdfs://hadoop103:9000/user/djm/hello.txt +``` + + + +**小文件存档** + +![HDFS小文件存档](images/BigData/HDFS小文件存档.png) \ No newline at end of file diff --git a/src/BigData/301.md b/src/BigData/301.md new file mode 100644 index 0000000..5da7fe8 --- /dev/null +++ b/src/BigData/301.md @@ -0,0 +1,3 @@ +在Storm中,需要先设计一个实时计算结构,我们称之为拓扑(topology)。之后,这个拓扑结构会被提交给集群,其中主节点(master node)负责给工作节点(worker node)分配代码,工作节点负责执行代码。在一个拓扑结构中,包含spout和bolt两种角色。数据在spouts之间传递,这些spouts将数据流以tuple元组的形式发送;而bolt则负责转换数据流。 + +![Apache-Storm](images/BigData/Apache-Storm.png) \ No newline at end of file diff --git a/src/BigData/302.md b/src/BigData/302.md new file mode 100644 index 0000000..07801f1 --- /dev/null +++ b/src/BigData/302.md @@ -0,0 +1,3 @@ +Spark Streaming,即核心Spark API的扩展,不像Storm那样一次处理一个数据流。相反,它在处理数据流之前,会按照时间间隔对数据流进行分段切分。Spark针对连续数据流的抽象,我们称为DStream(Discretized Stream)。 DStream是小批处理的RDD(弹性分布式数据集), RDD则是分布式数据集,可以通过任意函数和滑动数据窗口(窗口计算)进行转换,实现并行操作。 + +![Apache-Spark](images/BigData/Apache-Spark.png) \ No newline at end of file diff --git a/src/BigData/303.md b/src/BigData/303.md new file mode 100644 index 0000000..6c59437 --- /dev/null +++ b/src/BigData/303.md @@ -0,0 +1,530 @@ +Apache Flink是一个**框架**和**分布式处理引擎**,用于在**无界**和**有界**数据流上进行**有状态的计算**。Flink被设计为在所有常见的集群环境中运行,以内存中的速度和任何规模执行计算。 + +![Apache-Flink](images/BigData/Apache-Flink.png) + +针对流数据+批数据的计算框架。把批数据看作流数据的一种特例,延迟性较低(毫秒级),且能保证消息传输不丢失不重复。 + +Flink创造性地统一了流处理和批处理,作为流处理看待时输入数据流是无界的,而批处理被作为一种特殊的流处理,只是它的输入数据流被定义为有界的。Flink程序由Stream和Transformation这两个基本构建块组成,其中Stream是一个中间结果数据,而Transformation是一个操作,它对一个或多个输入Stream进行计算处理,输出一个或多个结果Stream。 + + + +### 处理无界和有界数据 + +数据可以作为无界流或有界流被处理: + +- **Unbounded streams**(无界流)有一个起点,但没有定义的终点。它们不会终止,而且会源源不断的提供数据。无边界的流必须被连续地处理,即事件达到后必须被立即处理。等待所有输入数据到达是不可能的,因为输入是无界的,并且在任何时间点都不会完成。处理无边界的数据通常要求以特定顺序(例如,事件发生的顺序)接收事件,以便能够推断出结果的完整性。 +- **Bounded streams**(有界流)有一个定义的开始和结束。在执行任何计算之前,可以通过摄取(提取)所有数据来处理有界流。处理有界流不需要有序摄取,因为有界数据集总是可以排序的。有界流的处理也称为批处理。 + +![处理无界和有界数据](images/BigData/处理无界和有界数据.png) + +**Apache Flink擅长处理无界和有界数据集**。对时间和状态的精确控制使Flink的运行时能够在无边界的流上运行任何类型的应用程序。有界流由专门为固定大小的数据集设计的算法和数据结构在内部处理,从而产生出色的性能。 + + + +### 分层API + +Flink提供了三层API。每个API在简洁性和表达性之间提供了不同的权衡,并且针对不同的使用场景 + +![Flink-分层API](images/BigData/Flink-分层API.png) + + + +### 应用场景 + +Apache Flink是开发和运行许多不同类型应用程序的最佳选择,因为它具有丰富的特性。Flink的特性包括支持流和批处理、复杂的状态管理、事件处理语义以及确保状态的一致性。此外,Flink可以部署在各种资源提供程序上,例如YARN、Apache Mesos和Kubernetes,也可以作为裸机硬件上的独立集群进行部署。配置为高可用性,Flink没有单点故障。Flink已经被证明可以扩展到数千个内核和TB级的应用程序状态,提供高吞吐量和低延迟,并支持世界上一些最苛刻的流处理应用程序。 + +下面是Flink支持的最常见的应用程序类型: + +- Event-driven Applications(事件驱动的应用程序) +- Data Analytics Applications(数据分析应用程序) +- Data Pipeline Applications(数据管道应用程序) + + + +#### Event-driven Applications + +Event-driven Applications(事件驱动的应用程序)。事件驱动的应用程序是一个有状态的应用程序,它从一个或多个事件流中获取事件,并通过触发计算、状态更新或外部操作对传入的事件作出反应。 + +事件驱动的应用程序基于有状态的流处理应用程序。在这种设计中,数据和计算被放在一起,从而可以进行本地(内存或磁盘)数据访问。通过定期将检查点写入远程持久存储,可以实现容错。下图描述了传统应用程序体系结构和事件驱动应用程序之间的区别。 + +![Event-driven-Applications](images/BigData/Event-driven-Applications.png) + +代替查询远程数据库,事件驱动的应用程序在本地访问其数据,从而在吞吐量和延迟方面获得更好的性能。可以定期异步地将检查点同步到远程持久存,而且支持增量同步。不仅如此,在分层架构中,多个应用程序共享同一个数据库是很常见的。因此,数据库的任何更改都需要协调,由于每个事件驱动的应用程序都负责自己的数据,因此更改数据表示或扩展应用程序所需的协调较少。 + +对于事件驱动的应用程序,Flink的突出特性是savepoint。保存点是一个一致的状态镜像,可以用作兼容应用程序的起点。给定一个保存点,就可以更新或调整应用程序的规模,或者可以启动应用程序的多个版本进行A/B测试。 + +典型的事件驱动的应用程序有: + +- 欺诈检测 +- 异常检测 +- 基于规则的提醒 +- 业务流程监控 +- Web应用(社交网络) + + + +#### Data Analytics Applications + +Data Analytics Applications(数据分析应用程序)。传统上的分析是作为批处理查询或应用程序对已记录事件的有限数据集执行的。为了将最新数据合并到分析结果中,必须将其添加到分析数据集中,然后重新运行查询或应用程序,结果被写入存储系统或作为报告发出。 + +有了复杂的流处理引擎,分析也可以以实时方式执行。流查询或应用程序不是读取有限的数据集,而是接收实时事件流,并在使用事件时不断地生成和更新结果。结果要么写入外部数据库,要么作为内部状态进行维护。Dashboard应用程序可以从外部数据库读取最新的结果,也可以直接查询应用程序的内部状态。 + +Apache Flink支持流以及批处理分析应用程序,如下图所示: + +![Data-Analytics-Applications](images/BigData/Data-Analytics-Applications.png) + +典型的数据分析应用程序有: + +- 电信网络质量监控 +- 产品更新分析及移动应用实验评估 +- 消费者技术中实时数据的特别分析 +- 大规模图分析 + + + +#### Data Pipeline Applications + +Data Pipeline Applications(数据管道应用程序)。提取-转换-加载(ETL)是在存储系统之间转换和移动数据的常用方法。通常,会定期触发ETL作业,以便将数据从事务性数据库系统复制到分析数据库或数据仓库。 + +数据管道的作用类似于ETL作业。它们转换和丰富数据,并可以将数据从一个存储系统移动到另一个存储系统。但是,它们以连续流模式运行,而不是周期性地触发。因此,它们能够从不断产生数据的源读取记录,并以低延迟将其移动到目的地。例如,数据管道可以监视文件系统目录中的新文件,并将它们的数据写入事件日志。另一个应用程序可能将事件流物化到数据库,或者增量地构建和完善搜索索引。 + +下图描述了周期性ETL作业和连续数据管道之间的差异: + +![Data-Pipeline-Applications](images/BigData/Data-Pipeline-Applications.png) + +与周期性ETL作业相比,连续数据管道的明显优势是减少了将数据移至其目的地的等待时间。此外,数据管道更通用,可用于更多场景,因为它们能够连续消费和产生数据。 + +典型的数据管道应用程序有: + +- 电商中实时搜索索引的建立 +- 电商中的持续ETL + + + +### 安装Flink + +https://flink.apache.org/downloads.html + +下载安装包,这里下载的是 flink-1.10.1-bin-scala_2.11.tgz + +安装参考 https://ci.apache.org/projects/flink/flink-docs-release-1.10/getting-started/tutorials/local_setup.html + +```shell +./bin/start-cluster.sh # Start Flink +``` + +![安装Flink1](images/BigData/安装Flink1.png) + +访问 http://localhost:8081 + +![安装Flink2](images/BigData/安装Flink2.png) + +运行 WordCount 示例 + +![安装Flink3](images/BigData/安装Flink3.png) + +![安装Flink4](images/BigData/安装Flink4.png) + +![安装Flink5](images/BigData/安装Flink5.png) + + + +### 商品实时推荐 + +基于Flink实现的商品实时推荐系统。flink统计商品热度,放入redis缓存,分析日志信息,将画像标签和实时记录放入Hbase。在用户发起推荐请求后,根据用户画像重排序热度榜,并结合协同过滤和标签两个推荐模块为新生成的榜单的每一个产品添加关联产品,最后返回新的用户列表。 + +#### 系统架构 + +![基于Flink商品实时推荐](images/BigData/基于Flink商品实时推荐.jpg) + +在日志数据模块(flink-2-hbase)中,又主要分为6个Flink任务: + +- **用户-产品浏览历史 -> 实现基于协同过滤的推荐逻辑** + + 通过Flink去记录用户浏览过这个类目下的哪些产品,为后面的基于Item的协同过滤做准备 实时的记录用户的评分到Hbase中,为后续离线处理做准备。数据存储在Hbase的p_history表 + +- **用户-兴趣 -> 实现基于上下文的推荐逻辑** + + 根据用户对同一个产品的操作计算兴趣度,计算规则通过操作间隔时间(如购物 - 浏览 < 100s)则判定为一次兴趣事件 通过Flink的ValueState实现,如果用户的操作Action=3(收藏),则清除这个产品的state,如果超过100s没有出现Action=3的事件,也会清除这个state。数据存储在Hbase的u_interest表 + +- **用户画像计算 -> 实现基于标签的推荐逻辑** + + v1.0按照三个维度去计算用户画像,分别是用户的颜色兴趣,用户的产地兴趣,和用户的风格兴趣.根据日志不断的修改用户画像的数据,记录在Hbase中。数据存储在Hbase的user表 + +- **产品画像记录 -> 实现基于标签的推荐逻辑** + + 用两个维度记录产品画像,一个是喜爱该产品的年龄段,另一个是性别。数据存储在Hbase的prod表 + +- **事实热度榜 -> 实现基于热度的推荐逻辑** + + 通过Flink时间窗口机制,统计当前时间的实时热度,并将数据缓存在Redis中。通过Flink的窗口机制计算实时热度,使用ListState保存一次热度榜。数据存储在redis中,按照时间戳存储list + +- **日志导入** + + 从Kafka接收的数据直接导入进Hbase事实表,保存完整的日志log,日志中包含了用户Id,用户操作的产品id,操作时间,行为(如购买,点击,推荐等)。数据按时间窗口统计数据大屏需要的数据,返回前段展示。数据存储在Hbase的con表 + + + +#### 推荐引擎逻辑 + +**基于热度的推荐逻辑** + +![基于热度的推荐逻辑](images/BigData/基于热度的推荐逻辑.jpg) + +​根据用户特征,重新排序热度榜,之后根据两种推荐算法计算得到的产品相关度评分,为每个热度榜中的产品推荐几个关联的产品。 + + + +**基于产品画像的产品相似度计算方法** + +基于产品画像的推荐逻辑依赖于产品画像和热度榜两个维度,产品画像有三个特征,包含color/country/style三个角度,通过计算用户对该类目产品的评分来过滤热度榜上的产品。 + +![基于产品画像的产品相似度计算方法](images/BigData/基于产品画像的产品相似度计算方法.jpg) + +在已经有产品画像的基础上,计算item与item之间的关联系,通过余弦相似度来计算两两之间的评分,最后在已有物品选中的情况下推荐关联性更高的产品。 + +| 相似度 | A | B | C | +| ------ | ---- | ---- | ---- | +| A | 1 | 0.7 | 0.2 | +| B | 0.7 | 1 | 0.6 | +| C | 0.2 | 0.6 | 1 | + + + +**基于协同过滤的产品相似度计算方法** + +根据产品用户表(Hbase) 去计算公式得到相似度评分: +![基于协同过滤的产品相似度计算方法.jpg](images/BigData/基于协同过滤的产品相似度计算方法.jpg) + + + +**前台推荐页面** + +当前推荐结果分为3列,分别是热度榜推荐,协同过滤推荐和产品画像推荐: +![前台推荐页面.jpg](images/BigData/前台推荐页面.jpg) + + + +### 实时计算TopN热榜 + +本案例将实现一个“实时热门商品”的需求,我们可以将“实时热门商品”翻译成程序员更好理解的需求:每隔5分钟输出最近一小时内点击量最多的前 N 个商品。将这个需求进行分解我们大概要做这么几件事情: + +- 抽取出业务时间戳,告诉 Flink 框架基于业务时间做窗口 +- 过滤出点击行为数据 +- 按一小时的窗口大小,每5分钟统计一次,做滑动窗口聚合(Sliding Window) +- 按每个窗口聚合,输出每个窗口中点击量前N名的商品 + + + +#### 数据准备 + +这里我们准备了一份淘宝用户行为数据集(来自[阿里云天池公开数据集](https://tianchi.aliyun.com/datalab/index.htm))。本数据集包含了淘宝上某一天随机一百万用户的所有行为(包括点击、购买、加购、收藏)。数据集的组织形式和MovieLens-20M类似,即数据集的每一行表示一条用户行为,由用户ID、商品ID、商品类目ID、行为类型和时间戳组成,并以逗号分隔。关于数据集中每一列的详细描述如下: + +| 列名称 | 说明 | +| :--------- | :------------------------------------------------- | +| 用户ID | 整数类型,加密后的用户ID | +| 商品ID | 整数类型,加密后的商品ID | +| 商品类目ID | 整数类型,加密后的商品所属类目ID | +| 行为类型 | 字符串,枚举类型,包括(‘pv’, ‘buy’, ‘cart’, ‘fav’) | +| 时间戳 | 行为发生的时间戳,单位秒 | + +你可以通过下面的命令下载数据集到项目的 `resources` 目录下: + +```shell +$ cd my-flink-project/src/main/resources +$ curl https://raw.githubusercontent.com/wuchong/my-flink-project/master/src/main/resources/UserBehavior.csv > UserBehavior.csv +``` + +这里是否使用 curl 命令下载数据并不重要,你也可以使用 wget 命令或者直接访问链接下载数据。关键是,**将数据文件保存到项目的 `resources` 目录下**,方便应用程序访问。 + + + +#### 编写程序 + + + +#### 创建模拟数据源 + +我们先创建一个 `UserBehavior` 的 POJO 类(所有成员变量声明成`public`便是POJO类),强类型化后能方便后续的处理。 + +```java +/** + * 用户行为数据结构 + **/ +public static class UserBehavior { + public long userId; // 用户ID + public long itemId; // 商品ID + public int categoryId; // 商品类目ID + public String behavior; // 用户行为, 包括("pv", "buy", "cart", "fav") + public long timestamp; // 行为发生的时间戳,单位秒 +} +``` + +接下来我们就可以创建一个 `PojoCsvInputFormat` 了, 这是一个读取 csv 文件并将每一行转成指定 POJO +类型(在我们案例中是 `UserBehavior`)的输入器。 + +```java +// UserBehavior.csv 的本地文件路径 +URL fileUrl = HotItems2.class.getClassLoader().getResource("UserBehavior.csv"); +Path filePath = Path.fromLocalFile(new File(fileUrl.toURI())); +// 抽取 UserBehavior 的 TypeInformation,是一个 PojoTypeInfo +PojoTypeInfo pojoType = (PojoTypeInfo) TypeExtractor.createTypeInfo(UserBehavior.class); +// 由于 Java 反射抽取出的字段顺序是不确定的,需要显式指定下文件中字段的顺序 +String[] fieldOrder = new String[]{"userId", "itemId", "categoryId", "behavior", "timestamp"}; +// 创建 PojoCsvInputFormat +PojoCsvInputFormat csvInput = new PojoCsvInputFormat<>(filePath, pojoType, fieldOrder); +``` + +下一步我们用 `PojoCsvInputFormat` 创建输入源。 + +```java +DataStream dataSource = env.createInput(csvInput, pojoType); +``` + +这就创建了一个 `UserBehavior` 类型的 `DataStream`。 + + + +#### EventTime与Watermark + +当我们说“统计过去一小时内点击量”,这里的“一小时”是指什么呢? 在 Flink 中它可以是指 ProcessingTime ,也可以是 EventTime,由用户决定。 + +- **ProcessingTime**:**事件被处理的时间**。也就是由机器的系统时间来决定 +- **EventTime**:**事件发生的时间**。一般就是数据本身携带的时间 + +在本案例中,我们需要统计业务时间上的每小时的点击量,所以要基于 EventTime 来处理。那么如果让 Flink 按照我们想要的业务时间来处理呢?这里主要有两件事情要做: + +- 告诉 Flink 我们现在按照 EventTime 模式进行处理,Flink 默认使用 ProcessingTime 处理,所以我们要显式设置下。 + + ```java + env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime); + ``` + +- 指定如何获得业务时间,以及生成 Watermark。Watermark 是用来追踪业务事件的概念,可以理解成 EventTime 世界中的时钟,用来指示当前处理到什么时刻的数据了。由于我们的数据源的数据已经经过整理,没有乱序,即事件的时间戳是单调递增的,所以可以将每条数据的业务时间就当做 Watermark。这里我们用 `AscendingTimestampExtractor` 来实现时间戳的抽取和 Watermark 的生成。 + + + +**注意**:真实业务场景一般都是存在乱序的,所以一般使用 `BoundedOutOfOrdernessTimestampExtractor`。 + +```java +DataStream timedData = dataSource + .assignTimestampsAndWatermarks(new AscendingTimestampExtractor() { + @Override + public long extractAscendingTimestamp(UserBehavior userBehavior) { + // 原始数据单位秒,将其转成毫秒 + return userBehavior.timestamp * 1000; + } + }); +``` + +这样我们就得到了一个带有时间标记的数据流了,后面就能做一些窗口的操作。 + + + +#### 过滤出点击事件 + +在开始窗口操作之前,先回顾下需求“每隔5分钟输出过去一小时内点击量最多的前 N 个商品”。由于原始数据中存在点击、加购、购买、收藏各种行为的数据,但是我们只需要统计点击量,所以先使用 `FilterFunction` 将点击行为数据过滤出来。 + +```java +DataStream pvData = timedData + .filter(new FilterFunction() { + @Override + public boolean filter(UserBehavior userBehavior) throws Exception { + // 过滤出只有点击的数据 + return userBehavior.behavior.equals("pv"); + } + }); +``` + + + +#### 窗口统计点击量 + +由于要每隔5分钟统计一次最近一小时每个商品的点击量,所以窗口大小是一小时,每隔5分钟滑动一次。即分别要统计 [09:00, 10:00), [09:05, 10:05), [09:10, 10:10)… 等窗口的商品点击量。是一个常见的滑动窗口需求(Sliding Window)。 + +```java +DataStream windowedData = pvData + // 对商品进行分组 + .keyBy("itemId") + // 对每个商品做滑动窗口(1小时窗口,5分钟滑动一次) + .timeWindow(Time.minutes(60), Time.minutes(5)) + // 做增量的聚合操作,它能使用AggregateFunction提前聚合掉数据,减少 state 的存储压力 + .aggregate(new CountAgg(), new WindowResultFunction()); +``` + + + +**CountAgg** + +这里的`CountAgg`实现了`AggregateFunction`接口,功能是统计窗口中的条数,即遇到一条数据就加一。 + +```java +/** + * COUNT 统计的聚合函数实现,每出现一条记录加一 + **/ +public static class CountAgg implements AggregateFunction { + @Override + public Long createAccumulator() { + return 0L; + } + + @Override + public Long add(UserBehavior userBehavior, Long acc) { + return acc + 1; + } + + @Override + public Long getResult(Long acc) { + return acc; + } + + @Override + public Long merge(Long acc1, Long acc2) { + return acc1 + acc2; + } +} +``` + + + +**WindowFunction** + +`.aggregate(AggregateFunction af, WindowFunction wf)` 的第二个参数`WindowFunction`将每个 key每个窗口聚合后的结果带上其他信息进行输出。这里实现的`WindowResultFunction`将主键商品ID,窗口,点击量封装成了`ItemViewCount`进行输出。 + +```java +/** + * 用于输出窗口的结果 + **/ +public static class WindowResultFunction implements WindowFunction { + @Override + public void apply( + Tuple key, // 窗口的主键,即 itemId + TimeWindow window, // 窗口 + Iterable aggregateResult, // 聚合函数的结果,即 count 值 + Collector collector // 输出类型为 ItemViewCount + ) throws Exception { + Long itemId = ((Tuple1) key).f0; + Long count = aggregateResult.iterator().next(); + collector.collect(ItemViewCount.of(itemId, window.getEnd(), count)); + } +} + +/** + * 商品点击量(窗口操作的输出类型) + **/ +public static class ItemViewCount { + public long itemId; // 商品ID + public long windowEnd; // 窗口结束时间戳 + public long viewCount; // 商品的点击量 + public static ItemViewCount of(long itemId, long windowEnd, long viewCount) { + ItemViewCount result = new ItemViewCount(); + result.itemId = itemId; + result.windowEnd = windowEnd; + result.viewCount = viewCount; + return result; + } +} +``` + +现在我们得到了每个商品在每个窗口的点击量的数据流。 + + + +#### TopN计算最热门商品 + +为了统计每个窗口下最热门的商品,我们需要再次按窗口进行分组,这里根据`ItemViewCount`中的`windowEnd`进行`keyBy()`操作。然后使用 `ProcessFunction` 实现一个自定义的 TopN 函数 `TopNHotItems` 来计算点击量排名前3名的商品,并将排名结果格式化成字符串,便于后续输出。 + +```java +DataStream topItems = windowedData + .keyBy("windowEnd") + .process(new TopNHotItems(3)); // 求点击量前3名的商品 +``` + +`ProcessFunction` 是 Flink 提供的一个 low-level API,用于实现更高级的功能。它主要提供了定时器 timer 的功能(支持EventTime或ProcessingTime)。本案例中我们将利用 timer 来判断何时**收齐**了某个 window 下所有商品的点击量数据。由于 Watermark 的进度是全局的, + +在 `processElement` 方法中,每当收到一条数据(`ItemViewCount`),我们就注册一个 `windowEnd+1` 的定时器(Flink 框架会自动忽略同一时间的重复注册)。`windowEnd+1` 的定时器被触发时,意味着收到了`windowEnd+1`的 Watermark,即收齐了该`windowEnd`下的所有商品窗口统计值。我们在 `onTimer()` 中处理将收集的所有商品及点击量进行排序,选出 TopN,并将排名信息格式化成字符串后进行输出。 + +这里我们还使用了 `ListState` 来存储收到的每条 `ItemViewCount` 消息,保证在发生故障时,状态数据的不丢失和一致性。`ListState` 是 Flink 提供的类似 Java `List` 接口的 State API,它集成了框架的 checkpoint 机制,自动做到了 exactly-once 的语义保证。 + +```java +/** + * 求某个窗口中前 N 名的热门点击商品,key 为窗口时间戳,输出为 TopN 的结果字符串 + **/ +public static class TopNHotItems extends KeyedProcessFunction { + private final int topSize; + public TopNHotItems(int topSize) { + this.topSize = topSize; + } + + // 用于存储商品与点击数的状态,待收齐同一个窗口的数据后,再触发 TopN 计算 + private ListState itemState; + + @Override + public void open(Configuration parameters) throws Exception { + super.open(parameters); + // 状态的注册 + ListStateDescriptor itemsStateDesc = new ListStateDescriptor<>("itemState-state", ItemViewCount.class); + itemState = getRuntimeContext().getListState(itemsStateDesc); + } + + @Override + public void processElement(ItemViewCount input, Context context, Collector collector) throws Exception { + // 每条数据都保存到状态中 + itemState.add(input); + // 注册 windowEnd+1 的 EventTime Timer, 当触发时,说明收齐了属于windowEnd窗口的所有商品数据 + context.timerService().registerEventTimeTimer(input.windowEnd + 1); + } + + @Override + public void onTimer(long timestamp, OnTimerContext ctx, Collector out) throws Exception { + // 获取收到的所有商品点击量 + List allItems = new ArrayList<>(); + for (ItemViewCount item : itemState.get()) { + allItems.add(item); + } + // 提前清除状态中的数据,释放空间 + itemState.clear(); + // 按照点击量从大到小排序 + allItems.sort(new Comparator() { + @Override + public int compare(ItemViewCount o1, ItemViewCount o2) { + return (int) (o2.viewCount - o1.viewCount); + } + }); + + // 将排名信息格式化成 String, 便于打印 + StringBuilder result = new StringBuilder(); + result.append("====================================\n"); + result.append("时间: ").append(new Timestamp(timestamp-1)).append("\n"); + for (int i=0;iBigData + +Introduction:收纳技术相关的基础知识 `Hadoop`、`Flume`、`Kafka`、`HBase`、`Spark` 等总结! + +## 🚀点击左侧菜单栏开始吧! \ No newline at end of file diff --git a/src/BigData/_sidebar.md b/src/BigData/_sidebar.md new file mode 100644 index 0000000..68b04eb --- /dev/null +++ b/src/BigData/_sidebar.md @@ -0,0 +1,11 @@ +* [🏁 Hadoop](src/BigData/1 "Hadoop") +* 🏁 数据采集 + * [✍ Flume](src/BigData/101 "Flume") + * [✍ Kafka](src/BigData/102 "Kafka") +* 🏁 数据存储 + * [✍ HBase](src/BigData/201 "HBase") + * [✍ HDFS](src/BigData/202 "HDFS") +* 🏁 数据分析 + * [✍ Apache Storm](src/BigData/301 "Apache Storm") + * [✍ Apache Spark](src/BigData/302 "Apache Spark") + * [✍ Apache Flink](src/BigData/303 "Apache Flink") \ No newline at end of file diff --git a/src/BigData/images/BigData/Apache-Flink.png b/src/BigData/images/BigData/Apache-Flink.png new file mode 100644 index 0000000..b502d15 Binary files /dev/null and b/src/BigData/images/BigData/Apache-Flink.png differ diff --git a/src/BigData/images/BigData/Apache-Spark.png b/src/BigData/images/BigData/Apache-Spark.png new file mode 100644 index 0000000..2006684 Binary files /dev/null and b/src/BigData/images/BigData/Apache-Spark.png differ diff --git a/src/BigData/images/BigData/Apache-Storm.png b/src/BigData/images/BigData/Apache-Storm.png new file mode 100644 index 0000000..3edb0d6 Binary files /dev/null and b/src/BigData/images/BigData/Apache-Storm.png differ diff --git a/src/BigData/images/BigData/Data-Analytics-Applications.png b/src/BigData/images/BigData/Data-Analytics-Applications.png new file mode 100644 index 0000000..50882c2 Binary files /dev/null and b/src/BigData/images/BigData/Data-Analytics-Applications.png differ diff --git a/src/BigData/images/BigData/Data-Pipeline-Applications.png b/src/BigData/images/BigData/Data-Pipeline-Applications.png new file mode 100644 index 0000000..252df33 Binary files /dev/null and b/src/BigData/images/BigData/Data-Pipeline-Applications.png differ diff --git a/src/BigData/images/BigData/Event-driven-Applications.png b/src/BigData/images/BigData/Event-driven-Applications.png new file mode 100644 index 0000000..8b1d43a Binary files /dev/null and b/src/BigData/images/BigData/Event-driven-Applications.png differ diff --git a/src/BigData/images/BigData/Flink-分层API.png b/src/BigData/images/BigData/Flink-分层API.png new file mode 100644 index 0000000..4de2c94 Binary files /dev/null and b/src/BigData/images/BigData/Flink-分层API.png differ diff --git a/src/BigData/images/BigData/Flume-telnet.jpg b/src/BigData/images/BigData/Flume-telnet.jpg new file mode 100644 index 0000000..ff60c57 Binary files /dev/null and b/src/BigData/images/BigData/Flume-telnet.jpg differ diff --git a/src/BigData/images/BigData/Flume复杂应用.png b/src/BigData/images/BigData/Flume复杂应用.png new file mode 100644 index 0000000..85bdd95 Binary files /dev/null and b/src/BigData/images/BigData/Flume复杂应用.png differ diff --git a/src/BigData/images/BigData/HBase.jpg b/src/BigData/images/BigData/HBase.jpg new file mode 100644 index 0000000..a6dc493 Binary files /dev/null and b/src/BigData/images/BigData/HBase.jpg differ diff --git a/src/BigData/images/BigData/HBase基本架构.jpg b/src/BigData/images/BigData/HBase基本架构.jpg new file mode 100644 index 0000000..9f74d78 Binary files /dev/null and b/src/BigData/images/BigData/HBase基本架构.jpg differ diff --git a/src/BigData/images/BigData/HDFSDataNode工作机制.png b/src/BigData/images/BigData/HDFSDataNode工作机制.png new file mode 100644 index 0000000..bb05302 Binary files /dev/null and b/src/BigData/images/BigData/HDFSDataNode工作机制.png differ diff --git a/src/BigData/images/BigData/HDFS剖析文件写入.png b/src/BigData/images/BigData/HDFS剖析文件写入.png new file mode 100644 index 0000000..c17682e Binary files /dev/null and b/src/BigData/images/BigData/HDFS剖析文件写入.png differ diff --git a/src/BigData/images/BigData/HDFS小文件存档.png b/src/BigData/images/BigData/HDFS小文件存档.png new file mode 100644 index 0000000..539827e Binary files /dev/null and b/src/BigData/images/BigData/HDFS小文件存档.png differ diff --git a/src/BigData/images/BigData/HDFS掉线时限参数设置.png b/src/BigData/images/BigData/HDFS掉线时限参数设置.png new file mode 100644 index 0000000..c7ff2b3 Binary files /dev/null and b/src/BigData/images/BigData/HDFS掉线时限参数设置.png differ diff --git a/src/BigData/images/BigData/HDFS数据完整性.png b/src/BigData/images/BigData/HDFS数据完整性.png new file mode 100644 index 0000000..da5005d Binary files /dev/null and b/src/BigData/images/BigData/HDFS数据完整性.png differ diff --git a/src/BigData/images/BigData/HDFS机架感知.png b/src/BigData/images/BigData/HDFS机架感知.png new file mode 100644 index 0000000..e255002 Binary files /dev/null and b/src/BigData/images/BigData/HDFS机架感知.png differ diff --git a/src/BigData/images/BigData/HDFS组成架构1.png b/src/BigData/images/BigData/HDFS组成架构1.png new file mode 100644 index 0000000..61cc2d9 Binary files /dev/null and b/src/BigData/images/BigData/HDFS组成架构1.png differ diff --git a/src/BigData/images/BigData/HDFS组成架构2.png b/src/BigData/images/BigData/HDFS组成架构2.png new file mode 100644 index 0000000..105ff3b Binary files /dev/null and b/src/BigData/images/BigData/HDFS组成架构2.png differ diff --git a/src/BigData/images/BigData/HDFS网络拓扑-节点距离计算.png b/src/BigData/images/BigData/HDFS网络拓扑-节点距离计算.png new file mode 100644 index 0000000..89ae3e1 Binary files /dev/null and b/src/BigData/images/BigData/HDFS网络拓扑-节点距离计算.png differ diff --git a/src/BigData/images/BigData/HDFS读数据流程.png b/src/BigData/images/BigData/HDFS读数据流程.png new file mode 100644 index 0000000..1e44740 Binary files /dev/null and b/src/BigData/images/BigData/HDFS读数据流程.png differ diff --git a/src/BigData/images/BigData/Hadoop生态架构图.png b/src/BigData/images/BigData/Hadoop生态架构图.png new file mode 100644 index 0000000..b5b66f5 Binary files /dev/null and b/src/BigData/images/BigData/Hadoop生态架构图.png differ diff --git a/src/BigData/images/BigData/Kafka-PageCache.png b/src/BigData/images/BigData/Kafka-PageCache.png new file mode 100644 index 0000000..7de0534 Binary files /dev/null and b/src/BigData/images/BigData/Kafka-PageCache.png differ diff --git a/src/BigData/images/BigData/Kafka发布-订阅消息传递模式.png b/src/BigData/images/BigData/Kafka发布-订阅消息传递模式.png new file mode 100644 index 0000000..21108de Binary files /dev/null and b/src/BigData/images/BigData/Kafka发布-订阅消息传递模式.png differ diff --git a/src/BigData/images/BigData/Kafka服务治理-ISR-1.png b/src/BigData/images/BigData/Kafka服务治理-ISR-1.png new file mode 100644 index 0000000..bd3a194 Binary files /dev/null and b/src/BigData/images/BigData/Kafka服务治理-ISR-1.png differ diff --git a/src/BigData/images/BigData/Kafka服务治理-ISR-2.png b/src/BigData/images/BigData/Kafka服务治理-ISR-2.png new file mode 100644 index 0000000..3d8c3e9 Binary files /dev/null and b/src/BigData/images/BigData/Kafka服务治理-ISR-2.png differ diff --git a/src/BigData/images/BigData/Kafka服务治理-ISR-3.png b/src/BigData/images/BigData/Kafka服务治理-ISR-3.png new file mode 100644 index 0000000..7ecaa39 Binary files /dev/null and b/src/BigData/images/BigData/Kafka服务治理-ISR-3.png differ diff --git a/src/BigData/images/BigData/Kafka服务治理-ISR-4.png b/src/BigData/images/BigData/Kafka服务治理-ISR-4.png new file mode 100644 index 0000000..bc27079 Binary files /dev/null and b/src/BigData/images/BigData/Kafka服务治理-ISR-4.png differ diff --git a/src/BigData/images/BigData/Kafka服务治理-故障恢复.png b/src/BigData/images/BigData/Kafka服务治理-故障恢复.png new file mode 100644 index 0000000..a2b9354 Binary files /dev/null and b/src/BigData/images/BigData/Kafka服务治理-故障恢复.png differ diff --git a/src/BigData/images/BigData/Kafka架构.png b/src/BigData/images/BigData/Kafka架构.png new file mode 100644 index 0000000..8300f90 Binary files /dev/null and b/src/BigData/images/BigData/Kafka架构.png differ diff --git a/src/BigData/images/BigData/Kafka点对点消息传递模式.png b/src/BigData/images/BigData/Kafka点对点消息传递模式.png new file mode 100644 index 0000000..e6d1857 Binary files /dev/null and b/src/BigData/images/BigData/Kafka点对点消息传递模式.png differ diff --git a/src/BigData/images/BigData/Kafka的网络设计.jpg b/src/BigData/images/BigData/Kafka的网络设计.jpg new file mode 100644 index 0000000..1d1de84 Binary files /dev/null and b/src/BigData/images/BigData/Kafka的网络设计.jpg differ diff --git a/src/BigData/images/BigData/consumer_group示例.png b/src/BigData/images/BigData/consumer_group示例.png new file mode 100644 index 0000000..692c457 Binary files /dev/null and b/src/BigData/images/BigData/consumer_group示例.png differ diff --git a/src/BigData/images/BigData/consumer_group示例2.png b/src/BigData/images/BigData/consumer_group示例2.png new file mode 100644 index 0000000..fba9684 Binary files /dev/null and b/src/BigData/images/BigData/consumer_group示例2.png differ diff --git a/src/BigData/images/BigData/kafka-consume.jpg b/src/BigData/images/BigData/kafka-consume.jpg new file mode 100644 index 0000000..e8edfb3 Binary files /dev/null and b/src/BigData/images/BigData/kafka-consume.jpg differ diff --git a/src/BigData/images/BigData/kafka-offset.png b/src/BigData/images/BigData/kafka-offset.png new file mode 100644 index 0000000..1d48fd5 Binary files /dev/null and b/src/BigData/images/BigData/kafka-offset.png differ diff --git a/src/BigData/images/BigData/kafka-partition.jpg b/src/BigData/images/BigData/kafka-partition.jpg new file mode 100644 index 0000000..56983f2 Binary files /dev/null and b/src/BigData/images/BigData/kafka-partition.jpg differ diff --git a/src/BigData/images/BigData/kafka-partition.png b/src/BigData/images/BigData/kafka-partition.png new file mode 100644 index 0000000..411682d Binary files /dev/null and b/src/BigData/images/BigData/kafka-partition.png differ diff --git a/src/BigData/images/BigData/kafka-producer.jpg b/src/BigData/images/BigData/kafka-producer.jpg new file mode 100644 index 0000000..0a9fe79 Binary files /dev/null and b/src/BigData/images/BigData/kafka-producer.jpg differ diff --git a/src/BigData/images/BigData/kafka-topic.jpg b/src/BigData/images/BigData/kafka-topic.jpg new file mode 100644 index 0000000..918de2f Binary files /dev/null and b/src/BigData/images/BigData/kafka-topic.jpg differ diff --git a/src/BigData/images/BigData/kafka-zookeeper.png b/src/BigData/images/BigData/kafka-zookeeper.png new file mode 100644 index 0000000..6f5c093 Binary files /dev/null and b/src/BigData/images/BigData/kafka-zookeeper.png differ diff --git a/src/BigData/images/BigData/kafka-传统数据请求.png b/src/BigData/images/BigData/kafka-传统数据请求.png new file mode 100644 index 0000000..d46acbe Binary files /dev/null and b/src/BigData/images/BigData/kafka-传统数据请求.png differ diff --git a/src/BigData/images/BigData/kafka-零拷贝.jpg b/src/BigData/images/BigData/kafka-零拷贝.jpg new file mode 100644 index 0000000..a6f7b01 Binary files /dev/null and b/src/BigData/images/BigData/kafka-零拷贝.jpg differ diff --git a/src/BigData/images/BigData/kafka-零拷贝优化.jpg b/src/BigData/images/BigData/kafka-零拷贝优化.jpg new file mode 100644 index 0000000..c94d4fd Binary files /dev/null and b/src/BigData/images/BigData/kafka-零拷贝优化.jpg differ diff --git a/src/BigData/images/BigData/kafka-零拷贝的方式.png b/src/BigData/images/BigData/kafka-零拷贝的方式.png new file mode 100644 index 0000000..1319e8c Binary files /dev/null and b/src/BigData/images/BigData/kafka-零拷贝的方式.png differ diff --git a/src/BigData/images/BigData/kafka分区副本.png b/src/BigData/images/BigData/kafka分区副本.png new file mode 100644 index 0000000..d071b6a Binary files /dev/null and b/src/BigData/images/BigData/kafka分区副本.png differ diff --git a/src/BigData/images/BigData/message物理结构.png b/src/BigData/images/BigData/message物理结构.png new file mode 100644 index 0000000..f3db3a2 Binary files /dev/null and b/src/BigData/images/BigData/message物理结构.png differ diff --git a/src/BigData/images/BigData/前台推荐页面.jpg b/src/BigData/images/BigData/前台推荐页面.jpg new file mode 100644 index 0000000..0bbfe99 Binary files /dev/null and b/src/BigData/images/BigData/前台推荐页面.jpg differ diff --git a/src/BigData/images/BigData/启动Kafka日志.png b/src/BigData/images/BigData/启动Kafka日志.png new file mode 100644 index 0000000..6e12834 Binary files /dev/null and b/src/BigData/images/BigData/启动Kafka日志.png differ diff --git a/src/BigData/images/BigData/基于Flink商品实时推荐.jpg b/src/BigData/images/BigData/基于Flink商品实时推荐.jpg new file mode 100644 index 0000000..20b5cb0 Binary files /dev/null and b/src/BigData/images/BigData/基于Flink商品实时推荐.jpg differ diff --git a/src/BigData/images/BigData/基于产品画像的产品相似度计算方法.jpg b/src/BigData/images/BigData/基于产品画像的产品相似度计算方法.jpg new file mode 100644 index 0000000..28984b0 Binary files /dev/null and b/src/BigData/images/BigData/基于产品画像的产品相似度计算方法.jpg differ diff --git a/src/BigData/images/BigData/基于协同过滤的产品相似度计算方法.jpg b/src/BigData/images/BigData/基于协同过滤的产品相似度计算方法.jpg new file mode 100644 index 0000000..1f15c3a Binary files /dev/null and b/src/BigData/images/BigData/基于协同过滤的产品相似度计算方法.jpg differ diff --git a/src/BigData/images/BigData/基于热度的推荐逻辑.jpg b/src/BigData/images/BigData/基于热度的推荐逻辑.jpg new file mode 100644 index 0000000..6a54aaa Binary files /dev/null and b/src/BigData/images/BigData/基于热度的推荐逻辑.jpg differ diff --git a/src/BigData/images/BigData/处理无界和有界数据.png b/src/BigData/images/BigData/处理无界和有界数据.png new file mode 100644 index 0000000..29dfe8a Binary files /dev/null and b/src/BigData/images/BigData/处理无界和有界数据.png differ diff --git a/src/BigData/images/BigData/安装Flink1.png b/src/BigData/images/BigData/安装Flink1.png new file mode 100644 index 0000000..621624a Binary files /dev/null and b/src/BigData/images/BigData/安装Flink1.png differ diff --git a/src/BigData/images/BigData/安装Flink2.png b/src/BigData/images/BigData/安装Flink2.png new file mode 100644 index 0000000..c2ca0c7 Binary files /dev/null and b/src/BigData/images/BigData/安装Flink2.png differ diff --git a/src/BigData/images/BigData/安装Flink3.png b/src/BigData/images/BigData/安装Flink3.png new file mode 100644 index 0000000..914f4ab Binary files /dev/null and b/src/BigData/images/BigData/安装Flink3.png differ diff --git a/src/BigData/images/BigData/安装Flink4.png b/src/BigData/images/BigData/安装Flink4.png new file mode 100644 index 0000000..ec9822a Binary files /dev/null and b/src/BigData/images/BigData/安装Flink4.png differ diff --git a/src/BigData/images/BigData/安装Flink5.png b/src/BigData/images/BigData/安装Flink5.png new file mode 100644 index 0000000..f1ff523 Binary files /dev/null and b/src/BigData/images/BigData/安装Flink5.png differ diff --git a/src/BigData/images/BigData/实时计算TopN热榜.png b/src/BigData/images/BigData/实时计算TopN热榜.png new file mode 100644 index 0000000..ee393d7 Binary files /dev/null and b/src/BigData/images/BigData/实时计算TopN热榜.png differ diff --git a/src/Database/_sidebar.md b/src/Database/_sidebar.md index 5f525d9..babc556 100644 --- a/src/Database/_sidebar.md +++ b/src/Database/_sidebar.md @@ -1,67 +1,67 @@ -* 🏁数据库范式 - * [✍第一范式(1NF)](src/Database/1 "第一范式(1NF)") - * [✍第二范式(2NF)](src/Database/2 "第二范式(2NF)") - * [✍第三范式(3NF)](src/Database/3 "第三范式(3NF)") - * [✍巴斯-科德范式(BCNF)](src/Database/4 "巴斯-科德范式(BCNF)") - * [✍第四范式(4NF)](src/Database/5 "第四范式(4NF)") - * [✍第五范式(5NF)](src/Database/6 "第五范式(5NF)") -* 🏁连接方式 - * [✍内连接(INNER JOIN)](src/Database/101 "内连接(INNER JOIN)") - * [✍左连接(LEFT JOIN)](src/Database/102 "左连接(LEFT JOIN)") - * [✍右连接(RIGHT JOIN)](src/Database/103 "右连接(RIGHT JOIN)") - * [✍全连接(FULL JOIN)](src/Database/104 "全连接(FULL JOIN)") - * [✍LEFT JOIN EXCLUDING INNER JOIN](src/Database/105 "LEFT JOIN EXCLUDING INNER JOIN") - * [✍RIGHT JOIN EXCLUDING INNER JOIN](src/Database/106 "RIGHT JOIN EXCLUDING INNER JOIN") - * [✍FULL JOIN EXCLUDING INNER JOIN](src/Database/107 "FULL JOIN EXCLUDING INNER JOIN") - * [✍CROSS JOIN](src/Database/108 "CROSS JOIN") - * [✍SELF JOIN](src/Database/109 "SELF JOIN") -* [🏁数据库锁](src/Database/201 "数据库锁") - * [✍全局锁(Global-Level)](src/Database/202 "全局锁(Global-Level)") - * [✍表级锁(Table-Level)](src/Database/203 "表级锁(Table-Level)") - * [✍页级锁(Page-Level)](src/Database/204 "页级锁(Page-Level)") - * [✍行级锁(Row-Level)](src/Database/205 "行级锁(Row-Level)") - * [✍加锁机制](src/Database/206 "加锁机制") - * [✍锁问题](src/Database/207 "锁问题") -* [🏁数据库事务](src/Database/301 "数据库事务") - * [✍事务特性(ACID)](src/Database/302 "事务特性(ACID)") - * [✍隔离级别](src/Database/303 "隔离级别") - * [✍Spring事务机制](src/Database/304 "Spring事务机制") -* 🏁InnoDB引擎 - * [✍线程模型](src/Database/401 "线程模型") - * [✍数据页](src/Database/402 "数据页") - * [✍行格式](src/Database/403 "行格式") - * [✍内存结构](src/Database/404 "内存结构") - * [✍磁盘结构](src/Database/405 "磁盘结构") - * [✍存储索引](src/Database/406 "存储索引") -* [🏁MySQL日志](src/Database/501 "MySQL日志") - * [✍二进制日志(bin log)](src/Database/502 "二进制日志(bin log)") - * [✍重做日志(redo log)](src/Database/503 "重做日志(redo log)") - * [✍回滚日志(undo log)](src/Database/504 "回滚日志(undo log)") -* [🏁索引机制](src/Database/601 "索引机制") - * [✍数据结构](src/Database/602 "数据结构") - * [✍索引类型](src/Database/603 "索引类型") - * [✍索引实现](src/Database/604 "索引实现") - * [✍失效场景](src/Database/605 "失效场景") -* 🏁数据切分 - * [✍水平切分](src/Database/701 "水平切分") - * [✍垂直切分](src/Database/702 "垂直切分") - * [✍Sharding策略](src/Database/703 "Sharding策略") - * [✍Sharding存在的问题](src/Database/704 "Sharding存在的问题") -* 🏁SQL优化 - * [✍优化步骤](src/Database/801 "优化步骤") - * [✍特殊需求](src/Database/802 "特殊需求") - * [✍场景分析](src/Database/803 "场景分析") -* 🏁MySQL原理 - * [✍架构设计](src/Database/901 "架构设计") - * [✍存储引擎](src/Database/902 "存储引擎") - * [✍复制](src/Database/903 "复制") - * [✍查询过程](src/Database/904 "查询过程") - * [✍mysql复制原理](src/Database/905 "mysql复制原理") -* [🏁高可用方案](src/Database/1001 "高可用方案") - * [✍主从或主主半同步复制](src/Database/1002 "主从或主主半同步复制") - * [✍半同步复制优化](src/Database/1003 "半同步复制优化") - * [✍高可用架构优化](src/Database/1004 "高可用架构优化") - * [✍共享存储](src/Database/1005 "共享存储") - * [✍分布式协议](src/Database/1006 "分布式协议") - * [✍主从延迟](src/Database/1007 "主从延迟") -* 🏁ClickHouse \ No newline at end of file +* 🏁 数据库范式 + * [✍ 第一范式(1NF)](src/Database/1 "第一范式(1NF)") + * [✍ 第二范式(2NF)](src/Database/2 "第二范式(2NF)") + * [✍ 第三范式(3NF)](src/Database/3 "第三范式(3NF)") + * [✍ 巴斯-科德范式(BCNF)](src/Database/4 "巴斯-科德范式(BCNF)") + * [✍ 第四范式(4NF)](src/Database/5 "第四范式(4NF)") + * [✍ 第五范式(5NF)](src/Database/6 "第五范式(5NF)") +* 🏁 连接方式 + * [✍ 内连接(INNER JOIN)](src/Database/101 "内连接(INNER JOIN)") + * [✍ 左连接(LEFT JOIN)](src/Database/102 "左连接(LEFT JOIN)") + * [✍ 右连接(RIGHT JOIN)](src/Database/103 "右连接(RIGHT JOIN)") + * [✍ 全连接(FULL JOIN)](src/Database/104 "全连接(FULL JOIN)") + * [✍ LEFT JOIN EXCLUDING INNER JOIN](src/Database/105 "LEFT JOIN EXCLUDING INNER JOIN") + * [✍ RIGHT JOIN EXCLUDING INNER JOIN](src/Database/106 "RIGHT JOIN EXCLUDING INNER JOIN") + * [✍ FULL JOIN EXCLUDING INNER JOIN](src/Database/107 "FULL JOIN EXCLUDING INNER JOIN") + * [✍ CROSS JOIN](src/Database/108 "CROSS JOIN") + * [✍ SELF JOIN](src/Database/109 "SELF JOIN") +* [🏁 数据库锁](src/Database/201 "数据库锁") + * [✍ 全局锁(Global-Level)](src/Database/202 "全局锁(Global-Level)") + * [✍ 表级锁(Table-Level)](src/Database/203 "表级锁(Table-Level)") + * [✍ 页级锁(Page-Level)](src/Database/204 "页级锁(Page-Level)") + * [✍ 行级锁(Row-Level)](src/Database/205 "行级锁(Row-Level)") + * [✍ 加锁机制](src/Database/206 "加锁机制") + * [✍ 锁问题](src/Database/207 "锁问题") +* [🏁 数据库事务](src/Database/301 "数据库事务") + * [✍ 事务特性(ACID)](src/Database/302 "事务特性(ACID)") + * [✍ 隔离级别](src/Database/303 "隔离级别") + * [✍ Spring事务机制](src/Database/304 "Spring事务机制") +* 🏁 InnoDB引擎 + * [✍ 线程模型](src/Database/401 "线程模型") + * [✍ 数据页](src/Database/402 "数据页") + * [✍ 行格式](src/Database/403 "行格式") + * [✍ 内存结构](src/Database/404 "内存结构") + * [✍ 磁盘结构](src/Database/405 "磁盘结构") + * [✍ 存储索引](src/Database/406 "存储索引") +* [🏁 MySQL日志](src/Database/501 "MySQL日志") + * [✍ 二进制日志(bin log)](src/Database/502 "二进制日志(bin log)") + * [✍ 重做日志(redo log)](src/Database/503 "重做日志(redo log)") + * [✍ 回滚日志(undo log)](src/Database/504 "回滚日志(undo log)") +* [🏁 索引机制](src/Database/601 "索引机制") + * [✍ 数据结构](src/Database/602 "数据结构") + * [✍ 索引类型](src/Database/603 "索引类型") + * [✍ 索引实现](src/Database/604 "索引实现") + * [✍ 失效场景](src/Database/605 "失效场景") +* 🏁 数据切分 + * [✍ 水平切分](src/Database/701 "水平切分") + * [✍ 垂直切分](src/Database/702 "垂直切分") + * [✍ Sharding策略](src/Database/703 "Sharding策略") + * [✍ Sharding存在的问题](src/Database/704 "Sharding存在的问题") +* 🏁 SQL优化 + * [✍ 优化步骤](src/Database/801 "优化步骤") + * [✍ 特殊需求](src/Database/802 "特殊需求") + * [✍ 场景分析](src/Database/803 "场景分析") +* 🏁 MySQL原理 + * [✍ 架构设计](src/Database/901 "架构设计") + * [✍ 存储引擎](src/Database/902 "存储引擎") + * [✍ 复制](src/Database/903 "复制") + * [✍ 查询过程](src/Database/904 "查询过程") + * [✍ mysql复制原理](src/Database/905 "mysql复制原理") +* [🏁 高可用方案](src/Database/1001 "高可用方案") + * [✍ 主从或主主半同步复制](src/Database/1002 "主从或主主半同步复制") + * [✍ 半同步复制优化](src/Database/1003 "半同步复制优化") + * [✍ 高可用架构优化](src/Database/1004 "高可用架构优化") + * [✍ 共享存储](src/Database/1005 "共享存储") + * [✍ 分布式协议](src/Database/1006 "分布式协议") + * [✍ 主从延迟](src/Database/1007 "主从延迟") +* 🏁 ClickHouse \ No newline at end of file diff --git a/src/DevOps/1.md b/src/DevOps/1.md new file mode 100644 index 0000000..1520310 --- /dev/null +++ b/src/DevOps/1.md @@ -0,0 +1 @@ +![AnalysisTools](images/DevOps/AnalysisTools.png) \ No newline at end of file diff --git a/src/DevOps/101.md b/src/DevOps/101.md new file mode 100644 index 0000000..b1c784a --- /dev/null +++ b/src/DevOps/101.md @@ -0,0 +1 @@ +![img](images/DevOps/1657486-20200110163906854-1971599861.png) \ No newline at end of file diff --git a/src/DevOps/102.md b/src/DevOps/102.md new file mode 100644 index 0000000..8a87f80 --- /dev/null +++ b/src/DevOps/102.md @@ -0,0 +1,93 @@ +从 CPU 的角度来说,主要的性能指标就是 **CPU 的使用率**、**上下文切换**以及 **CPU 缓存的命中率**等。 + +![img](images/DevOps/d474b437af17bd1d35eb6f64b520a8ac.png) + +![img](images/DevOps/1477786-20201122134301506-441066821.png) + +![img](images/DevOps/9ca30729b6120a06dff8d3c72a93f8e2.png) + +### top + +top可以查看CPU总体消耗,包括分项消耗,如User,System,Idle,nice等。 + +- `Shift + H` 显示java线程 +- `Shift + M` 按照内存使用排序 +- `Shift + P` 按照CPU使用时间(使用率)排序 +- `Shift + T` 按照CPU累积使用时间排序 + +```shell +top - 15:24:11 up 8 days, 7:52, 1 user, load average: 5.73, 6.85, 7.33 +Tasks: 17 total, 1 running, 16 sleeping, 0 stopped, 0 zombie +%Cpu(s): 13.9 us, 9.2 sy, 0.0 ni, 76.1 id, 0.1 wa, 0.0 hi, 0.1 si, 0.7 st +KiB Mem : 11962365+total, 50086832 free, 38312808 used, 31224016 buff/cache +KiB Swap: 0 total, 0 free, 0 used. 75402760 avail Mem + + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 300 ymmapp 20 0 17.242g 1.234g 14732 S 2.3 1.1 9:40.38 java + 1 root 20 0 15376 1988 1392 S 0.0 0.0 0:00.06 sh + 11 root 20 0 120660 11416 1132 S 0.0 0.0 0:04.94 python + 54 root 20 0 85328 2240 1652 S 0.0 0.0 0:00.00 su +...... +``` + +第三行:`%Cpu(s): 13.9 us, 9.2 sy, 0.0 ni, 76.1 id, 0.1 wa, 0.0 hi, 0.1 si, 0.7 st`:**用户空间CPU占比13.9%** ,内核空间CPU占比9.2%,改变过优先级的进程CPU占比0%,**空闲CPU占比76.1** ,**IO等待占用CPU占比0.1%** ,硬中断占用CPU占比0%,软中断占用CPU占比0.1%,当前VM中的cpu 时钟被虚拟化偷走的比例0.7%。其中: + +- `PID`:进程id +- `USER`:进程所有者 +- `VIRT`:虚拟内存,进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES +- `RES`:常驻内存,进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA +- `SHR`:共享内存,共享内存大小,单位kb +- `%CPU`:上次更新到现在的CPU时间占用百分比 +- `%MEM`:进程使用的物理内存百分比 + + + +### htop + +htop基本上是一个top改善版本,它能够以更加多彩的方式显示更多的统计信息,同时允许你采用不同的方式进行排序,它提供了一个用户友好的接口。 + +![htop](images/DevOps/htop.png) + +![htop](images/DevOps/htop.gif) + + + +### sar + +① 通过`sar -u 1 3`可以查看CUP总体消耗占比,每间隔1秒钟统计1次总共统计3次: + +```shell +[root@localhost ~]# sar -u 1 3 +Linux 3.10.0-1062.el7.x86_64 (localhost.localdomain) 2020年05月01日 _x86_64_ (2 CPU) +15时18分03秒 CPU %user %nice %system %iowait %steal %idle +15时18分06秒 all 0.00 0.00 0.17 0.00 0.00 99.83 +15时18分09秒 all 0.00 0.00 0.17 0.00 0.00 99.83 +15时18分12秒 all 0.17 0.00 0.17 0.00 0.00 99.66 +15时18分15秒 all 0.00 0.00 0.00 0.00 0.00 100.00 +15时18分18秒 all 0.00 0.00 0.00 0.00 0.00 100.00 +``` + +- `%user`:用户空间的CPU使用 +- `%nice`:改变过优先级的进程的CPU使用率 +- `%system`:内核空间的CPU使用率 +- `%iowait`:CPU等待IO的百分比 +- `%steal`:虚拟机的虚拟机CPU使用的CPU +- `%idle`:空闲的CPU + +在以上的显示当中,主要看`%iowait`和`%idle`: + +- 若 `%iowait`的值过高,表示硬盘存在I/O瓶颈 +- 若 `%idle`的值高但系统响应慢时,有可能是 CPU 等待分配内存,此时应加大内存容量 +- 若 `%idle`的值持续低于 10,则系统的 CPU 处理能力相对较低,表明系统中最需要解决的资源是 CPU + + + +② 查看平均负载` sar -q 1 3`: + +![sar-q-1-3](images/DevOps/sar-q-1-3.png) + +- `runq-sz`:运行队列的长度(等待运行的进程数,每核的CP不能超过3个) +- `plist-sz`:进程列表中的进程(processes)和线程数(threads)的数量 +- `ldavg-1`:最后1分钟的CPU平均负载,即将多核CPU过去一分钟的负载相加再除以核心数得出的平均值, +- `ldavg-5`:最后5分钟的CPU平均负载 +- `ldavg-15`:最后15分钟的CPU平均负载 \ No newline at end of file diff --git a/src/DevOps/103.md b/src/DevOps/103.md new file mode 100644 index 0000000..6c33932 --- /dev/null +++ b/src/DevOps/103.md @@ -0,0 +1,107 @@ +从内存的角度来说,主要的性能指标,就是系统内存的分配和使用、进程内存的分配和使用以及 SWAP 的用量。 + +![img](images/DevOps/4dc3e5aba96c56ac1b3e8d51611934dd.png) + +![img](images/DevOps/1477786-20201122135426680-1563483565.png) + +![img](images/DevOps/b4e930f089487cc2431f3f2f067f0425.png) + +### free + +`free`是查看内存使用情况,包括物理内存、交换内存(swap)和内核缓冲区内存。 + +```shell +# 语法 +free [-bkmhotV][-s <间隔秒数>] + +# 参数说明: +# -b  以Byte为单位显示内存使用情况 +# -k  以KB为单位显示内存使用情况 +# -m 以MB为单位显示内存使用情况 +# -h  以合适的单位显示内存使用情况,最大为三位数,自动计算对应单位值。单位:B=bytes, K=kilos, M=megas, G=gigas, T=teras +# -o  不显示缓冲区调节列 +# -s <间隔秒数>  持续观察内存使用状况 +# -t  显示内存总和列 +# -V  显示版本信息 +``` + +`free -h -s 3`表示每隔三秒输出一次内存情况,命令如下: + +```shell +[1014154@cc69dd4c5-4tdb5 ~]$ free -h -s 3 + total used free shared buff/cache available +Mem: 114G 41G 43G 4.1G 29G 67G +Swap: 0B 0B 0B + total used free shared buff/cache available +Mem: 114G 41G 43G 4.1G 29G 67G +Swap: 0B 0B 0B +``` + +- `Mem`:是内存的使用情况 +- `Swap`:是交换空间的使用情况 +- `total`:系统总的可用物理内存和交换空间大小 +- `used`:已经被使用的物理内存和交换空间 +- `free`:还有多少物理内存和交换空间可用使用,**是真正尚未被使用的物理内存数量** +- `shared`:被共享使用的物理内存大小 +- `buff/cache`:被 buffer(缓冲区) 和 cache(缓存) 使用的物理内存大小 +- `available`:还可以被应用程序使用的物理内存大小,**它是从应用程序的角度看到的可用内存数量,available ≈ free + buffer + cache** + +**交换空间(swap space)** + +swap space 是磁盘上的一块区域,当系统物理内存吃紧时,Linux 会将内存中不常访问的数据保存到 swap 上,这样系统就有更多的物理内存为各个进程服务,而当系统需要访问 swap 上存储的内容时,再将 swap 上的数据加载到内存中,这就是常说的换出和换入。交换空间可以在一定程度上缓解内存不足情况,但它需要读写磁盘数据,所以性能不是很高。 + + + +### vmstat + +vmstat(Virtual Meomory Statistics,虚拟内存统计)是Linux中监控内存的常用工具,它收集和显示关于**内存**,**进程**,**终端**和**分页**和**I/O阻塞**的概括信息。 + +```shell +# 每隔1秒打印一次,一共打印3次。-S指定显示单位, M代表Mb, 默认为Kb +[root@localhost ~]# vmstat -SM 1 3 +procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- + r b swpd free buff cache si so bi bo in cs us sy id wa st + 1 0 0 2433 2 657 0 0 132 8 77 95 1 2 97 1 0 + 0 0 0 2433 2 657 0 0 0 0 47 71 0 0 100 0 0 + 0 0 0 2433 2 657 0 0 0 0 54 72 0 0 100 0 0 +``` + +- **procs** + + - `r`:表示运行和等待CPU时间片的进程数(就是说多少个进程真的分配到CPU),**这个值如果长期大于系统CPU个数,说明CPU不足,需要增加CPU** + - `b`:表示在等待资源的进程数,比如正在等待I/O或者内存交换等 + +- **memory** + + - `swpd`:表示切换到内存交换区的内存大小,即虚拟内存已使用的大小(单位KB),**如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器** + - `free`:表示当前空闲的物理内存 + - `buff`:表示缓冲大小,一般对块设备的读写才需要缓冲 + - `cache`:表示缓存大小,一般作为文件系统进行缓冲,频繁访问的文件都会被缓存,如果cache值非常大说明缓存文件比较多,如果此时io中的bi比较小,说明文件系统效率比较好 + +- **swap**:交换空间 + + 一般情况下si、so的值都为0,如果si、so的值长期不为0,则说明系统内存不足,需要增加系统内存。 + + - `si`:表示数据由磁盘读入内存;通俗的讲就是每秒从磁盘读入虚拟内存的大小,**如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉** + - `so`:表示由内存写入磁盘,也就是由内存交换区进入内存的数据大小 + +- **io** + + 如果bi+bo的值过大,且wa值较大,则表示系统磁盘IO瓶颈。 + + - `bi`:表示由块设备读入数据的总量,即读磁盘,单位kb/s + - `bo`:表示写到块设备数据的总量,即写磁盘,单位kb/s + +- **system** + + 这两个值越大,则由内核消耗的CPU就越多。 + + - `in`:表示某一时间间隔内观测到的每秒设备终端数 + - `cs`:表示每秒产生的上下文切换次数,**这个值要越小越好,太大了,要考虑调低线程或者进程的数目** + +- **CPU(百分比)** + + - `us`:表示用户进程消耗的CPU时间比,**us值越高,说明用户进程消耗CPU时间越多。如果长期大于50%,则需要考虑优化程序或者算法** + - `sy`:表示系统内核进程消耗的CPU时间比,**一般us+sy应该小于80%,如果大于80%,说明可能存在CPU瓶颈** + - `id`:表示CPU处在空间状态的时间百分比 + - `wa`:表示IP等待所占用的CPU时间百分比,**wa值越高,说明I/O等待越严重,根据经验wa的参考值为20%,如果超过20%,说明I/O等待严重,引起I/O等待的原因可能是磁盘大量随机读写造成的,也可能是磁盘或者监控器的贷款瓶颈(主要是块操作)造成的** \ No newline at end of file diff --git a/src/DevOps/104.md b/src/DevOps/104.md new file mode 100644 index 0000000..8a22a07 --- /dev/null +++ b/src/DevOps/104.md @@ -0,0 +1,73 @@ +从文件系统和磁盘 I/O 的角度来说,主要性能指标,就是文件系统的使用、缓存和缓冲区的使用,以及磁盘 I/O 的使用率、吞吐量和延迟等。 + +![img](images/DevOps/7df09cbf580b688f84384e209c24c173.png)![img](images/DevOps/1477786-20201122135610356-597293017-1629438006328.png) + +![img](images/DevOps/817fec330eb2e96f1e355ad53dfa74c6.png) + +### iostat + +iostat用于报告中央处理器(CPU)统计信息和整个系统、适配器、tty 设备、磁盘和 CD-ROM 的输入/输出统计信息,默认显示了与vmstat相同的cpu使用信息,使用以下命令显示扩展的设备统计: + +```shell +# 每隔一秒打印一次磁盘的详细信息 +iostat -dx 1 +# 每秒打印一次统计信息,打印30次后退出 +iostat 1 30 +``` + +![iostat](images/DevOps/iostat.png) + +- **rrqm/s和wrqm/s**:每秒合并的读写请求,“合并的”即操作系统从队列中拿出多个逻辑请求合并为一个请求到实际磁盘 +- **r/s和w/s**:每秒发送到设备的读和写请求数 +- **rsec/s和wsec/s**:每秒读和写的扇区数 +- **avgrq –sz**:请求的扇区数 +- **avgqu –sz**:在设备队列中等待的请求数 +- **await**:每个IO请求花费的时间 +- **svctm**:实际请求(服务)时间 +- **%util**:至少有一个活跃请求所占时间的百分比 + + + +### pidstat + +pidstat主要用于监控全部或指定进程占用系统资源的情况。如CPU、内存、设备IO、任务切换和线程等。 + +![pidstat](images/DevOps/pidstat.jpg) + +```shell +# 统计IO使用信息 +pidstat –d +# 统计CPU使用信息 +pidstat –u +# 统计内存使用信息 +pidstat –r +# 查看特定进程的cpu统计信息 +pidstat –p + +# 查看特定进程的CPU使用情况 +pidstat –u –p {pid} {interval} [count] + +# 作用:以1秒为信息采集周期,采集10次程序“admin”的CPU统计信息,最后一行会输出10次统计信息的平均值 +pidstat -u -p `pgrep admin` 1 10 + +# 查看特定进程的内存使用情况 +pidstat –r –p {pid} {interval} [count] + +# 查看特定进程的IO使用情况 +pidstat –d –p {pid} {interval} [count] +``` + + + +### iotop + +iotop命令是专门显示硬盘IO的命令,界面风格类似top命令,可以显示IO负载具体是由哪个进程产生的。是一个用来监视磁盘I/O使用状况的top类工具,具有与top相似的UI,其中包括PID、用户、I/O、进程等相关信息。可以以非交互的方式使用:iotop –bod interval。查看每个进程的I/O,可以使用pidstat,pidstat –d instat。 + +```shell +# Linux安装iotop +yum install iotop +# Ubuntu安装iotop +sudo apt-get install iotop +# 实时监控IO读写 +iotop +``` \ No newline at end of file diff --git a/src/DevOps/105.md b/src/DevOps/105.md new file mode 100644 index 0000000..5ae969c --- /dev/null +++ b/src/DevOps/105.md @@ -0,0 +1,123 @@ +从网络的角度来说,主要性能指标就是吞吐量、响应时间、连接数、丢包数等。 + +![img](images/DevOps/7aace9181112609a0621e63c13bf4088.png) + +![img](images/DevOps/1477786-20201122135828625-682254107.png) + +![img](images/DevOps/4737bd5fae25f97303f4a761f78b3419.png) + +### netstat + +netstat 是一个内置工具,用于显示IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口网络连接情况。 + +![netstat](images/DevOps/netstat.png) + +```shell +# 查看当前连接,注意CLOSE_WAIT偏高的情况 +netstat -nat|awk '{print $6}'|sort|uniq -c|sort -rn +# 显示所有tcp连接,并包括pid和程序名 +netstat -atnp +# 统计所有tcp状态的数量并排序 +netstat -atn | awk '{print $6}' | sort | uniq -c | sort -rn +# 每隔1s显示网络信息(-c参数) +netstat -ctn | grep "ESTABLISHED" +# 列出所有处于连接状态的ip并按数量排序 +netstat -an | grep ESTABLISHED | awk '/^tcp/ {print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -nr +``` + +**案例分析** + +```shell +[root@localhost ~]# netstat +Active Internet connections (w/o servers) +Proto Recv-Q Send-Q Local Address Foreign Address State +tcp 0 2 210.34.6.89:telnet 210.34.6.96:2873 ESTABLISHED +tcp 296 0 210.34.6.89:1165 210.34.6.84:netbios-ssn ESTABLISHED +tcp 0 0 localhost.localdom:9001 localhost.localdom:1162 ESTABLISHED +tcp 0 0 localhost.localdom:1162 localhost.localdom:9001 ESTABLISHED +tcp 0 80 210.34.6.89:1161 210.34.6.10:netbios-ssn CLOSE + +Active UNIX domain sockets (w/o servers) +Proto RefCnt Flags Type State I-Node Path +unix 1 [ ] STREAM CONNECTED 16178 @000000dd +unix 1 [ ] STREAM CONNECTED 16176 @000000dc +unix 9 [ ] DGRAM 5292 /dev/log +unix 1 [ ] STREAM CONNECTED 16182 @000000df +``` + +其中"Recv-Q"和"Send-Q"指%0A的是接收队列和发送队列,这些数字一般都应该是0。如果不是则表示软件包正在队列中堆积,这种情况只能在非常少的情况见到。 + + + +### iftop + +iftop可用来监控网卡的实时流量(可以指定网段)、反向解析IP、显示端口信息等,详细的将会在后面的使用参数中说明。 + +```shell +# 安装命令 +yum install iftop +# 开始监控 +iftop + +# 结果参数说明: +# 1.中间的<= =>这两个左右箭头,表示的是流量的方向。 +# 2.TX:发送流量 +# 3.RX:接收流量 +# 4.TOTAL:总流量 +# 5.Cumm:运行iftop到目前时间的总流量 +# 6.peak:流量峰值 +# 7.rates:分别表示过去 2s 10s 40s 的平均流量 +``` + +![iftop](images/DevOps/iftop.png) + + + +### tcpdump + +tcpdump可以用来查看网络连接的封包内容。它显示了传输过程中封包内容的各种信息。为了使得输出信息更为有用,它允许使用者通过不同的过滤器获取自己想要的信息。 + +![tcpdump](images/DevOps/tcpdump.jpg) + +```shell +# 过滤主机-------- +# 抓取所有经过 eth1,目的或源地址是 192.168.1.1 的网络数据 +tcpdump -i eth1 host 192.168.1.1 +# 源地址 +tcpdump -i eth1 src host 192.168.1.1 +# 目的地址 +tcpdump -i eth1 dst host 192.168.1.1 + +# 过滤端口-------- +# 抓取所有经过 eth1,目的或源端口是 25 的网络数据 +tcpdump -i eth1 port 25 +# 源端口 +tcpdump -i eth1 src port 25 +# 目的端口 +tcpdump -i eth1 dst port 25 + +# 网络过滤-------- +tcpdump -i eth1 net 192.168 +tcpdump -i eth1 src net 192.168 +tcpdump -i eth1 dst net 192.168 + +# 协议过滤-------- +tcpdump -i eth1 arp +tcpdump -i eth1 ip +tcpdump -i eth1 tcp +tcpdump -i eth1 udp + +# 常用表达式---------- +# 非 : ! or "not" (去掉双引号) +# 且 : && or "and" +# 或 : || or "or" +# 抓取所有经过 eth1,目的地址是 192.168.1.254 或 192.168.1.200 端口是 80 的 TCP 数据 +tcpdump -i eth1 '((tcp) and (port 80) and ((dst host 192.168.1.254) or (dst host 192.168.1.200)))' +# 抓取所有经过 eth1,目标 MAC 地址是 00:01:02:03:04:05 的 ICMP 数据 +tcpdump -i eth1 '((icmp) and ((ether dst host 00:01:02:03:04:05)))' +# 抓取所有经过 eth1,目的网络是 192.168,但目的主机不是 192.168.1.200 的 TCP 数据 +tcpdump -i eth1 '((tcp) and ((dst net 192.168) and (not dst host 192.168.1.200)))' + +# 实时抓取端口号8000的GET包,然后写入GET.log +tcpdump -i eth0 '((port 8000) and (tcp[(tcp[12]>>2):4]=0x47455420))' -nnAl -w /tmp/GET.log +``` \ No newline at end of file diff --git a/src/DevOps/106.md b/src/DevOps/106.md new file mode 100644 index 0000000..fdbd2f2 --- /dev/null +++ b/src/DevOps/106.md @@ -0,0 +1,146 @@ +### dstat + +该命令整合了 **vmstat、iostat、ifstat** 三种命令。同时增加了新的特性和功能可以让你能及时看到各种的资源使用情况,从而能够使你对比和整合不同的资源使用情况。通过不同颜色和区块布局的界面帮助你能够更加清晰容易的获取信息。它也支持将信息数据导出到cvs格式文件中,从而用其他应用程序打开,或者导入到数据库中。你可以用该命令来监控cpu,内存和网络状态随着时间的变化。 + +**安装** + +```shell +# Ubuntu安装方法 +sudo apy-get install dstat +# Centos安装方法 +yum install dstat +# ArchLinux系统 +pacman -S dstat +``` + +**使用参数** + +```shell +# 参数说明: +# -l :显示负载统计量 +# -m :显示内存使用率(包括used,buffer,cache,free值) +# -r :显示I/O统计 +# -s :显示交换分区使用情况 +# -t :将当前时间显示在第一行 +# –fs :显示文件系统统计数据(包括文件总数量和inodes值) +# –nocolor :不显示颜色(有时候有用) +# –socket :显示网络统计数据 +# –tcp :显示常用的TCP统计 +# –udp :显示监听的UDP接口及其当前用量的一些动态数据 + +# 插件库: +# -–disk-util :显示某一时间磁盘的忙碌状况 +# -–freespace :显示当前磁盘空间使用率 +# -–proc-count :显示正在运行的程序数量 +# -–top-bio :指出块I/O最大的进程 +# -–top-cpu :图形化显示CPU占用最大的进程 +# -–top-io :显示正常I/O最大的进程 +# -–top-mem :显示占用最多内存的进程 + +# eg: +# 查看全部内存都有谁在占用 +dstat -g -l -m -s --top-mem +# 显示一些关于CPU资源损耗的数据 +dstat -c -y -l --proc-count --top-cpu +# 想输出一个csv格式的文件用于以后,可以通过下面的命令 +dstat –output /tmp/sampleoutput.csv -cdn +``` + +**监控分析** + +```shell +dstat + +# 结果参数说明: +# 1.CPU状态:CPU的使用率。这项报告更有趣的部分是显示了用户,系统和空闲部分,这更好地分析了CPU当前的使用状况。如果你看到"wait"一栏中,CPU的状态是一个高使用率值,那说明系统存在一些其它问题。当CPU的状态处在"waits"时,那是因为它正在等待I/O设备(例如内存,磁盘或者网络)的响应而且还没有收到。 +# 2.磁盘统计:磁盘的读写操作,这一栏显示磁盘的读、写总数。 +# 3.网络统计:网络设备发送和接受的数据,这一栏显示的网络收、发数据总数。 +# 4.分页统计:系统的分页活动。分页指的是一种内存管理技术用于查找系统场景,一个较大的分页表明系统正在使用大量的交换空间,或者说内存非常分散,大多数情况下你都希望看到page in(换入)和page out(换出)的值是0 0。 +# 5.系统统计:这一项显示的是中断(int)和上下文切换(csw)。这项统计仅在有比较基线时才有意义。这一栏中较高的统计值通常表示大量的进程造成拥塞,需要对CPU进行关注。你的服务器一般情况下都会运行运行一些程序,所以这项总是显示一些数值。 + +# 默认情况下,dstat每秒都会刷新数据。如果想退出dstat,你可以按"CTRL-C"键。 +``` + +![dstat](images/DevOps/dstat.png) + + + +### saidar + +saidar是一个简单且轻量的系统信息监控工具。虽然它无法提供大多性能报表,但是它能够通过一个简单明了的方式显示最有用的系统运行状况数据。可以容易地看到运行时间、平均负载、CPU、内存、进程、磁盘和网络接口统计信息。 + +```powershell +# Usage: saidar [-d delay] [-c] [-v] [-h] +# -d 设置更新时间(秒) +# -c 彩色显示 +# -v 显示版本号 +# -h 显示本帮助 +``` + +![saidar](images/DevOps/saidar.png) + + + +### Glances + +**Glances** 是一个由 Python 编写,使用 **psutil** 库来从系统抓取信息的基于 curses 开发的跨平台命令行系统监视工具。 通过 Glances,我们可以监视 **CPU、平均负载、内存、网络流量、磁盘 I/O、其它处理器** 和 **文件系统** 空间的利用情况。 + +![glances](images/DevOps/glance.png) + +**在 Linux/Unix 系统中安装 Glances** + +```powershell +# 对于 RHEL/CentOS/Fedora 发行版 +# yum install -y glances + +#对于 Debian/Ubuntu/Linux Mint 发行版 +# sudo apt-add-repository ppa:arnaud-hartmann/glances-stable +# sudo apt-get update +# sudo apt-get install glances +``` + +**使用 Glances** + +```powershell +# Glances 的默认刷新频率是 1 (秒),但是你可以通过在终端指定参数来手动定义其刷新频率 +# glances -t 2 + +# 按下 ‘**q**‘ (‘**ESC**‘ 和 ‘**Ctrl-C**‘ 也可以) 退出 Glances 终端 +``` + +**Glances 的选项** + +- `m` : 按内存占用排序进程 +- `p` : 按进程名称排序进程 +- `c` : 按 CPU 占用率排序进程 +- `i` : 按 I/O 频率排序进程 +- `a` : 自动排序进程 +- `d` : 显示/隐藏磁盘 I/O 统计信息 +- `f` : 显示/隐藏文件系统统计信息 +- `s` : 显示/隐藏传感器统计信息 +- `y` : 显示/隐藏硬盘温度统计信息 +- `l` : 显示/隐藏日志 +- `n` : 显示/隐藏网络统计信息 +- `x` : 删除警告和严重日志 +- `h` : 显示/隐藏帮助界面 +- `q` : 退出 +- `w` : 删除警告记录 + + + +### GoAccess + +**GoAccess 是一个实时的网络日志分析器**。它能分析 apache、nginx 和 amazon cloudfront 的访问日志。它也可以将数据输出成 HTML、JSON 或 CSV 格式。它会给你一个基本的统计信息、访问量、404 页面,访客位置和其他东西。 + +![img](images/DevOps/goaccess-dashboard.png) + +**下载与安装** + +```powershell +# wget https://tar.goaccess.io/goaccess-1.3.tar.gz +# tar -xzvf goaccess-1.3.tar.gz +# cd goaccess-1.3/ +# ./configure --enable-utf8 --enable-geoip=legacy +# make +# make install +``` \ No newline at end of file diff --git a/src/DevOps/107.md b/src/DevOps/107.md new file mode 100644 index 0000000..ed4a171 --- /dev/null +++ b/src/DevOps/107.md @@ -0,0 +1,175 @@ +### 定位线上最耗CPU的线程 + +**第一步:通过 `top` 命令找到最耗时 ( `Shift + P` ) 的进程** + +```shell +[root@localhost ~]# top +top - 11:11:05 up 20:02, 3 users, load average: 0.09, 0.07, 0.05 +Tasks: 225 total, 1 running, 224 sleeping, 0 stopped, 0 zombie +%Cpu(s): 0.0 us, 0.7 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st +KiB Mem : 1421760 total, 135868 free, 758508 used, 527384 buff/cache +KiB Swap: 2097148 total, 2070640 free, 26508 used. 475852 avail Mem +Change delay from 3.0 to + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 98344 root 20 0 2422552 23508 12108 S 0.7 1.7 0:00.32 java + 1 root 20 0 194100 6244 3184 S 0.0 0.4 0:20.41 systemd + 2 root 20 0 0 0 0 S 0.0 0.0 0:00.12 kthreadd + 4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H + 6 root 20 0 0 0 0 S 0.0 0.0 0:20.25 ksoftirqd/0 +``` + +找到进程号是98344。 + +**第二步:找到进程中最耗CUP的线程** + +使用`ps -Lp cu`命令,查看某个进程中的线程CPU消耗排序: + +```shell +[root@localhost ~]# ps -Lp 98344 cu +USER PID LWP %CPU NLWP %MEM VSZ RSS TTY STAT START TIME COMMAND +root 98344 98344 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 java +root 98344 98345 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:04 java +root 98344 98346 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:01 VM Thread +root 98344 98347 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 Reference Handl +root 98344 98348 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 Finalizer +root 98344 98349 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 Signal Dispatch +root 98344 98350 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:05 C2 CompilerThre +root 98344 98351 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 C1 CompilerThre +root 98344 98352 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 Service Thread +root 98344 98353 0.1 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:19 VM Periodic Tas +``` + +看`TIME`列可看出哪个线程耗费CUP多,`LWP`列可以看到线程的ID号,但需要转换成16进制才可以查询线程堆栈信息。 + +**第三步:获取线程id的十六进制码** + +使用`printf '%x\n' `命令做进制转换: + +```shell +[root@localhost ~]# printf '%x\n' 98345 +18029 +``` + +**第四步:查看线程堆栈信息** + +使用jstack获取堆栈信息`jstack | grep -A 10 <16进制LWP>`: + +```shell +[root@localhost ~]# jstack 98344 | grep -A 10 0x18029 +"main" #1 prio=5 os_prio=0 tid=0x00007fb88404b800 nid=0x18029 waiting on condition [0x00007fb88caab000] + java.lang.Thread.State: TIMED_WAITING (sleeping) + at java.lang.Thread.sleep(Native Method) + at java.lang.Thread.sleep(Thread.java:340) + at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386) + at demo.MathGame.main(MathGame.java:17) + +"VM Thread" os_prio=0 tid=0x00007fb8840f2800 nid=0x1802a runnable +"VM Periodic Task Thread" os_prio=0 tid=0x00007fb884154000 nid=0x18031 waiting on condition +``` + +通过命令我们可以看到这个线程的对应的耗时代码是在 `demo.MathGame.main(MathGame.java:17)` + + + +### 定位丢包错包情况 + +`watch more /proc/net/dev`用于定位丢包,错包情况,以便看网络瓶颈,重点关注drop(包被丢弃)和网络包传送的总量,不要超过网络上限: + +```shell +[root@localhost ~]# watch -n 2 more /proc/net/dev +Every 2.0s: more /proc/net/dev Fri May 1 17:16:55 2020 +Inter-| Receive | Transmit + face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed + lo: 10025 130 0 0 0 0 0 0 10025 130 0 0 0 0 0 0 + ens33: 759098071 569661 0 0 0 0 0 0 19335572 225551 0 0 0 0 0 0 +``` + +- 最左边的表示接口的名字,Receive表示收包,Transmit表示发送包 +- `bytes`:表示收发的字节数 +- `packets`:表示收发正确的包量 +- `errs`:表示收发错误的包量 +- `drop`:表示收发丢弃的包量 + + + +### 查看路由经过的地址 + +`traceroute ip`可以查看路由经过的地址,常用来统计网络在各个路由区段的耗时,如: + +```shell +[root@localhost ~]# traceroute 14.215.177.38 +traceroute to 14.215.177.38 (14.215.177.38), 30 hops max, 60 byte packets + 1 CD-HZTK5H2.mshome.net (192.168.137.1) 0.126 ms * * + 2 * * * + 3 10.250.112.3 (10.250.112.3) 12.587 ms 12.408 ms 12.317 ms + 4 172.16.227.230 (172.16.227.230) 2.152 ms 2.040 ms 1.956 ms + 5 172.16.227.202 (172.16.227.202) 11.884 ms 11.746 ms 12.692 ms + 6 172.16.227.65 (172.16.227.65) 2.665 ms 3.143 ms 2.923 ms + 7 171.223.206.217 (171.223.206.217) 2.834 ms 2.752 ms 2.654 ms + 8 182.150.18.205 (182.150.18.205) 5.145 ms 5.815 ms 5.542 ms + 9 110.188.6.33 (110.188.6.33) 3.514 ms 171.208.199.185 (171.208.199.185) 3.431 ms 171.208.199.181 (171.208.199.181) 10.768 ms +10 202.97.29.17 (202.97.29.17) 29.574 ms 202.97.30.146 (202.97.30.146) 32.619 ms * +11 113.96.5.126 (113.96.5.126) 36.062 ms 113.96.5.70 (113.96.5.70) 35.940 ms 113.96.4.42 (113.96.4.42) 45.859 ms +12 90.96.135.219.broad.fs.gd.dynamic.163data.com.cn (219.135.96.90) 35.680 ms 35.468 ms 35.304 ms +13 14.215.32.102 (14.215.32.102) 35.135 ms 14.215.32.110 (14.215.32.110) 35.613 ms 14.29.117.242 (14.29.117.242) 54.712 ms +14 * 14.215.32.134 (14.215.32.134) 49.518 ms 14.215.32.122 (14.215.32.122) 47.652 ms +15 * * * +... +``` + + + +### 查看网络错误 + +`netstat -i`可以查看网络错误: + +```shell +[root@localhost ~]# netstat -i +Kernel Interface table +Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg +ens33 1500 570291 0 0 0 225897 0 0 0 BMRU +lo 65536 130 0 0 0 130 0 0 0 LRU +``` + +- `Iface`: 网络接口名称 +- `MTU`: 最大传输单元,它限制了数据帧的最大长度,不同的网络类型都有一个上限值,如:以太网的MTU是1500 +- `RX-OK`:接收时,正确的数据包数 +- `RX-ERR`:接收时,产生错误的数据包数 +- `RX-DRP`:接收时,丢弃的数据包数 +- `RX-OVR`:接收时,由于过速(在数据传输中,由于接收设备不能接收按照发送速率传送来的数据而使数据丢失)而丢失的数据包数 +- `TX-OK`:发送时,正确的数据包数 +- `TX-ERR`:发送时,产生错误的数据包数 +- `TX-DRP`:发送时,丢弃的数据包数 +- `TX-OVR`:发送时,由于过速而丢失的数据包数 +- `Flg`:标志,B 已经设置了一个广播地址。L 该接口是一个回送设备。M 接收所有数据包(混乱模式)。N 避免跟踪。O 在该接口上,禁用ARP。P 这是一个点到点链接。R 接口正在运行。U 接口处于“活动”状态 + + + +### 包的重传率 + +`cat /proc/net/snmp` 查看和分析240秒内网络包量、流量、错包和丢包。通过 `RetransSegs` 和 `OutSegs` 来计算: + +**TCP重传率 =(RetransSegs ÷ OutSegs)× 100%** + +```shell +[root@localhost ~]# cat /proc/net/snmp +Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates +Ip: 1 64 241708 0 0 0 0 0 238724 225517 15 0 0 0 0 0 0 0 0 +Icmp: InMsgs InErrors InCsumErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps +Icmp: 149 0 0 50 99 0 0 0 0 0 0 0 0 0 147 0 147 0 0 0 0 0 0 0 0 0 0 +IcmpMsg: InType3 InType11 OutType3 +IcmpMsg: 50 99 147 +Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts InCsumErrors +Tcp: 1 200 120000 -1 376 6 0 0 4 236711 223186 292 0 4 0 +Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors +Udp: 1405 438 0 1896 0 0 0 +UdpLite: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors +UdpLite: 0 0 0 0 0 0 0 +``` + +TCP重传率为:(292÷223186) × 100% = 0.13% + +- **平均每秒新增TCP连接数**:通过/proc/net/snmp文件得到最近240秒内PassiveOpens的增量,除以240得到每秒的平均增量 +- **机器的TCP连接数** :通过/proc/net/snmp文件的CurrEstab得到TCP连接数 +- **平均每秒的UDP接收数据报**:通过/proc/net/snmp文件得到最近240秒内InDatagrams的增量,除以240得到平均每秒的UDP接收数据报 +- **平均每秒的UDP发送数据报**:通过/proc/net/snmp文件得到最近240秒内OutDatagrams的增量,除以240得到平均每秒的UDP发送数据报 \ No newline at end of file diff --git a/src/DevOps/2.md b/src/DevOps/2.md new file mode 100644 index 0000000..19853c3 --- /dev/null +++ b/src/DevOps/2.md @@ -0,0 +1,315 @@ +`$`和`#`区别:`$`普通用户即可执行,`#`为root用户才可执行,或普通用户使用`sudo`。 + +**JDK环境变量配置** + +```shell +# 方式一:非root用户安装JDK +# 编辑用户根目录下的.bash_profile文件 +vi .bash_profile +# 向.bash_profile文件中导入配置 +export JAVA_HOME=/home/lry/jdk1.7.0_80 +export PATH=$JAVA_HOME/bin:$PATH +export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar + +# 立刻生效 +source .bash_profile +``` + +```shell +# 方式二:yum安装JDK配置环境变量 +# 查看CentOS自带JDK是否已安装 +yum list installed |grep java +# 批量卸载JDK +rpm -qa | grep java | xargs rpm -e --nodeps +# 直接yum安装1.8.0版本openjdk +yum install java-1.8.0-openjdk* -y + +# 默认jre jdk安装路径是/usr/lib/jvm下面 +vim /etc/profile +# 添加以下配置 +export JAVA_HOME=/usr/lib/jvm/java +export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/jre/lib/rt.jar +export PATH=$PATH:$JAVA_HOME/bin + +# 使得配置生效 +. /etc/profile +``` + +```shell +# 方式三:root用户下是配置JDK +vim /etc/profile +# 添加以下配置 +export JAVA_HOME=/home/hmf/jdk1.7.0_80 +export PATH=.:$JAVA_HOME/bin:$PATH +export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar + +# source环境变量 +source /etc/profile +``` + + + +**基本常用命令** + +```shell +# 查看机器cpu核数: +# 1.CPU总核数 = 物理CPU个数 * 每颗物理CPU的核数 +# 2.总逻辑CPU数 = 物理CPU个数 * 每颗物理CPU的核数 * 超线程数 +# 查看CPU信息(型号) +cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c +# 查看物理CPU个数 +cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l +# 查看每个物理CPU中core的个数(即核数) +cat /proc/cpuinfo| grep "cpu cores"| uniq +# 查看逻辑CPU的个数 +cat /proc/cpuinfo| grep "processor"| wc -l + +# 重启 +reboot +# 关机 +poweroff +# 添加用户 +useradd +# 设置密码 +passwd +# 查看nginx的位置 +whereis nginx + +# Tab补全 +# 1.未输入状态下连按两次Tab列出所有可用命令 +# 2.已输入部分命令名或文件名,按Tab进行自动补全 + +# 根据端口查看占用情况 +netstat -tln | grep 8080 +# 根据端口查看进程 +lsof -i :8080 +# 查看java关键词的进程 +ps aux|grep java +# 查看所有进程 +ps aux +# 查看java关键词的进程 +ps -ef | grep java +``` + +**常用复合命令** + +```powershell +# 查找和tomcat相关的所有进程并杀死 +ps -ef | grep tomcat | grep -v grep | awk '{print $2}' | xargs kill -9 + +# 从100行开始显示,支持滚动 +less +100 /home/test/example.log +# 从100行开始显示,不支持滚动 +more +100 /home/test/example.log +# 查看文件头10行 +head -n 10 example.txt + +# 每隔3s出12234进程的gc情况,每个20录就打印隐藏列标题 +jstat -gc -t -h20 3s +# Java线程Dump快照导出(建议使用tdump或log格式) +jstack -l > thread-dump.tdump +# Java内存Dump快照导出(建议使用hprof格式),format=b表示二进制文件(一般较大) +jmap -dump:[live,]format=b,file=heap-dump.hprof + +# JMC分析 +jcmd VM.unlock_commercial_features +jcmd JFR.start name=test duration=60s filename=output.jfr +``` + + + +### cd/ls + +`cd` 用于切换当前目录,它的参数是要切换到的目录的路径,可以是绝对路径,也可以是相对路径 + +```shell +cd /home # 进入 '/ home' 目录 +cd .. # 返回上一级目录 +cd ../.. # 返回上两级目录 +cd # 进入个人的主目录 +cd ~user1 # 进入个人的主目录 +cd - # 返回上次所在的目录 + +ls # 查看目录中的文件 +ls -l # 显示文件和目录的详细资料 +ls -a # 列出全部文件,包含隐藏文件 +ls -R # 连同子目录的内容一起列出(递归列出),等于该目录下的所有文件都会显示出来 +ls [0-9] # 显示包含数字的文件名和目录名 +``` + + + +### chmod/chown/chgrp + +```shell +# 显示权限 +ls -lh +# 设置目录的所有人(u)、群组(g)以及其他人(o)以读(r,4 )、写(w,2)和执行(x,1)的权限 +chmod ugo+rwx directory1 +# 删除群组(g)与其他人(o)对目录的读写执行权限 +chmod go-rwx directory1 + +# chown改变文件的所有者 +# 改变一个文件的所有人属性 +chown user1 file1 +# 改变一个目录的所有人属性并同时改变改目录下所有文件的属性 +chown -R user1 directory1 +# 改变一个文件的所有人和群组属性 +chown user1:group1 file1 + +# chgrp改变文件所属用户组 +# 改变文件的群组 +chgrp group1 file1 + +# 常用命令 +# 修改start.sh文件为最高权限777 +chmod 777 start.sh +# 修改test.txt文件所属的用户和组, – R表示递归处理 +chown - R username:group test.txt +# 改变/opt/local和/book/及其子目录下的所有文件的属组为lry, – R表示递归处理 +chgrp - R lry /opt/local /book +``` + + + +### vi/vim + +```shell +:set nu # 设置显示行号 +:set nonu # 取消显示行号 +ctr+f # 向前翻页 +ctr+b # 向后翻页 +u # 恢复修改操作 +yy # 复制本行 +nyy # 本行往下n行进行复制 +p # 粘贴在光标以下的行 +P # 粘贴在光标以上的行 +x # 向后删除一个字符 +X # 向前删除一个字符 +nx # 向后删除n个字符 + +:w # 保存 +:q # 退出 +:q! # 强制退出不保存 +:w! # 强制保存 +:wq # 保存并退出 +:w otherfilename # 另存为 + +# 在文件中移动 +nG # 光标移动到n行 +gg # 光标移动到文件第1行 +G # 光标移动到文件最后1行 +75% # 光标移动到百分之75的位置 +$ # 移动到行末 +0 # 移动到行首 + +dd # 删除当前行 +dG # 删除当前后面的全部内容 + +# 移动到指定字符 +fx # 把光标移动到右边的第一个’x’字符上 +Fx # 把光标移动到左边的第一个’x’字符上 +3fx # 把光标移动到光标右边的第3个’x’字符上 +tx # 把光标移动到右边的第一个’x’字符之前 +Tx # 把光标移动到左边的第一个’x’字之后 +n空格 # 光标移动到本行第n个字符 +$ # 光标移动到本行最后一个字符 + +# H/M/L(大写):可以让光标跳到当前窗口的顶部、中间、和底部,停留在第一个非空字符上 +3H # 表示光标移动到距窗口顶部第3行的位置 +5L # 表示光标移动到距窗口底部5行的位置 + +# 相对于光标滚屏 +zt # 把光标所在行移动窗口的顶端 +zz # 把光标所在行移动窗口的中间 +zb # 把光标所在行移动窗口的底部 + +# 查找 +/word # 向光标之后搜索字符串 +?word # 向光标之前搜索字符串 +n # 重复上一次的查找命令向后查找 +N # 重复上一次的查找命令向前查找 + +:n1,n2s/word1/word2/gc # 逐个替换 +:1,$s/word1/word2/g # 从第一行到最后一行进行替换应该是 +:n1,n2s/word1/word2/g # 从第n1行到第n2行搜索word1字符串,并替换为word2 +``` + + + +### scp + +```shell +# 拷贝本机/home/lry/test整个目录至远程主机192.168.1.100的/test目录下 +scp -r /home/lry/test/ root@192.168.1.100:/test/ +# 拷贝单个文件至远程主机 +scp /home/lry/test.txt root@192.168.1.100:/test/ +# 远程文件/文件夹下载举例 +# 把192.168.62.10上面的/test/文件夹,下载到本地的/home/lry/下 +scp -r root@192.168.62.10:/test/ /home/lry/ +``` + + + +### tar + +```shell +# 格式:tar [-cxtzjvfpPN] 文件与目录 .... +# 参数说明: +# -c :压缩 +# -x :解压 +# -t :查看内容 +# 注意:c/x/t只能同时存在一个 +# +# -r:向压缩归档文件末尾追加文件 +# -u:更新原压缩包中的文件 +# -v:显示操作过程 +# -f:指定备份文件,其后不能再跟参数 + +# 压缩文件 +tar -czf test.tar.gz /test1 /test2 +# 列出压缩文件列表 +tar -tzf test.tar.gz +# 解压文件 +tar -xvzf test.tar.gz + +# 仅打包,不压缩 +tar -cvf log.tar log01.log +# 打包后,以gzip压缩 +tar -zcvf log.tar.gz log01.log +# 打包后,以bzip2压缩 +tar -jcvf log.tar.bz2 log01.log + +# 总结 +# *.tar:用tar –xvf解压 +# *.gz:用gzip -d或者gunzip解压 +# *.tar.gz和*.tgz:用tar –xzf解压 +# *.bz2:用bzip2 -d或者用bunzip2解压 +# *.tar.bz2:用tar –xjf解压 +# *.Z:用uncompress解压 +# *.tar.Z:用tar –xZf解压 +# *.rar:用unrar解压 +# *.zip:用unzip解压 +``` + + + +### su + +```shell +# 切换到其它身份用户,默认是root,如下相同 +su - +# 切换到root用户,并至root目录,不带-只切换用户 +su - root +# 变更帐号为root并在执行ls指令后退出变回原使用者 +su -c ls root +``` + + + +### df + +```shell +# 易读的显示目前磁盘空间和使用情况,-h(1024计算)/-H(1000计算) +df -h +``` \ No newline at end of file diff --git a/src/DevOps/201.md b/src/DevOps/201.md new file mode 100644 index 0000000..eb2c34d --- /dev/null +++ b/src/DevOps/201.md @@ -0,0 +1,52 @@ +### 第一行 + +第一行必须是 `#!/bin/sh`。 + +- 它不是注释,`#!/bin/sh` 是对shell的声明,说明你所用的是那种类型的shell及其路径所在 +- 如果没有声明,则脚本将在默认的shell中执行,默认shell是由用户所在的系统定义为执行shell脚本的shell +- 如果脚本被编写为在Kornshell ksh中运行,而默认运行shell脚本的为C shell csh,则脚本在执行过程中很可能失败 +- 所以建议大家就把 `#!/bin/sh` 当成C 语言的main函数一样,写shell必须有,以使shell程序更严密 + + + +### 注释 + +一行开头为 `#`。 + + + + + +### 接收参数 + +脚本文件“copy.sh”,其内容如下: + +```shell +m=$1 +n=$2 +echo $m-$n +``` + +执行命令:“sh copy.sh 111 222”;输出 111-222 + + + +### 格式化输出日期 + +```shell +curdate="`date +%Y%m%d%H%M%S`" +echo $curdate +``` + +执行结果:20210504175817 + + + +### exist + +退出当前shell脚本,一般来说,返回0表示执行成功,其他值表示没有执行成功。 + +```shell +exist 0 # 返回0 +exist 1 # 返回1 +``` \ No newline at end of file diff --git a/src/DevOps/202.md b/src/DevOps/202.md new file mode 100644 index 0000000..7b8db16 --- /dev/null +++ b/src/DevOps/202.md @@ -0,0 +1,47 @@ +### 变量命名 + +shell 变量的命名规则如下:开头是一个字母或下划线,后面可以接任意长度的字母、数字或下划线符号,变量名的字符长度并无限制(Bourne shell中)。不过为了兼容性(一些早期的shell里变量名是有长度限制的),一般还是不要超过255个字符。另外,**Linux区分大小写**。当用户自己定义变量的时候,要注意变量名不能与 shell 中的关键字重名。 + + + +### 变量赋值 + +`变量名=值` + +注意:**赋值语句两边不能有空格(即 “=” 号两边不能有空格)**。**等号右边若有空格的话,需要加上引号(单引号或双引号都是可以的)**。shell 中可以在变量名前加上 $ 字符来取变量的值。 + + + +### 定义变量 + +定义单变量: + +```shell +p_name='kang' +``` + +使用单变量: + +```shell +echo $p_name'.js' # 输出kang.js +echo $p_name.js # 输出kang.js +cp $p_name.js copy.js; +``` + + + +### 系统变量 + +```shell +pwd=$PWD # 当前目录 +user=$USER # 当前用户 +echo $pwd +echo $user +``` + +运行脚本后输出: + +```shell +/home/rainman/test +rainman +``` \ No newline at end of file diff --git a/src/DevOps/203.md b/src/DevOps/203.md new file mode 100644 index 0000000..a1c5f09 --- /dev/null +++ b/src/DevOps/203.md @@ -0,0 +1,94 @@ +- Shell 并且没有限制数组的大小,理论上可以存放无限量的数据 +- Shell 数组元素的下标也是从 0 开始计数 +- 获取数组中的元素要使用下标`[ ]`,下标可以是一个整数,也可以是一个结果为整数的表达式、 +- 下标必须大于等于 0 +- 常用的 Bash Shell 只支持一维数组,不支持多维数组 + +```shell + #!/bin/bash + +nums=(29 100 13 8 91 44) +echo ${nums[@]} # 输出所有数组元素 +nums[10]=66 # 给第10个元素赋值(此时会增加数组长度) +echo ${nums[*]} # 输出所有数组元素 +echo ${nums[4]} # 输出第4个元素 +``` + + + +### 获取数组长度 + +利用`@`或`*`,可以将数组扩展成列表,然后使用`#`来获取数组元素的个数,格式如下: + +```shell +${#array_name[@]} +${#array_name[*]} +``` + +其中 array_name 表示数组名。两种形式是等价的,选择其一即可。示例如下: + +```shell + #!/bin/bash + +nums=(29 100 13) +echo ${#nums[*]} # 输出3 + +# 向数组中添加元素 +nums[10]="http://c.biancheng.net/shell/" +echo ${#nums[@]} # 输出4 +``` + + + +### 数组拼接 + +拼接数组的思路是:先利用`@`或`*`,将数组扩展成列表,然后再合并到一起。具体格式如下: + +```shell +array_new=(${array1[@]} ${array2[@]}) +array_new=(${array1[*]} ${array2[*]}) +``` + +两种方式是等价的,选择其一即可。其中,array1 和 array2 是需要拼接的数组,array_new 是拼接后形成的新数组。完整示例如下: + +```shell + #!/bin/bash + +array1=(23 56) +array2=(99 "https://www.baidu.com/") +array_new=(${array1[@]} ${array2[*]}) +echo ${array_new[@]} # 也可以写作 ${array_new[*]} +``` + +运行结果:`23 56 99 https://www.baidu.com/` + + + +### 删除数组元素 + +在 Shell 中,使用 unset 关键字来删除数组元素,具体格式如下: + +```shell +unset array_name[index] +``` + +其中,array_name 表示数组名,index 表示数组下标。如果不写下标,而是写成下面的形式: + +```shell +unset array_name +``` + +那么就是删除整个数组,所有元素都会消失。 + +```shell + #!/bin/bash + +arr=(23 56 99 "https://www.baidu.com/") +unset arr[1] +echo ${arr[@]} + +unset arr +echo ${arr[*]} +``` + +运行结果:`23 99 https://www.baidu.com/` \ No newline at end of file diff --git a/src/DevOps/204.md b/src/DevOps/204.md new file mode 100644 index 0000000..9dc69ed --- /dev/null +++ b/src/DevOps/204.md @@ -0,0 +1,64 @@ +### expr命令求值 + +使用 expr 命令对算术表达式求值,常见的命令如下: + +| 表达式 | 说明 | +| ---------------- | -------------------------------------------------------- | +| `expr1 | expr2` | 若 expr1 非零,则等于 expr1 ,否则等于 expr2。 | +| `expr1 & expr2` | 只要有一个表达式为零,则等于零,否则等于 expr1。 | +| `expr1 = expr2` | 等于(与 == 是同义的),若两式相等则结果为1,不等结果为0 | +| `expr1 > expr2` | 大于 | +| `expr1 >= expr2` | 大于等于 | +| `expr1 < expr2` | 小于 | +| `expr1 <= expr2` | 小于等于 | +| `expr1 != expr2` | 不等于 | +| `expr1 + expr2` | 加 | +| `expr1 - expr2` | 减 | +| `expr1 * expr2` | 乘 | +| `expr1 / expr2` | 整除 | +| `expr1 % expr2` | 取余 | + +注意:在 expr 命令所支持的操作符中,“`|`、`&`、`<`、`<=`、`>`、`>=`、 `\*` ” 这几个需要用 `\` 符进行转义再使用。此外,表达式的各字符之间需要用空格隔开。使用方法如下: + +```shell + #!/bin/bash + + a=5;b=6;c=0 + echo $(expr $a \| $c) # 输出 5 + echo $(expr $b \& $c) # 输出 0 + echo $(expr $a \& $b) # 输出 5 + echo $(expr $a \<= $b) # 输出 1 + echo $(expr $a \* $b) # 输出 30 + echo $(expr $a = 2) # 输出 1 exit 0 +``` + + + +**逻辑符号** + +- `命令1 && 命令2`:如果左边的“命令1”执行成功,那么右边的“命令2”才会被执行 + +- `命令1 || 命令2`:与&&相反。如果“命令1”未执行成功,那么就执行“命令2” + + + +### $(( ... ))求值 + +使用 `$(( ... ))` 的方式对算术表达式求值。 + +expr 虽然功能强大,但是上面已经提到,在进行一些运算的时候,需要使用 `\` 符来进行转义,这对于阅读代码的人来说并不友好。另一方面,expr 命令执行起来其实很慢,因为它需要调用一个新的 shell 来处理 expr 命令。更新更好的一种做法是使用 `$((...))` 扩展的方式。只需要将准备求值的表达式放在 `$((...))` 的括号中即可进行简单的算术求值。且,所有支持 `$(( ... ))` 的 shell,都可以让用户在提供变量名称时,无须前置 `$` 符。用一段代码演示一下用法: + +```shell + #!/bin/bash + + a=5;b=6 + + echo $(($a + $b))  # 输出 11 。在变量名前加上 $,这在shell中一般是取变量值的意思 + echo $((a + b)) # 输出 11 。可见,变量前不加 $ 也是可以的,为了简便,后面的代码就不加 $ 了 + echo $((a | b)) # 输出 7 。这里的 | 是按位或操作符 + echo $((a || b)) # 输出 1 。这里的 || 是逻辑或操作符 + echo $((a & b)) # 输出 4 。这里的 & 是按位与操作符 + echo $((a && b)) # 输出 1 。这里的 && 是逻辑与操作符 + echo $((a * b)) # 输出 30 + echo $((a == b)) # 输出 0 exit 0 +``` \ No newline at end of file diff --git a/src/DevOps/205.md b/src/DevOps/205.md new file mode 100644 index 0000000..fd5c9b6 --- /dev/null +++ b/src/DevOps/205.md @@ -0,0 +1,53 @@ +字符串可以由单引号`' '`包围,也可以由双引号`" "`包围,也可以不用引号。它们之间的区别: + +- 由单引号`' '`包围的字符串 + - 任何字符都会原样输出,在其中使用变量是无效的 + - 字符串中不能出现单引号,即使对单引号进行转义也不行 + +- 由双引号`" "`包围的字符串 + - 如果其中包含了某个变量,那么该变量会被解析(得到该变量的值),而不是原样输出 + - 字符串中可以出现双引号,只要它被转义了就行 + +- 不被引号包围的字符串 + - 不被引号包围的字符串中出现变量时也会被解析,这一点和双引号`" "`包围的字符串一样 + - 字符串中不能出现空格,否则空格后边的字符串会作为其他变量或者命令解析 + + + +### 拼接 + +字符串拼接连接、合并。 + +```shell + #!/bin/bash + +name="Shell" +url="https://www.baidu.com/" + +str1=$name$url # 中间不能有空格 +str2="$name $url" # 如果被双引号包围,那么中间可以有空格 +str3=$name": "$url # 中间可以出现别的字符串 +str4="$name: $url" # 这样写也可以 +str5="${name}Script: ${url}index.html" # 这个时候需要给变量名加上大括号 + +echo $str1 +echo $str2 +echo $str3 +echo $str4 +echo $str5 +``` + + + +### 截取 + +| 格式 | 说明 | +| ---------------------------- | ------------------------------------------------------------ | +| `${string: start :length}` | 从 string 字符串的左边第 start 个字符开始,向右截取 length 个字符。 | +| `${string: start}` | 从 string 字符串的左边第 start 个字符开始截取,直到最后。 | +| `${string: 0-start :length}` | 从 string 字符串的右边第 start 个字符开始,向右截取 length 个字符。 | +| `${string: 0-start}` | 从 string 字符串的右边第 start 个字符开始截取,直到最后。 | +| `${string#*chars}` | 从 string 字符串第一次出现 *chars 的位置开始,截取 *chars 右边的所有字符。 | +| `${string##*chars}` | 从 string 字符串最后一次出现 *chars 的位置开始,截取 *chars 右边的所有字符。 | +| `${string%*chars}` | 从 string 字符串第一次出现 *chars 的位置开始,截取 *chars 左边的所有字符。 | +| `${string%%*chars}` | 从 string 字符串最后一次出现 *chars 的位置开始,截取 *chars 左边的所有字符。 | \ No newline at end of file diff --git a/src/DevOps/206.md b/src/DevOps/206.md new file mode 100644 index 0000000..c106e59 --- /dev/null +++ b/src/DevOps/206.md @@ -0,0 +1,116 @@ +test 命令可以处理 shell 脚本中的各类工作。它产生的不是一般的输出,而是可使用的退出状态。test 命令通过接受各种不同的参数,来控制要执行哪种测试。在许多系统上,test 命令与 [ 命令的作用其实是一样的,使用 [ 命令的时候,一般在结尾加上 ] 符号,使代码更具可读性。另外,需要注意一点的是,在使用 [ 命令时,[ 符号与被检查的语句之间应该留有空格**。**shell 中通常使用 test 命令来产生控制结构所需要的条件,根据 test 命令的退出码决定是否需要执行后面的代码。 + +test 命令可以使用的条件类型有三类:字符串比较、算术比较和与文件有关的条件测试。 + +### 字符串比较 + +| 表达式 | 结果 | +| -------------------- | ---------------------------------- | +| `string1 = string2` | 如果两个字符串相同则结果为真 | +| `string1 != string2` | 如果两个字符串不同则结果为真 | +| `-n string` | 如果字符串不为空则结果为真 | +| `-z string` | 如果字符串为空(null),则结果为真 | + +使用方法如下: + +```shell +str1="tongye" +str2="ttyezi" + +# 用 test 命令,test 语句的结果将作为 if 的判断条件,结果为真即条件为真,则执行 if 下面的语句 +if test "$str1" = "$str2" ; then + .... +fi + +# 用 [ 命令的话,可以这样,注意 [ 与表达式之间要有空格 +if [ "$str1" != "$str2" ] ; then + .... +fi if [ -n "$str1" ] ; then ....fi +``` + +使用字符串比较的时候,必须给变量加上引号 " " ,避免因为空字符或字符串中的空格导致一些问题。实际上,对于条件测试语句里的变量,都建议加上双引号,能做字符串比较的时候,不要用数值比较。 + + + +### 算术比较 + +| 算术比较 | 结果 | +| ----------------- | -------------------------------- | +| `expr1 -eq expr2` | 如果两个表达式相等,则结果为真 | +| `expr1 -ne expr2` | 如果两个表达式不相等,则结果为真 | +| `expr1 -gt expr2` | 如果 expr1 > expr2 ,则结果为真 | +| `expr1 -ge expr2` | 如果 expr1 >= expr2 ,则结果为真 | +| `expr1 -lt expr2` | 如果 expr1 < expr2,则结果为真 | +| `expr1 -le expr2` | 如果 expr1 <= expr2,则结果为真 | +| `!expr` | 如果表达式为假,则结果为真 | + +使用方法如下: + +```shell +num1=2 +num2=3 + +if [ "$num1" -eq "$num2" ] ; then + ... +fi + +if [ "$num1" -le "$num2" ] ; then + .... +fi +``` + +注意算术比较和字符串比较之间的不同之处,字符串比较比较的是两个字符串,数字也是能组成字符串的,因此,当我们使用字符串比较的方式和数字比较的方式来比较两串数字的时候,结果会有些不同。案例如下: + +```shell + #!/bin/bash + + val1="1" + val2="001" + val3="1 " # 字符串 val3 在 1 的后面还有一个空格    + + [ "$val1" = "$val2" ] + echo $?        # 使用字符串比较,退出码为 1,说明两个字符串不相等 + + [ "$val1" -eq "$val2" ] + echo $?        # 使用数值比较,退出码为 0,说明两个数值相等 + + [ "$val1" = "$val3" ] + echo $?        # 退出码为 1 + + [ "$val1" -eq "$val3" ] + echo $?        # 退出码为 0 exit 0 +``` + +需要注意的是,如果在编写代码时,变量没有加上双引号,上述程序的结果又会不同,仅对 val3 进行取值,将会忽略该字符串中的空格,则第三个表达式的退出码将为 0 。这也说明了在变量两边加上双引号的重要性。 + + + +### 文件条件测试 + +| 文件条件测试 | 结果 | +| ------------ | ------------------------------------------------------------ | +| `-d file` | 如果文件是一个目录,则结果为真 | +| `-e file` | 如果文件存在,则结果为真。注意,历史上 -e 选项不可移植,所以通常使用的是 -f 选项 | +| `-f file` | 如果文件存在且为普通文件,则结果为真 | +| `-g file` | 如果文件的 set-group-id 位被设置,则结果为真 | +| `-r file` | 如果文件可读,则结果为真 | +| `-s file` | 如果文件大小不为 0 ,则结果为真 | +| `-u file` | 如果文件的 set-user-id 为被设置,则结果为真 | +| `-w file` | 如果文件可写,则结果为真 | +| `-x file` | 如果文件可执行,则结果为真 | + +用一个例子演示一下: + +```shell +#!/bin/bash + +if [ -f /bin/bash ] ; then + echo "file /bin/bash exists" +fi + +if [ -d /bin/bash ] ; then +  echo "/bin/bash is a directory" +else +  echo "/bin/bash is not a directory" +fiexit 0 +``` \ No newline at end of file diff --git a/src/DevOps/207.md b/src/DevOps/207.md new file mode 100644 index 0000000..fee9b7a --- /dev/null +++ b/src/DevOps/207.md @@ -0,0 +1,143 @@ +### if语句 + +"["和"]"前后的空格必须有,否则提示错误。 + +```shell +m="kang2" +if [ "$m" == 'kang' ]; then + echo 'kang' +elif [ $m == 'kang2' ]; then + echo 'kang2' +else + echo 'no' +fi +``` + +示例:判断文件夹 + +```shell +if [ -d './js' ]; then + echo 'js是文件夹' +fi +``` + + + +### case语句 + +与其他编程语言中的 case 语句类似, shell 中的 case 语句也可以用来进行模式匹配,语法如下: + +```shell +case variable in + pattern [ | pattern ] ... ) statements;; + pattern [ | pattern ] ... ) statements;; + ... +esac +``` + +关于 case 的语法,有以下几点需要说明一下: + +- case 语句以 case 作为开头,以 esac 作为结尾 +- case 语句的每个模式行都是以双分号 ;; 结尾的 +- 一个模式行可以合并匹配多个模式,使用 | 符作为分隔 +- 一个模式行可以执行多条语句,各语句之间可以使用单分号 ; 隔开,这也是为什么每行的结尾要使用双分号 ;; 作为结束标志的原因 +- case 语句支持使用正则表达式作为匹配项,这使得 case 语句的功能更为强大 + +```shell +#!/bin/bash + +read -p "please keyin a word:" -t 5 word + +case $word in + [a-z] | [A-Z] ) echo "You have keyin a letter";; + [1-9] ) echo "You have keyin a number";; + * ) echo "Unknow input" +esac + +exit 0 +``` + +这段代码从键盘输入一个字符,然后进行匹配,判断这个字符是字母还是数字,都不是的话返回未知输入。 + + + +### for语句 + +循环:`for/do/done`。注意循环项是以“空格”拆分的字符串。 + +**foreach形式**: + +```shell +name="rain man's blog" +for loop in $name; do + echo $loop; +done +``` + +**自定义步长循环**: + +```shell +for ((初始值; 限定值; 执行步长 )) +do + # 程序段 +done + +# 例如 +for (( i = 1; i < ${number}; i = i + 1 )) +do + # 程序段 +done +``` + +```shell + #!/bin/bash + + for name in tongye wuhen xiaodong wufei laowang + do + echo $name + done + + exit 0 +# 依次输出:tongye wuhen xiaodong wufei laowang +``` + + + +### while与until语句 + +如果你需要进行循环操作而是先不知道需要循环的次数,可以使用 while 循环,while 循环的语法如下: + +```shell +while condition +do + statements +done +``` + +until 循环语句的功能与 while 一样,不同的是对于条件判断结果的处理上。until 循环的语法如下: + +```shell +until condition +do + statements +done +``` + +在 while 和 until 语句中,condition 是判断条件,不同的是,while 语句中,若判断条件为真,则执行循环体;until 语句中,若判断条件为真,则停止执行循环体。 + +```shell + #!/bin/bash + + i=1 + + while [ "$i" -le 10 ] + do + read -p "please keyin a number:" i + done + 9 + 10 echo "$i" + 11 + 12 exit 0 +``` + +这段代码从键盘中输入一个数字,直到输入数值大于 10,退出循环并打印最后输入的那个值。 \ No newline at end of file diff --git a/src/DevOps/208.md b/src/DevOps/208.md new file mode 100644 index 0000000..63f71cb --- /dev/null +++ b/src/DevOps/208.md @@ -0,0 +1,47 @@ +### 输出重定向 + +- 标准输出重定向 + - `command >file`:以覆盖的方式,把 command 的正确输出结果输出到 file 文件中 + - `command >>file`:以追加的方式,把 command 的正确输出结果输出到 file 文件中 +- 标准错误输出重定向 + - `command 2>file`:以覆盖的方式,把 command 的错误信息输出到 file 文件中 + - `command 2>>file`:以追加的方式,把 command 的错误信息输出到 file 文件中 +- 正确输出和错误信息同时保存 + - `command >file 2>&1`:以覆盖的方式,把正确输出和错误信息同时保存到同一个文件(file)中 + - `command >>file 2>&1`:以追加的方式,把正确输出和错误信息同时保存到同一个文件(file)中 + - `command >file1 2>file2`:以覆盖的方式,把正确输出结果输出到 file1 文件中,把错误信息输出到 file2 文件中 + - `command >>file1 2>>file2`: 以追加的方式,把正确输出结果输出到 file1 文件中,把错误信息输出到 file2 文件中 + +示例: + +```shell + #!/bin/bash + +for str in "test1" "test2" "test3" +do + echo $str >>demo.txt # 将输入结果以追加的方式重定向到文件 +done +``` + +```shell +[localhost]$ ls -l >demo.txt # 重定向 +[localhost]$ cat demo.txt # 查看文件内容 +``` + + + +### 自定义函数 + +`$?` 获取函数的返回值。 + +```shell + #!/bin/bash + +# 得到两个数相加的和 +function add(){ + return `expr $1 + $2` +} + +add 23 50 # 调用函数 +echo $? # 获取函数返回值 +``` \ No newline at end of file diff --git a/src/DevOps/209.md b/src/DevOps/209.md new file mode 100644 index 0000000..ca3c6c7 --- /dev/null +++ b/src/DevOps/209.md @@ -0,0 +1,449 @@ +**检测两台服务器指定目录下的文件一致性** + +```shell +#!/bin/bash +##################################### +#检测两台服务器指定目录下的文件一致性 +##################################### +#通过对比两台服务器上文件的md5值,达到检测一致性的目的 +dir=/data/web +b_ip=192.168.88.10 +#将指定目录下的文件全部遍历出来并作为md5sum命令的参数,进而得到所有文件的md5值,并写入到指定文件中 +find $dir -type f|xargs md5sum > /tmp/md5_a.txt +ssh $b_ip "find $dir -type f|xargs md5sum > /tmp/md5_b.txt" +scp $b_ip:/tmp/md5_b.txt /tmp +#将文件名作为遍历对象进行一一比对 +for f in `awk '{print 2} /tmp/md5_a.txt'` +do +#以a机器为标准,当b机器不存在遍历对象中的文件时直接输出不存在的结果 +if grep -qw "$f" /tmp/md5_b.txt +then +md5_a=`grep -w "$f" /tmp/md5_a.txt|awk '{print 1}'` +md5_b=`grep -w "$f" /tmp/md5_b.txt|awk '{print 1}'` +#当文件存在时,如果md5值不一致则输出文件改变的结果 +if [ $md5_a != $md5_b ] +then +echo "$f changed." +fi +else +echo "$f deleted." +fi +done +``` + +**定时清空文件内容,定时记录文件大小** + +```shell +#!/bin/bash +################################################################ +#每小时执行一次脚本(任务计划),当时间为0点或12点时,将目标目录下的所有文件内 +#容清空,但不删除文件,其他时间则只统计各个文件的大小,一个文件一行,输出到以时#间和日期命名的文件中,需要考虑目标目录下二级、三级等子目录的文件 +################################################################ +logfile=/tmp/`date +%H-%F`.log +n=`date +%H` +if [ $n -eq 00 ] || [ $n -eq 12 ] +then +#通过for循环,以find命令作为遍历条件,将目标目录下的所有文件进行遍历并做相应操作 +for i in `find /data/log/ -type f` +do +true > $i +done +else +for i in `find /data/log/ -type f` +do +du -sh $i >> $logfile +done +fi +``` + +**检测网卡流量,并按规定格式记录在日志中** + +```shell +#!/bin/bash +####################################################### +#检测网卡流量,并按规定格式记录在日志中 +#规定一分钟记录一次 +#日志格式如下所示: +#2019-08-12 20:40 +#ens33 input: 1234bps +#ens33 output: 1235bps +######################################################3 +while : +do +#设置语言为英文,保障输出结果是英文,否则会出现bug +LANG=en +logfile=/tmp/`date +%d`.log +#将下面执行的命令结果输出重定向到logfile日志中 +exec >> $logfile +date +"%F %H:%M" +#sar命令统计的流量单位为kb/s,日志格式为bps,因此要*1000*8 +sar -n DEV 1 59|grep Average|grep ens33|awk '{print $2,"\t","input:","\t",$5*1000*8,"bps","\n",$2,"\t","output:","\t",$6*1000*8,"bps"}' +echo "####################" +#因为执行sar命令需要59秒,因此不需要sleep +done +``` + +**杀死所有脚本** + +```shell +#!/bin/bash +################################################################ +#有一些脚本加入到了cron之中,存在脚本尚未运行完毕又有新任务需要执行的情况, +#导致系统负载升高,因此可通过编写脚本,筛选出影响负载的进程一次性全部杀死。 +################################################################ +ps aux|grep 指定进程名|grep -v grep|awk '{print $2}'|xargs kill -9 +``` + +**从FTP服务器下载文件** + +```shell +#!/bin/bash +if [ $# -ne 1 ]; then + echo "Usage: $0 filename" +fi +dir=$(dirname $1) +file=$(basename $1) +ftp -n -v << EOF # -n 自动登录 +open 192.168.1.10 # ftp服务器 +user admin password +binary # 设置ftp传输模式为二进制,避免MD5值不同或.tar.gz压缩包格式错误 +cd $dir +get "$file" +EOF +``` + +**监测Nginx访问日志502情况,并做相应动作** + +假设服务器环境为lnmp,近期访问经常出现502现象,且502错误在重启php-fpm服务后消失,因此需要编写监控脚本,一旦出现502,则自动重启php-fpm服务。 + +```shell +#场景: +#1.访问日志文件的路径:/data/log/access.log +#2.脚本死循环,每10秒检测一次,10秒的日志条数为300条,出现502的比例不低于10%(30条)则需要重启php-fpm服务 +#3.重启命令为:/etc/init.d/php-fpm restart +#!/bin/bash +########################################################### +#监测Nginx访问日志502情况,并做相应动作 +########################################################### +log=/data/log/access.log +N=30 #设定阈值 +while : +do + #查看访问日志的最新300条,并统计502的次数 + err=`tail -n 300 $log |grep -c '502" '` + if [ $err -ge $N ] + then + /etc/init.d/php-fpm restart 2> /dev/null + #设定60s延迟防止脚本bug导致无限重启php-fpm服务 + sleep 60 + fi + sleep 10 +done +``` + +**批量修改文件名** + +```shell +# touch article_{1..3}.html +# ls +article_1.html article_2.html article_3.html + +# 目的:把article改为bbs +# 方法1 +for file in $(ls *html); do + mv $file bbs_${file#*_} + # mv $file $(echo $file |sed -r 's/.*(_.*)/bbs\1/') + # mv $file $(echo $file |echo bbs_$(cut -d_ -f2) +done + +# 方法2 +for file in $(find . -maxdepth 1 -name "*html"); do + mv $file bbs_${file#*_} +done + +# 方法3 +rename article bbs *.html +``` + +**统计当前目录中以.html结尾的文件总大** + +```shell +# 方法1 +find . -name "*.html" -exec du -k {} \; |awk '{sum+=$1}END{print sum}' + +# 方法2 +for size in $(ls -l *.html |awk '{print $5}'); do + sum=$(($sum+$size)) +done +echo $sum +``` + +**扫描主机端口状态** + +```shell +#!/bin/bash +HOST=$1 +PORT="22 25 80 8080" +for PORT in $PORT; do + if echo &>/dev/null > /dev/tcp/$HOST/$PORT; then + echo "$PORT open" + else + echo "$PORT close" + fi +done +``` + +**输入数字运行相应命令** + +```shell +#!/bin/bash +############################################################## +#输入数字运行相应命令 +############################################################## +echo "*cmd menu* 1-date 2-ls 3-who 4-pwd 0-exit " +while : +do +#捕获用户键入值 + read -p "please input number :" n + n1=`echo $n|sed s'/[0-9]//'g` +#空输入检测 + if [ -z "$n" ] + then + continue + fi +#非数字输入检测 + if [ -n "$n1" ] + then + exit 0 + fi + break +done +case $n in + 1) + date + ;; + 2) + ls + ;; + 3) + who + ;; + 4) + pwd + ;; + 0) + break + ;; + #输入数字非1-4的提示 + *) + echo "please input number is [1-4]" +esac +``` + +**Expect实现SSH免交互执行命令** + +Expect是一个自动交互式应用程序的工具,如telnet,ftp,passwd等。需先安装expect软件包。 + +```shell +# 将expect脚本独立出来为登录脚本 +# cat login.exp +#!/usr/bin/expect +set ip [lindex $argv 0] +set user [lindex $argv 1] +set passwd [lindex $argv 2] +set cmd [lindex $argv 3] +if { $argc != 4 } { +puts "Usage: expect login.exp ip user passwd" +exit 1 +} +set timeout 30 +spawn ssh $user@$ip +expect { + "(yes/no)" {send "yes\r"; exp_continue} + "password:" {send "$passwd\r"} +} +expect "$user@*" {send "$cmd\r"} +expect "$user@*" {send "exit\r"} +expect eof + +# 执行命令脚本:写个循环可以批量操作多台服务器 +#!/bin/bash +HOST_INFO=user_info.txt +for ip in $(awk '{print $1}' $HOST_INFO) +do + user=$(awk -v I="$ip" 'I==$1{print $2}' $HOST_INFO) + pass=$(awk -v I="$ip" 'I==$1{print $3}' $HOST_INFO) + expect login.exp $ip $user $pass $1 +done + +# Linux主机SSH连接信息: +# cat user_info.txt +192.168.1.120 root 123456 +``` + +**监控httpd的进程数,根据监控情况做相应处理** + +```sh +#!/bin/bash +############################################################################################################################### +#需求: +#1.每隔10s监控httpd的进程数,若进程数大于等于500,则自动重启Apache服务,并检测服务是否重启成功 +#2.若未成功则需要再次启动,若重启5次依旧没有成功,则向管理员发送告警邮件,并退出检测 +#3.如果启动成功,则等待1分钟后再次检测httpd进程数,若进程数正常,则恢复正常检测(10s一次),否则放弃重启并向管理员发送告警邮件,并退出检测 +############################################################################################################################### +#计数器函数 +check_service() +{ + j=0 + for i in `seq 1 5` + do + #重启Apache的命令 + /usr/local/apache2/bin/apachectl restart 2> /var/log/httpderr.log + #判断服务是否重启成功 + if [ $? -eq 0 ] + then + break + else + j=$[$j+1] + fi + #判断服务是否已尝试重启5次 + if [ $j -eq 5 ] + then + mail.py + exit + fi + done +} +while : +do + n=`pgrep -l httpd|wc -l` + #判断httpd服务进程数是否超过500 + if [ $n -gt 500 ] + then + /usr/local/apache2/bin/apachectl restart + if [ $? -ne 0 ] + then + check_service + else + sleep 60 + n2=`pgrep -l httpd|wc -l` + #判断重启后是否依旧超过500 + if [ $n2 -gt 500 ] + then + mail.py + exit + fi + fi + fi + #每隔10s检测一次 + sleep 10 +done +``` + +**iptables自动屏蔽访问网站频繁的IP** + +```shell +#场景:恶意访问,安全防范 +#1)屏蔽每分钟访问超过200的IP +#方法1:根据访问日志(Nginx为例) +#!/bin/bash +DATE=$(date +%d/%b/%Y:%H:%M) +ABNORMAL_IP=$(tail -n5000 access.log |grep $DATE |awk '{a[$1]++}END{for(i in a)if(a[i]>100)print i}') +#先tail防止文件过大,读取慢,数字可调整每分钟最大的访问量。awk不能直接过滤日志,因为包含特殊字符。 +for IP in $ABNORMAL_IP; do + if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then + iptables -I INPUT -s $IP -j DROP + fi +done + +#方法2:通过TCP建立的连接 +#!/bin/bash +ABNORMAL_IP=$(netstat -an |awk '$4~/:80$/ && $6~/ESTABLISHED/{gsub(/:[0-9]+/,"",$5);{a[$5]++}}END{for(i in a)if(a[i]>100)print i}') +#gsub是将第五列(客户端IP)的冒号和端口去掉 +for IP in $ABNORMAL_IP; do + if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then + iptables -I INPUT -s $IP -j DROP + fi +done + +#2)屏蔽每分钟SSH尝试登录超过10次的IP +#方法1:通过lastb获取登录状态: +#!/bin/bash +DATE=$(date +"%a %b %e %H:%M") #星期月天时分 %e单数字时显示7,而%d显示07 +ABNORMAL_IP=$(lastb |grep "$DATE" |awk '{a[$3]++}END{for(i in a)if(a[i]>10)print i}') +for IP in $ABNORMAL_IP; do + if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then + iptables -I INPUT -s $IP -j DROP + fi +done + +#方法2:通过日志获取登录状态 +#!/bin/bash +DATE=$(date +"%b %d %H") +ABNORMAL_IP="$(tail -n10000 /var/log/auth.log |grep "$DATE" |awk '/Failed/{a[$(NF-3)]++}END{for(i in a)if(a[i]>5)print i}')" +for IP in $ABNORMAL_IP; do + if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then + iptables -A INPUT -s $IP -j DROP + echo "$(date +"%F %T") - iptables -A INPUT -s $IP -j DROP" >>~/ssh-login-limit.log + fi +done +``` + +**根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁** + +```shell +#!/bin/bash +#################################################################################### +#根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁 +#################################################################################### +logfile=/data/log/access.log +#显示一分钟前的小时和分钟 +d1=`date -d "-1 minute" +%H%M` +d2=`date +%M` +ipt=/sbin/iptables +ips=/tmp/ips.txt +block() +{ + #将一分钟前的日志全部过滤出来并提取IP以及统计访问次数 + grep '$d1:' $logfile|awk '{print $1}'|sort -n|uniq -c|sort -n > $ips + #利用for循环将次数超过100的IP依次遍历出来并予以封禁 + for i in `awk '$1>100 {print $2}' $ips` + do + $ipt -I INPUT -p tcp --dport 80 -s $i -j REJECT + echo "`date +%F-%T` $i" >> /tmp/badip.log + done +} +unblock() +{ + #将封禁后所产生的pkts数量小于10的IP依次遍历予以解封 + for a in `$ipt -nvL INPUT --line-numbers |grep '0.0.0.0/0'|awk '$2<10 {print $1}'|sort -nr` + do + $ipt -D INPUT $a + done + $ipt -Z +} +#当时间在00分以及30分时执行解封函数 +if [ $d2 -eq "00" ] || [ $d2 -eq "30" ] + then + #要先解再封,因为刚刚封禁时产生的pkts数量很少 + unblock + block + else + block +fi +``` + +**添加脚本开机自启动** + +```shell +# 将脚本移动到/etc/rc.d/init.d目录 +mv test.sh /etc/rc.d/init.d/test.sh + +# 赋予可执行权限 +chmod +x /etc/rc.d/init.d/test.sh + +# 添加脚本到开机自动启动项目中 +cd /etc/rc.d/init.d +chkconfig --add test.sh +chkconfig test.sh on +``` \ No newline at end of file diff --git a/src/DevOps/3.md b/src/DevOps/3.md new file mode 100644 index 0000000..bb47366 --- /dev/null +++ b/src/DevOps/3.md @@ -0,0 +1,78 @@ +### rpm + +```shell +rpm -ivh package.rpm # 安装一个rpm包 +rpm -ivh --nodeeps package.rpm # 安装一个rpm包而忽略依赖关系警告 +rpm -U package.rpm # 更新一个rpm包但不改变其配置文件 +rpm -F package.rpm # 更新一个确定已经安装的rpm包 +rpm -e package_name.rpm # 删除一个rpm包 +rpm -qa # 显示系统中所有已经安装的rpm包 +rpm -qa | grep httpd # 显示所有名称中包含 "httpd" 字样的rpm包 +rpm -qi package_name # 获取一个已安装包的特殊信息 +rpm -qg "System Environment/Daemons" # 显示一个组件的rpm包 +rpm -ql package_name # 显示一个已经安装的rpm包提供的文件列表 +rpm -qc package_name # 显示一个已经安装的rpm包提供的配置文件列表 +rpm -q package_name --whatrequires # 显示与一个rpm包存在依赖关系的列表 +rpm -q package_name --whatprovides # 显示一个rpm包所占的体积 +rpm -q package_name --scripts # 显示在安装/删除期间所执行的脚本l +rpm -q package_name --changelog # 显示一个rpm包的修改历史 +rpm -qf /etc/httpd/conf/httpd.conf # 确认所给的文件由哪个rpm包所提供 +rpm -qp package.rpm -l # 显示由一个尚未安装的rpm包提供的文件列表 +rpm --import /media/cdrom/RPM-GPG-KEY # 导入公钥数字证书 +rpm --checksig package.rpm # 确认一个rpm包的完整性 +rpm -qa gpg-pubkey # 确认已安装的所有rpm包的完整性 +rpm -V package_name # 检查文件尺寸、 许可、类型、所有者、群组、MD5检查以及最后修改时间 +rpm -Va # 检查系统中所有已安装的rpm包- 小心使用 +rpm -Vp package.rpm # 确认一个rpm包还未安装 +rpm2cpio package.rpm | cpio --extract --make-directories *bin* # 从一个rpm包运行可执行文件 +rpm -ivh /usr/src/redhat/RPMS/`arch`/package.rpm # 从一个rpm源码安装一个构建好的包 +rpmbuild --rebuild package_name.src.rpm # 从一个rpm源码构建一个 rpm 包 +``` + + + +### yum + +```shell +# 下载并安装一个rpm包 +yum install package_name +# 将安装一个rpm包,使用你自己的软件仓库为你解决所有依赖关系 +yum localinstall package_name.rpm +# 更新当前系统中所有安装的rpm包 +yum update package_name.rpm +# 更新一个rpm包 +yum update package_name +# 删除一个rpm包 +yum remove package_name +# 列出当前系统中安装的所有包 +yum list +# 在rpm仓库中搜寻软件包 +yum search package_name +# 删除所有缓存的包和头文件 +yum clean all +``` + + + +### deb/apt + +```shell +dpkg -i package.deb # 安装/更新一个 deb 包 +dpkg -r package_name # 从系统删除一个 deb 包 +dpkg -l # 显示系统中所有已经安装的 deb 包 +dpkg -l | grep httpd # 显示所有名称中包含 "httpd" 字样的deb包 +dpkg -s package_name # 获得已经安装在系统中一个特殊包的信息 +dpkg -L package_name # 显示系统中已经安装的一个deb包所提供的文件列表 +dpkg --contents package.deb # 显示尚未安装的一个包所提供的文件列表 +dpkg -S /bin/ping # 确认所给的文件由哪个deb包提供 + +# APT 软件工具 (Debian, Ubuntu 以及类似系统) +apt-get install package_name # 安装/更新一个 deb 包 +apt-cdrom install package_name # 从光盘安装/更新一个 deb 包 +apt-get update # 升级列表中的软件包 +apt-get upgrade # 升级所有已安装的软件 +apt-get remove package_name # 从系统删除一个deb包 +apt-get check # 确认依赖的软件仓库正确 +apt-get clean # 从下载的软件包中清理缓存 +apt-cache search searched-package # 返回包含所要搜索字符串的软件包名称 +``` \ No newline at end of file diff --git a/src/DevOps/301.md b/src/DevOps/301.md new file mode 100644 index 0000000..7b3dd66 --- /dev/null +++ b/src/DevOps/301.md @@ -0,0 +1 @@ +![SVN集中式](images/DevOps/SVN集中式.png) \ No newline at end of file diff --git a/src/DevOps/302.md b/src/DevOps/302.md new file mode 100644 index 0000000..ffd77f6 --- /dev/null +++ b/src/DevOps/302.md @@ -0,0 +1,32 @@ +### Git Flow + +- 主干分支 +- 稳定分支 +- 开发分支 +- 补丁分支 +- 修改分支 + +![GitFlow](images/DevOps/GitFlow.jpg) + + + +### Github Flow + +- 创建分支 +- 添加提交 +- 提交 PR 请求 +- 讨论和评估代码 +- 部署检测 +- 合并代码 + +![Github-Flow](images/DevOps/Github-Flow.jpg) + + + +### Gitlab Flow + +- 带生产分支 +- 带环境分支 +- 带发布分支 + +![GitlabFlow](images/DevOps/GitlabFlow.jpg) \ No newline at end of file diff --git a/src/DevOps/303.md b/src/DevOps/303.md new file mode 100644 index 0000000..63c3750 --- /dev/null +++ b/src/DevOps/303.md @@ -0,0 +1,71 @@ +Gitflow 工作流是目前非常成熟的一个方案,它定义了一个围绕项目发布的严格分支模型,通过为代码研发、项目发布以及维护分配独立的分支来让项目的迭代过程更加地顺畅,不同于之前的集中式工作流以及功能分支工作流,Gitflow 工作流常驻的分支有两个:主干分支 master、开发分支 develop。和功能分支工作流相比,Gitflow工作流没有增加任何新的概念或命令,它给不同的分支指定了特定的角色,定义它们应该如何、什么时候交互。除了功能分支之外,还为准备发布、维护发布、记录发布分别使用了单独的分支。 + + + +**Gitflow常见分支** + +- 开发主分支:master 分支 + + master 分支的代码是可以直接部署到生成环境的,为了保持稳定性一般不会直接在这个分支上修改代码,都是通过其他分支合并过来的。 + +- 开发主分支:develop分支 + + develop 分支是主开发分支,包含所有要发布到下一个release的代码,主要是由feature分支合并过来的。 + +- 临时分支:feature 分支 + + feature 分支主要是用来开发一个新特性,一旦开发完成会合入 develop 分支,feature 分支也随即删除掉。 + +- 临时分支:release 分支 + + 当需要一个发布一个新release版本时,会基于develop分支创建一个release分支,经过测试人员充分测试后再合入 master 分支和 develop 分支。 + +- 临时分支:hotfix 分支 + + 当在生成环境发现新的Bug时候,如果需要紧急修复,会创建一个hotfix分支, 充分测试后合入master和develop分支,随后删除该分支。 + + + +**分支命名规范** + +团队内部可以约定每个分支的命名样式,这里举个例子,大家可以参考: + +- feature分支:以feature_开头,如 feature_order + +- release分支:以release_开头,如 release_v1.0 + +- hotfix分支:以hotfix_开头,如hotfix_20210117 + +- tag标记:如果是release分支合并,则以release\_开头,如果是hotfix分支合并,则以hotfix\_开头。 + + + +### master与develop分支 + +原则上master分支上所有的commit 都应该打上Tag,因为一般情况下master不存在直接commit。devlop分支是基于 master分支创建的,与 master 分支一样都是主分支,不会被删除。develop 从 master 拉出来之后会独立发展,不会与 master 直接产生联系。 + +![master与develop分支](images/DevOps/master与develop分支.png) + + + +### feature分支 + +通常一个独立的特性都会基于develop拉出一个feature分支,feature 分支之间没有任何交互,互不影响。feature 分支一旦开发完成后会立马合入 develop 分支(采用 merge request 或者 pull request),feature 分支的生命周期也随之结束。 + +![feature分支](images/DevOps/feature分支.png) + + + +### release分支 + +通常一个迭代上线会拉一个release 分支,开发人员开发完毕所有的代码都已合入 develop 分支,这时候会基于 develop 分支拉出一个 release 分支,测试人员基于该分支进行测试。 + +![release分支](images/DevOps/release分支.png) + + + +### hotfix分支 + +hotfix分支基于master分支创建,开发完后需要同时回合到master和develop分支,同时在master上打一个tag。 + +![hotfix分支](images/DevOps/hotfix分支.png) \ No newline at end of file diff --git a/src/DevOps/304.md b/src/DevOps/304.md new file mode 100644 index 0000000..96b5b0a --- /dev/null +++ b/src/DevOps/304.md @@ -0,0 +1,203 @@ +### 新建代码库 + +```shell +# 在当前目录新建一个Git代码库 +$ git init +# 新建一个目录,将其初始化为Git代码库 +$ git init [project-name] +# 下载一个项目和它的整个代码历史 +$ git clone [url] +``` + + + +### 配置信息 + +Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置) + +```shell +# 显示当前的Git配置 +$ git config --list + +# 编辑Git配置文件 +$ git config -e [--global] + +# 设置提交代码时的用户信息 +$ git config [--global] user.name "[name]" +$ git config [--global] user.email "[email address]" + + +# 颜色设置 +git config --global color.ui true # git status等命令自动着色 +git config --global color.status auto +git config --global color.diff auto +git config --global color.branch auto +git config --global color.interactive auto +git config --global --unset http.proxy # remove proxy configuration on git +``` + + + +### 增加/删除文件 + +```shell +# 添加指定文件到暂存区 +$ git add [file] [dir] ... +# 删除工作区文件,并且将这次删除放入暂存区 +$ git rm [file1] [file2] ... +``` + + + +### 代码提交 + +```shell +# 提交暂存区到仓库区 +$ git commit -m [message] +# 提交暂存区的指定文件到仓库区 +$ git commit [file1] [file2] ... -m [message] +``` + + + +### 分支 + +```shell +# 列出所有本地分支和远程分支 +$ git branch -a + +# 新建一个分支,但依然停留在当前分支 +$ git branch [branch-name] +# 新建一个分支,并切换到该分支 +$ git checkout -b [branch] +# 从远程分支develop创建新本地分支devel并检出 +$ git checkout -b devel origin/develop + +# 切换到指定分支,并更新工作区 +$ git checkout [branch-name] + +# 合并指定分支到当前分支 +$ git merge [branch] +# 选择一个commit,合并进当前分支 +$ git cherry-pick [commit] + +# 删除分支 +$ git branch -d [branch-name] +# 删除远程分支 +$ git push origin --delete [branch-name] +``` + + + +### 标签 + +```shell +# 列出所有tag +$ git tag +# 新建一个tag在当前commit +$ git tag [tag] + +# 删除本地tag +$ git tag -d [tag] +# 删除远程tag +$ git push origin :refs/tags/[tagName] + +# 查看tag信息 +$ git show [tag] + +# 提交指定tag +$ git push [remote] [tag] +# 提交所有tag +$ git push [remote] --tags +``` + + + +### 查看信息 + +```shell +# 显示有变更的文件 +$ git status + +# 显示当前分支的版本历史 +$ git log +# 显示commit历史,以及每次commit发生变更的文件 +$ git log --stat +# 搜索提交历史,根据关键词 +$ git log -S [keyword] +# 显示某个commit之后的所有变动,每个commit占据一行 +$ git log [tag] HEAD --pretty=format:%s +# 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件 +$ git log [tag] HEAD --grep feature +# 显示某个文件的版本历史,包括文件改名 +$ git log --follow [file] + +# 显示指定文件相关的每一次diff +$ git log -p [file] +# 显示过去5次提交 +$ git log -5 --pretty --oneline + +# 显示所有提交过的用户,按提交次数排序 +$ git shortlog -sn + +# 显示指定文件是什么人在什么时间修改过 +$ git blame [file] + +# 显示暂存区和工作区的差异 +$ git diff +# 显示暂存区和上一个commit的差异 +$ git diff --cached [file] +# 显示工作区与当前分支最新commit之间的差异 +$ git diff HEAD +# 显示两次提交之间的差异 +$ git diff [first-branch]...[second-branch] +# 显示今天你写了多少行代码 +$ git diff --shortstat "@{0 day ago}" + +# 显示某次提交的元数据和内容变化 +$ git show [commit] +# 显示某次提交发生变化的文件 +$ git show --name-only [commit] +# 显示某次提交时,某个文件的内容 +$ git show [commit]:[filename] + +# 显示当前分支的最近几次提交 +$ git reflog +``` + + + +### 远程同步 + +```shell +# 下载远程仓库的所有变动 +$ git fetch [remote] + +# 显示所有远程仓库 +$ git remote -v +# 显示某个远程仓库的信息 +$ git remote show [remote] +# 增加一个新的远程仓库,并命名 +$ git remote add [shortname] [url] + +# 取回远程仓库的变化,并与本地分支合并 +$ git pull [remote] [branch] + +# 上传本地指定分支到远程仓库 +$ git push [remote] [branch] +``` + + + +### 撤销 + +```shell +# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变 +$ git reset [file] +# 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变 +$ git reset [commit] +# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致 +$ git reset --hard [commit] +# 后者的所有变化都将被前者抵消,并且应用到当前分支 +$ git revert [commit] +``` \ No newline at end of file diff --git a/src/DevOps/305.md b/src/DevOps/305.md new file mode 100644 index 0000000..cafb8b9 --- /dev/null +++ b/src/DevOps/305.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待!有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/DevOps/4.md b/src/DevOps/4.md new file mode 100644 index 0000000..7f9ed95 --- /dev/null +++ b/src/DevOps/4.md @@ -0,0 +1,320 @@ +### tail + +```shell +# tail语法格式: +# tail [-f] [-c Number|-n Number|-m Number|-b Number|-k Number] [File] + +# 倒数300行并进入实时监听文件写入模式 +tail -300f example.log +# 查看文件尾10行 +tail -n 10 example.log +# 实时查看日志文件 +tail -f example.log +``` + + + +### grep + +```shell +# 文件查找 +grep forest test.txt +# 多文件查找 +grep forest test.txt example.txt +# 目录下查号所有符合关键词的文件 +grep 'log' /home/test -r -n +# 在文件 '/var/log/messages'中查找以"Aug"开始的词汇 +grep ^Aug /var/log/messages +# 查找指定文件中的关键词并打印至控制台 +cat f.txt | grep -i shopbase +# 查找指定文件中的关键词并统计其出现次数 +cat f.txt | grep -c 'shopbase' +# 指定文件后缀 +grep 'shopbase' /home/test -r -n --include *.{vm,java} +# 反匹配 +grep 'shopbase' /home/test -r -n --exclude *.{vm,java} + +# 上匹配 +seq 10 | grep 5 -A 3 +# 下匹配 +seq 10 | grep 5 -B 3 +# 上下匹配,平时用这个就妥了 +seq 10 | grep 5 -C 3 + +# 查找当前目录中的所有jar文件 +ls -l | grep '.jar' +# 查找所以有的包含spring的xml文件 +grep -H 'spring' *.xml +# 显示所有以d开头的文件中包含test的行 +grep 'test' d* +# 显示在aa,bb,cc文件中匹配test的行 +grep 'test' aa bb cc +# 显示所有包含每个字符串至少有5个连续小写字符的字符串的行 +grep '[a-z]\{5\}' aa +# 找出文件中包含123或者包含abc的行 +grep -E '123|abc' filename.txt +# 找出文件中包含123,且包含abc的行 +grep '123' filename.txt | grep 'abc' + +# 显示foo及后5行 +grep -A 5 Exception app.log +# 显示foo及前5行 +grep -B 5 Exception app.log +# 显示app.log文件里匹配Exception字串那行以及上下5行 +grep -C 5 Exception app.log +``` + +**查看文件内容** + +```shell +cat file1 # 从第一个字节开始正向查看文件的内容 +tac file1 # 从最后一行开始反向查看一个文件的内容 +more file1 # 查看一个长文件的内容 +less file1 # 类似于 'more' 命令,但是它允许在文件中和正向操作一样的反向操作 +head -2 file1 # 查看一个文件的前两行 +tail -2 file1 # 查看一个文件的最后两行 +tail -f /var/log/messages # 实时查看被添加到一个文件中的内容 +``` + +**文本处理** + +```shell +cat file1 file2 ... | command <> file1_in.txt_or_file1_out.txt general syntax for text manipulation using PIPE, STDIN and STDOUT +cat file1 | command( sed, grep, awk, grep, etc...) > result.txt # 合并一个文件的详细说明文本,并将简介写入一个新文件中 +cat file1 | command( sed, grep, awk, grep, etc...) >> result.txt # 合并一个文件的详细说明文本,并将简介写入一个已有的文件中 +grep Aug /var/log/messages # 在文件 '/var/log/messages'中查找关键词"Aug" +grep ^Aug /var/log/messages # 在文件 '/var/log/messages'中查找以"Aug"开始的词汇 +grep [0-9] /var/log/messages # 选择 '/var/log/messages' 文件中所有包含数字的行 +grep Aug -R /var/log/* # 在目录 '/var/log' 及随后的目录中搜索字符串"Aug" +sed 's/stringa1/stringa2/g' example.txt # 将example.txt文件中的 "string1" 替换成 "string2" +sed '/^$/d' example.txt # 从example.txt文件中删除所有空白行 +sed '/ *#/d; /^$/d' example.txt # 从example.txt文件中删除所有注释和空白行 +echo 'esempio' | tr '[:lower:]' '[:upper:]' # 合并上下单元格内容 +sed -e '1d' result.txt # 从文件example.txt 中排除第一行 +sed -n '/stringa1/p' # 查看只包含词汇 "string1"的行 +sed -e 's/ *$//' example.txt # 删除每一行最后的空白字符 +sed -e 's/stringa1//g' example.txt # 从文档中只删除词汇 "string1" 并保留剩余全部 +sed -n '1,5p;5q' example.txt # 查看从第一行到第5行内容 +sed -n '5p;5q' example.txt # 查看第5行 +sed -e 's/00*/0/g' example.txt # 用单个零替换多个零 +cat -n file1 # 标示文件的行数 +cat example.txt | awk 'NR%2==1' # 删除example.txt文件中的所有偶数行 +echo a b c | awk '{print $1}' # 查看一行第一栏 +echo a b c | awk '{print $1,$3}' # 查看一行的第一和第三栏 +paste file1 file2 # 合并两个文件或两栏的内容 +paste -d '+' file1 file2 # 合并两个文件或两栏的内容,中间用"+"区分 +sort file1 file2 # 排序两个文件的内容 +sort file1 file2 | uniq # 取出两个文件的并集(重复的行只保留一份) +sort file1 file2 | uniq -u # 删除交集,留下其他的行 +sort file1 file2 | uniq -d # 取出两个文件的交集(只留下同时存在于两个文件中的文件) +comm -1 file1 file2 # 比较两个文件的内容只删除 'file1' 所包含的内容 +comm -2 file1 file2 # 比较两个文件的内容只删除 'file2' 所包含的内容 +comm -3 file1 file2 # 比较两个文件的内容只删除两个文件共有的部分 +``` + + + +### awk + +```shell +# 1.原理 +# 逐行处理文件中的数据 + +# 2.语法 +awk 'pattern + {action}' +# 说明: +# 单引号''是为了和shell命令区分开 +# 大括号{}表示一个命令分组 +# pattern是一个过滤器,表示命中pattern的行才进行action处理 +# action是处理动作 +# 使用#作为注释 + +# 3.内置变量 +FS # 分隔符,默认是空格 +NR # 当前行数,从1开始 +NF # 当前记录字段个数 +$0 # 当前记录 +$1~$n # 当前记录第n个字段 + +# 4.内置函数 +gsub(r,s) # 在$0中用s代替r +index(s,t) # 返回s中t的第一个位置 +length(s) # s的长度 +match(s,r) # s是否匹配r +split(s,a,fs) # 在fs上将s分成序列a +substr(s,p) # 返回s从p开始的子串 + +# 5.案例 +# 显示hello.txt中的第3行至第5行的命令为 +cat hello.txt | awk 'NR==3, NR==5{print;}' +# 显示hello.txt中,正则匹配hello的行的命令为 +cat hello.txt | awk '/hello/' +# 显示hello.txt中,长度大于100的行号的命令为 +cat hello.txt | awk 'length($0)>80{print NR}' +# 显示hello.txt中的第3行至第5行的第一列与最后一列 +cat hello.txt | awk 'NR==3, NR==5{print $1,$NF}' + +# 基础命令 +# 在控制台循环打印打印第4列和第6列数据 +awk '{print $4,$6}' f.txt +awk '{print NR,$0}' f.txt cpf.txt +awk '{print FNR,$0}' f.txt cpf.txt +awk '{print FNR,FILENAME,$0}' f.txt cpf.txt +awk '{print FILENAME,"NR="NR,"FNR="FNR,"$"NF"="$NR}' f.txt cpf.txt +echo 1:2:3:4 | awk -F: '{print $1,$2,$3}' + +# 匹配 +# 匹配ldb +awk '/ldb/ {print}' f.txt +# 不匹配ldb +awk '!/ldb/ {print}' f.txt +# 匹配ldb和LISTEN +awk '/ldb/ && /LISTEN/ {print}' f.txt +# 第五列匹配ldb +awk '$5 ~ /ldb/ {print}' f.txt + +# 内建变量 +# NR:NR表示从awk开始执行后,按照记录分隔符读取的数据次数,默认的记录分隔符为换行符,因此默认的就是读取的数据行数,NR可以理解为Number of Record的缩写 +# FNR:在awk处理多个输入文件的时候,在处理完第一个文件后,NR并不会从1开始,而是继续累加,因此就出现了FNR,每当处理一个新文件的时候,FNR就从1开始计数,FNR可以理解为File Number of Record +# NF: NF表示目前的记录被分割的字段的数目,NF可以理解为Number of Field +``` + + + +### find + +```shell +# 根据名称查找/目录下的filename.txt文件 +find / -name filename.txt +# 递归查找所有的xml文件 +find . -name "*.xml" +# 递归查找所有文件内容中包含hello world的xml文件 +find . -name "*.xml" |xargs grep "hello world" +# 删除文件大小为零的文件 +find ./ -size 0 | xargs rm -f & + +# 多个目录查找 +find /home/admin /tmp /usr -name \*.log +# 大小写都匹配 +find . -iname \*.txt +# 当前目录下的所有子目录 +find . -type d +# 当前目录下所有的符号链接 +find /usr -type l +# 符号链接的详细信息 eg:inode,目录 +find /usr -type l -name "z*" -ls +# 超过250000k的文件,当然+改成-就是小于了 +find /home/admin -size +250000k +# 按照权限查询文件 +find /home/admin -f -perm 777 -exec ls -l {} \; + +# 1天内访问过的文件 +find /home/admin -atime -1 +# 1天内状态改变过的文件 +find /home/admin -ctime -1 +# 1天内修改过的文件 +find /home/admin -mtime -1 + +# 1分钟内访问过的文件 +find /home/admin -amin -1 +# 1分钟内状态改变过的文件 +find /home/admin -cmin -1 +# 1分钟内修改过的文件 +find /home/admin -mmin -1 + +# 删除大于50M的文件 +find /var/mail/ -size +50M -exec rm {} \ +``` + + + +### netstat + +```shell +# 查看当前连接,注意CLOSE_WAIT偏高的情况 +netstat -nat|awk '{print $6}'|sort|uniq -c|sort -rn +# 显示所有tcp连接,并包括pid和程序名 +netstat -atnp +# 统计所有tcp状态的数量并排序 +netstat -atn | awk '{print $6}' | sort | uniq -c | sort -rn +# 每隔1s显示网络信息(-c参数) +netstat -ctn | grep "ESTABLISHED" +# 列出所有处于连接状态的ip并按数量排序 +netstat -an | grep ESTABLISHED | awk '/^tcp/ {print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -nr +``` + + + +### echo + +```shell +# 创建test.txt文件,并向该文件写入“内容” +echo "内容" > test.txt +# 输出环境变量$JAVA_HOME的值 +echo $JAVA_HOME +``` + + + +### telnet + +```shell +# 查看端口是否通畅:telnet IP 端口号 +telnet 10.150.159.71 5516 +``` + + + +### whereis + +Linux whereis命令用于查找文件。 + +```shell +whereis [-bfmsu][-B <目录>...][-M <目录>...][-S <目录>...][文件...] + +# 参数: +# -b:只查找二进制文件 +# -B<目录>:只在设置的目录下查找二进制文件 +# -f:不显示文件名前的路径名称 +# -m:只查找说明文件 +# -M<目录>:只在设置的目录下查找说明文件 +# -s:只查找原始代码文件 +# -S<目录>:只在设置的目录下查找原始代码文件 +# -u:查找不包含指定类型的文件 +``` + + + +### touch/mkdir + + + +### gzip/rar/tar + +```shell +bunzip2 file1.bz2 # 解压一个叫做 'file1.bz2'的文件 +bzip2 file1 # 压缩一个叫做 'file1' 的文件 + +gunzip file1.gz # 解压一个叫做 'file1.gz'的文件 +gzip file1 # 压缩一个叫做 'file1'的文件 +gzip -9 file1 # 最大程度压缩 + +rar a file1.rar test_file # 创建一个叫做 'file1.rar' 的包 +rar a file1.rar file1 file2 dir1 # 同时压缩 'file1', 'file2' 以及目录 'dir1' +rar x file1.rar # 解压rar包 +unrar x file1.rar # 解压rar包 + +tar -cvf archive.tar file1 # 创建一个非压缩的 tarball +tar -cvf archive.tar file1 file2 dir1 # 创建一个包含了 'file1', 'file2' 以及 'dir1'的档案文件 +tar -tf archive.tar # 显示一个包中的内容 +tar -xvf archive.tar # 释放一个包 +tar -xvf archive.tar -C /tmp # 将压缩包释放到 /tmp目录下 +tar -cvfj archive.tar.bz2 dir1 # 创建一个bzip2格式的压缩包 +tar -xvfj archive.tar.bz2 # 解压一个bzip2格式的压缩包 +tar -cvfz archive.tar.gz dir1 # 创建一个gzip格式的压缩包 +tar -xvfz archive.tar.gz # 解压一个gzip格式的压缩包 + +zip file1.zip file1 # 创建一个zip格式的压缩包 +zip -r file1.zip file1 file2 dir1 # 将几个文件和目录同时压缩成一个zip格式的压缩包 +unzip file1.zip # 解压一个zip格式压缩包 +``` \ No newline at end of file diff --git a/src/DevOps/401.md b/src/DevOps/401.md new file mode 100644 index 0000000..308bbfd --- /dev/null +++ b/src/DevOps/401.md @@ -0,0 +1,32 @@ +```shell +# 参数说明: +# -n:即requests,用于指定压力测试总共的执行次数 +# -c:即concurrency,用于指定压力测试的并发数 +# -t:即timelimit,等待响应的最大时间(单位:秒) +# -b:即windowsize,TCP发送/接收的缓冲大小(单位:字节) +# -p:即postfile,发送POST请求时需要上传的文件,此外还必须设置-T参数 +# -u:即putfile,发送PUT请求时需要上传的文件,此外还必须设置-T参数 +# -T:即content-type,用于设置Content-Type请求头信息,例如:application/json,默认值为text/plain +# -w:以HTML表格形式打印结果 +# -i:使用HEAD请求代替GET请求 +# -x:插入字符串作为table标签的属性 +# -y:插入字符串作为tr标签的属性 +# -z:插入字符串作为td标签的属性 +# -C:添加cookie信息,例如:"Apache=1234"(可以重复该参数选项以添加多个) +# -H:添加任意的请求头,如:"Accept-Encoding: gzip",可以重复该参数选项以添加多个 +# -A:添加一个基本的网络认证信息,用户名和密码之间用英文冒号隔开 +# -P:添加一个基本的代理认证信息,用户名和密码之间用英文冒号隔开 +# -X:指定使用的代理服务器和端口号,例如:"126.10.10.3:88" +# -k:使用HTTP的KeepAlive特性 +# -e:输出结果信息到CSV格式的文件中。 +# -r:指定接收到错误信息时不退出程序。 + +# 在任意目录下执行该命令 +yum -y install httpd-tools +# 添加请求头参数 +ab -n100 -c10 -H "Cookie: Key1=Value1; Key2=Value2" http://127.0.0.1:8080/get +# ab测试简单HTTP GET接口 +ab -n30000 -c1000 http://127.0.0.1:8080/get +# ab测试HTTP POST接口,img.json为符合接口格式的字符串 +ab -n400 -c20 -p "img.json" -T "application/x-www-form-urlencoded" http://127.0.0.1:8080/add +``` \ No newline at end of file diff --git a/src/DevOps/402.md b/src/DevOps/402.md new file mode 100644 index 0000000..a408f99 --- /dev/null +++ b/src/DevOps/402.md @@ -0,0 +1,222 @@ +**第一步**:安装JDK,配置环境变量 + +**第二步**:Linux下安装jmeter + +官方网站下载最新版本:http://jmeter.apache.org/download_jmeter.cgi,目前最新版是Apache JMeter 3.3。下载二进制包,使用JMeter依赖jdk,建议安装jdk 1.6版本以上。解压JMeter:`tar -zxvf apache-jmeter-3.3.tgz` + +### Junit + +**第一步**:编写测试类Jmeter Junit代码,然后进行编译验证通过 + +**第二步**:调试通过后,导出Jar包,并将该Jar包导入到.\Jmeter\apache-jmeter-2.13\lib\junit目录下。(如果编写代码时,存在第三方Jar包引入,那么就将该第三方Jar包放在.\Jmeter\apache-jmeter-2.13\lib中) + +![Junit-Export](images/DevOps/Junit-Export.png) + +![Junit-Jar-Export](images/DevOps/Junit-Jar-Export.png) + +**第三步**:重新启动Jmeter,添加三条:Junit Request、查看结果树、图形结果 + +![Junit-Reuest1](images/DevOps/Junit-Reuest1.png) + + ![Junit-Reuest2](images/DevOps/Junit-Reuest2.png)![Junit-Reuest3](images/DevOps/Junit-Reuest3.png) + +**第四步**:点击运行按钮,可以在查看结果树中查看结果,如果想要将测试结果保存到文件,可以如下图配置: + +![Junit-查看结果树](images/DevOps/Junit-查看结果树.png) + + + +### Thread Group + +使用Thread Group, 控制模拟多少用户。选中Thread Group + +![Junit-Thread-Group](images/DevOps/Junit-Thread-Group.png) + +- `Number of Threads(users)`: 一个用户占一个线程, 200个线程就是模拟200个用户 +- `Ramp-Up Period(in seconds)`: 设置线程需要多长时间全部启动。如果线程数为200 ,准备时长为10 ,那么需要1秒钟启动20个线程。也就是每秒钟启动20个线程 +- `Loop Count`: 每个线程发送请求的次数。如果线程数为200 ,循环次数为10 ,那么每个线程发送10次请求。总请求数为200*10=2000 。如果勾选了“永远”,那么所有线程会一直发送请求,直到选择停止运行脚本 + + + +### HTTP Request + +![Junit-HTTP-Request-Add](images/DevOps/Junit-HTTP-Request-Add.png) + +比如我要发送一个GET方法的http请求,可以按照下图这么填: + +![Junit-HTTP-Request-Config](images/DevOps/Junit-HTTP-Request-Config.png) + + + +### Summary Report + +添加Summary Report 用来查看测试结果。选中Thread Group 右键(Add -> Listener -> Summary Report)。运行一下,到目前为止, 脚本就全写好了, 我们来运行下, 如何看下测试的结果: + +![Junit-Summary-Report](images/DevOps/Junit-Summary-Report.png) + + + +### CSV Data Set Config + +使用CSV Data Set Config 来参数化。首先我们把测试需要用到的2个参数放在txt文件中。新建一个data.txt文件,输入些数据, 一行有两个数据,用逗号分隔。 + +![Junit-CSV-Data-Set-Config-Data](images/DevOps/Junit-CSV-Data-Set-Config-Data.png) + +启动Jmeter, 先添加一个Thread Group, 然后添加一个CSV Data Set Config (Add -> Config Element -> CSV Data Set Config) + +![Junit-CSV-Data-Set-Config-Set](images/DevOps/Junit-CSV-Data-Set-Config-Set.png) + +我们添加http 请求,模拟发送get 到:`http://cn.bing.com/search?q=博客园+小坦克`。选择Thread Group 右键 (Add ->Sampler -> HTTP Request), 需要填的数据如下: + +![Junit-HTTP-Request-GetCityCode](images/DevOps/Junit-HTTP-Request-GetCityCode.png) + + + +### HTTP Head Manager + +添加HTTP Head Manager。选中新建的HTTP request,右键,新建一个Http Header manager,添加一个header: + +![Junit-HTTP-Head-Manager-Add](images/DevOps/Junit-HTTP-Head-Manager-Add.png) + +![Junit-HTTP-Head-Manager-Referer](images/DevOps/Junit-HTTP-Head-Manager-Referer.png) + + + +### Http Cookie Manager + +**Http Cookie Manager的作用**: + +- **自动管理cookie**:像浏览器一样的存储和发送Cookie,如果发送一个http请求他的响应中包含Cookie,那么Cookie Manager就会自动地保存这些Cookie并在所有后来发送到该站点的请求中使用这些Cookie的值。每个线程都自己存储cookie的区域。在cookie manager中看不到自动保存的cookie,我们可以在View Results Tree的Request界面看到被发送的Cookie Data。 + + 接受到的Cookie的值能被存储到JMeter 线程变量中(2.3.2版本后的JMeter不自动做这个事情)。要把Cookies保存到线程变量中,要定义属性”CookieManager.save.cookies=true”。线程变量名为COOKIE_ + Cookie名。属性CookieManager.name.prefix= 可以用来修改默认的COOKIE_的值。 + +- **手动管理Cookie**:手动添加Cookie到Cookie Manager,这些Cookie的值被会所有线程共享。 + +比较简单的做法是使用firefox的firebug导出cookies: + +![Junit-Http-Cookie-Manager-Cookies](images/DevOps/Junit-Http-Cookie-Manager-Cookies.png) + +然后,在把文件导入到jmeter: + +![Junit-Http-Cookie-Manager-Config](images/DevOps/Junit-Http-Cookie-Manager-Config.png) + +**特别注意**: + +如果在一个测试计划内有多个Cookie Manager ,Jmeter目前无法指定哪个被使用。所以一个测试计划内最好只有一个cookie manager。并且一个manager里的 cookie 并不能被其它manager所引用。所以在使用多个Cookie Managers 时要谨慎。 + + + +### View Results Tree + +添加View Results Tree,View Results Tree 是用来看运行的结果的: + +![Junit-View-Results-Tree](images/DevOps/Junit-View-Results-Tree.png) + +运行测试,查看结果: + +![Junit-View-Results-Tree-Run](images/DevOps/Junit-View-Results-Tree-Run.png) + +![Junit-View-Results-Tree-JSON](images/DevOps/Junit-View-Results-Tree-JSON.png) + + + +### Assertion & Assert Results + +添加Assertion和Assert Results来实现结果的断言。选择HTTP Request, 右键 Add-> Assertions -> Response Assertion,添加 Patterns To Test: + +![Junit-Response-Assertion](images/DevOps/Junit-Response-Assertion.png) + +然后添加一个Assetion Results 用来查看Assertion执行的结果。选中Thread Group 右键 Add -> Listener -> Assertion Results。运行后,如果HTTP Response中没有包含期待的字符串,那么test 就会Fail: + +![Junit-View-Results-Tree-Fail](images/DevOps/Junit-View-Results-Tree-Fail.png) + +![Junit-Assert-Results](images/DevOps/Junit-Assert-Results.png) + + + +### User Defined Variables + +使用用户自定义变量。我们还可以在Jmeter中定义变量,比如我定义一个变量叫 city,使用它的时候用 ${city} + +添加一个 User Defined Variables,选中Thread Group: 右键Add -> Config Element -> User Defined Variables: + +![Junit-User-Defined-Variables](images/DevOps/Junit-User-Defined-Variables.png) + + 然后在Http Request中使用这个变量: + +![Junit-User-Defined-Variables变量](images/DevOps/Junit-User-Defined-Variables变量.png) + + + +### Regular Expression Extractor + +Regular Expression Extractor所谓关联, 就是第二个Requst, 使用第一个Request中的数据,我们需要在第一个Http Requst 中新建一个正则表达式,把Response的值提取到变量中,提供给别的Http Request 使用。选择第一个Http Request, 右键 Add -> Post Processors -> Regular Expresstion Extractor: + +![Junit-Regular-Expresstion-Extractor](images/DevOps/Junit-Regular-Expresstion-Extractor.png) + + 现在新建第二个Http Request, 发送到: http://www.weather.com.cn/weather2d/${citycode}.html + +${citycode} 中的数据, 是从Regular Expression Extractor 中取来的: + +![Junit-Regular-Expresstion-Extractor变量](images/DevOps/Junit-Regular-Expresstion-Extractor变量.png) + + 到这, 脚本就全部写好了, 运行下,看下最终结果: + +![Junit-Regular-Expresstion-Extractor结果](images/DevOps/Junit-Regular-Expresstion-Extractor结果.png) + + + +### Run AS + +运行测试,查看结果: + +![Junit-View-Results-Tree-Run](images/DevOps/Junit-View-Results-Tree-Run.png) + + + +### HTTP Mirror Server + +HTTP Mirror Server可以在本地临时搭建一个HTTP服务器,该服务器把接收到的请求原样返回,这样就可以看到发送出的请求的具体内容,以供调试。 **实例如下**: + +**第一步**:添加HTTP Mirror Server + +右键点击WorkBench-->Add-->Non-Test Elements-->HTTP Mirror Server ,点击【Start】启动。 + +![HTTP-Mirror-Server](images/DevOps/HTTP-Mirror-Server.png) + +**第二步**:发送请求到该服务器 + +![HTTP-Mirror-Server-Send](images/DevOps/HTTP-Mirror-Server-Send.png) + + **第三步**:对比Request与Response + +![HTTP-Mirror-Server-Response](images/DevOps/HTTP-Mirror-Server-Response.png) + +![HTTP-Mirror-Server-Response-Data](images/DevOps/HTTP-Mirror-Server-Response-Data.png) + +可以看到,Response中的内容与Request内容一模一样,我们就可以通过此种方法判断我们发送出去的请求是否确实是我们预期的结果。 + + + +### Non-GUI Mode + +Non-GUI Mode (Command Line mode) + +```shell +-n 指定JMeter以非GUI模式运行 +-t 包含测试计划的jmx文件的名称(.jmx测试脚本) +-l 记录样本结果日志的jtl文件名称 +-j JMeter运行日志文件名称 +-r 在JMeter属性"remote_hosts"所指定的服务器中运行测试 +-R [远程服务器列表]在指定的远程服务器上运行测试 +-g [CSV文件路径]只生成报表 +-e 负载测试后生成报表 +-o 负载测试完成后,用于存放所生成报表的文件夹(文件夹必须不存在or文件夹内为空) +``` + +e.g: + +```powershell +[root@localhost ~]# jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder] +[root@localhost ~]# jmeter -n -t [jmx file] -l [results file] -R host1,host2 -e -o [Path to web report folder] +``` \ No newline at end of file diff --git a/src/DevOps/5.md b/src/DevOps/5.md new file mode 100644 index 0000000..2289262 --- /dev/null +++ b/src/DevOps/5.md @@ -0,0 +1,25 @@ +```shell +# 查看某个进程的PID +ps -ef | grep arthas-demo.jar + +# 查看java关键词的进程的数量 +ps -ef | grep java| wc -l + +# 查看线程是否存在死锁 +jstack -l + +# 统计某个进程的线程数量 +ps -efL | grep [pid] | wc -l + +# 查看某个进制有哪些线程 +ps -Lp [pid] cu + +# 统计所有的log文件中,包含Error字符的行 +find / -type f -name "*.log" | xargs grep "ERROR" + +# 统计日志文件中包含特定异常数量 +cat xxx.log | grep ** *Exception| wc -l + +# 统计log中301、302状态码的行数,$8表示第八列是状态码,可以根据实际情况更改 +awk'{print $8}' 2017-05-22-access_log|egrep '301|302'| wc -l +``` \ No newline at end of file diff --git a/src/DevOps/501.md b/src/DevOps/501.md new file mode 100644 index 0000000..c75af81 --- /dev/null +++ b/src/DevOps/501.md @@ -0,0 +1,5 @@ +当写完一个Spring boot Maven 工程,使用 mvn clean package 打包成可运行的jar文件后,可使用如下命令开始执行: + +```shell +nohup java -Xloggc:${logging_file_location}gc.log -XX:+PrintGCDetails -jar app.jar --spring.profiles.active=${environment} --logging.file.location=${logging_file_location} --domain=com.xx.xxx.xxxx > /dev/null 2>&1 & +``` \ No newline at end of file diff --git a/src/DevOps/601.md b/src/DevOps/601.md new file mode 100644 index 0000000..cafb8b9 --- /dev/null +++ b/src/DevOps/601.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待!有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/DevOps/602.md b/src/DevOps/602.md new file mode 100644 index 0000000..c3a9708 --- /dev/null +++ b/src/DevOps/602.md @@ -0,0 +1,107 @@ +### 镜像命令 + +```sh +# 列出 Docker 本地镜像列表 +$ docker images +$ docker image ls -a + +# 运行 Docker 镜像(守护态方式) +$ docker run -d {镜像名} + +# 删除指定 Docker 镜像 +$ docker image rm {镜像名} +``` + + + +### 容器命令 + + + +```bash +# 列出正在运行的容器 +$ docker ps -a + +# 列出所有容器(包括已停止容器) +$ docker ps -l +``` + +```bash +$ docker exec -it {容器ID} /bin/bash +``` + +停止 Docker 容器: + +```bash +$ docker stop {容器ID} +``` + +删除指定 Docker 容器: + +```bash +$ docker rm -f {容器ID} +``` + +删除停止的 Docker 容器: + +```bash +$ docker container prune +``` + +查看 Docker 容器历史运行日志: + +```bash +$ docker logs {容器名} +``` + +实时监听 Docker 容器运行日志: + +```bash +$ docker logs -f {容器名} +``` + + + +### 数据卷命令 + +创建 Docker 数据卷: + +```bash +$ docker volume create {数据卷名} +``` + +列出所有 Docker 数据卷: + +```bash +$ docker volume ls +``` + +删除指定 Docker 数据卷: + +```bash +$ docker volume rm {数据卷名} +``` + +删除未关联(失效) Docker 数据卷: + +```bash +$ docker volume prune +$ docker volume rm $(docker volume ls -qf dangling=true) +``` + + + +### 文件操作命令 + +从主机复制文件到 Docker 容器中: + +```bash +$ sudo docker cp {主机内文件路径} {容器ID}:{容器内文件存储路径} +``` + +从 Docker 容器中复制文件到主机中: + +```bash +$ sudo docker cp {容器ID}:{容器内文件路径} {主机内文件存储路径} +``` + diff --git a/src/DevOps/701.md b/src/DevOps/701.md new file mode 100644 index 0000000..0f956f0 --- /dev/null +++ b/src/DevOps/701.md @@ -0,0 +1,147 @@ +### 侦听端口 + +```nginx +server { + # Standard HTTP Protocol + listen 80; + # Standard HTTPS Protocol + listen 443 ssl; + # For http2 + listen 443 ssl http2; + # Listen on 80 using IPv6 + listen [::]:80; + # Listen only on using IPv6 + listen [::]:80 ipv6only=on; +} +``` + + + +### 访问日志 + +```nginx +server { + # Relative or full path to log file + access_log /path/to/file.log; + # Turn 'on' or 'off' + access_log on; +} +``` + + + +### 域名 + +```nginx +server { + # Listen to yourdomain.com + server_name yourdomain.com; + # Listen to multiple domains server_name yourdomain.com www.yourdomain.com; + # Listen to all domains + server_name *.yourdomain.com; + # Listen to all top-level domains + server_name yourdomain.*; + # Listen to unspecified Hostnames (Listens to IP address itself) + server_name ""; +} +``` + + + +### 静态资产 + +```nginx +server { + listen 80; + server_name yourdomain.com; + location / { + root /path/to/website; + } +} +``` + + + +### 重定向 + +```nginx +server { + listen 80; + server_name www.yourdomain.com; + return 301 http://yourdomain.com$request_uri; +} +server { + listen 80; + server_name www.yourdomain.com; + location /redirect-url { + return 301 http://otherdomain.com; + } +} +``` + + + +### 反向代理 + +```nginx +server { + listen 80; + server_name yourdomain.com; + location / { + proxy_pass http://0.0.0.0:3000; + # where 0.0.0.0:3000 is your application server (Ex: node.js) bound on 0.0.0.0 listening on port 3000 + } +} +``` + + + +### 负载均衡 + +```nginx +upstream node_js { + server 0.0.0.0:3000; + server 0.0.0.0:4000; + server 123.131.121.122; +} +server { + listen 80; + server_name yourdomain.com; + location / { + proxy_pass http://node_js; + } +} +``` + + + +### SSL 协议 + +```nginx +server { + listen 443 ssl; + server_name yourdomain.com; + ssl on; + ssl_certificate /path/to/cert.pem; + ssl_certificate_key /path/to/privatekey.pem; + ssl_stapling on; + ssl_stapling_verify on; + ssl_trusted_certificate /path/to/fullchain.pem; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_session_timeout 1h; + ssl_session_cache shared:SSL:50m; + add_header Strict-Transport-Security max-age=15768000; +} +# Permanent Redirect for HTTP to HTTPS +server { + listen 80; + server_name yourdomain.com; + return 301 https://$host$request_uri; +} +``` + +其实可以采用可视化的方式对 Nginx 进行配置,我在 GitHub 上发现了一款可以一键生成 Nginx 配置的神器,相当给力。 + +先来看看它都支持什么功能的配置:反向代理、HTTPS、HTTP/2、IPv6, 缓存、WordPress、CDN、Node.js 支持、 Python (Django) 服务器等等。 + +如果你想在线进行配置,只需要打开网站:**https://nginxconfig.io/** \ No newline at end of file diff --git a/src/DevOps/702.md b/src/DevOps/702.md new file mode 100644 index 0000000..121d917 --- /dev/null +++ b/src/DevOps/702.md @@ -0,0 +1,437 @@ +### HTTP服务器 + +Nginx本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用Nginx来做服务器,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署。 + +1、 首先在文档根目录`Docroot(/usr/local/var/www)`下创建html目录, 然后在html中放一个test.html; + +2、 配置`nginx.conf`中的server + +```nginx +user mengday staff; + +http { + server { + listen 80; + server_name localhost; + client_max_body_size 1024M; + + # 默认location + location / { + root /usr/local/var/www/html; + index index.html index.htm; + } + } +} +``` + +3、访问测试 + +- `http://localhost/` 指向`/usr/local/var/www/index.html`, index.html是安装nginx自带的html +- `http://localhost/test.html` 指向`/usr/local/var/www/html/test.html` + +> 注意:如果访问图片出现403 Forbidden错误,可能是因为nginx.conf 的第一行user配置不对,默认是#user nobody;是注释的,linux下改成user root; macos下改成user 用户名 所在组; 然后重新加载配置文件或者重启,再试一下就可以了, 用户名可以通过who am i 命令来查看。 + +4、指令简介 + +- server : 用于定义服务,http中可以有多个server块 +- listen : 指定服务器侦听请求的IP地址和端口,如果省略地址,服务器将侦听所有地址,如果省略端口,则使用标准端口 +- server_name : 服务名称,用于配置域名 +- location : 用于配置映射路径uri对应的配置,一个server中可以有多个location, location后面跟一个uri,可以是一个正则表达式, / 表示匹配任意路径, 当客户端访问的路径满足这个uri时就会执行location块里面的代码 +- root : 根路径,当访问`http://localhost/test.html`,“/test.html”会匹配到”/”uri, 找到root为`/usr/local/var/www/html`,用户访问的资源物理地址=`root + uri = /usr/local/var/www/html + /test.html=/usr/local/var/www/html/test.html` +- index : 设置首页,当只访问`server_name`时后面不跟任何路径是不走root直接走index指令的;如果访问路径中没有指定具体的文件,则返回index设置的资源,如果访问`http://localhost/html/` 则默认返回index.html + +5、location uri正则表达式 + +- `.` :匹配除换行符以外的任意字符 +- `?` :重复0次或1次 +- `+` :重复1次或更多次 +- `*` :重复0次或更多次 +- `\d` :匹配数字 +- `^` :匹配字符串的开始 +- `$` :匹配字符串的结束 +- `{n}` :重复n次 +- `{n,}` :重复n次或更多次 +- `[c]` :匹配单个字符c +- `[a-z]` :匹配a-z小写字母的任意一个 +- `(a|b|c)` : 属线表示匹配任意一种情况,每种情况使用竖线分隔,一般使用小括号括括住,匹配符合a字符 或是b字符 或是c字符的字符串 +- `\` 反斜杠:用于转义特殊字符 + +小括号()之间匹配的内容,可以在后面通过`$1`来引用,`$2`表示的是前面第二个()里的内容。正则里面容易让人困惑的是`\`转义特殊字符。 + + + +### 静态服务器 + +在公司中经常会遇到静态服务器,通常会提供一个上传的功能,其他应用如果需要静态资源就从该静态服务器中获取。 + +在`/usr/local/var/www` 下分别创建images和img目录,分别在每个目录下放一张`test.jpg` + +```nginx +http { + server { + listen 80; + server_name localhost; + + + set $doc_root /usr/local/var/www; + + # 默认location + location / { + root /usr/local/var/www/html; + index index.html index.htm; + } + + location ^~ /images/ { + root $doc_root; + } + + location ~* \.(gif|jpg|jpeg|png|bmp|ico|swf|css|js)$ { + root $doc_root/img; + } + } +} +``` + +自定义变量使用set指令,语法 set 变量名值;引用使用变量名值;引用使用变量名; 这里自定义了doc_root变量。 + +静态服务器location的映射一般有两种方式: + +- 使用路径,如 /images/ 一般图片都会放在某个图片目录下, +- 使用后缀,如 .jpg、.png 等后缀匹配模式 + +访问`http://localhost/test.jpg` 会映射到 `$doc_root/img` + +访问`http://localhost/images/test.jpg` 当同一个路径满足多个location时,优先匹配优先级高的location,由于`^~` 的优先级大于 `~`, 所以会走`/images/`对应的location + +常见的location路径映射路径有以下几种: + +- `=` 进行普通字符精确匹配。也就是完全匹配。 +- `^~` 前缀匹配。如果匹配成功,则不再匹配其他location。 +- `~` 表示执行一个正则匹配,区分大小写 +- `~*` 表示执行一个正则匹配,不区分大小写 +- `/xxx/` 常规字符串路径匹配 +- `/` 通用匹配,任何请求都会匹配到 + + + +**location优先级** + +当一个路径匹配多个location时究竟哪个location能匹配到时有优先级顺序的,而优先级的顺序于location值的表达式类型有关,和在配置文件中的先后顺序无关。相同类型的表达式,字符串长的会优先匹配。推荐:[Java面试题大全](http://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247504489&idx=1&sn=afd92248113146b086652ad7f89c7a7c&chksm=ebd5ed45dca26453c0cf91265d669711a4e2b4ea52f3ff4a00b063a9de46d69fcc599f151210&scene=21#wechat_redirect) + +以下是按优先级排列说明: + +- 等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他匹配项,停止搜索。 +- `^~`类型表达式,不属于正则表达式。一旦匹配成功,则不再查找其他匹配项,停止搜索。 +- 正则表达式类型(`~ ~*`)的优先级次之。如果有多个location的正则能匹配的话,则使用正则表达式最长的那个。 +- 常规字符串匹配类型。按前缀匹配。 +- / 通用匹配,如果没有匹配到,就匹配通用的 + +优先级搜索问题:不同类型的location映射决定是否继续向下搜索 + +- 等号类型、`^~`类型:一旦匹配上就停止搜索了,不会再匹配其他location了 +- 正则表达式类型(`~ ~*`),常规字符串匹配类型`/xxx/` : 匹配到之后,还会继续搜索其他其它location,直到找到优先级最高的,或者找到第一种情况而停止搜索 + +location优先级从高到底: + +(`location =`) > (`location 完整路径`) > (`location ^~ 路径`) > (`location ~,~* 正则顺序`) > (`location 部分起始路径`) > (`/`) + +```nginx +location = / { + # 精确匹配/,主机名后面不能带任何字符串 / + [ configuration A ] +} +location / { + # 匹配所有以 / 开头的请求。 + # 但是如果有更长的同类型的表达式,则选择更长的表达式。 + # 如果有正则表达式可以匹配,则优先匹配正则表达式。 + [ configuration B ] +} +location /documents/ { + # 匹配所有以 /documents/ 开头的请求,匹配符合以后,还要继续往下搜索。 + # 但是如果有更长的同类型的表达式,则选择更长的表达式。 + # 如果有正则表达式可以匹配,则优先匹配正则表达式。 + [ configuration C ] +} +location ^~ /images/ { + # 匹配所有以 /images/ 开头的表达式,如果匹配成功,则停止匹配查找,停止搜索。 + # 所以,即便有符合的正则表达式location,也不会被使用 + [ configuration D ] +} + +location ~* \.(gif|jpg|jpeg)$ { + # 匹配所有以 gif jpg jpeg结尾的请求。 + # 但是 以 /images/开头的请求,将使用 Configuration D,D具有更高的优先级 + [ configuration E ] +} + +location /images/ { + # 字符匹配到 /images/,还会继续往下搜索 + [ configuration F ] +} + + +location = /test.htm { + root /usr/local/var/www/htm; + index index.htm; +} +``` + +注意:location的优先级与location配置的位置无关 + + + +### 反向代理 + +反向代理应该是Nginx使用最多的功能了,反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。 + +简单来说就是真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器在同一个网络环境,当然也可能是同一台服务器,端口不同而已。 + +反向代理通过`proxy_pass`指令来实现。 + +启动一个Java Web项目,端口号为8081 + +```nginx +server { + listen 80; + server_name localhost; + + location / { + proxy_pass http://localhost:8081; + proxy_set_header Host $host:$server_port; + # 设置用户ip地址 + proxy_set_header X-Forwarded-For $remote_addr; + # 当请求服务器出错去寻找其他服务器 + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; + } + +} +``` + +当我们访问localhost的时候,就相当于访问 `localhost:8081`了 + + + +### 负载均衡 + +负载均衡也是Nginx常用的一个功能,负载均衡其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。 + +简单而言就是当有2台或以上服务器时,根据规则随机的将请求分发到指定的服务器上处理,负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。而Nginx目前支持自带3种负载均衡策略,还有2种常用的第三方策略。负载均衡通过upstream指令来实现。 + +#### RR(round robin :轮询 默认) + +每个请求按时间顺序逐一分配到不同的后端服务器,也就是说第一次请求分配到第一台服务器上,第二次请求分配到第二台服务器上,如果只有两台服务器,第三次请求继续分配到第一台上,这样循环轮询下去,也就是服务器接收请求的比例是 1:1, 如果后端服务器down掉,能自动剔除。轮询是默认配置,不需要太多的配置,同一个项目分别使用8081和8082端口启动项目: + +```nginx +upstream web_servers { + server localhost:8081; + server localhost:8082; +} + +server { + listen 80; + server_name localhost; + #access_log logs/host.access.log main; + + + location / { + proxy_pass http://web_servers; + # 必须指定Header Host + proxy_set_header Host $host:$server_port; + } + } +``` + +访问地址仍然可以获得响应 `http://localhost/api/user/login?username=zhangsan&password=111111` ,这种方式是轮询的 + + + +#### 权重 + +指定轮询几率,weight和访问比率成正比, 也就是服务器接收请求的比例就是各自配置的weight的比例,用于后端服务器性能不均的情况,比如服务器性能差点就少接收点请求,服务器性能好点就多处理点请求。 + +```nginx +upstream test { + server localhost:8081 weight=1; + server localhost:8082 weight=3; + server localhost:8083 weight=4 backup; +} +``` + +示例是4次请求只有一次被分配到8081上,其他3次分配到8082上。backup是指热备,只有当8081和8082都宕机的情况下才走8083 + + + +#### ip_hash + +上面的2种方式都有一个问题,那就是下一个请求来的时候请求可能分发到另外一个服务器,当我们的程序不是无状态的时候(采用了session保存数据),这时候就有一个很大的很问题了,比如把登录信息保存到了session中,那么跳转到另外一台服务器的时候就需要重新登录了,所以很多时候我们需要一个客户只访问一个服务器,那么就需要用iphash了,iphash的每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。 + +```nginx +upstream test { + ip_hash; + server localhost:8080; + server localhost:8081; +} +``` + + + +#### fair(第三方) + +按后端服务器的响应时间来分配请求,响应时间短的优先分配。这个配置是为了更快的给用户响应 + +```nginx +upstream backend { + fair; + server localhost:8080; + server localhost:8081; +} +``` + +#### url_hash(第三方) + +按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。在upstream中加入hash语句,server语句中不能写入weight等其他的参数,`hash_method`是使用的hash算法 + +```nginx +upstream backend { + hash $request_uri; + hash_method crc32; + server localhost:8080; + server localhost:8081; +} +``` + +以上5种负载均衡各自适用不同情况下使用,所以可以根据实际情况选择使用哪种策略模式,不过fair和url_hash需要安装第三方模块才能使用。 + + + +### 动静分离 + +动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路。 + +```nginx +upstream web_servers { + server localhost:8081; + server localhost:8082; +} + +server { + listen 80; + server_name localhost; + + set $doc_root /usr/local/var/www; + + location ~* \.(gif|jpg|jpeg|png|bmp|ico|swf|css|js)$ { + root $doc_root/img; + } + + location / { + proxy_pass http://web_servers; + # 必须指定Header Host + proxy_set_header Host $host:$server_port; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root $doc_root; + } + + } +``` + + + +### 其他 + +#### return指令 + +返回http状态码 和 可选的第二个参数可以是重定向的URL + +```nginx +location /permanently/moved/url { + return 301 http://www.example.com/moved/here; +} +``` + + + +#### rewrite指令 + +重写URI请求 rewrite,通过使用rewrite指令在请求处理期间多次修改请求URI,该指令具有一个可选参数和两个必需参数。 + +第一个(必需)参数是请求URI必须匹配的正则表达式。 + +第二个参数是用于替换匹配URI的URI。 + +可选的第三个参数是可以停止进一步重写指令的处理或发送重定向(代码301或302)的标志 + +```nginx +location /users/ { + rewrite ^/users/(.*)$ /show?user=$1 break; +} +``` + + + +#### error_page指令 + +使用error_page指令,您可以配置NGINX返回自定义页面以及错误代码,替换响应中的其他错误代码,或将浏览器重定向到其他URI。在以下示例中,`error_page`指令指定要返回404页面错误代码的页面(/404.html)。 + +```nginx +error_page 404 /404.html; +``` + + + +#### 日志 + +访问日志:需要开启压缩 gzip on; 否则不生成日志文件,打开`log_format`、`access_log`注释 + +```nginx +log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + +access_log /usr/local/etc/nginx/logs/host.access.log main; + +gzip on; +``` + + + +#### deny 指令 + +```nginx +# 禁止访问某个目录 +location ~* \.(txt|doc)${ + root $doc_root; + deny all; +} +``` + + + +#### 内置变量 + +nginx的配置文件中可以使用的内置变量以美元符`$`开始,也有人叫全局变量。其中,部分预定义的变量的值是可以改变的。另外,关注Java知音公众号,回复“后端面试”,送你一份面试题宝典! + +- `$args` :`#`这个变量等于请求行中的参数,同`$query_string` +- `$content_length` :请求头中的Content-length字段。 +- `$content_type` :请求头中的Content-Type字段。 +- `$document_root` :当前请求在root指令中指定的值。 +- `$host` :请求主机头字段,否则为服务器名称。 +- `$http_user_agent` :客户端agent信息 +- `$http_cookie` :客户端cookie信息 +- `$limit_rate` :这个变量可以限制连接速率。 +- `$request_method` :客户端请求的动作,通常为GET或POST。 +- `$remote_addr` :客户端的IP地址。 +- `$remote_port` :客户端的端口。 +- `$remote_user` :已经经过Auth Basic Module验证的用户名。 +- `$request_filename` :当前请求的文件路径,由root或alias指令与URI请求生成。 +- `$scheme` :HTTP方法(如http,https)。 +- `$server_protocol` :请求使用的协议,通常是HTTP/1.0或HTTP/1.1。 +- `$server_addr` :服务器地址,在完成一次系统调用后可以确定这个值。 +- `$server_name` :服务器名称。 +- `$server_port` :请求到达服务器的端口号。 +- `$request_uri` :包含请求参数的原始URI,不包含主机名,如:”`/foo/bar.php?arg=baz`”。 +- `$uri` :不带请求参数的当前URI,`$uri`不包含主机名,如”`/foo/bar.html`”。 +- `$document_uri` :与`$uri`相同 \ No newline at end of file diff --git a/src/DevOps/801.md b/src/DevOps/801.md new file mode 100644 index 0000000..2af670e --- /dev/null +++ b/src/DevOps/801.md @@ -0,0 +1,58 @@ +VMware15.5安装,傻瓜式安装,只记录变动步骤,其余都下一步,软件安装位置自己选择,最好别选c盘,软件地址https://www.nocmd.com/windows/740.html(内含激活码),安装时需要注意它文件不会在一个文件夹下,自己多建一个版本文件夹,方便管理。 + +![在这里插入图片描述](images/DevOps/20210717124755337.png) + +![在这里插入图片描述](images/DevOps/2021071712480749.png) + +**文件 > 新建虚拟机**: + +![在这里插入图片描述](images/DevOps/20210717125629709.png) + +![在这里插入图片描述](images/DevOps/20210717125643324.png) + +![在这里插入图片描述](images/DevOps/20210717125659179.png) + +![在这里插入图片描述](images/DevOps/20210717125714713.png) + +![在这里插入图片描述](images/DevOps/20210717125727428.png) + +![在这里插入图片描述](images/DevOps/20210717125743717.png) + +点击安装计算机的设置 > 选择镜像后 > 点确定: + +![在这里插入图片描述](images/DevOps/20210717125911587.png) + +开启虚拟机》选第一个install centos7 + +![在这里插入图片描述](images/DevOps/20210717125946871.png) + +等待一段时间不要乱点,乱点会卡死,》软件选择》最小安装或gui服务器或gnome桌面,选好后点完成。开发中一般都选最小安装,需要什么软件在自行选择,但其它安装可以省略jdk,mysql等安装,会自行安装。 + +![在这里插入图片描述](images/DevOps/20210717130014474.png) + +在这一步也可以选择自动配置分区,这里更快,这里我选择我要配置分区。 + +![在这里插入图片描述](images/DevOps/202107171300526.png)设置好/boot要1G,swap要2G,剩余都在根目录分区大小后,设备类型点标准分区,点完成。 + +![在这里插入图片描述](images/DevOps/20210717130123660.png) + +点接受更改 + +![在这里插入图片描述](images/DevOps/20210717130215238.png) + +网络和主机名设置,需要联网就打开以太网。 + +![在这里插入图片描述](images/DevOps/20210717130237758.png) + +最后一个像一把锁的安检策略可以关闭。 + +点开始安装 +在这个页面配置root账号密码,创建用户账号密码。在实际开发中root账号要复杂点,避免被破解。 + +![在这里插入图片描述](images/DevOps/20210717130319942.png)等待完成后,点击重启。 + +![在这里插入图片描述](images/DevOps/20210717130343591.png) + +![在这里插入图片描述](images/DevOps/20210717130404642.png) + +再把网络连接打开。 \ No newline at end of file diff --git a/src/DevOps/802.md b/src/DevOps/802.md new file mode 100644 index 0000000..61ec1c2 --- /dev/null +++ b/src/DevOps/802.md @@ -0,0 +1,3 @@ +- 桥接模式:同一网段中,最多只能连接255台机子,一旦超出容易造成IP冲突。IP地址的前3位就是网段(192.168.0.1) +- NAT(网络地址装换)模式:虚拟机和外部通信,不会造成IP冲突。虚拟机地址不再是以0开头,而是生成1-255之间的数,如192.168.6.1,然后主机会生成一个对应的虚拟网卡如192.168.6.6,两者能通信。这种模式下虚拟机能访问192.168.0.1,由于网段不同,192.168.0.1不能访问虚拟机 +- 主机模式:虚拟网络对主机可见,虚拟机不能上网 \ No newline at end of file diff --git a/src/DevOps/803.md b/src/DevOps/803.md new file mode 100644 index 0000000..8f4d03f --- /dev/null +++ b/src/DevOps/803.md @@ -0,0 +1,10 @@ +vmtools工具是实现虚拟机和主机文件进行共享,两个地方都能修改同一文件。安装步骤如下 + +- 右击虚拟机 install vmware tools +- 双击VMware Tools,复制XXX.tar.gz压缩包到/opt目录下 +- 桌面上打开终端,cd /opt ,进入到opt目录下,使用解压命令tar -zxvfVM+tab键提示自动补全名称, 得到一个解压文件夹 +- 进入该vm解压的目录cd vmxxx,/opt目录下 +- 安装./vmware-install.pl +- 全部使用默认设置即可,一直按回车,就可以安装成功 + +注意:安装vmtools需有gcc ,可以使用gcc -v查看gcc版本 \ No newline at end of file diff --git a/src/DevOps/804.md b/src/DevOps/804.md new file mode 100644 index 0000000..b342187 --- /dev/null +++ b/src/DevOps/804.md @@ -0,0 +1,15 @@ +- /bin :存放着最经常使用的命令 +- /home :存放普通用户的主目录,一般该目录名是以用户的账号命名 +- /root :该目录为系统管理员,也称作超级权限者的用户主目录(根目录) +- /boot:Linux启动相关文件 +- /lib:系统开机所需要最基本的动态连接共享库,其作用类似于Windows里的DLL文件。 +- /lost+ found这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件 +- /etc:系统管理所需配置和子文件目录 +- /user:用户应用程序和文件 +- /proc[不能动]:是虚拟目录,系统内存映射,访问这个目录获取系统信息 +- /srv[不能动]:存放服务启动后所需数据 +- /sys[不能动]:该目录安装了2.6内核新出现的文件系统 +- /tmp:存放临时文件 +- /mnt:存放挂载文件 +- /opt:给主机额外安装软件的目录,即软件存放目录 +- /user/local:软件安装后的目标目录,一般是编译源码的方式安装的程序 \ No newline at end of file diff --git a/src/DevOps/805.md b/src/DevOps/805.md new file mode 100644 index 0000000..60a3a24 --- /dev/null +++ b/src/DevOps/805.md @@ -0,0 +1,5 @@ +- 启动系统,进入开机页面,按e键进入编辑页面 +- 光标向下移动,找到以“Linux16”开头的行数,行末输入init=/bin/sh,接着按ctr+x进入单用户模式 +- 在光标闪烁位置输入:mount -o remount,rw /,完成后回车 +- 接着输入passwd,完成后回车,输入密码后回车,再次输入密码。修改成功后会显示passwd…… +- 接着在光标位置输入:touch /.autorelabel,完成后回车,等待系统重启,新密码就生效了 \ No newline at end of file diff --git a/src/DevOps/README.md b/src/DevOps/README.md new file mode 100644 index 0000000..c77755f --- /dev/null +++ b/src/DevOps/README.md @@ -0,0 +1,5 @@ +
DevOps
+ +Introduction:收纳技术相关的 `JDK Tools`、`Linux Tools`、`Git` 等总结! + +## 🚀点击左侧菜单栏开始吧! \ No newline at end of file diff --git a/src/DevOps/_sidebar.md b/src/DevOps/_sidebar.md new file mode 100644 index 0000000..11e34cc --- /dev/null +++ b/src/DevOps/_sidebar.md @@ -0,0 +1,44 @@ +* [🏁 Linux Command](src/DevOps/1 "Linux Command") + * [✍ Base)](src/DevOps/2 "Base") + * [✍ Install](src/DevOps/3 "Install") + * [✍ Filter](src/DevOps/4 "Filter") + * [✍ Statistics](src/DevOps/5 "Statistics") +* [🏁 Linux Monitor](src/DevOps/101 "Linux Monitor") + * [✍ CPU](src/DevOps/102 "CPU") + * [✍ Memory](src/DevOps/103 "Memory") + * [✍ I/O](src/DevOps/104 "I/O") + * [✍ Network](src/DevOps/105 "Network") + * [✍ Others](src/DevOps/106 "Others") + * [✍ 瓶颈排查](src/DevOps/107 "瓶颈排查") +* 🏁 Shell + * [✍ 基本语法](src/DevOps/201 "基本语法") + * [✍ 变量](src/DevOps/202 "变量") + * [✍ 数组](src/DevOps/203 "数组") + * [✍ 算术运算](src/DevOps/204 "算术运算") + * [✍ 字符串](src/DevOps/205 "字符串") + * [✍ 条件判断](src/DevOps/206 "条件判断") + * [✍ 流程控制](src/DevOps/207 "流程控制") + * [✍ 高级命令](src/DevOps/208 "高级命令") + * [✍ 常用脚本](src/DevOps/209 "常用脚本") +* [🏁 Git](src/DevOps/301 "Git") + * [✍ 工作流程](src/DevOps/302 "工作流程") + * [✍ GitFlow工作流](src/DevOps/303 "GitFlow工作流") + * [✍ 常用命令](src/DevOps/304 "常用命令") + * [✍ 特殊命令](src/DevOps/305.md "特殊命令") +* 🏁 Test Tools + * [✍ AB](src/DevOps/401 "AB") + * [✍ Jmeter](src/DevOps/402 "Jmeter") +* 🏁 Pack + * [✍ 其它](src/DevOps/501 "其它") +* 🏁 Docker + * [✍ 安装](src/DevOps/601 "安装") + * [✍ 常用命令](src/DevOps/602 "常用命令") +* 🏁 Nginx + * [✍ 常用配置](src/DevOps/701 "常用配置") + * [✍ 应用场景](src/DevOps/702 "应用场景") +* 🏁 VMware + * [✍ 虚拟机安装](src/DevOps/801 "虚拟机安装") + * [✍ 虚拟机网络连接方式](src/DevOps/802 "虚拟机网络连接方式") + * [✍ 安装vmtools](src/DevOps/803 "安装vmtools") + * [✍ 虚拟机目录](src/DevOps/804 "虚拟机目录") + * [✍ CentOS7找回root密码](src/DevOps/805 "CentOS7找回root密码") \ No newline at end of file diff --git a/src/DevOps/images/DevOps/1477786-20201122134301506-441066821.png b/src/DevOps/images/DevOps/1477786-20201122134301506-441066821.png new file mode 100644 index 0000000..df3d32e Binary files /dev/null and b/src/DevOps/images/DevOps/1477786-20201122134301506-441066821.png differ diff --git a/src/DevOps/images/DevOps/1477786-20201122135426680-1563483565.png b/src/DevOps/images/DevOps/1477786-20201122135426680-1563483565.png new file mode 100644 index 0000000..dc59d62 Binary files /dev/null and b/src/DevOps/images/DevOps/1477786-20201122135426680-1563483565.png differ diff --git a/src/DevOps/images/DevOps/1477786-20201122135610356-597293017-1629438006328.png b/src/DevOps/images/DevOps/1477786-20201122135610356-597293017-1629438006328.png new file mode 100644 index 0000000..2641f15 Binary files /dev/null and b/src/DevOps/images/DevOps/1477786-20201122135610356-597293017-1629438006328.png differ diff --git a/src/DevOps/images/DevOps/1477786-20201122135610356-597293017.png b/src/DevOps/images/DevOps/1477786-20201122135610356-597293017.png new file mode 100644 index 0000000..2641f15 Binary files /dev/null and b/src/DevOps/images/DevOps/1477786-20201122135610356-597293017.png differ diff --git a/src/DevOps/images/DevOps/1477786-20201122135828625-682254107.png b/src/DevOps/images/DevOps/1477786-20201122135828625-682254107.png new file mode 100644 index 0000000..ef9c2ed Binary files /dev/null and b/src/DevOps/images/DevOps/1477786-20201122135828625-682254107.png differ diff --git a/src/DevOps/images/DevOps/1657486-20200110163906854-1971599861.png b/src/DevOps/images/DevOps/1657486-20200110163906854-1971599861.png new file mode 100644 index 0000000..e57af17 Binary files /dev/null and b/src/DevOps/images/DevOps/1657486-20200110163906854-1971599861.png differ diff --git a/src/DevOps/images/DevOps/20210717124755337.png b/src/DevOps/images/DevOps/20210717124755337.png new file mode 100644 index 0000000..264adb1 Binary files /dev/null and b/src/DevOps/images/DevOps/20210717124755337.png differ diff --git a/src/DevOps/images/DevOps/2021071712480749.png b/src/DevOps/images/DevOps/2021071712480749.png new file mode 100644 index 0000000..6ef2dc7 Binary files /dev/null and b/src/DevOps/images/DevOps/2021071712480749.png differ diff --git a/src/DevOps/images/DevOps/20210717125629709.png b/src/DevOps/images/DevOps/20210717125629709.png new file mode 100644 index 0000000..16575de Binary files /dev/null and b/src/DevOps/images/DevOps/20210717125629709.png differ diff --git a/src/DevOps/images/DevOps/20210717125643324.png b/src/DevOps/images/DevOps/20210717125643324.png new file mode 100644 index 0000000..1b75605 Binary files /dev/null and b/src/DevOps/images/DevOps/20210717125643324.png differ diff --git a/src/DevOps/images/DevOps/20210717125659179.png b/src/DevOps/images/DevOps/20210717125659179.png new file mode 100644 index 0000000..81f236f Binary files /dev/null and b/src/DevOps/images/DevOps/20210717125659179.png differ diff --git a/src/DevOps/images/DevOps/20210717125714713.png b/src/DevOps/images/DevOps/20210717125714713.png new file mode 100644 index 0000000..6a5174b Binary files /dev/null and b/src/DevOps/images/DevOps/20210717125714713.png differ diff --git a/src/DevOps/images/DevOps/20210717125727428.png b/src/DevOps/images/DevOps/20210717125727428.png new file mode 100644 index 0000000..f6a7dc8 Binary files /dev/null and b/src/DevOps/images/DevOps/20210717125727428.png differ diff --git a/src/DevOps/images/DevOps/20210717125743717.png b/src/DevOps/images/DevOps/20210717125743717.png new file mode 100644 index 0000000..12b952c Binary files /dev/null and b/src/DevOps/images/DevOps/20210717125743717.png differ diff --git a/src/DevOps/images/DevOps/20210717125911587.png b/src/DevOps/images/DevOps/20210717125911587.png new file mode 100644 index 0000000..d2a471c Binary files /dev/null and b/src/DevOps/images/DevOps/20210717125911587.png differ diff --git a/src/DevOps/images/DevOps/20210717125946871.png b/src/DevOps/images/DevOps/20210717125946871.png new file mode 100644 index 0000000..1ac81b9 Binary files /dev/null and b/src/DevOps/images/DevOps/20210717125946871.png differ diff --git a/src/DevOps/images/DevOps/20210717130014474.png b/src/DevOps/images/DevOps/20210717130014474.png new file mode 100644 index 0000000..c92cc02 Binary files /dev/null and b/src/DevOps/images/DevOps/20210717130014474.png differ diff --git a/src/DevOps/images/DevOps/202107171300526.png b/src/DevOps/images/DevOps/202107171300526.png new file mode 100644 index 0000000..4325c04 Binary files /dev/null and b/src/DevOps/images/DevOps/202107171300526.png differ diff --git a/src/DevOps/images/DevOps/20210717130123660.png b/src/DevOps/images/DevOps/20210717130123660.png new file mode 100644 index 0000000..02cce0a Binary files /dev/null and b/src/DevOps/images/DevOps/20210717130123660.png differ diff --git a/src/DevOps/images/DevOps/20210717130215238.png b/src/DevOps/images/DevOps/20210717130215238.png new file mode 100644 index 0000000..b4e50fe Binary files /dev/null and b/src/DevOps/images/DevOps/20210717130215238.png differ diff --git a/src/DevOps/images/DevOps/20210717130237758.png b/src/DevOps/images/DevOps/20210717130237758.png new file mode 100644 index 0000000..c73d1b8 Binary files /dev/null and b/src/DevOps/images/DevOps/20210717130237758.png differ diff --git a/src/DevOps/images/DevOps/20210717130319942.png b/src/DevOps/images/DevOps/20210717130319942.png new file mode 100644 index 0000000..9ea4f1a Binary files /dev/null and b/src/DevOps/images/DevOps/20210717130319942.png differ diff --git a/src/DevOps/images/DevOps/20210717130343591.png b/src/DevOps/images/DevOps/20210717130343591.png new file mode 100644 index 0000000..73a678c Binary files /dev/null and b/src/DevOps/images/DevOps/20210717130343591.png differ diff --git a/src/DevOps/images/DevOps/20210717130404642.png b/src/DevOps/images/DevOps/20210717130404642.png new file mode 100644 index 0000000..0725eac Binary files /dev/null and b/src/DevOps/images/DevOps/20210717130404642.png differ diff --git a/src/DevOps/images/DevOps/4737bd5fae25f97303f4a761f78b3419.png b/src/DevOps/images/DevOps/4737bd5fae25f97303f4a761f78b3419.png new file mode 100644 index 0000000..908d071 Binary files /dev/null and b/src/DevOps/images/DevOps/4737bd5fae25f97303f4a761f78b3419.png differ diff --git a/src/DevOps/images/DevOps/4dc3e5aba96c56ac1b3e8d51611934dd.png b/src/DevOps/images/DevOps/4dc3e5aba96c56ac1b3e8d51611934dd.png new file mode 100644 index 0000000..0f404e1 Binary files /dev/null and b/src/DevOps/images/DevOps/4dc3e5aba96c56ac1b3e8d51611934dd.png differ diff --git a/src/DevOps/images/DevOps/7aace9181112609a0621e63c13bf4088.png b/src/DevOps/images/DevOps/7aace9181112609a0621e63c13bf4088.png new file mode 100644 index 0000000..1f19b71 Binary files /dev/null and b/src/DevOps/images/DevOps/7aace9181112609a0621e63c13bf4088.png differ diff --git a/src/DevOps/images/DevOps/7df09cbf580b688f84384e209c24c173.png b/src/DevOps/images/DevOps/7df09cbf580b688f84384e209c24c173.png new file mode 100644 index 0000000..3e2b328 Binary files /dev/null and b/src/DevOps/images/DevOps/7df09cbf580b688f84384e209c24c173.png differ diff --git a/src/DevOps/images/DevOps/817fec330eb2e96f1e355ad53dfa74c6.png b/src/DevOps/images/DevOps/817fec330eb2e96f1e355ad53dfa74c6.png new file mode 100644 index 0000000..90137d0 Binary files /dev/null and b/src/DevOps/images/DevOps/817fec330eb2e96f1e355ad53dfa74c6.png differ diff --git a/src/DevOps/images/DevOps/9ca30729b6120a06dff8d3c72a93f8e2.png b/src/DevOps/images/DevOps/9ca30729b6120a06dff8d3c72a93f8e2.png new file mode 100644 index 0000000..5826eb7 Binary files /dev/null and b/src/DevOps/images/DevOps/9ca30729b6120a06dff8d3c72a93f8e2.png differ diff --git a/src/DevOps/images/DevOps/AnalysisTools.png b/src/DevOps/images/DevOps/AnalysisTools.png new file mode 100644 index 0000000..0eb28c0 Binary files /dev/null and b/src/DevOps/images/DevOps/AnalysisTools.png differ diff --git a/src/DevOps/images/DevOps/GitFlow.jpg b/src/DevOps/images/DevOps/GitFlow.jpg new file mode 100644 index 0000000..abdb269 Binary files /dev/null and b/src/DevOps/images/DevOps/GitFlow.jpg differ diff --git a/src/DevOps/images/DevOps/Github-Flow.jpg b/src/DevOps/images/DevOps/Github-Flow.jpg new file mode 100644 index 0000000..7954a89 Binary files /dev/null and b/src/DevOps/images/DevOps/Github-Flow.jpg differ diff --git a/src/DevOps/images/DevOps/GitlabFlow.jpg b/src/DevOps/images/DevOps/GitlabFlow.jpg new file mode 100644 index 0000000..5c0c037 Binary files /dev/null and b/src/DevOps/images/DevOps/GitlabFlow.jpg differ diff --git a/src/DevOps/images/DevOps/Git仿集中式.png b/src/DevOps/images/DevOps/Git仿集中式.png new file mode 100644 index 0000000..d755f4a Binary files /dev/null and b/src/DevOps/images/DevOps/Git仿集中式.png differ diff --git a/src/DevOps/images/DevOps/HTTP-Mirror-Server-Response-Data.png b/src/DevOps/images/DevOps/HTTP-Mirror-Server-Response-Data.png new file mode 100644 index 0000000..2e578d5 Binary files /dev/null and b/src/DevOps/images/DevOps/HTTP-Mirror-Server-Response-Data.png differ diff --git a/src/DevOps/images/DevOps/HTTP-Mirror-Server-Response.png b/src/DevOps/images/DevOps/HTTP-Mirror-Server-Response.png new file mode 100644 index 0000000..136aab8 Binary files /dev/null and b/src/DevOps/images/DevOps/HTTP-Mirror-Server-Response.png differ diff --git a/src/DevOps/images/DevOps/HTTP-Mirror-Server-Send.png b/src/DevOps/images/DevOps/HTTP-Mirror-Server-Send.png new file mode 100644 index 0000000..9d1e59a Binary files /dev/null and b/src/DevOps/images/DevOps/HTTP-Mirror-Server-Send.png differ diff --git a/src/DevOps/images/DevOps/HTTP-Mirror-Server.png b/src/DevOps/images/DevOps/HTTP-Mirror-Server.png new file mode 100644 index 0000000..d25b052 Binary files /dev/null and b/src/DevOps/images/DevOps/HTTP-Mirror-Server.png differ diff --git a/src/DevOps/images/DevOps/Junit-Assert-Results.png b/src/DevOps/images/DevOps/Junit-Assert-Results.png new file mode 100644 index 0000000..7326f73 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Assert-Results.png differ diff --git a/src/DevOps/images/DevOps/Junit-CSV-Data-Set-Config-Data.png b/src/DevOps/images/DevOps/Junit-CSV-Data-Set-Config-Data.png new file mode 100644 index 0000000..4fbef4c Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-CSV-Data-Set-Config-Data.png differ diff --git a/src/DevOps/images/DevOps/Junit-CSV-Data-Set-Config-Set.png b/src/DevOps/images/DevOps/Junit-CSV-Data-Set-Config-Set.png new file mode 100644 index 0000000..cc95a5f Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-CSV-Data-Set-Config-Set.png differ diff --git a/src/DevOps/images/DevOps/Junit-Export.png b/src/DevOps/images/DevOps/Junit-Export.png new file mode 100644 index 0000000..0b76972 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Export.png differ diff --git a/src/DevOps/images/DevOps/Junit-HTTP-Head-Manager-Add.png b/src/DevOps/images/DevOps/Junit-HTTP-Head-Manager-Add.png new file mode 100644 index 0000000..96d841b Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-HTTP-Head-Manager-Add.png differ diff --git a/src/DevOps/images/DevOps/Junit-HTTP-Head-Manager-Referer.png b/src/DevOps/images/DevOps/Junit-HTTP-Head-Manager-Referer.png new file mode 100644 index 0000000..344d864 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-HTTP-Head-Manager-Referer.png differ diff --git a/src/DevOps/images/DevOps/Junit-HTTP-Request-Add.png b/src/DevOps/images/DevOps/Junit-HTTP-Request-Add.png new file mode 100644 index 0000000..ab8c261 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-HTTP-Request-Add.png differ diff --git a/src/DevOps/images/DevOps/Junit-HTTP-Request-Config.png b/src/DevOps/images/DevOps/Junit-HTTP-Request-Config.png new file mode 100644 index 0000000..0c1b412 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-HTTP-Request-Config.png differ diff --git a/src/DevOps/images/DevOps/Junit-HTTP-Request-GetCityCode.png b/src/DevOps/images/DevOps/Junit-HTTP-Request-GetCityCode.png new file mode 100644 index 0000000..d9d17b8 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-HTTP-Request-GetCityCode.png differ diff --git a/src/DevOps/images/DevOps/Junit-Http-Cookie-Manager-Config.png b/src/DevOps/images/DevOps/Junit-Http-Cookie-Manager-Config.png new file mode 100644 index 0000000..44cccae Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Http-Cookie-Manager-Config.png differ diff --git a/src/DevOps/images/DevOps/Junit-Http-Cookie-Manager-Cookies.png b/src/DevOps/images/DevOps/Junit-Http-Cookie-Manager-Cookies.png new file mode 100644 index 0000000..4a38e0c Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Http-Cookie-Manager-Cookies.png differ diff --git a/src/DevOps/images/DevOps/Junit-Jar-Export.png b/src/DevOps/images/DevOps/Junit-Jar-Export.png new file mode 100644 index 0000000..7883f94 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Jar-Export.png differ diff --git a/src/DevOps/images/DevOps/Junit-Regular-Expresstion-Extractor.png b/src/DevOps/images/DevOps/Junit-Regular-Expresstion-Extractor.png new file mode 100644 index 0000000..aa3d2b6 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Regular-Expresstion-Extractor.png differ diff --git a/src/DevOps/images/DevOps/Junit-Regular-Expresstion-Extractor变量.png b/src/DevOps/images/DevOps/Junit-Regular-Expresstion-Extractor变量.png new file mode 100644 index 0000000..6e727ad Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Regular-Expresstion-Extractor变量.png differ diff --git a/src/DevOps/images/DevOps/Junit-Regular-Expresstion-Extractor结果.png b/src/DevOps/images/DevOps/Junit-Regular-Expresstion-Extractor结果.png new file mode 100644 index 0000000..110ab7e Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Regular-Expresstion-Extractor结果.png differ diff --git a/src/DevOps/images/DevOps/Junit-Response-Assertion.png b/src/DevOps/images/DevOps/Junit-Response-Assertion.png new file mode 100644 index 0000000..30044e6 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Response-Assertion.png differ diff --git a/src/DevOps/images/DevOps/Junit-Reuest1.png b/src/DevOps/images/DevOps/Junit-Reuest1.png new file mode 100644 index 0000000..b897a55 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Reuest1.png differ diff --git a/src/DevOps/images/DevOps/Junit-Reuest2.png b/src/DevOps/images/DevOps/Junit-Reuest2.png new file mode 100644 index 0000000..b7d43e0 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Reuest2.png differ diff --git a/src/DevOps/images/DevOps/Junit-Reuest3.png b/src/DevOps/images/DevOps/Junit-Reuest3.png new file mode 100644 index 0000000..dad50b1 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Reuest3.png differ diff --git a/src/DevOps/images/DevOps/Junit-Summary-Report.png b/src/DevOps/images/DevOps/Junit-Summary-Report.png new file mode 100644 index 0000000..7c889b4 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Summary-Report.png differ diff --git a/src/DevOps/images/DevOps/Junit-Thread-Group.png b/src/DevOps/images/DevOps/Junit-Thread-Group.png new file mode 100644 index 0000000..4c31031 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-Thread-Group.png differ diff --git a/src/DevOps/images/DevOps/Junit-User-Defined-Variables.png b/src/DevOps/images/DevOps/Junit-User-Defined-Variables.png new file mode 100644 index 0000000..fc84908 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-User-Defined-Variables.png differ diff --git a/src/DevOps/images/DevOps/Junit-User-Defined-Variables变量.png b/src/DevOps/images/DevOps/Junit-User-Defined-Variables变量.png new file mode 100644 index 0000000..496e3c5 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-User-Defined-Variables变量.png differ diff --git a/src/DevOps/images/DevOps/Junit-View-Results-Tree-Fail.png b/src/DevOps/images/DevOps/Junit-View-Results-Tree-Fail.png new file mode 100644 index 0000000..8d4f7fd Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-View-Results-Tree-Fail.png differ diff --git a/src/DevOps/images/DevOps/Junit-View-Results-Tree-JSON.png b/src/DevOps/images/DevOps/Junit-View-Results-Tree-JSON.png new file mode 100644 index 0000000..3e90b12 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-View-Results-Tree-JSON.png differ diff --git a/src/DevOps/images/DevOps/Junit-View-Results-Tree-Run.png b/src/DevOps/images/DevOps/Junit-View-Results-Tree-Run.png new file mode 100644 index 0000000..33e67be Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-View-Results-Tree-Run.png differ diff --git a/src/DevOps/images/DevOps/Junit-View-Results-Tree.png b/src/DevOps/images/DevOps/Junit-View-Results-Tree.png new file mode 100644 index 0000000..4faa4e3 Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-View-Results-Tree.png differ diff --git a/src/DevOps/images/DevOps/Junit-查看结果树.png b/src/DevOps/images/DevOps/Junit-查看结果树.png new file mode 100644 index 0000000..9654c4f Binary files /dev/null and b/src/DevOps/images/DevOps/Junit-查看结果树.png differ diff --git a/src/DevOps/images/DevOps/SVN集中式.png b/src/DevOps/images/DevOps/SVN集中式.png new file mode 100644 index 0000000..55db7e4 Binary files /dev/null and b/src/DevOps/images/DevOps/SVN集中式.png differ diff --git a/src/DevOps/images/DevOps/b4e930f089487cc2431f3f2f067f0425.png b/src/DevOps/images/DevOps/b4e930f089487cc2431f3f2f067f0425.png new file mode 100644 index 0000000..1cf5306 Binary files /dev/null and b/src/DevOps/images/DevOps/b4e930f089487cc2431f3f2f067f0425.png differ diff --git a/src/DevOps/images/DevOps/d474b437af17bd1d35eb6f64b520a8ac.png b/src/DevOps/images/DevOps/d474b437af17bd1d35eb6f64b520a8ac.png new file mode 100644 index 0000000..060b5cd Binary files /dev/null and b/src/DevOps/images/DevOps/d474b437af17bd1d35eb6f64b520a8ac.png differ diff --git a/src/DevOps/images/DevOps/dstat.png b/src/DevOps/images/DevOps/dstat.png new file mode 100644 index 0000000..e0bf7e1 Binary files /dev/null and b/src/DevOps/images/DevOps/dstat.png differ diff --git a/src/DevOps/images/DevOps/feature分支.png b/src/DevOps/images/DevOps/feature分支.png new file mode 100644 index 0000000..263b95e Binary files /dev/null and b/src/DevOps/images/DevOps/feature分支.png differ diff --git a/src/DevOps/images/DevOps/glance.png b/src/DevOps/images/DevOps/glance.png new file mode 100644 index 0000000..a059210 Binary files /dev/null and b/src/DevOps/images/DevOps/glance.png differ diff --git a/src/DevOps/images/DevOps/goaccess-dashboard.png b/src/DevOps/images/DevOps/goaccess-dashboard.png new file mode 100644 index 0000000..7f41284 Binary files /dev/null and b/src/DevOps/images/DevOps/goaccess-dashboard.png differ diff --git a/src/DevOps/images/DevOps/hotfix分支.png b/src/DevOps/images/DevOps/hotfix分支.png new file mode 100644 index 0000000..7f3bdcc Binary files /dev/null and b/src/DevOps/images/DevOps/hotfix分支.png differ diff --git a/src/DevOps/images/DevOps/htop.gif b/src/DevOps/images/DevOps/htop.gif new file mode 100644 index 0000000..6bbd9da Binary files /dev/null and b/src/DevOps/images/DevOps/htop.gif differ diff --git a/src/DevOps/images/DevOps/htop.png b/src/DevOps/images/DevOps/htop.png new file mode 100644 index 0000000..197c168 Binary files /dev/null and b/src/DevOps/images/DevOps/htop.png differ diff --git a/src/DevOps/images/DevOps/iftop.png b/src/DevOps/images/DevOps/iftop.png new file mode 100644 index 0000000..9841202 Binary files /dev/null and b/src/DevOps/images/DevOps/iftop.png differ diff --git a/src/DevOps/images/DevOps/iostat.png b/src/DevOps/images/DevOps/iostat.png new file mode 100644 index 0000000..b7feee2 Binary files /dev/null and b/src/DevOps/images/DevOps/iostat.png differ diff --git a/src/DevOps/images/DevOps/master与develop分支.png b/src/DevOps/images/DevOps/master与develop分支.png new file mode 100644 index 0000000..2057388 Binary files /dev/null and b/src/DevOps/images/DevOps/master与develop分支.png differ diff --git a/src/DevOps/images/DevOps/netstat.png b/src/DevOps/images/DevOps/netstat.png new file mode 100644 index 0000000..53b0edf Binary files /dev/null and b/src/DevOps/images/DevOps/netstat.png differ diff --git a/src/DevOps/images/DevOps/pidstat.jpg b/src/DevOps/images/DevOps/pidstat.jpg new file mode 100644 index 0000000..8dc00fa Binary files /dev/null and b/src/DevOps/images/DevOps/pidstat.jpg differ diff --git a/src/DevOps/images/DevOps/release分支.png b/src/DevOps/images/DevOps/release分支.png new file mode 100644 index 0000000..26a0aad Binary files /dev/null and b/src/DevOps/images/DevOps/release分支.png differ diff --git a/src/DevOps/images/DevOps/saidar.png b/src/DevOps/images/DevOps/saidar.png new file mode 100644 index 0000000..53c8173 Binary files /dev/null and b/src/DevOps/images/DevOps/saidar.png differ diff --git a/src/DevOps/images/DevOps/sar-q-1-3.png b/src/DevOps/images/DevOps/sar-q-1-3.png new file mode 100644 index 0000000..0a8f588 Binary files /dev/null and b/src/DevOps/images/DevOps/sar-q-1-3.png differ diff --git a/src/DevOps/images/DevOps/tcpdump.jpg b/src/DevOps/images/DevOps/tcpdump.jpg new file mode 100644 index 0000000..d523735 Binary files /dev/null and b/src/DevOps/images/DevOps/tcpdump.jpg differ diff --git a/src/JAVA/_sidebar.md b/src/JAVA/_sidebar.md index c689a9b..e93c3bd 100644 --- a/src/JAVA/_sidebar.md +++ b/src/JAVA/_sidebar.md @@ -1,54 +1,54 @@ -* 🏁J.U.C - * [✍并发特性](src/JAVA/1 "并发特性") - * [✍Unsafe](src/JAVA/2 "Unsafe") - * [✍LockSupport](src/JAVA/3 "LockSupport") - * [✍CAS机制](src/JAVA/4 "CAS机制") - * [✍AQS框架](src/JAVA/5 "AQS框架") - * [✍Condition](src/JAVA/6 "Condition") - * [✍volatile](src/JAVA/7 "volatile") - * [✍lambda](src/JAVA/8 "lambda") - * [✍Striped64](src/JAVA/9 "Striped64") - * [✍LongAdder](src/JAVA/10 "LongAdder") - * [✍Semaphore](src/JAVA/11 "Semaphore") - * [✍CyclicBarrier](src/JAVA/12 "CyclicBarrier") - * [✍CountDownLatch](src/JAVA/13 "CountDownLatch") - * [✍CompletableFuture](src/JAVA/14 "CompletableFuture") -* 🏁集合 - * [✍List](src/JAVA/101 "List") - * [✍Set](src/JAVA/102 "Set") - * [✍Map](src/JAVA/103 "Map") -* 🏁Queue - * [✍队列](src/JAVA/201 "队列") - * [✍阻塞队列](src/JAVA/202 "阻塞队列") -* [🏁Thread](src/JAVA/301 "Thread") - * [✍线程实现方式](src/JAVA/302 "线程实现方式") - * [✍线程创建方式](src/JAVA/303 "线程创建方式") - * [✍线程生命周期](src/JAVA/304 "线程生命周期") - * [✍JDK线程池](src/JAVA/305 "JDK线程池") - * [✍线程方法](src/JAVA/306 "线程方法") - * [✍线程安全](src/JAVA/307 "线程安全") - * [✍线程同步](src/JAVA/308 "线程同步") - * [✍多线程通信](src/JAVA/309 "多线程通信") - * [✍线程协作](src/JAVA/310 "线程协作") - * [✍线程死锁](src/JAVA/311 "线程死锁") - * [✍守护线程](src/JAVA/312 "守护线程") - * [✍常见问题](src/JAVA/313 "常见问题") - * [✍ThreadLocal](src/JAVA/314 "ThreadLocal") - * [✍ThreadPoolExecutor](src/JAVA/315 "ThreadPoolExecutor") -* 🏁Lock - * [✍synchronized](src/JAVA/401 "synchronized") - * [✍ReentrantLock](src/JAVA/402 "ReentrantLock") - * [✍ReentrantReadWriteLock](src/JAVA/403 "ReentrantReadWriteLock") - * [✍锁的状态](src/JAVA/404 "锁的状态") - * [✍自旋锁(SpinLock)](src/JAVA/405 "自旋锁(SpinLock)") - * [✍常见锁](src/JAVA/406 "常见锁") - * [✍锁优化](src/JAVA/407 "锁优化") -* [🏁Throwable](src/JAVA/501 "Throwable") - * [✍Error](src/JAVA/502 "Error") - * [✍Exception](src/JAVA/503 "Exception") - * [✍异常处理方式](src/JAVA/504 "异常处理方式") -* 🏁Others - * [✍Annotation](src/JAVA/601 "Annotation") - * [✍JAVA内部类](src/JAVA/602 "JAVA内部类") - * [✍泛型](src/JAVA/603 "泛型") - * [✍JAVA复制](src/JAVA/604 "JAVA复制") \ No newline at end of file +* 🏁 J.U.C + * [✍ 并发特性](src/JAVA/1 "并发特性") + * [✍ Unsafe](src/JAVA/2 "Unsafe") + * [✍ LockSupport](src/JAVA/3 "LockSupport") + * [✍ CAS机制](src/JAVA/4 "CAS机制") + * [✍ AQS框架](src/JAVA/5 "AQS框架") + * [✍ Condition](src/JAVA/6 "Condition") + * [✍ volatile](src/JAVA/7 "volatile") + * [✍ lambda](src/JAVA/8 "lambda") + * [✍ Striped64](src/JAVA/9 "Striped64") + * [✍ LongAdder](src/JAVA/10 "LongAdder") + * [✍ Semaphore](src/JAVA/11 "Semaphore") + * [✍ CyclicBarrier](src/JAVA/12 "CyclicBarrier") + * [✍ CountDownLatch](src/JAVA/13 "CountDownLatch") + * [✍ CompletableFuture](src/JAVA/14 "CompletableFuture") +* 🏁 集合 + * [✍ List](src/JAVA/101 "List") + * [✍ Set](src/JAVA/102 "Set") + * [✍ Map](src/JAVA/103 "Map") +* 🏁 Queue + * [✍ 队列](src/JAVA/201 "队列") + * [✍ 阻塞队列](src/JAVA/202 "阻塞队列") +* [🏁 Thread](src/JAVA/301 "Thread") + * [✍ 线程实现方式](src/JAVA/302 "线程实现方式") + * [✍ 线程创建方式](src/JAVA/303 "线程创建方式") + * [✍ 线程生命周期](src/JAVA/304 "线程生命周期") + * [✍ JDK线程池](src/JAVA/305 "JDK线程池") + * [✍ 线程方法](src/JAVA/306 "线程方法") + * [✍ 线程安全](src/JAVA/307 "线程安全") + * [✍ 线程同步](src/JAVA/308 "线程同步") + * [✍ 多线程通信](src/JAVA/309 "多线程通信") + * [✍ 线程协作](src/JAVA/310 "线程协作") + * [✍ 线程死锁](src/JAVA/311 "线程死锁") + * [✍ 守护线程](src/JAVA/312 "守护线程") + * [✍ 常见问题](src/JAVA/313 "常见问题") + * [✍ ThreadLocal](src/JAVA/314 "ThreadLocal") + * [✍ ThreadPoolExecutor](src/JAVA/315 "ThreadPoolExecutor") +* 🏁 Lock + * [✍ synchronized](src/JAVA/401 "synchronized") + * [✍ ReentrantLock](src/JAVA/402 "ReentrantLock") + * [✍ ReentrantReadWriteLock](src/JAVA/403 "ReentrantReadWriteLock") + * [✍ 锁的状态](src/JAVA/404 "锁的状态") + * [✍ 自旋锁(SpinLock)](src/JAVA/405 "自旋锁(SpinLock)") + * [✍ 常见锁](src/JAVA/406 "常见锁") + * [✍ 锁优化](src/JAVA/407 "锁优化") +* [🏁 Throwable](src/JAVA/501 "Throwable") + * [✍ Error](src/JAVA/502 "Error") + * [✍ Exception](src/JAVA/503 "Exception") + * [✍ 异常处理方式](src/JAVA/504 "异常处理方式") +* 🏁 Others + * [✍ Annotation](src/JAVA/601 "Annotation") + * [✍ JAVA内部类](src/JAVA/602 "JAVA内部类") + * [✍ 泛型](src/JAVA/603 "泛型") + * [✍ JAVA复制](src/JAVA/604 "JAVA复制") \ No newline at end of file diff --git a/src/JVM/1.md b/src/JVM/1.md new file mode 100644 index 0000000..c0997eb --- /dev/null +++ b/src/JVM/1.md @@ -0,0 +1,14 @@ +JVM把描述类的数据加载到内存里面,并对数据进行校验、解析和初始化,最终变成可以被虚拟机直接使用的class对象。整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。其中准备、验证、解析3个部分统称为连接(Linking)。 + +![JVM类加载机制](images/JVM/JVM类加载机制.png) + +类加载过程如下: + +- 加载。加载分为三步: + - 通过类的全限定性类名获取该类的二进制流 + - 将该二进制流的静态存储结构转为方法区的运行时数据结构 + - 在堆中为该类生成一个class对象 +- 验证:验证该class文件中的字节流信息复合虚拟机的要求,不会威胁到jvm的安全 +- 准备:为class对象的静态变量分配内存,初始化其初始值 +- 解析:该阶段主要完成符号引用转化成直接引用 +- 初始化:到了初始化阶段,才开始执行类中定义的java代码;初始化阶段是调用类构造器的过程 \ No newline at end of file diff --git a/src/JVM/101.md b/src/JVM/101.md new file mode 100644 index 0000000..a398ba0 --- /dev/null +++ b/src/JVM/101.md @@ -0,0 +1,21 @@ +Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来**屏蔽掉各种硬件和操作系统的内存访问差异**,以实现让Java程序在各种平台下都能达到一致的内存访问效果。 + +![JAVA内存模型](images/JVM/JAVA内存模型.jpg) + +JMM描述了Java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存中读取出变量这样的底层细节。所有的变量都存储在主内存中,每个线程都有自己独立的工作内存,里面保存该线程使用到的变量的副本(主内存中变量的一份拷贝)。JMM的两条规定: + +- **线程对共享变量的所有操作都必须在自己的工作内存中进行,不能直接从主内存中读写** +- **不同的线程之间无法直接访问其他线程工作内存中的变量,线程变量值的传递需要通过主内存来完成** + + + +**Java 内存模型**(下文简称 **JMM**)就是在底层处理器内存模型的基础上,定义自己的多线程语义。它明确指定了一组排序规则,来保证线程间的可见性。这一组规则被称为 **Happens-Before**, JMM 规定,要想保证 B 操作能够看到 A 操作的结果(无论它们是否在同一个线程),那么 A 和 B 之间必须满足 **Happens-Before 关系**: + +- **单线程规则**:一个线程中的每个动作都 happens-before 该线程中后续的每个动作 +- **监视器锁定规则**:监听器的**解锁**动作 happens-before 后续对这个监听器的**锁定**动作 +- **volatile 变量规则**:对 volatile 字段的写入动作 happens-before 后续对这个字段的每个读取动作 +- **线程 start 规则**:线程 **start()** 方法的执行 happens-before 一个启动线程内的任意动作 +- **线程 join 规则**:一个线程内的所有动作 happens-before 任意其他线程在该线程 **join()** 成功返回之前 +- **传递性**:如果 A happens-before B, 且 B happens-before C, 那么 A happens-before C + +![JMM](images/JVM/JMM.png) \ No newline at end of file diff --git a/src/JVM/102.md b/src/JVM/102.md new file mode 100644 index 0000000..4946c33 --- /dev/null +++ b/src/JVM/102.md @@ -0,0 +1,14 @@ +JVM包含**堆**、**元空间**、**Java虚拟机栈**、**本地方法栈**、**程序计数器**等内存区域,其中**堆**是占用内存最大的,如下图所示: + +![JVM架构](images/JVM/JVM架构.png) + + + +**JVM常量池** + +JVM常量池主要分为**Class文件常量池、运行时常量池、全局字符串常量池、以及基本类型包装类对象常量池**。 + +- **Class文件常量池**:class文件是一组以字节为单位的二进制数据流,在java代码的编译期间,我们编写的java文件就被编译为.class文件格式的二进制数据存放在磁盘中,其中就包括class文件常量池。 +- **运行时常量池**:运行时常量池相对于class常量池一大特征就是具有动态性,java规范并不要求常量只能在运行时才产生,也就是说运行时常量池的内容并不全部来自class常量池,在运行时可以通过代码生成常量并将其放入运行时常量池中,这种特性被用的最多的就是String.intern()。 +- **全局字符串常量池**:字符串常量池是JVM所维护的一个字符串实例的引用表,在HotSpot VM中,它是一个叫做StringTable的全局表。在字符串常量池中维护的是字符串实例的引用,底层C++实现就是一个Hashtable。这些被维护的引用所指的字符串实例,被称作”被驻留的字符串”或”interned string”或通常所说的”进入了字符串常量池的字符串”。 +- **基本类型包装类对象常量池**:java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外上面这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象。 \ No newline at end of file diff --git a/src/JVM/103.md b/src/JVM/103.md new file mode 100644 index 0000000..30e6678 --- /dev/null +++ b/src/JVM/103.md @@ -0,0 +1,100 @@ +JVM试图定义一种统一的内存模型,能将各种底层硬件以及操作系统的内存访问差异进行封装,使Java程序在不同硬件以及操作系统上都能达到相同的并发效果。**它分为工作内存和主内存,线程无法对主存储器直接进行操作,如果一个线程要和另外一个线程通信,那么只能通过主存进行交换**。如下图所示: + +![JVM内存结构(JDK1.6)](images/JVM/JVM内存结构(JDK1.6).png) + +![JVM内存结构(JDK1.7)](images/JVM/JVM内存结构(JDK1.7).png) + +![JVM内存结构(JDK1.8)](images/JVM/JVM内存结构(JDK1.8).png) + +**线程隔离数据区:** + +- **程序计数器:** 一块较小的内存空间,存储当前线程所执行的字节码行号指示器 +- **虚拟机栈:** 里面的元素叫栈帧,存储 **局部变量表、操作栈、动态链接、方法返回地址** 等 +- **本地方法栈:** 为虚拟机使用到的本地Native方法服务时的栈帧,和虚拟机栈类似 + +**线程共享数据区:** + +- **方法区:** 存储已被虚拟机加载的**类信息、常量、静态变量、即时编译器编译后的代码**等数据 +- **堆:** 唯一目的就是存放**对象的实例**,是垃圾回收管理器的主要区域 +- **元数据区**:常量池、方法元信息、 + + + +### 程序计数器 + +程序计数器(Program Counter Register)也叫PC寄存器。程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。JVM支持多个线程同时运行,每个线程都有自己的程序计数器。倘若当前执行的是 JVM 的方法,则该寄存器中保存当前执行指令的地址;倘若执行的是native 方法,则PC寄存器中为空(undefined)。 + +- 当前线程私有 +- 当前线程所执行的字节码的行号指示器 +- 不会出现OutOfMemoryError情况 +- 以一种数据结构的形式放置于内存中 + +**注意**:程序计数器是唯一一个不会出现 `OutOfMemoryError` 的内存区域,它的生命周期随着线程的创建而创建,随着线程的结束而死亡。 + + + +### JAVA虚拟机栈 + +![JAVA虚拟机栈](images/JVM/JAVA虚拟机栈.png) + +JAVA虚拟机栈(Java Virtual Machine Stacks)是每个线程有一个私有的栈,随着线程的创建而创建,其生命周期与线程同进同退。栈里面存着的是一种叫“栈帧”的东西,每个Java方法在被调用的时候都会创建一个栈帧,一旦完成调用,则出栈。所有的的栈帧都出栈后,线程也就完成了使命。栈帧中存放了局部变量表(基本数据类型和对象引用)、操作数栈、动态链接(指向当前方法所属的类的运行时常量池的引用等)、方法出口(方法返回地址)、和一些额外的附加信息。栈的大小可以固定也可以动态扩展。当栈调用深度大于JVM所允许的范围,会抛出StackOverflowError的错误,不过这个深度范围不是一个恒定的值。 + +- 线程私有,生命周期与线程相同 +- java方法执行的内存模型,每个方法执行的同时都会创建一个栈帧,存储局部变量表(基本类型、对象引用)、操作数栈、动态链接、方法出口等信息 +- `StackOverflowError`:当线程请求的栈深度大于虚拟机所允许的深度 +- `OutOfMemoryError`:如果栈的扩展时无法申请到足够的内存 + +> **相关参数:** +> +> -Xss:设置方法栈的最大值 + + + +### 本地方法栈 + +本地方法栈(Native Method Stacks)与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的。在JVM规范中,并没有对本地方法栈的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotSopt虚拟机中直接就把本地方法栈和Java栈合二为一。 + + + +### 方法区 + +方法区(Method Area)用于存放**虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码**等数据。 + +- **又称之为:非堆(Non-Heap)或 永久区** +- **线程共享** +- **主要存储:类的类型信息、常量池(Runtime Constant Pool)、字段信息、方法信息、类变量和Class类的引用等** +- **Java虚拟机规范规定:当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常** + +> **相关参数:** +> +> -XX:PermSize:设置Perm区的初始大小 +> +> -XX:MaxPermSize:设置Perm区的最大值 + + + +### 堆内存 + +堆内存(JAVA Heap)。是被线程共享的一块内存区域,创建的对象和数组都保存在 Java 堆内存中,也是垃圾收集器进行垃圾收集的最重要的内存区域。由于现代 VM 采用**分代收集算法**, 因此 Java 堆从 GC 的角度还可以细分为: **新生代**(Eden区、From Survivor 区和 To Survivor 区)和老年代。 + +- **线程共享** +- **主要用于存储JAVA实例或对象** +- **GC发生的主要区域** +- **是Java虚拟机所管理的内存中最大的一块** +- **当堆中没有内存能完成实例分配,且堆也无法再扩展,则会抛出OutOfMemoryError异常** + +> **相关参数:** +> +> -Xms:设置堆内存初始大小 +> +> -Xmx:设置堆内存最大值 +> +> -XX:MaxTenuringThreshold:设置对象在新生代中存活的次数 +> +> -XX:PretenureSizeThreshold:设置超过指定大小的大对象直接分配在旧生代中 +> +> **新生代相关参数**(注意:当新生代设置得太小时,也可能引发大对象直接分配到旧生代): +> +> -Xmn:设置新生代内存大小 +> +> -XX:SurvivorRatio:设置Eden与Survivor空间的大小比例 \ No newline at end of file diff --git a/src/JVM/104.md b/src/JVM/104.md new file mode 100644 index 0000000..fca1a84 --- /dev/null +++ b/src/JVM/104.md @@ -0,0 +1,130 @@ +JVM运行时内存又称堆内存(Heap)。Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年代。 + +![RuntimeDataArea](images/JVM/RuntimeDataArea.png) + +![JVM堆内存划分](images/JVM/JVM堆内存划分.png) + +当代主流虚拟机(Hotspot VM)的垃圾回收都采用“分代回收”的算法。“分代回收”是基于这样一个事实:对象的生命周期不同,所以针对不同生命周期的对象可以采取不同的回收方式,以便提高回收效率。Hotspot VM将内存划分为不同的物理区,就是“分代”思想的体现。 + + + +**一个对象从出生到消亡** + +![JVM对象申请空间流程](images/JVM/JVM对象申请空间流程.png) + +一个对象产生之后首先进行栈上分配,栈上如果分配不下会进入伊甸区,伊甸区经过一次垃圾回收之后进入surivivor区,survivor区在经过一次垃圾回收之后又进入另外一个survivor,与此同时伊甸区的某些对象也跟着进入另外一个survivot,什么时候年龄够了就会进入old区,这是整个对象的一个逻辑上的移动过程。 + + + +### 新生代(Young Generation) + +**主要是用来存放新生的对象**。一般占据堆的1/3空间。由于频繁创建对象,所以新生代会频繁触发MinorGC进行垃圾回收。新生代又分为 Eden区、ServivorFrom、ServivorTo三个区。 + +- **Eden区**:Java新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当Eden区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收 +- **ServivorTo**:保留了一次MinorGC过程中的幸存者 +- **ServivorFrom**:上一次GC的幸存者,作为这一次GC的被扫描者 + + + +**MinorGC流程** + +- **MinorGC采用复制算法** +- 首先把Eden和ServivorFrom区域中存活的对象复制到ServicorTo区域(如果有对象的年龄以及达到了老年的标准,则复制到老年代区),同时把这些对象的年龄+1(如果ServicorTo不够位置了就放到老年区) +- 然后清空Eden和ServicorFrom中的对象 +- 最后ServicorTo和ServicorFrom互换,原ServicorTo成为下一次GC时的ServicorFrom区 + + + +**为什么 Survivor 分区不能是 0 个?** + +如果 Survivor 是 0 的话,也就是说新生代只有一个 Eden 分区,每次垃圾回收之后,存活的对象都会进入老生代,这样老生代的内存空间很快就被占满了,从而触发最耗时的 Full GC ,显然这样的收集器的效率是我们完全不能接受的。 + +**为什么 Survivor 分区不能是 1 个?** + +如果 Survivor 分区是 1 个的话,假设我们把两个区域分为 1:1,那么任何时候都有一半的内存空间是闲置的,显然空间利用率太低不是最佳的方案。 + +但如果设置内存空间的比例是 8:2 ,只是看起来似乎“很好”,假设新生代的内存为 100 MB( Survivor 大小为 20 MB ),现在有 70 MB 对象进行垃圾回收之后,剩余活跃的对象为 15 MB 进入 Survivor 区,这个时候新生代可用的内存空间只剩了 5 MB,这样很快又要进行垃圾回收操作,显然这种垃圾回收器最大的问题就在于,需要频繁进行垃圾回收。 + +**为什么 Survivor 分区是 2 个?** + +如果Survivor分区有2个分区,我们就可以把 Eden、From Survivor、To Survivor 分区内存比例设置为 8:1:1 ,那么任何时候新生代内存的利用率都 90% ,这样空间利用率基本是符合预期的。再者就是虚拟机的大部分对象都符合“朝生夕死”的特性,所以每次新对象的产生都在空间占比比较大的Eden区,垃圾回收之后再把存活的对象方法存入Survivor区,如果是 Survivor区存活的对象,那么“年龄”就+1,当年龄增长到15(可通过 -XX:+MaxTenuringThreshold 设定)对象就升级到老生代。 + + + +**总结** + +根据上面的分析可以得知,当新生代的 Survivor 分区为 2 个的时候,不论是空间利用率还是程序运行的效率都是最优的,所以这也是为什么 Survivor 分区是 2 个的原因了。 + + + +### 老年代(Old Generation) + +**主要存放应用程序中生命周期长的内存对象**。老年代的对象比较稳定,所以MajorGC不会频繁执行。在进行MajorGC前一般都先进行了一次MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。当无法找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次MajorGC进行垃圾回收腾出空间。 + + + +**MajorGC流程** + +MajorGC采用标记—清除算法。首先扫描一次所有老年代,标记出存活的对象,然后回收没有标记的对象。MajorGC的耗时比较长,因为要扫描再回收。MajorGC会产生内存碎片,为了减少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。当老年代也满了装不下的时候,就会抛出OOM(Out of Memory)异常。 + + + +### 永久区(Perm Generation) + +指内存的永久保存区域,**主要存放元数据**,例如Class、Method的元信息,与垃圾回收要回收的Java对象关系不大。相对于新生代和年老代来说,该区域的划分对垃圾回收影响比较小。GC不会在主程序运行期对永久区域进行清理,所以这也导致了永久代的区域会随着加载的Class的增多而胀满,最终抛出OOM异常。 + + + +**JAVA8与元数据** + +在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:**元空间并不在虚拟机中,而是使用本地内存**。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入Native Memory,字符串池和类的静态变量放入java堆中,这样可以加载多少类的元数据就不再由MaxPermSize控制,而由系统的实际可用空间来控制。 + + + +### 内存分配策略 + +堆内存常见的分配测试如下: + +- 对象优先在Eden区分配 +- 大对象直接进入老年代 +- 长期存活的对象将进入老年代 + +| **参数** | **说明信息** | +| :------------------------------ | ------------------------------------------------------------ | +| -Xms | 初始堆大小。如:-Xms256m | +| -Xmx | 最大堆大小。如:-Xmx512m | +| -Xmn | 新生代大小。通常为Xmx的1/3或1/4。新生代=Eden+2个Survivor空间。实际可用空间为=Eden+1个Survivor,即 90% | +| -Xss | JDK1.5+每个线程堆栈大小为 1M,一般来说如果栈不是很深的话, 1M 是绝对够用了的 | +| -XX:NewRatio | 新生代与老年代的比例。如–XX:NewRatio=2,则新生代占整个堆空间的1/3,老年代占2/3 | +| -XX:SurvivorRatio | 新生代中Eden与Survivor的比值。默认值为 8,即Eden占新生代空间的8/10,另外两个Survivor各占1/10 | +| -XX:PermSize | 永久代(方法区)的初始大小 | +| -XX:MaxPermSize | 永久代(方法区)的最大值 | +| -XX:+PrintGCDetails | 打印GC信息 | +| -XX:+HeapDumpOnOutOfMemoryError | 让虚拟机在发生内存溢出时Dump出当前的内存堆转储快照,以便分析用 | + + + +**参数基本策略** + +各分区的大小对GC的性能影响很大。如何将各分区调整到合适的大小,分析活跃数据的大小是很好的切入点。 + +**活跃数据的大小**:指应用程序稳定运行时长期存活对象在堆中占用的空间大小,即Full GC后堆中老年代占用空间的大小。 + +可以通过GC日志中Full GC之后老年代数据大小得出,比较准确的方法是在程序稳定后,多次获取GC数据,通过取平均值的方式计算活跃数据的大小。活跃数据和各分区之间的比例关系如下: + +| 空间 | 倍数 | +| ------ | --------------------------------------- | +| 总大小 | **3-4** 倍活跃数据的大小 | +| 新生代 | **1-1.5** 活跃数据的大小 | +| 老年代 | **2-3** 倍活跃数据的大小 | +| 永久代 | **1.2-1.5** 倍Full GC后的永久代空间占用 | + +例如,根据GC日志获得老年代的活跃数据大小为300M,那么各分区大小可以设为: + +> 总堆:1200MB = 300MB × 4 +> +> 新生代:450MB = 300MB × 1.5 +> +> 老年代: 750MB = 1200MB - 450MB + +这部分设置仅仅是堆大小的初始值,后面的优化中,可能会调整这些值,具体情况取决于应用程序的特性和需求。 \ No newline at end of file diff --git a/src/JVM/105.md b/src/JVM/105.md new file mode 100644 index 0000000..f7ebfd7 --- /dev/null +++ b/src/JVM/105.md @@ -0,0 +1,120 @@ +Java中4种引用的级别和强度由高到低依次为:**强引用→软引用→弱引用→虚引用** + +当**垃圾回收器**回收时,某些对象会被回收,某些不会被回收。垃圾回收器会从**根对象**`Object`来**标记**存活的对象,然后将某些不可达的对象和一些引用的对象进行回收。如下所示: + +| 引用类型 | 被垃圾回收时间 | 用途 | 生存时间 | +| -------- | -------------- | ------------------ | ----------------- | +| 强引用 | 从来不会 | 对象的一般状态 | JVM停止运行时终止 | +| 软引用 | 当内存不足时 | 对象缓存 | 内存不足时终止 | +| 弱引用 | 正常垃圾回收时 | 对象缓存 | 垃圾回收后终止 | +| 虚引用 | 正常垃圾回收时 | 跟踪对象的垃圾回收 | 垃圾回收后终止 | + +![引用级别](images/JVM/引用级别.png) + + + +### 强引用(StrongReference) + +强引用是我们最常见的对象,它属于不可回收资源,垃圾回收器(后面简称GC)绝对不会回收它,即使是内存不足,JVM宁愿抛出 OutOfMemoryError 异常,使程序终止,也不会来回收强引用对象。如果一个对象具有强引用,那**垃圾回收器**绝不会回收它。如下: + +```java +Object strongReference = new Object(); +``` + +当**内存空间不足**时,`Java`虚拟机宁愿抛出`OutOfMemoryError`错误,使程序**异常终止**,也不会靠随意**回收**具有**强引用**的**对象**来解决内存不足的问题。 如果强引用对象**不使用时**,需要弱化从而使`GC`能够回收,如下: + +```java +strongReference = null; +``` + +显式地设置`strongReference`对象为`null`,或让其**超出**对象的**生命周期**范围,则`gc`认为该对象**不存在引用**,这时就可以回收这个对象。具体什么时候收集这要取决于`GC`算法。 + +```java +public void test() { + Object strongReference = new Object(); + // 省略其他操作 +} +``` + +在一个**方法的内部**有一个**强引用**,这个引用保存在`Java`**栈**中,而真正的引用内容(`Object`)保存在`Java`**堆**中。 当这个**方法运行完成**后,就会退出**方法栈**,则引用对象的**引用数**为`0`,这个对象会被回收。但是如果这个`strongReference`是**全局变量**时,就需要在不用这个对象时赋值为`null`,因为**强引用**不会被垃圾回收。 + + + +### 软引用(SoftReference) + +如果一个对象只具有**软引用**,则**内存空间充足**时,**垃圾回收器**就**不会**回收它;如果**内存空间不足**了,就会**回收**这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。 + +```java +// 强引用 +String strongReference = new String("abc"); +// 软引用 +String str = new String("abc"); +SoftReference softReference = new SoftReference(str); +``` + +**软引用**可以和一个**引用队列**(`ReferenceQueue`)联合使用。如果**软引用**所引用对象被**垃圾回收**,`JAVA`虚拟机就会把这个**软引用**加入到与之关联的**引用队列**中。 + +```java +ReferenceQueue referenceQueue = new ReferenceQueue<>(); +String str = new String("abc"); +SoftReference softReference = new SoftReference<>(str, referenceQueue); +``` + +**注意**:软引用对象是在jvm内存不够时才会被回收,我们调用System.gc()方法只是起通知作用,JVM什么时候扫描回收对象是JVM自己的状态决定的。就算扫描到软引用对象也不一定会回收它,只有内存不够的时候才会回收。 + +**垃圾收集线程**会在虚拟机抛出`OutOfMemoryError`之前回**收软引用对象**,而**虚拟机**会尽可能优先回收**长时间闲置不用**的**软引用对象**。对那些**刚构建**的或刚使用过的**"较新的"**软对象会被虚拟机尽可能**保留**,这就是引入**引用队列**`ReferenceQueue`的原因。 + + + +### 弱引用(WeakReference) + +弱引用对象相对软引用对象具有更短暂的生命周期,只要 GC 发现它仅有弱引用,不管内存空间是否充足,都会回收它,不过 GC 是一个优先级很低的线程,因此不一定会很快发现那些仅有弱引用的对象。 + +**弱引用**与**软引用**的区别在于:只具有**弱引用**的对象拥有**更短暂**的**生命周期**。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有**弱引用**的对象,不管当前**内存空间足够与否**,都会**回收**它的内存。不过,由于垃圾回收器是一个**优先级很低的线程**,因此**不一定**会**很快**发现那些只具有**弱引用**的对象。 + +```java +String str = new String("abc"); +WeakReference weakReference = new WeakReference<>(str); +str = null; +``` + +`JVM`首先将**软引用**中的**对象**引用置为`null`,然后通知**垃圾回收器**进行回收: + +```java +str = null; +System.gc(); +``` + +**注意**:如果一个对象是偶尔(很少)的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么你应该用Weak Reference来记住此对象。 + +下面的代码会让一个**弱引用**再次变为一个**强引用**: + +```java +String str = new String("abc"); +WeakReference weakReference = new WeakReference<>(str); +// 弱引用转强引用 +String strongReference = weakReference.get(); +``` + +同样,**弱引用**可以和一个**引用队列**(`ReferenceQueue`)联合使用,如果**弱引用**所引用的**对象**被**垃圾回收**,`Java`虚拟机就会把这个**弱引用**加入到与之关联的**引用队列**中。 + + + +### 虚引用(PhantomReference) + +**虚引用**顾名思义,就是**形同虚设**。与其他几种引用都不同,**虚引用**并**不会**决定对象的**生命周期**。如果一个对象**仅持有虚引用**,那么它就和**没有任何引用**一样,在任何时候都可能被垃圾回收器回收。 + +**应用场景:** + +**虚引用**主要用来**跟踪对象**被垃圾回收器**回收**的活动。 **虚引用**与**软引用**和**弱引用**的一个区别在于: + +> 虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。 + +```java +String str = new String("abc"); +ReferenceQueue queue = new ReferenceQueue(); +// 创建虚引用,要求必须与一个引用队列关联 +PhantomReference pr = new PhantomReference(str, queue); +``` + +程序可以通过判断引用**队列**中是否已经加入了**虚引用**,来了解被引用的对象是否将要进行**垃圾回收**。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的**内存被回收之前**采取必要的行动。 \ No newline at end of file diff --git a/src/JVM/106.md b/src/JVM/106.md new file mode 100644 index 0000000..3b53ed8 --- /dev/null +++ b/src/JVM/106.md @@ -0,0 +1,160 @@ +JVM发生OOM的九种场景如下: + +**场景一:Java heap space** + +> 当堆内存(Heap Space)没有足够空间存放新创建的对象时,就会抛出 `java.lang.OutOfMemoryError:Javaheap space` 错误(根据实际生产经验,可以对程序日志中的 OutOfMemoryError 配置关键字告警,一经发现,立即处理)。 +> +> **原因分析** +> +> `Javaheap space` 错误产生的常见原因可以分为以下几类: +> +> - 请求创建一个超大对象,通常是一个大数组 +> - 超出预期的访问量/数据量,通常是上游系统请求流量飙升,常见于各类促销/秒杀活动,可以结合业务流量指标排查是否有尖状峰值 +> - 过度使用终结器(Finalizer),该对象没有立即被 GC +> - 内存泄漏(Memory Leak),大量对象引用没有释放,JVM 无法对其自动回收,常见于使用了 File 等资源没有回收 +> +> **解决方案** +> +> 针对大部分情况,通常只需通过 `-Xmx` 参数调高 JVM 堆内存空间即可。如果仍然没有解决,可参考以下情况做进一步处理: +> +> - 如果是超大对象,可以检查其合理性,比如是否一次性查询了数据库全部结果,而没有做结果数限制 +> - 如果是业务峰值压力,可以考虑添加机器资源,或者做限流降级 +> - 如果是内存泄漏,需要找到持有的对象,修改代码设计,比如关闭没有释放的连接 + +**场景二:GC overhead limit exceeded** + +> 当 Java 进程花费 98% 以上的时间执行 GC,但只恢复了不到 2% 的内存,且该动作连续重复了 5 次,就会抛出 `java.lang.OutOfMemoryError:GC overhead limit exceeded` 错误。简单地说,就是应用程序已经基本耗尽了所有可用内存, GC 也无法回收。 +> +> 此类问题的原因与解决方案跟 `Javaheap space` 非常类似,可以参考上文。 + +**场景三:Permgen space** + +> 该错误表示永久代(Permanent Generation)已用满,通常是因为加载的 class 数目太多或体积太大。 +> +> **原因分析** +> +> 永久代存储对象主要包括以下几类: +> +> - 加载/缓存到内存中的 class 定义,包括类的名称,字段,方法和字节码 +> - 常量池 +> - 对象数组/类型数组所关联的 class +> - JIT 编译器优化后的 class 信息 +> +> PermGen 的使用量与加载到内存的 class 的数量/大小正相关。 +> +> **解决方案** +> +> 根据 Permgen space 报错的时机,可以采用不同的解决方案,如下所示: +> +> - 程序启动报错,修改 `-XX:MaxPermSize` 启动参数,调大永久代空间 +> - 应用重新部署时报错,很可能是没有应用没有重启,导致加载了多份 class 信息,只需重启 JVM 即可解决 +> - 运行时报错,应用程序可能会动态创建大量 class,而这些 class 的生命周期很短暂,但是 JVM 默认不会卸载 class,可以设置 `-XX:+CMSClassUnloadingEnabled` 和 `-XX:+UseConcMarkSweepGC` 这两个参数允许 JVM 卸载 class。 +> +> 如果上述方法无法解决,可以通过 jmap 命令 dump 内存对象 `jmap-dump:format=b,file=dump.hprof` ,然后利用 Eclipse MAT https://www.eclipse.org/mat 功能逐一分析开销最大的 classloader 和重复 class。 + +**场景四:Metaspace** + +> JDK 1.8 使用 Metaspace 替换了永久代(Permanent Generation),该错误表示 Metaspace 已被用满,通常是因为加载的 class 数目太多或体积太大。 +> +> 此类问题的原因与解决方法跟 `Permgenspace` 非常类似,可以参考上文。需要特别注意的是调整 Metaspace 空间大小的启动参数为 `-XX:MaxMetaspaceSize`。 + +**场景五:Unable to create new native thread** + +> 每个 Java 线程都需要占用一定的内存空间,当 JVM 向底层操作系统请求创建一个新的 native 线程时,如果没有足够的资源分配就会报此类错误。 +> +> **原因分析** +> +> JVM 向 OS 请求创建 native 线程失败,就会抛出 `Unableto createnewnativethread`,常见的原因包括以下几类: +> +> - 线程数超过操作系统最大线程数 ulimit 限制 +> - 线程数超过 kernel.pid_max(只能重启) +> - native 内存不足 +> +> 该问题发生的常见过程主要包括以下几步: +> +> - JVM 内部的应用程序请求创建一个新的 Java 线程 +> - JVM native 方法代理了该次请求,并向操作系统请求创建一个 native 线程 +> - 操作系统尝试创建一个新的 native 线程,并为其分配内存 +> - 如果操作系统的虚拟内存已耗尽,或是受到 32 位进程的地址空间限制,操作系统就会拒绝本次 native 内存分配 +> - JVM 将抛出 `java.lang.OutOfMemoryError:Unableto createnewnativethread`错误 +> +> **解决方案** +> +> - 升级配置,为机器提供更多的内存 +> - 降低 Java Heap Space 大小 +> - 修复应用程序的线程泄漏问题 +> - 限制线程池大小 +> - 使用 -Xss 参数减少线程栈的大小 +> - 调高 OS 层面的线程最大数:执行 `ulimia-a` 查看最大线程数限制,使用 `ulimit-u xxx` 调整最大线程数限制 + +**场景六:Out of swap space?** + +> 该错误表示所有可用的虚拟内存已被耗尽。虚拟内存(Virtual Memory)由物理内存(Physical Memory)和交换空间(Swap Space)两部分组成。当运行时程序请求的虚拟内存溢出时就会报 `Outof swap space?` 错误。 +> +> **原因分析** +> +> 该错误出现的常见原因包括以下几类: +> +> - 地址空间不足 +> - 物理内存已耗光 +> - 应用程序的本地内存泄漏(native leak),例如不断申请本地内存,却不释放 +> - 执行 `jmap-histo:live` 命令,强制执行 Full GC;如果几次执行后内存明显下降,则基本确认为 Direct ByteBuffer 问题 +> +> **解决方案** +> +> 根据错误原因可以采取如下解决方案: +> +> - 升级地址空间为 64 bit +> - 使用 Arthas 检查是否为 Inflater/Deflater 解压缩问题,如果是,则显式调用 end 方法 +> - Direct ByteBuffer 问题可以通过启动参数 `-XX:MaxDirectMemorySize` 调低阈值 +> - 升级服务器配置/隔离部署,避免争用 + +**场景七:Kill process or sacrifice child** + +> 有一种内核作业(Kernel Job)名为 Out of Memory Killer,它会在可用内存极低的情况下“杀死”(kill)某些进程。OOM Killer 会对所有进程进行打分,然后将评分较低的进程“杀死”,具体的评分规则可以参考 Surviving the Linux OOM Killer。不同于其它OOM错误, `Killprocessorsacrifice child` 错误不是由 JVM 层面触发的,而是由操作系统层面触发的。 +> +> **原因分析** +> +> 默认情况下,Linux 内核允许进程申请的内存总量大于系统可用内存,通过这种“错峰复用”的方式可以更有效的利用系统资源。然而,这种方式也会无可避免地带来一定的“超卖”风险。例如某些进程持续占用系统内存,然后导致其他进程没有可用内存。此时,系统将自动激活 OOM Killer,寻找评分低的进程,并将其“杀死”,释放内存资源。 +> +> **解决方案** +> +> - 升级服务器配置/隔离部署,避免争用 +> - OOM Killer 调优 + +**场景八:Requested array size exceeds VM limit** + +> JVM 限制了数组的最大长度,该错误表示程序请求创建的数组超过最大长度限制。JVM 在为数组分配内存前,会检查要分配的数据结构在系统中是否可寻址,通常为 `Integer.MAX_VALUE-2`。 +> +> 此类问题比较罕见,通常需要检查代码,确认业务是否需要创建如此大的数组,是否可以拆分为多个块,分批执行。 + +**场景九:Direct buffer memory** + +> Java 允许应用程序通过 Direct ByteBuffer 直接访问堆外内存,许多高性能程序通过 Direct ByteBuffer 结合内存映射文件(Memory Mapped File)实现高速 IO。 +> +> **原因分析** +> +> Direct ByteBuffer 的默认大小为 64 MB,一旦使用超出限制,就会抛出 `Directbuffer memory` 错误。 +> +> **解决方案** +> +> - Java 只能通过 ByteBuffer.allocateDirect 方法使用 Direct ByteBuffer,因此,可以通过 Arthas 等在线诊断工具拦截该方法进行排查 +> - 检查是否直接或间接使用了 NIO,如 netty,jetty 等 +> - 通过启动参数 `-XX:MaxDirectMemorySize` 调整 Direct ByteBuffer 的上限值 +> - 检查 JVM 参数是否有 `-XX:+DisableExplicitGC` 选项,如果有就去掉,因为该参数会使 `System.gc()` 失效 +> - 检查堆外内存使用代码,确认是否存在内存泄漏;或者通过反射调用 `sun.misc.Cleaner` 的 `clean()` 方法来主动释放被 Direct ByteBuffer 持有的内存空间 +> - 内存容量确实不足,升级配置 + +**最佳实践** + +> ① OOM发生时输出堆dump: +> +> `-XX:+HeapDumpOnOutOfMemoryError` `-XX:HeapDumpPath=$CATALINA_HOME/logs` +> +> ② OOM发生后的执行动作: +> +> `-XX:OnOutOfMemoryError=$CATALINA_HOME/bin/stop.sh` +> +> `-XX:OnOutOfMemoryError=$CATALINA_HOME/bin/restart.sh` +> +> OOM之后除了保留堆dump外,根据管理策略选择合适的运行脚本。 \ No newline at end of file diff --git a/src/JVM/2.md b/src/JVM/2.md new file mode 100644 index 0000000..c258d0e --- /dev/null +++ b/src/JVM/2.md @@ -0,0 +1,27 @@ +虚拟机设计团队把加载动作放到 JVM 外部实现,以便让应用程序决定如何获取所需的类,JVM 提供了 3 种类加载器: + +![Classloader](images/JVM/Classloader.png) + +- **启动类加载器(Bootstrap ClassLoader)** + + **用来加载java核心类库,无法被java程序直接引用**。负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath 参数指定路径中的,且被虚拟机认可(按文件名识别,如 rt.jar)的类。 + +- **扩展类加载器(Extension ClassLoader)** + + **用来加载java的扩展库,java的虚拟机实现会提供一个扩展库目录,该类加载器在扩展库目录里面查找并加载java类**。负责加载 JAVA_HOME\lib\ext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类库。 + +- **应用程序类加载器(Application ClassLoader)** + + **它根据java的类路径来加载类,一般来说,java应用的类都是通过它来加载的**。负责加载用户路径(classpath)上的类库。JVM 通过双亲委派模型进行类的加载,当然我们也可以通过继承java.lang.ClassLoader 实现自定义的类加载器。 + +- **自定义类加载器(User ClassLoader)** + + 由JAVA语言实现,继承自ClassLoader。 + + + +此外我们比较需要知道的几点: + +- 一个类是由 jvm 加载是通过类加载器+全限定类名确定唯一性的 +- 双亲委派,众所周知,子加载器会尽量委托给父加载器进行加载,父加载器找不到再自己加载 +- 线程上下文类加载,为了满足 spi 等需求突破双亲委派机制,当高层类加载器想加载底层类时通过 Thread.contextClassLoader 来获取当前线程的类加载器(往往是底层类加载器)去加载类 \ No newline at end of file diff --git a/src/JVM/201.md b/src/JVM/201.md new file mode 100644 index 0000000..2e266e2 --- /dev/null +++ b/src/JVM/201.md @@ -0,0 +1,53 @@ +![寻找垃圾算法](images/JVM/寻找垃圾算法.png) + +### 引用计数法 + +引用计数法(Reference Count)会给对象中添加一个引用计数器,每当有一个地方引用它的时候,计数器的值就 +1 ,当引用失效时,计数器值就 -1 ,计数器的值为 0 的对象不可能在被使用,这个时候就可以判定这个对象是垃圾。 + +![引用计数法](images/JVM/引用计数法.png) + +当图中的数值变成0时,这个时候使用引用计数算法就可以判定它是垃圾了,但是引用计数法不能解决一个问题,就是当对象是循环引用的时候,计数器值都不为0,这个时候引用计数器无法通知GC收集器来回收他们,如下图所示: + +![引用计数法-问题](images/JVM/引用计数法-问题.png) + +这个时候就需要使用到我们的根可达算法。 + + + +### 可达性分析 + +根可达算法(Root Searching)的意思是说从根上开始搜索,当一个程序启动后,马上需要的那些个对象就叫做根对象,所谓的根可达算法就是首先找到根对象,然后跟着这根线一直往外找到那些有用的。常见的GC roots如下: + +- **线程栈变量:** 线程里面会有线程栈和main栈帧,从这个main() 里面开始的这些对象都是我们的根对象 + +- **静态变量:** 一个class 它有一个静态的变量,load到内存之后马上就得对静态变量进行初始化,所以静态变量到的对象这个叫做根对象 + +- **常量池:** 如果你这个class会用到其他的class的那些个类的对象,这些就是根对象 + +- **JNI:** 如果我们调用了 C和C++ 写的那些本地方法所用到的那些个类或者对象 + +![根可达算法](images/JVM/根可达算法.png) + +图中的 object5 和object6 虽然他们之间互相引用了,但是从根找不到它,所以就是垃圾,而object8没有任何引用自然而然也是垃圾,其他的Object对象都有可以从根找到的,所以是有用的,不会被垃圾回收掉。 + + + +**GC Root** + +GC Roots 是一组必须活跃的引用。用通俗的话来说,就是程序接下来通过直接引用或者间接引用,能够访问到的潜在被使用的对象。GC Roots 包括: + +- **Java 线程中,当前所有正在被调用的方法的引用类型参数、局部变量、临时值等。也就是与我们栈帧相关的各种引用** +- **所有当前被加载的 Java 类** +- **Java 类的引用类型静态变量** +- **运行时常量池里的引用类型常量(String 或 Class 类型)** +- **JVM 内部数据结构的一些引用,比如 sun.jvm.hotspot.memory.Universe 类** +- **用于同步的监控对象,比如调用了对象的 wait() 方法** +- **JNI handles,包括 global handles 和 local handles** + + + +GC Roots 大体可以分为三大类: + +- **活动线程相关的各种引用** +- **类的静态变量的引用** +- **JNI 引用** \ No newline at end of file diff --git a/src/JVM/202.md b/src/JVM/202.md new file mode 100644 index 0000000..f11bb94 --- /dev/null +++ b/src/JVM/202.md @@ -0,0 +1,172 @@ +清理垃圾算法又叫内存回收算法。 + +### 标记(Mark) + +垃圾回收的第一步,就是找出活跃的对象。根据 GC Roots 遍历所有的可达对象,这个过程,就叫作标记。 + +![标记(Mark)](images/JVM/标记(Mark).png) + +如图所示,圆圈代表的是对象。绿色的代表 GC Roots,红色的代表可以追溯到的对象。可以看到标记之后,仍然有多个灰色的圆圈,它们都是被回收的对象。 + + + +### 清除(Sweep) + +清除阶段就是把未被标记的对象回收掉。 + +![清除(Sweep)](images/JVM/清除(Sweep).png) + +但是这种简单的清除方式,有一个明显的弊端,那就是碎片问题。比如我申请了 1k、2k、3k、4k、5k 的内存。 + +![清除(Sweep)-内存](images/JVM/清除(Sweep)-内存.jpg) + +由于某种原因 ,2k 和 4k 的内存,我不再使用,就需要交给垃圾回收器回收。 + +![清除(Sweep)-回收](images/JVM/清除(Sweep)-回收.jpg) + +这个时候,我应该有足足 6k 的空闲空间。接下来,我打算申请另外一个 5k 的空间,结果系统告诉我内存不足了。系统运行时间越长,这种碎片就越多。在很久之前使用 Windows 系统时,有一个非常有用的功能,就是内存整理和磁盘整理,运行之后有可能会显著提高系统性能。这个出发点是一样的。 + + + +### 复制(Copying) + +![复制(Copying)算法](images/JVM/复制(Copying)算法.png) + +**优点** + +- 因为是对整个半区进行内存回收,内存分配时不用考虑内存碎片等情况。实现简单,效率较高 + +**不足之处** + +- 既然要复制,需要提前预留内存空间,有一定的浪费 +- 在对象存活率较高时,需要复制的对象较多,效率将会变低 + + + +### 整理(Compact) + +其实,不用分配一个对等的额外空间,也是可以完成内存的整理工作。可以把内存想象成一个非常大的数组,根据随机的 index 删除了一些数据。那么对整个数组的清理,其实是不需要另外一个数组来进行支持的,使用程序就可以实现。它的主要思路,就是移动所有存活的对象,且按照内存地址顺序依次排列,然后将末端内存地址以后的内存全部回收。 + +![整理(Compact)](images/JVM/整理(Compact).png) + +但是需要注意,这只是一个理想状态。对象的引用关系一般都是非常复杂的,我们这里不对具体的算法进行描述。你只需要了解,从效率上来说,一般整理算法是要低于复制算法的。 + + + +### 扩展回收算法 + +https://juejin.cn/post/6896035896916148237 + +目前JVM的垃圾回收器都是对几种朴素算法的发扬光大(没有最优的算法,只有最合适的算法): + +- **复制算法(Copying)**:复制算法是所有算法里面效率最高的,缺点是会造成一定的空间浪费 +- **标记-清除(Mark-Sweep)**:效率一般,缺点是会造成内存碎片问题 +- **标记-整理(Mark-Compact)**:效率比前两者要差,但没有空间浪费,也消除了内存碎片问题 + +![收集算法](images/JVM/收集算法.png) + + + +#### 标记清除(Mark-Sweep) + +![标记清除(Mark-Sweep)算法](images/JVM/标记清除(Mark-Sweep)算法.png) + +首先从 GC Root 开始遍历对象图,并标记(Mark)所遇到的每个对象,标识出所有要回收的对象。然后回收器检查堆中每一个对象,并将所有未被标记的对象进行回收。 + +**不足之处** + +- 标记、清除的效率都不高 +- 清除后产生大量的内存碎片,空间碎片太多会导致在分配大对象时无法找到足够大的连续内存,从而不得不触发另一次垃圾回收动作 + + + +#### 标记整理(Mark-Compact) + +![标记整理(Mark-Compact)算法](images/JVM/标记整理(Mark-Compact)算法.png) + +与标记清除算法类似,但不是在标记完成后对可回收对象进行清理,而是将所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。 + +**优点** + +- 消除了标记清除导致的内存分散问题,也消除了复制算法中内存减半的高额代价 + +**不足之处** + +- 效率低下,需要标记所有存活对象,还要标记所有存活对象的引用地址。效率上低于复制算法 + + + +#### 标记复制(Mark-Coping) + +标记-复制算法将内存分为两块相同大小的区域(比如新生代的Survivor区),每次在其中一块区域分配元素,当这块区域内存占满时,就会将存活下来的元素复制到另一块内存区域并清空当前内存区域。 + +- 缺点:浪费一半的内存空间 +- 优点:简单高效 + +**JVM在Eden区保存新对象,在GC时,将Eden和Survivor中存活对象复制到Survivor的另一个分区。这是JVM对复制算法的一个优化。只浪费了1/10的内存空间【JVM的Eden区和Survivor区的比例为 8:2】** + + ![标记复制](images/JVM/标记复制.jpg) + + + +#### 分代收集(Generational Collection) + +分代收集就是根据对象的存活周期将内存分为新生代和老年代。 + +- **新生代**对象“朝生夕死”,每次收集都有大量对象(99%)死去,所以可以选择**标记-复制算法**,只需要付出少量对象的复制成本就可以完成每次垃圾收集 +- **老年代**对象生存几率比较高,存活对象比较多,如果选择复制算法需要付出较高的IO成本,而且没用额外的空间可以用于复制,此时选择**标记-清除**或者**标记-整理**就比较合理 + + + +研究表明大部分对象可以分为两类: + +- 大部分对象的生命周期都很短 +- 其他对象则很可能会存活很长时间 + +根据对象存活周期的不同将内存划分为几块。对不同周期的对象采取不同的收集算法: + +- **新生代**:每次垃圾收集会有大批对象回收,所以采取复制算法 +- **老年代**:对象存活率高,采取标记清理或者标记整理算法 + + + +**① 年轻代(Young Generation)** + +年轻代使用的垃圾回收算法是复制算法。因为年轻代发生 GC 后,只会有非常少的对象存活,复制这部分对象是非常高效的。但复制算法会造成一定的空间浪费,所以年轻代中间也会分很多区域。 + +![年轻代](images/JVM/年轻代.jpg) + +如图所示,年轻代分为:**1个伊甸园空间(Eden )**,**2个幸存者空间(Survivor )**。当年轻代中的 Eden 区分配满的时候,就会触发年轻代的 GC(Minor GC)。具体过程如下: + +- 在 Eden 区执行了第一次 GC 之后,存活的对象会被移动到其中一个 Survivor 分区(以下简称from) +- Eden 区再次 GC,这时会采用复制算法,将 Eden 和 from 区一起清理。存活的对象会被复制到 to 区,然后只需要清空 from 区就可以了 + +在这个过程中,总会有1个 Survivor 分区是空置的。Eden、from、to 的默认比例是 8:1:1,所以只会造成 10% 的空间浪费。这个比例,是由参数 **-XX:SurvivorRatio** 进行配置的(默认为 8)。 + + + +**② 老年代(Old/Tenured Generation)** + +老年代一般使用“**标记-清除**”、“**标记-整理**”算法,因为老年代的对象存活率一般是比较高的,空间又比较大,拷贝起来并不划算,还不如采取就地收集的方式。对象进入老年代的途径如下: + +- **提升(Promotion)** + + 如果对象够老,会通过“提升”进入老年代 + +- **分配担保** + + 年轻代回收后存活的对象大于10%时,因Survivor空间不够存储,对象就会直接在老年代上分配 + +- **大对象直接在老年代分配** + + 超出某个大小的对象将直接在老年代分配 + +- **动态对象年龄判定** + + 有的垃圾回收算法,并不要求 age 必须达到 15 才能晋升到老年代,它会使用一些动态的计算方法。 + + 比如,如果幸存区中相同年龄对象大小的和,大于幸存区的一半,大于或等于 age 的对象将会直接进入老年代。 + + + +#### 分区收集 \ No newline at end of file diff --git a/src/JVM/203.md b/src/JVM/203.md new file mode 100644 index 0000000..baafa70 --- /dev/null +++ b/src/JVM/203.md @@ -0,0 +1,262 @@ +![收集器](images/JVM/收集器.jpg) + +GC垃圾收集器的JVM配置参数: + +- **-XX:+UseSerialGC**:年轻代和老年代都用串行收集器 +- **-XX:+UseParNewGC**:年轻代使用 ParNew,老年代使用 Serial Old +- **-XX:+UseParallelGC**:年轻代使用 ParallerGC,老年代使用 Serial Old +- **-XX:+UseParallelOldGC**:新生代和老年代都使用并行收集器 +- **-XX:+UseConcMarkSweepGC**:表示年轻代使用 ParNew,老年代的用 CMS +- **-XX:+UseG1GC**:使用 G1垃圾回收器 +- **-XX:+UseZGC**:使用 ZGC 垃圾回收器 + + + +### 年轻代收集器 + +#### Serial收集器 + +处理GC的只有一条线程,并且在垃圾回收的过程中暂停一切用户线程。最简单的垃圾回收器,但千万别以为它没有用武之地。因为简单,所以高效,它通常用在客户端应用上。因为客户端应用不会频繁创建很多对象,用户也不会感觉出明显的卡顿。相反,它使用的资源更少,也更轻量级。 + +![Serial收集器](images/JVM/Serial收集器.jpg) + + + +#### ParNew收集器 + +ParNew是Serial的多线程版本。由多条GC线程并行地进行垃圾清理。清理过程依然要停止用户线程。ParNew 追求“低停顿时间”,与 Serial 唯一区别就是使用了多线程进行垃圾收集,在多 CPU 环境下性能比 Serial 会有一定程度的提升;但线程切换需要额外的开销,因此在单 CPU 环境中表现不如 Serial。 + +![ParNew收集器](images/JVM/ParNew收集器.jpg) + + + +#### Parallel Scavenge收集器 + +另一个多线程版本的垃圾回收器。它与ParNew的主要区别是: + +- **Parallel Scavenge**:追求CPU吞吐量,能够在较短时间完成任务,适合没有交互的后台计算。弱交互强计算 +- **ParNew**:追求降低用户停顿时间,适合交互式应用。强交互弱计算 + + + +### 老年代收集器 + +#### Serial Old收集器 + +与年轻代的 Serial 垃圾收集器对应,都是单线程版本,同样适合客户端使用。年轻代的 Serial,使用复制算法。老年代的 Old Serial,使用标记-整理算法。 + +![SerialOld收集器](images/JVM/SerialOld收集器.jpg) + + + +#### Parallel Old收集器 + +Parallel Old 收集器是 Parallel Scavenge 的老年代版本,追求 CPU 吞吐量。 + +![ParallelOld收集器](images/JVM/ParallelOld收集器.jpg) + + + +#### CMS收集器 + +**并发标记清除(Concurrent Mark Sweep,CMS)垃圾回收器**,是一款致力于获取最短停顿时间的收集器,使用多个线程来扫描堆内存并标记可被清除的对象,然后清除标记的对象。在下面两种情形下会暂停工作线程: + +- 在老年代中标记引用对象的时候 + +- 在做垃圾回收的过程中堆内存中有变化发生 + + +对比与并行垃圾回收器,CMS回收器使用更多的CPU来保证更高的吞吐量。如果我们可以有更多的CPU用来提升性能,那么CMS垃圾回收器是比并行回收器更好的选择。使用 `-XX:+UseParNewGCJVM` 参数来开启使用CMS垃圾回收器。 + +![CMS收集器](images/JVM/CMS收集器.png) + +**主要流程如下**: + +- **初始标记(CMS initial mark)**:仅标记出GC Roots能直接关联到的对象。需要Stop-the-world +- **并发标记(CMS concurrenr mark)**:进行GC Roots遍历的过程,寻找出所有可达对象 +- **重新标记(CMS remark)**:修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录。需要Stop-the-world +- **并发清除(CMS concurrent sweep)**:清出垃圾 + + + +**CMS触发机制**:当老年代的使用率达到80%时,就会触发一次CMS GC。 + +- `-XX:CMSInitiatingOccupancyFraction=80` +- `-XX:+UseCMSInitiatingOccupancyOnly` + + + +**优点** + +- 并发收集 +- 停顿时间最短 + + + +**缺点** + +- **并发回收导致CPU资源紧张** + + 在并发阶段,它虽然不会导致用户线程停顿,但却会因为占用了一部分线程而导致应用程序变慢,降低程序总吞吐量。CMS默认启动的回收线程数是:(CPU核数 + 3)/ 4,当CPU核数不足四个时,CMS对用户程序的影响就可能变得很大。 + +- **无法清理浮动垃圾** + + 在CMS的并发标记和并发清理阶段,用户线程还在继续运行,就还会伴随有新的垃圾对象不断产生,但这一部分垃圾对象是出现在标记过程结束以后,CMS无法在当次收集中处理掉它们,只好留到下一次垃圾收集时再清理掉。这一部分垃圾称为“浮动垃圾”。 + +- **并发失败(Concurrent Mode Failure)** + + 由于在垃圾回收阶段用户线程还在并发运行,那就还需要预留足够的内存空间提供给用户线程使用,因此CMS不能像其他回收器那样等到老年代几乎完全被填满了再进行回收,必须预留一部分空间供并发回收时的程序运行使用。默认情况下,当老年代使用了 80% 的空间后就会触发 CMS 垃圾回收,这个值可以通过 -XX**:** CMSInitiatingOccupancyFraction 参数来设置。 + + 这里会有一个风险:要是CMS运行期间预留的内存无法满足程序分配新对象的需要,就会出现一次“并发失败”(Concurrent Mode Failure),这时候虚拟机将不得不启动后备预案:Stop The World,临时启用 Serial Old 来重新进行老年代的垃圾回收,这样一来停顿时间就很长了。 + +- **内存碎片问题** + + CMS是一款基于“标记-清除”算法实现的回收器,这意味着回收结束时会有内存碎片产生。内存碎片过多时,将会给大对象分配带来麻烦,往往会出现老年代还有很多剩余空间,但就是无法找到足够大的连续空间来分配当前对象,而不得不提前触发一次 Full GC 的情况。 + + 为了解决这个问题,CMS收集器提供了一个 -XX:+UseCMSCompactAtFullCollection 开关参数(默认开启),用于在 Full GC 时开启内存碎片的合并整理过程,由于这个内存整理必须移动存活对象,是无法并发的,这样停顿时间就会变长。还有另外一个参数 -XX:CMSFullGCsBeforeCompaction,这个参数的作用是要求CMS在执行过若干次不整理空间的 Full GC 之后,下一次进入 Full GC 前会先进行碎片整理(默认值为0,表示每次进入 Full GC 时都进行碎片整理)。 + + + +**作用内存区域**:老年代 + +**适用场景**:对停顿时间敏感的场合 + +**算法类型**:标记-清除 + + + +### 新生代和老年代收集 + +#### G1收集器 + +G1(Garbage First)回收器采用面向局部收集的设计思路和基于Region的内存布局形式,是一款主要面向服务端应用的垃圾回收器。G1设计初衷就是替换 CMS,成为一种全功能收集器。G1 在JDK9 之后成为服务端模式下的默认垃圾回收器,取代了 Parallel Scavenge 加 Parallel Old 的默认组合,而 CMS 被声明为不推荐使用的垃圾回收器。G1从整体来看是基于 标记-整理 算法实现的回收器,但从局部(两个Region之间)上看又是基于 标记-复制 算法实现的。**G1 回收过程**,G1 回收器的运作过程大致可分为四个步骤: + +- **初始标记(会STW)**:仅仅只是标记一下 GC Roots 能直接关联到的对象,并且修改TAMS指针的值,让下一阶段用户线程并发运行时,能正确地在可用的Region中分配新对象。这个阶段需要停顿线程,但耗时很短,而且是借用进行Minor GC的时候同步完成的,所以G1收集器在这个阶段实际并没有额外的停顿。 +- **并发标记**:从 GC Roots 开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。当对象图扫描完成以后,还要重新处理在并发时有引用变动的对象。 +- **最终标记(会STW)**:对用户线程做短暂的暂停,处理并发阶段结束后仍有引用变动的对象。 +- **清理阶段(会STW)**:更新Region的统计数据,对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个Region构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动,必须暂停用户线程,由多条回收器线程并行完成的。 + + + +G1收集器中的堆内存被划分为多个大小相等的内存块(Region),每个Region是逻辑连续的一段内存,结构如下: + +![G1-Region](images/JVM/G1-Region.png) + +每个Region被标记了E、S、O和H,说明每个Region在运行时都充当了一种角色,其中H是以往算法中没有的,它代表Humongous(巨大的),这表示这些Region存储的是巨型对象(humongous object,H-obj),当新建对象大小超过Region大小一半时,直接在新的一个或多个连续Region中分配,并标记为H。 + + + +**Region** + +堆内存中一个Region的大小可以通过 `-XX:G1HeapRegionSize`参数指定,大小区间只能是1M、2M、4M、8M、16M和32M,总之是2的幂次方。如果G1HeapRegionSize为默认值,则在堆初始化时计算Region的实际大小,默认把堆内存按照2048份均分,最后得到一个合理的大小。 + + + +**GC模式** + +- **young gc** + + 发生在年轻代的GC算法,一般对象(除了巨型对象)都是在eden region中分配内存,当所有eden region被耗尽无法申请内存时,就会触发一次young gc,这种触发机制和之前的young gc差不多,执行完一次young gc,活跃对象会被拷贝到survivor region或者晋升到old region中,空闲的region会被放入空闲列表中,等待下次被使用。 + + - `-XX:MaxGCPauseMillis`:设置G1收集过程目标时间,默认值`200ms` + - `-XX:G1NewSizePercent`:新生代最小值,默认值`5%` + - `-XX:G1MaxNewSizePercent`:新生代最大值,默认值`60%` + +- **mixed gc** + + 当越来越多的对象晋升到老年代old region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,即mixed gc,该算法并不是一个old gc,除了回收整个young region,还会回收一部分的old region,这里需要注意:**是一部分老年代,而不是全部老年代**,可以选择哪些old region进行收集,从而可以对垃圾回收的耗时时间进行控制 + +- **full gc** + + - 如果对象内存分配速度过快,mixed gc来不及回收,导致老年代被填满,就会触发一次full gc,G1的full gc算法就是单线程执行的serial old gc,会导致异常长时间的暂停时间,需要进行不断的调优,尽可能的避免full gc + + + +**G1垃圾回收器** 应用于大的堆内存空间。它将堆内存空间划分为不同的区域,对各个区域并行地做回收工作。G1在回收内存空间后还立即对空闲空间做整合工作以减少碎片。CMS却是在全部停止(stop the world,STW)时执行内存整合工作。对于不同的区域G1根据垃圾的数量决定优先级。使用 `-XX:UseG1GCJVM` 参数来开启使用G1垃圾回收器。 + +![G1收集器](images/JVM/G1收集器.jpg) + +**主要流程如下**: + +- 初始标记(Initial Marking):标记从GC Root可达的对象。会发生STW +- 并发标记(Concurrenr Marking):标记出GC Root可达对象衍生出去的存活对象,并收集各个Region的存活对象信息。整个过程gc collector线程与应用线程可以并行执行 +- **最终标记(Final Marking)**:标记出在并发标记过程中遗漏的,或内部引用发生变化的对象。会发生STW +- 筛选回收(Live Data Counting And Evacution):垃圾清除过程,如果发现一个Region中没有存活对象,则把该Region加入到空闲列表中 + + + + `-XX:InitiatingHeapOccupancyPercent`:当老年代大小占整个堆大小百分比达到该阈值时,会触发一次mixed gc。 + + + +**优点**: + +- 并行与并发,充分发挥多核优势 +- 分代收集,所以不需要与其它收集器配合即可工作 +- 空间整合,整体来看基于”标记-整理算法“,局部采用”复制算法“都不会产生内存碎片 +- 可以指定GC最大停顿时长 + +**缺点**: + +- 需要记忆集来记录新生代和老年代之间的引用关系 +- 需要占用大量的内存,可能达到整个堆内存容量的20%甚至更多 + + + +**作用内存区域**:跨代 + +**适用场景**:作为关注停顿时间的场景的收集器备选方案 + +**算法类型**:整体来看基于”标记-整理算法“,局部采用"复制算法" + + + +#### ZGC收集器 + +Z Garbage Collector,简称 ZGC,是 JDK 11 中新加入的尚在实验阶段的低延迟垃圾收集器。它和 Shenandoah 同属于超低延迟的垃圾收集器,但在吞吐量上比 Shenandoah 有更优秀的表现,甚至超过了 G1,接近了“吞吐量优先”的 Parallel 收集器组合,可以说近乎实现了“鱼与熊掌兼得”。 + +与CMS中的ParNew和G1类似,ZGC也采用标记-复制算法,不过ZGC对该算法做了重大改进:ZGC在标记、转移和重定位阶段几乎都是并发的,这是ZGC实现停顿时间小于10ms目标的最关键原因。ZGC垃圾回收周期如下图所示: + +![ZGC收集器](images/JVM/ZGC收集器.jpg) + +ZGC只有三个STW阶段:**初始标记**,**再标记**,**初始转移**。其中,初始标记和初始转移分别都只需要扫描所有GC Roots,其处理时间和GC Roots的数量成正比,一般情况耗时非常短;再标记阶段STW时间很短,最多1ms,超过1ms则再次进入并发标记阶段。即,ZGC几乎所有暂停都只依赖于GC Roots集合大小,停顿时间不会随着堆的大小或者活跃对象的大小而增加。与ZGC对比,G1的转移阶段完全STW的,且停顿时间随存活对象的大小增加而增加。 + + + +**ZGC 的内存布局** + +与 Shenandoah 和 G1 一样,ZGC 也采用基于 Region 的堆内存布局,但与它们不同的是, ZGC 的 Region 具有动态性,也就是可以动态创建和销毁,容量大小也是动态的,有大、中、小三类容量: + +![ZGC内存布局](images/JVM/ZGC内存布局.jpg) + +- 小型 Region (Small Region):容量固定为 2MB,用于放置小于 256KB 的小对象 +- 中型 Region (M edium Region):容量固定为 32MB,用于放置大于等于 256KB 但小于 4MB 的对象 +- 大型 Region (Large Region):容量不固定,可以动态变化,但必须为 2MB 的整数倍,用于放置 4MB 或以上的大对象。每个大型 Region 中只会存放一个大对象,这也预示着虽然名字叫作“大型 Region”,但它的实际容量完全有可能小于中型 Region,最小容量可低至 4MB + +在 JDK 11 及以上版本,可以通过以下参数开启 ZGC:`-XX:+UnlockExperimentalVMOptions -XX:+UseZGC` 。 + + + +#### Shenandoah收集器 + +Shenandoah 与 G1 有很多相似之处,比如都是基于 Region 的内存布局,都有用于存放大对象的 Humongous Region,默认回收策略也是优先处理回收价值最大的 Region。不过也有三个重大的区别: + +- Shenandoah支持并发的整理算法,G1整理阶段虽是多线程并行,但无法与用户程序并发执行 +- 默认不使用分代收集理论 +- 使用连接矩阵 (Connection Matrix)记录跨Region的引用关系,替换掉了G1中的记忆级(Remembered Set),内存和计算成本更低 + +Shenandoah 收集器的工作原理相比 G1 要复杂不少,其运行流程示意图如下: + +![Shenandoah收集器运行流程](images/JVM/Shenandoah收集器运行流程.jpg) + +可见Shenandoah的并发程度明显比G1更高,只需要在初始标记、最终标记、初始引用更新和最终引用更新这几个阶段进行短暂的“Stop The World”,其他阶段皆可与用户程序并发执行,其中最重要的并发标记、并发回收和并发引用更新详情如下: + +- **并发标记( Concurrent Marking)** +- **并发回收( Concurrent Evacuation)** +- **并发引用更新( Concurrent Update Reference)** + +Shenandoah 的高并发度让它实现了超低的停顿时间,但是更高的复杂度也伴随着更高的系统开销,这在一定程度上会影响吞吐量,下图是 Shenandoah 与之前各种收集器在停顿时间维度和系统开销维度上的对比: + +![收集器停顿时间和系统开销对比](images/JVM/收集器停顿时间和系统开销对比.png) + +OracleJDK 并不支持 Shenandoah,如果你用的是 OpenJDK 12 或某些支持 Shenandoah 移植版的 JDK 的话,可以通过以下参数开启 Shenandoah:`-XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC` 。 \ No newline at end of file diff --git a/src/JVM/204.md b/src/JVM/204.md new file mode 100644 index 0000000..ae04565 --- /dev/null +++ b/src/JVM/204.md @@ -0,0 +1,108 @@ +### 日志格式 + +**ParallelGC YoungGC日志** + +![ParallelGCYoungGC日志](images/JVM/ParallelGCYoungGC日志.jpg) + +**ParallelGC FullGC日志** + +![ParallelGCFullGC日志](images/JVM/ParallelGCFullGC日志.jpg) + + + +### 最佳实践 + +在不同的 JVM 的不垃圾回收器上,看参数默认是什么,不要轻信别人的建议,命令行示例如下: + +```shell +java -XX:+PrintFlagsFinal -XX:+UseG1GC  2>&1 | grep UseAdaptiveSizePolicy +``` + +PrintCommandLineFlags:通过它,你能够查看当前所使用的垃圾回收器和一些默认的值。 + +```shell +# java -XX:+PrintCommandLineFlags -version +-XX:InitialHeapSize=127905216 -XX:MaxHeapSize=2046483456 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC +openjdk version "1.8.0_41" +OpenJDK Runtime Environment (build 1.8.0_41-b04) +OpenJDK 64-Bit Server VM (build 25.40-b25, mixed mode) +``` + + + +G1垃圾收集器JVM参数最佳实践: + +```shell +# 1.基本参数 +-server # 服务器模式 +-Xmx12g # 初始堆大小 +-Xms12g # 最大堆大小 +-Xss256k # 每个线程的栈内存大小 +-XX:+UseG1GC # 使用 G1 (Garbage First) 垃圾收集器 +-XX:MetaspaceSize=256m # 元空间初始大小 +-XX:MaxMetaspaceSize=1g # 元空间最大大小 +-XX:MaxGCPauseMillis=200 # 每次YGC / MixedGC 的最多停顿时间 (期望最长停顿时间) + +# 2.必备参数 +-XX:+PrintGCDetails # 输出详细GC日志 +-XX:+PrintGCDateStamps # 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800) +-XX:+PrintTenuringDistribution # 打印对象分布:为了分析GC时的晋升情况和晋升导致的高暂停,看对象年龄分布日志 +-XX:+PrintHeapAtGC # 在进行GC的前后打印出堆的信息 +-XX:+PrintReferenceGC # 打印Reference处理信息:强引用/弱引用/软引用/虚引用/finalize方法万一有问题 +-XX:+PrintGCApplicationStoppedTime # 打印STW时间 +-XX:+PrintGCApplicationConCurrentTime # 打印GC间隔的服务运行时长 + +# 3.日志分割参数 +-XX:+UseGCLogFileRotation # 开启日志文件分割 +-XX:NumberOfGCLogFiles=14 # 最多分割几个文件,超过之后从头文件开始写 +-XX:GCLogFileSize=32M # 每个文件上限大小,超过就触发分割 +-Xloggc:/path/to/gc-%t.log # GC日志输出的文件路径,使用%t作为日志文件名,即gc-2021-03-29_20-41-47.log +``` + +CMS垃圾收集器JVM参数最佳实践: + +```shell +# 1.基本参数 +-server # 服务器模式 +-Xmx4g # JVM最大允许分配的堆内存,按需分配 +-Xms4g # JVM初始分配的堆内存,一般和Xmx配置成一样以避免每次gc后JVM重新分配内存 +-Xmn256m # 年轻代内存大小,整个JVM内存=年轻代 + 年老代 + 持久代 +-Xss512k # 设置每个线程的堆栈大小 +-XX:+DisableExplicitGC # 忽略手动调用GC, System.gc()的调用就会变成一个空调用,完全不触发GC +-XX:+UseConcMarkSweepGC # 使用 CMS 垃圾收集器 +-XX:+CMSParallelRemarkEnabled # 降低标记停顿 +-XX:+UseCMSCompactAtFullCollection # 在FULL GC的时候对年老代的压缩 +-XX:+UseFastAccessorMethods # 原始类型的快速优化 +-XX:+UseCMSInitiatingOccupancyOnly # 使用手动定义初始化定义开始CMS收集 +-XX:LargePageSizeInBytes=128m # 内存页的大小 +-XX:CMSInitiatingOccupancyFraction=70 # 使用cms作为垃圾回收使用70%后开始CMS收集 + +# 2.必备参数 +-XX:+PrintGCDetails # 输出详细GC日志 +-XX:+PrintGCDateStamps # 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800) +-XX:+PrintTenuringDistribution # 打印对象分布:为分析GC时的晋升情况和晋升导致的高暂停,看对象年龄分布 +-XX:+PrintHeapAtGC # 在进行GC的前后打印出堆的信息 +-XX:+PrintReferenceGC # 打印Reference处理信息:强引用/弱引用/软引用/虚引用/finalize方法万一有问题 +-XX:+PrintGCApplicationStoppedTime # 打印STW时间 +-XX:+PrintGCApplicationConCurrentTime # 打印GC间隔的服务运行时长 + +# 3.日志分割参数 +-XX:+UseGCLogFileRotation # 开启日志文件分割 +-XX:NumberOfGCLogFiles=14 # 最多分割几个文件,超过之后从头文件开始写 +-XX:GCLogFileSize=32M # 每个文件上限大小,超过就触发分割 +-Xloggc:/path/to/gc-%t.log # GC日志输出的文件路径,使用%t作为日志文件名,即gc-2021-03-29_20-41-47.log +``` + + + +**test、stage 环境jvm使用CMS 参数配置(jdk8)** + +```shell +-server -Xms256M -Xmx256M -Xss512k -Xmn96M -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=128M -XX:InitialHeapSize=256M -XX:MaxHeapSize=256M -XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=80 -XX:+CMSClassUnloadingEnabled -XX:+CMSParallelRemarkEnabled -XX:+CMSScavengeBeforeRemark -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=2 -XX:+CMSParallelInitialMarkEnabled -XX:+CMSParallelRemarkEnabled -XX:+UnlockDiagnosticVMOptions -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch -XX:MaxTenuringThreshold=8 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+PrintGC -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:SurvivorRatio=8 -Xloggc:../logs/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=../dump +``` + +**online 环境jvm使用CMS参数配置(jdk8)** + +```shell +-server -Xms4G -Xmx4G -Xss512k -Xmn1536M -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=128M -XX:InitialHeapSize=4G -XX:MaxHeapSize=4G -XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=80 -XX:+CMSClassUnloadingEnabled -XX:+CMSParallelRemarkEnabled -XX:+CMSScavengeBeforeRemark -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=2 -XX:+CMSParallelInitialMarkEnabled -XX:+CMSParallelRemarkEnabled -XX:+UnlockDiagnosticVMOptions -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch -XX:MaxTenuringThreshold=10 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+PrintGC -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:SurvivorRatio=8 -Xloggc:../logs/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=../dump +``` \ No newline at end of file diff --git a/src/JVM/205.md b/src/JVM/205.md new file mode 100644 index 0000000..3e89999 --- /dev/null +++ b/src/JVM/205.md @@ -0,0 +1,293 @@ +### Full GC场景 + +**场景一:System.gc()方法的调用** + +此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full GC的频率,也即增加了间歇性停顿的次数。强烈影响系建议能不使用此方法就别使用,让虚拟机自己去管理它的内存,可通过通过 `-XX:+ DisableExplicitGC` 来禁止RMI调用System.gc()。 + + + +**场景二:老年代代空间不足** + +- 原因分析:新生代对象转入老年代、创建大对象或数组时,执行FullGC后仍空间不足 +- 抛出错误:`Java.lang.OutOfMemoryError: Java heap space` +- 解决办法: + - 尽量让对象在YoungGC时被回收 + - 让对象在新生代多存活一段时间 + - 不要创建过大的对象或数组 + + + +**场景三:永生区空间不足** + +- 原因分析:JVM方法区因系统中要加载的类、反射的类和调用的方法较多而可能会被占满 +- 抛出错误:`java.lang.OutOfMemoryError: PermGen space` +- 解决办法: + - 增大老年代空间大小 + - 使用CMS GC + + + +**场景四:CMS GC时出现promotion failed和concurrent mode failure** + +- 原因分析: + - `promotion failed`:是在进行Minor GC时,survivor space放不下、对象只能放入老年代,而此时老年代也放不下造成 + - `concurrent mode failure`:是在执行CMS GC的过程中同时有对象要放入老年代,而此时老年代空间不足造成的 +- 抛出错误:GC日志中存在`promotion failed`和`concurrent mode` +- 解决办法:增大幸存区或老年代 + + + +**场景五:堆中分配很大的对象** + +- 原因分析:创建大对象或长数据时,此对象直接进入老年代,而老年代虽有很大剩余空间,但没有足够的连续空间来存储 +- 抛出错误:触发FullGC +- 解决办法:配置-XX:+UseCMSCompactAtFullCollection开关参数,用于享受用完FullGC后额外免费赠送的碎片整理过程,但同时停顿时间不得不变长。可以使用-XX:CMSFullGCsBeforeCompaction参数来指定执行多少次不压缩的FullGC后才执行一次压缩 + + + +### CMS GC场景 + +**场景一:动态扩容引起的空间震荡** + +- **现象** + + 服务**刚刚启动时 GC 次数较多**,最大空间剩余很多但是依然发生 GC,这种情况我们可以通过观察 GC 日志或者通过监控工具来观察堆的空间变化情况即可。GC Cause 一般为 Allocation Failure,且在 GC 日志中会观察到经历一次 GC ,堆内各个空间的大小会被调整,如下图所示: + + ![动态扩容引起的空间震荡](images/JVM/动态扩容引起的空间震荡.png) + +- **原因** + + 在 JVM 的参数中 `-Xms` 和 `-Xmx` 设置的不一致,在初始化时只会初始 `-Xms` 大小的空间存储信息,每当空间不够用时再向操作系统申请,这样的话必然要进行一次 GC。另外,如果空间剩余很多时也会进行缩容操作,JVM 通过 `-XX:MinHeapFreeRatio` 和 `-XX:MaxHeapFreeRatio` 来控制扩容和缩容的比例,调节这两个值也可以控制伸缩的时机。整个伸缩的模型理解可以看这个图,当 committed 的空间大小超过了低水位/高水位的大小,capacity 也会随之调整: + + ![JVM内存伸缩模型](images/JVM/JVM内存伸缩模型.png) + +- **策略** + + 观察 CMS GC 触发时间点 Old/MetaSpace 区的 committed 占比是不是一个固定的值,或者像上文提到的观察总的内存使用率也可以。尽量 **将成对出现的空间大小配置参数设置成固定的** ,如 `-Xms` 和 `-Xmx`,`-XX:MaxNewSize` 和 `-XX:NewSize`,`-XX:MetaSpaceSize` 和 `-XX:MaxMetaSpaceSize` 等。 + + + +**场景二:显式GC的去与留** + +- **现象** + + 除了扩容缩容会触发 CMS GC 之外,还有 Old 区达到回收阈值、MetaSpace 空间不足、Young 区晋升失败、大对象担保失败等几种触发条件,如果这些情况都没有发生却触发了 GC ?这种情况有可能是代码中手动调用了 System.gc 方法,此时可以找到 GC 日志中的 GC Cause 确认下。 + +- **原因** + + **保留 System.gc**:CMS中使用 Foreground Collector 时将会带来非常长的 STW,在应用程序中 System.gc 被频繁调用,那就非常危险。增加 `-XX:+DisableExplicitGC` 参数则可以禁用。**去掉 System.gc**:禁用掉后会带来另一个内存泄漏的问题,为 DirectByteBuffer 分配空间过程中会显式调用 System.gc ,希望通过 Full GC 来强迫已经无用的 DirectByteBuffer 对象释放掉它们关联的 Native Memory,如Netty等。 + +- **策略** + + 无论是保留还是去掉都会有一定的风险点,不过目前互联网中的 RPC 通信会大量使用 NIO,所以建议保留。此外 JVM 还提供了 `-XX:+ExplicitGCInvokesConcurrent` 和 `-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses` 参数来将 System.gc 的触发类型从 Foreground 改为 Background,同时 Background 也会做 Reference Processing,这样的话就能大幅降低了 STW 开销,同时也不会发生 NIO Direct Memory OOM。 + + + +**场景三:MetaSpace区OOM** + +- **现象** + + JVM 在启动后或者某个时间点开始, **MetaSpace 的已使用大小在持续增长,同时每次 GC 也无法释放,调大 MetaSpace 空间也无法彻底解决** 。 + +- **原因** + + 在讨论为什么会 OOM 之前,我们先来看一下这个区里面会存什么数据,Java 7 之前字符串常量池被放到了 Perm 区,所有被 intern 的 String 都会被存在这里,由于 String.intern 是不受控的,所以 `-XX:MaxPermSize` 的值也不太好设置,经常会出现 `java.lang.OutOfMemoryError: PermGen space` 异常,所以在 Java 7 之后常量池等字面量(Literal)、类静态变量(Class Static)、符号引用(Symbols Reference)等几项被移到 Heap 中。而 Java 8 之后 PermGen 也被移除,取而代之的是 MetaSpace。由场景一可知,为了避免弹性伸缩带来的额外 GC 消耗,我们会将 `-XX:MetaSpaceSize` 和 `-XX:MaxMetaSpaceSize` 两个值设置为固定的,但这样也会导致在空间不够的时候无法扩容,然后频繁地触发 GC,最终 OOM。所以关键原因是 **ClassLoader不停地在内存中load了新的Class ,一般这种问题都发生在动态类加载等情况上。** + +- **策略** + + 可以 dump 快照之后通过 JProfiler 或 MAT 观察 Classes 的 Histogram(直方图) 即可,或者直接通过命令即可定位, jcmd 打几次 Histogram 的图,看一下具体是哪个包下的 Class 增加较多就可以定位。如果无法从整体的角度定位,可以添加 `-XX:+TraceClassLoading` 和 `-XX:+TraceClassUnLoading` 参数观察详细的类加载和卸载信息。 + + + +**场景四:过早晋升** + +- **现象** + + 这种场景主要发生在分代的收集器上面,专业的术语称为“Premature Promotion”。90% 的对象朝生夕死,只有在 Young 区经历过几次 GC 的洗礼后才会晋升到 Old 区,每经历一次 GC 对象的 GC Age 就会增长 1,最大通过 `-XX:MaxTenuringThreshold` 来控制。过早晋升一般不会直接影响 GC,总会伴随着浮动垃圾、大对象担保失败等问题,但这些问题不是立刻发生的,我们可以观察以下几种现象来判断是否发生了过早晋升: + + - **分配速率接近于晋升速率** ,对象晋升年龄较小。 + + GC 日志中出现“Desired survivor size 107347968 bytes, **new threshold 1(max 6)** ”等信息,说明此时经历过一次 GC 就会放到 Old 区。 + + - **Full GC 比较频繁** ,且经历过一次 GC 之后 Old 区的 **变化比例非常大** 。 + + 如Old区触发回收阈值是80%,经历一次GC之后下降到了10%,这说明Old区70%的对象存活时间其实很短。 + + ![FullGC变化比例大](images/JVM/FullGC变化比例大.png) + + 过早晋升的危害: + + - Young GC 频繁,总的吞吐量下降 + - Full GC 频繁,可能会有较大停顿 + +- **原因** + + 主要的原因有以下两点: + + - **Young/Eden 区过小**: 过小的直接后果就是 Eden 被装满的时间变短,本应该回收的对象参与了 GC 并晋升,Young GC 采用的是复制算法,由基础篇我们知道 copying 耗时远大于 mark,也就是 Young GC 耗时本质上就是 copy 的时间(CMS 扫描 Card Table 或 G1 扫描 Remember Set 出问题的情况另说),没来及回收的对象增大了回收的代价,所以 Young GC 时间增加,同时又无法快速释放空间,Young GC 次数也跟着增加 + - **分配速率过大**: 可以观察出问题前后 Mutator 的分配速率,如果有明显波动可以尝试观察网卡流量、存储类中间件慢查询日志等信息,看是否有大量数据被加载到内存中 + +- **策略** + + - 如果是 **Young/Eden 区过小** ,可以在总的 Heap 内存不变的情况下适当增大Young区。一般情况下Old的大小应当为活跃对象的2~3倍左右,考虑到浮动垃圾问题最好在3倍左右,剩下的都可以分给Young区 + + - 过早晋升优化来看,原配置为Young 1.2G+Old 2.8G,通过观察CMS GC的情况找到存活对象大概为 300~400M,于是调整Old 1.5G左右,剩下2.5G分给Young 区。仅仅调了一个Young区大小参数(`-Xmn`),整个 JVM 一分钟Young GC从26次降低到了11次,单次时间也没有增加,总的GC时间从1100ms降低到了500ms,CMS GC次数也从40分钟左右一次降低到了7小时30分钟一次: + + ![过早晋升优化GC](images/JVM/过早晋升优化GC.png) + + ![过早晋升优化Oldgen](images/JVM/过早晋升优化Oldgen.png) + + 如果是分配速率过大: + + - **偶发较大** :通过内存分析工具找到问题代码,从业务逻辑上做一些优化 + - **一直较大** :当前的 Collector 已经不满足 Mutator 的期望了,这种情况要么扩容 Mutator 的 VM,要么调整 GC 收集器类型或加大空间 + +- **小结** + + 过早晋升问题一般不会特别明显,但日积月累之后可能会爆发一波收集器退化之类的问题,所以我们还是要提前避免掉的,可以看看自己系统里面是否有这些现象,如果比较匹配的话,可以尝试优化一下。一行代码优化的 ROI 还是很高的。如果在观察 Old 区前后比例变化的过程中,发现可以回收的比例非常小,如从 80% 只回收到了 60%,说明我们大部分对象都是存活的,Old 区的空间可以适当调大些。 + + + +**场景五:CMS Old GC频繁** + +- **现象** + + Old 区频繁的做 CMS GC,但是每次耗时不是特别长,整体最大 STW 也在可接受范围内,但由于 GC 太频繁导致吞吐下降比较多。 + +- **原因** + + 这种情况比较常见,基本都是一次 Young GC 完成后,负责处理 CMS GC 的一个后台线程 concurrentMarkSweepThread 会不断地轮询,使用 `shouldConcurrentCollect()` 方法做一次检测,判断是否达到了回收条件。如果达到条件,使用 `collect_in_background()` 启动一次 Background 模式 GC。轮询的判断是使用 `sleepBeforeNextCycle()` 方法,间隔周期为 `-XX:CMSWaitDuration` 决定,默认为 2s。 + +- **策略** + + 处理这种常规内存泄漏问题基本是一个思路,主要步骤如下: + + ![CMSOldGC频繁](images/JVM/CMSOldGC频繁.png) + + Dump Diff 和 Leak Suspects 比较直观,这里说下其它几个关键点: + + - **内存 Dump**: 使用 jmap、arthas 等 dump 堆进行快照时记得摘掉流量,同时 **分别在 CMS GC 的发生前后分别 dump 一次** + - **分析 Top Component**: 要记得按照对象、类、类加载器、包等多个维度观察Histogram,同时使用 outgoing和incoming分析关联的对象,其次Soft Reference和Weak Reference、Finalizer 等也要看一下 + - **分析 Unreachable**: 重点看一下这个,关注下 Shallow 和 Retained 的大小。如下图所示的一次 GC 优化,就根据 Unreachable Objects 发现了 Hystrix 的滑动窗口问题。 + + ![分析Unreachable](images/JVM/分析Unreachable.png) + + + +**场景六:单次CMS Old GC耗时长** + +- **现象** + + CMS GC 单次 STW 最大超过 1000ms,不会频繁发生,如下图所示最长达到了 8000ms。某些场景下会引起“雪崩效应”,这种场景非常危险,我们应该尽量避免出现。 + + ![CMSGC单次STW长](images/JVM/CMSGC单次STW长.png) + +- **原因** + + CMS在回收的过程中,STW的阶段主要是 Init Mark 和 Final Remark 这两个阶段,也是导致CMS Old GC 最多的原因,另外有些情况就是在STW前等待Mutator的线程到达SafePoint也会导致时间过长,但这种情况较少。 + +- **策略** + + 知道了两个 STW 过程执行流程,我们分析解决就比较简单了,由于大部分问题都出在 Final Remark 过程,这里我们也拿这个场景来举例,主要步骤: + + - **【方向】** 观察详细 GC 日志,找到出问题时 Final Remark 日志,分析下 Reference 处理和元数据处理 real 耗时是否正常,详细信息需要通过 `-XX:+PrintReferenceGC` 参数开启。 **基本在日志里面就能定位到大概是哪个方向出了问题,耗时超过 10% 的就需要关注** 。 + + ```shell + 2019-02-27T19:55:37.920+0800: 516952.915: [GC (CMS Final Remark) 516952.915: [ParNew516952.939: [SoftReference, 0 refs, 0.0003857 secs]516952.939: [WeakReference, 1362 refs, 0.0002415 secs]516952.940: [FinalReference, 146 refs, 0.0001233 secs]516952.940: [PhantomReference, 0 refs, 57 refs, 0.0002369 secs]516952.940: [JNI Weak Reference, 0.0000662 secs] + [class unloading, 0.1770490 secs]516953.329: [scrub symbol table, 0.0442567 secs]516953.373: [scrub string table, 0.0036072 secs][1 CMS-remark: 1638504K(2048000K)] 1667558K(4352000K), 0.5269311 secs] [Times: user=1.20 sys=0.03, real=0.53 secs] + ``` + + - **【根因】** 有了具体的方向我们就可以进行深入的分析,一般来说最容易出问题的地方就是 Reference 中的 FinalReference 和元数据信息处理中的 scrub symbol table 两个阶段,想要找到具体问题代码就需要内存分析工具 MAT 或 JProfiler 了,注意要 dump 即将开始 CMS GC 的堆。在用 MAT 等工具前也可以先用命令行看下对象 Histogram,有可能直接就能定位问题。 + - 对 FinalReference 的分析主要观察 `java.lang.ref.Finalizer` 对象的 dominator tree,找到泄漏的来源。经常会出现问题的几个点有 Socket 的 `SocksSocketImpl` 、Jersey 的 `ClientRuntime`、MySQL 的 `ConnectionImpl` 等等 + - scrub symbol table 表示清理元数据符号引用耗时,符号引用是 Java 代码被编译成字节码时,方法在 JVM 中的表现形式,生命周期一般与 Class 一致,当 `_should_unload_classes` 被设置为 true 时在 `CMSCollector::refProcessingWork()` 中与 Class Unload、String Table 一起被处理 + + - **【策略】** 知道 GC 耗时的根因就比较好处理了,这种问题不会大面积同时爆发,不过有很多时候单台 STW 的时间会比较长,如果业务影响比较大,及时摘掉流量,具体后续优化策略如下: + - FinalReference:找到内存来源后通过优化代码的方式来解决,如果短时间无法定位可以增加 `-XX:+ParallelRefProcEnabled` 对 Reference 进行并行处理 + - symbol table:观察 MetaSpace 区的历史使用峰值,以及每次 GC 前后的回收情况,一般没有使用动态类加载或者 DSL 处理等,MetaSpace 的使用率上不会有什么变化,这种情况可以通过 `-XX:-CMSClassUnloadingEnabled` 来避免 MetaSpace 的处理,JDK8 会默认开启 CMSClassUnloadingEnabled,这会使得 CMS 在 CMS-Remark 阶段尝试进行类的卸载 + +- **小结** + + 正常情况进行的 Background CMS GC,出现问题基本都集中在 Reference 和 Class 等元数据处理上,在 Reference 类的问题处理方面,不管是 FinalReference,还是 SoftReference、WeakReference 核心的手段就是找准时机 dump快照,然后用内存分析工具来分析。Class处理方面目前除了关闭类卸载开关,没有太好的方法。在 G1 中同样有 Reference 的问题,可以观察日志中的 Ref Proc,处理方法与 CMS 类似。 + + + +**场景七:内存碎片&收集器退化** + +- **现象** + + 并发的 CMS GC 算法,退化为 Foreground 单线程串行 GC 模式,STW 时间超长,有时会长达十几秒。其中 CMS 收集器退化后单线程串行 GC 算法有两种: + + - 带压缩动作的算法,称为 MSC,上面我们介绍过,使用标记-清理-压缩,单线程全暂停的方式,对整个堆进行垃圾收集,也就是真正意义上的 Full GC,暂停时间要长于普通 CMS + - 不带压缩动作的算法,收集 Old 区,和普通的 CMS 算法比较相似,暂停时间相对 MSC 算法短一些 + +- **原因** + + CMS 发生收集器退化主要有以下几种情况: + + - **晋升失败(Promotion Failed)** + + - **增量收集担保失败** + + - **显式 GC** + + - **并发模式失败(Concurrent Mode Failure)** + +- **策略** + + 分析到具体原因后,我们就可以针对性解决了,具体思路还是从根因出发,具体解决策略: + + - **内存碎片**: 通过配置 `-XX:UseCMSCompactAtFullCollection=true` 来控制 Full GC 的过程中是否进行空间的整理(默认开启,注意是 Full GC,不是普通 CMS GC),以及 `-XX: CMSFullGCsBeforeCompaction=n` 来控制多少次 Full GC 后进行一次压缩 + - **增量收集**: 降低触发 CMS GC 的阈值,即参数 `-XX:CMSInitiatingOccupancyFraction` 的值,让 CMS GC 尽早执行,以保证有足够的连续空间,也减少 Old 区空间的使用大小,另外需要使用 `-XX:+UseCMSInitiatingOccupancyOnly` 来配合使用,不然 JVM 仅在第一次使用设定值,后续则自动调整 + - **浮动垃圾**: 视情况控制每次晋升对象的大小,或者缩短每次 CMS GC 的时间,必要时可调节 NewRatio 的值。另外使用 `-XX:+CMSScavengeBeforeRemark` 在过程中提前触发一次Young GC,防止后续晋升过多对象 + +- **小结** + + 正常情况下触发并发模式的 CMS GC,停顿非常短,对业务影响很小,但 CMS GC 退化后,影响会非常大,建议发现一次后就彻底根治。只要能定位到内存碎片、浮动垃圾、增量收集相关等具体产生原因,还是比较好解决的,关于内存碎片这块,如果 `-XX:CMSFullGCsBeforeCompaction` 的值不好选取的话,可以使用 `-XX:PrintFLSStatistics` 来观察内存碎片率情况,然后再设置具体的值。最后就是在编码的时候也要避免需要连续地址空间的大对象的产生,如过长的字符串,用于存放附件、序列化或反序列化的 byte 数组等,还有就是过早晋升问题尽量在爆发问题前就避免掉。 + + + +**场景八:堆外内存OOM** + +- **现象** + + 内存使用率不断上升,甚至开始使用 SWAP 内存,同时可能出现 GC 时间飙升,线程被 Block 等现象, **通过 top 命令发现 Java 进程的 RES 甚至超过了** `**-Xmx**` **的大小** 。出现这些现象时,基本可确定是出现堆外内存泄漏。 + +- **原因** + + JVM 的堆外内存泄漏,主要有两种的原因: + + - 通过 `UnSafe#allocateMemory`,`ByteBuffer#allocateDirect` 主动申请了堆外内存而没有释放,常见于 NIO、Netty 等相关组件 + - 代码中有通过 JNI 调用 Native Code 申请的内存没有释放 + +- **策略** + + **原因一:主动申请未释放** + + **原因二:通过 JNI 调用的 Native Code 申请的内存未释放** + + + +**场景九:JNI引发的GC问题** + +- **现象** + + 在 GC 日志中,出现 GC Cause 为 GCLocker Initiated GC。 + + ```shell + 2020-09-23T16:49:09.727+0800: 504426.742: [GC (GCLocker Initiated GC) 504426.742: [ParNew (promotion failed): 209716K->6042K(1887488K), 0.0843330 secs] 1449487K->1347626K(3984640K), 0.0848963 secs] [Times: user=0.19 sys=0.00, real=0.09 secs]2020-09-23T16:49:09.812+0800: 504426.827: [Full GC (GCLocker Initiated GC) 504426.827: [CMS: 1341583K->419699K(2097152K), 1.8482275 secs] 1347626K->419699K(3984640K), [Metaspace: 297780K->297780K(1329152K)], 1.8490564 secs] [Times: user=1.62 sys=0.20, real=1.85 secs] + ``` + +- **原因** + + JNI(Java Native Interface)意为 Java 本地调用,它允许 Java 代码和其他语言写的 Native 代码进行交互。JNI 如果需要获取 JVM 中的 String 或者数组,有两种方式: + + - 拷贝传递 + - 共享引用(指针),性能更高 + + 由于 Native 代码直接使用了 JVM 堆区的指针,如果这时发生 GC,就会导致数据错误。因此,在发生此类 JNI 调用时,禁止 GC 的发生,同时阻止其他线程进入 JNI 临界区,直到最后一个线程退出临界区时触发一次 GC。 + +- **策略** + + - 添加 `-XX+PrintJNIGCStalls` 参数,可以打印出发生 JNI 调用时的线程,进一步分析,找到引发问题的 JNI 调用 + - JNI 调用需要谨慎,不一定可以提升性能,反而可能造成 GC 问题 + - 升级 JDK 版本到 14,避免 [JDK-8048556](https://bugs.openjdk.java.net/browse/JDK-8048556) 导致的重复 GC \ No newline at end of file diff --git a/src/JVM/3.md b/src/JVM/3.md new file mode 100644 index 0000000..f41b126 --- /dev/null +++ b/src/JVM/3.md @@ -0,0 +1,18 @@ +当一个类加载器收到一个类加载的请求,他首先不会尝试自己去加载,而是将这个请求委派给父类加载器去加载,只有父类加载器在自己的搜索范围类查找不到给类时,子加载器才会尝试自己去加载该类。 + +所有的加载请求都会传送到根加载器去加载,只有当父加载器无法加载时,子类加载器才会去加载: + +![双亲委派](images/JVM/双亲委派.png) + +**为什么需要双亲委派模型?** + +为了防止内存中出现多个相同的字节码。因为如果没有双亲委派的话,用户就可以自己定义一个java.lang.String类,那么就无法保证类的唯一性。 + +**那怎么打破双亲委派模型?** + +自定义类加载器,继承ClassLoader类,重写loadClass方法和findClass方法。 + +**双亲委派模型的作用** + +- 避免类的重复加载 +- 保证Java核心类库的安全 \ No newline at end of file diff --git a/src/JVM/301.md b/src/JVM/301.md new file mode 100644 index 0000000..1e6ac63 --- /dev/null +++ b/src/JVM/301.md @@ -0,0 +1,15 @@ +其实,磁盘不足排查算是系统、程序层面的问题排查,并不算是JVM,但是另一方面考虑过来就是,系统磁盘的不足,也会导致JVM的运行异常,所以也把磁盘不足算进来了。并且排查磁盘不足,是比较简单,就是几个命令,然后就是逐层的排查,首先第一个命令就是**df -h**,查询磁盘的状态: + +![JVM-磁盘不足排查](images/JVM/JVM-磁盘不足排查.jpg) + +从上面的显示中其中第一行使用的2.8G最大,然后是挂载在 **/** 目录下,我们直接**cd /**。然后通过执行: + +```shell +du -sh * +``` + +查看各个文件的大小,找到其中最大的,或者说存储量级差不多的并且都非常大的文件,把那些没用的大文件删除就好。 + +![JVM-磁盘不足排查-du-sh](images/JVM/JVM-磁盘不足排查-du-sh.jpg) + +然后,就是直接cd到对应的目录也是执行:du -sh *,就这样一层一层的执行,找到对应的没用的,然后文件又比较大的,可以直接删除。 \ No newline at end of file diff --git a/src/JVM/302.md b/src/JVM/302.md new file mode 100644 index 0000000..12b4dba --- /dev/null +++ b/src/JVM/302.md @@ -0,0 +1,60 @@ +**排查过程** + +- 使用`top`查找进程id +- 使用`top -Hp `查找进程中耗cpu比较高的线程id +- 使用`printf %x `将线程id十进制转十六进制 +- 使用` jstack -pid | grep -A 20 `过滤出线程id锁关联的栈信息 +- 根据栈信息中的调用链定位业务代码 + + + +案例代码如下: + +```java +public class CPUSoaring { + public static void main(String[] args) { + + Thread thread1 = new Thread(new Runnable(){ + @Override + public void run() { + for (;;){ + System.out.println("I am children-thread1"); + } + } + },"children-thread1"); + + Thread thread2 = new Thread(new Runnable(){ + @Override + public void run() { + for (;;){ + System.out.println("I am children-thread2"); + } + } + },"children-thread2"); + + thread1.start(); + thread2.start(); + System.err.println("I am is main thread!!!!!!!!"); + } +} +``` + +- 第一步:首先通过**top**命令可以查看到id为**3806**的进程所占的CPU最高: + + ![CPU过高排查-top](images/JVM/CPU过高排查-top.jpg) + +- 第二步:然后通过**top -Hp pid**命令,找到占用CPU最高的线程: + + ![CPU过高排查-top-Hp-pid](images/JVM/CPU过高排查-top-Hp-pid.jpg) + +- 第三步:接着通过:**printf '%x\n' tid**命令将线程的tid转换为十六进制:xid: + + ![CPU过高排查-printf](images/JVM/CPU过高排查-printf.jpg) + +- 第四步:最后通过:**jstack pid|grep xid -A 30**命令就是输出线程的堆栈信息,线程所在的位置: + + ![CPU过高排查-jstack](images/JVM/CPU过高排查-jstack.jpg) + +- 第五步:还可以通过**jstack -l pid > 文件名称.txt** 命令将线程堆栈信息输出到文件,线下查看。 + + 这就是一个CPU飙高的排查过程,目的就是要**找到占用CPU最高的线程所在的位置**,然后就是**review**你的代码,定位到问题的所在。使用Arthas的工具排查也是一样的,首先要使用top命令找到占用CPU最高的Java进程,然后使用Arthas进入该进程内,**使用dashboard命令排查占用CPU最高的线程。**,最后通过**thread**命令线程的信息。 \ No newline at end of file diff --git a/src/JVM/303.md b/src/JVM/303.md new file mode 100644 index 0000000..e672be0 --- /dev/null +++ b/src/JVM/303.md @@ -0,0 +1,28 @@ +**排查过程** + +- 查找进程id:`top -d 2 -c` +- 查看JVM堆内存分配情况:`jmap -heap pid` +- 查看占用内存比较多的对象:`jmap -histo pid | head -n 100` +- 查看占用内存比较多的存活对象:`jmap -histo:live pid | head -n 100` + + + +**示例** + +- 第一步:top -d 2 -c + + ![img](images/JVM/20200119164639576.png) + +- 第二步:jmap -heap 8338 + + ![img](images/JVM/20200119164641390.png) + +- 第三步:定位占用内存比价多的对象 + + ![img](images/JVM/20200119164633443.png) + + 这里就能看到对象个数以及对象大小…… + + ![img](images/JVM/20200119164640148.png) + + 这里看到一个自定义的类,这样我们就定位到具体对象,看看这个对象在那些地方有使用、为何会有大量的对象存在。 \ No newline at end of file diff --git a/src/JVM/304.md b/src/JVM/304.md new file mode 100644 index 0000000..a23fb53 --- /dev/null +++ b/src/JVM/304.md @@ -0,0 +1,73 @@ +OOM的异常排查也比较简单,首先服务上线的时候,要先设置这两个参数: + +```shell +-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${目录} +``` + +指定项目出现OOM异常的时候自动导出堆转储文件,然后通过内存分析工具(**Visual VM**)来进行线下的分析。 + +首先我们来聊一聊,哪些原因会导致OOM异常,站在JVM的分区的角度: + +- **Java堆** +- **方法区** +- **虚拟机栈** +- **本地方法栈** +- **程序计数器** +- **直接内存** + +只有**程序计数器**区域不会出现OOM,在Java 8及以上的**元空间**(本地内存)都会出现OOM。 + +而站在程序代码的角度来看,总结了大概有以下几点原因会导致OOM异常: + +- **内存泄露** +- **对象过大、过多** +- **方法过长** +- **过度使用代理框架,生成大量的类信息** + +接下来我们屋来看看OOM的排查,出现OOM异常后dump出了堆转储文件,然后打开jdk自带的Visual VM工具,导入堆转储文件,首先我使用的OOM异常代码如下: + +```java +import java.util.ArrayList; +import java.util.List; + +class OOM { + + static class User{ + private String name; + private int age; + + public User(String name, int age){ + this.name = name; + this.age = age; + } + } + + public static void main(String[] args) throws InterruptedException { + List list = new ArrayList<>(); + for (int i = 0; i < Integer.MAX_VALUE; i++) { + Thread.sleep(1000); + User user = new User("zhangsan"+i,i); + list.add(user); + } + } + +} +``` + +代码很简单,就是往集合里面不断地add对象,带入堆转储文件后,在类和实例那栏就可以看到实例最多的类: + +![OOM异常排查-查看实例最多的类](images/JVM/OOM异常排查-查看实例最多的类.jpg) + +这样就找到导致OOM异常的类,还可以通过下面的方法查看导致OOM异常的线程堆栈信息,找到对应异常的代码段。 + +![OOM异常排查-查看异常代码](images/JVM/OOM异常排查-查看异常代码.jpg) + +![OOM异常排查-查看异常代码堆栈](images/JVM/OOM异常排查-查看异常代码堆栈.jpg) + +上面的方法是排查已经出现了OOM异常的方法,肯定是防线的最后一步,那么在此之前怎么防止出现OOM异常呢? + +一般大厂都会有自己的监控平台,能够实施的**监控测试环境、预览环境、线上实施的服务健康状况(CPU、内存)** 等信息,对于频繁GC,并且GC后内存的回收率很差的,就要引起我们的注意了。 + +因为一般方法的长度合理,95%以上的对象都是朝生夕死,在**Minor GC**后只剩少量的存活对象,所以在代码层面上应该避免**方法过长、大对象**的现象。 + +每次自己写完代码,自己检查后,都可以提交给比自己高级别的工程师**review**自己的代码,就能及时的发现代码的问题,基本上代码没问题,百分之九十以上的问题都能避免,这也是大厂注重代码质量,并且时刻**review**代码的习惯。 \ No newline at end of file diff --git a/src/JVM/305.md b/src/JVM/305.md new file mode 100644 index 0000000..d2cb105 --- /dev/null +++ b/src/JVM/305.md @@ -0,0 +1,31 @@ +项目频繁YGC 、FGC问题排查 + +### 内存问题 + +对象内存占用、实例个数监控 + +![img](images/JVM/20200119164751943.png) + + +对象内存占用、年龄值监控 + +![img](images/JVM/2020011916475242.png) + + +通过上面两张图发现这些对象占用内存比较大而且存活时间也是比较常,所以survivor 中的空间被这些对象占用,而如果缓存再次刷新则会创建同样大小对象来替换老数据,这时发现eden内存空间不足,就会触发yonggc 如果yonggc 结束后发现eden空间还是不够则会直接放到老年代,所以这样就产生了大对象的提前晋升,导致fgc增加…… + +**优化办法**:优化两个缓存对象,将缓存对象大小减小。优化一下两个对象,缓存关键信息! + + + +### CPU耗时问题排查 + +Cpu使用耗时监控: + +![img](images/JVM/20200119164752266.png) + +耗时、调用次数监控: + +![img](images/JVM/20200119164749513.png) + +从上面监控图可以看到主要耗时还是在网络请求,没有看到具体业务代码消耗过错cpu…… \ No newline at end of file diff --git a/src/JVM/306.md b/src/JVM/306.md new file mode 100644 index 0000000..e47b1aa --- /dev/null +++ b/src/JVM/306.md @@ -0,0 +1,19 @@ +**初始堆空间大小设置** + +- 使用系统默认配置在系统稳定运行一段时间后查看记录内存使用情况:Eden、survivor0 、survivor1 、old、metaspace +- 按照通用法则通过gc信息分配调整大小,整个堆大小是Full GC后老年代空间占用大小的3-4倍 +- 老年代大小为Full GC后老年代空间占用大小的2-3倍 +- 新生代大小为Full GC后老年代空间占用大小的1-1.5倍 +- 元数据空间大小为Full GC后元数据空间占用大小的1.2-1.5倍 + +活跃数大小是应用程序运行在稳定态时,长期存活的对象在java堆中占用的空间大小。也就是在应用趋于稳太时FullGC之后Java堆中存活对象占用空间大小。(注意在jdk8中将jdk7中的永久代改为元数据区,metaspace 使用的物理内存,不占用堆内存) + + + +**堆大小调整的着手点、分析点** + +- 统计Minor GC 持续时间 +- 统计Minor GC 的次数 +- 统计Full GC的最长持续时间 +- 统计最差情况下Full GC频率 +- 统计GC持续时间和频率对优化堆的大小是主要着手点,我们按照业务系统对延迟和吞吐量的需求,在按照这些分析我们可以进行各个区大小的调整 \ No newline at end of file diff --git a/src/JVM/307.md b/src/JVM/307.md new file mode 100644 index 0000000..6cb7b68 --- /dev/null +++ b/src/JVM/307.md @@ -0,0 +1,55 @@ +**年轻代调优规则** + +- 老年代空间大小不应该小于活跃数大小1.5倍。老年代空间大小应为老年代活跃数2-3倍 +- 新生代空间至少为java堆内存大小的10% 。新生代空间大小应为1-1.5倍的老年代活跃数 +- 在调小年轻代空间时应保持老年代空间不变 + + + +MinorGC是收集eden+from survivor 区域的,当业务系统匀速生成对象的时候如果年轻带分配内存偏小会发生频繁的MinorGC,如果分配内存过大则会导致MinorGC停顿时间过长,无法满足业务延迟性要求。所以按照堆分配空间分配之后分析gc日志,看看MinorGC的频率和停顿时间是否满足业务要求。 + +- **MinorGC频繁原因** + MinorGC 比较频繁说明eden内存分配过小,在恒定的对象产出的情况下很快无空闲空间来存放新对象所以产生了MinorGC,所以eden区间需要调大。 + +- **年轻代大小调整** + Eden调整到多大那,我们可以查看GC日志查看业务多长时间填满了eden空间,然后按照业务能承受的收集频率来计算eden空间大小。比如eden空间大小为128M每5秒收集一次,则我们为了达到10秒收集一次则可以调大eden空间为256M这样能降低收集频率。年轻代调大的同时相应的也要调大老年代,否则有可能会出现频繁的concurrent model failed 从而导致Full GC 。 + +- **MinorGC停顿时间过长** + MinorGC 收集过程是要产生STW的。如果年轻代空间太大,则gc收集时耗时比较大,所以我们按业务对停顿的要求减少内存,比如现在一次MinorGC 耗时12.8毫秒,eden内存大小192M ,我们为了减少MinorGC 耗时我们要减少内存。比如我们MinorGC 耗时标准为10毫秒,这样耗时减少16.6% 同样年轻代内存也要减少16.6% 即192*0.1661 = 31.89M 。年轻代内存为192-31.89=160.11M,在减少年轻代大小,而要保持老年代大小不变则要减少堆内存大小至512-31.89=480.11M + + + +堆内存:512M 年轻代: 192M 收集11次耗时141毫秒 12.82毫秒/次 + +![img](images/JVM/20200119164911457.png) + +堆内存:512M 年轻代:192M 收集12次耗时151毫秒 12.85毫秒/次 + +![img](images/JVM/20200119164911559.png) + +**按照上面计算调优** +堆内存: 480M 年轻带: 160M 收集14次 耗时154毫秒 11毫秒/次 相比之前的 12.82毫秒/次 停顿时间减少1.82毫秒 + +![img](images/JVM/20200119164911817.png) + +**但是还没达到10毫秒的要求,继续按照这样的逻辑进行 11-10=1 ;1/11= 0.909 即 0.09 所以耗时还要降低9%。** +年轻代减少:160*0.09 = 14.545=14.55 M; 160-14.55 =145.45=145M +堆大小: 480-14.55 = 465.45=465M +但是在这样调整后使用jmap -heap 查看的时候年轻代大小和实际配置数据有出入(年轻代大小为150M大于配置的145M),这是因为-XX:NewRatio 默认2 即年轻代和老年代1:2的关系,所以这里将-XX:NewRatio 设置为3 即年轻代、老年大小比为1:3 ,最终堆内存大小为: + +![img](images/JVM/20200119164913228.png) + +MinorGC耗时 159/16=9.93毫秒 + +![img](images/JVM/20200119164912847.png) + +MinorGC耗时 185/18=10.277=10.28毫秒 + +![img](images/JVM/2020011916490666.png) + +MinorGC耗时 205/20=10.25毫秒 + +![img](images/JVM/20200119164912355.png) + + +Ok 这样MinorGC停顿时间过长问题解决,MinorGC要么比较频繁要么停顿时间比较长,解决这个问题就是调整年轻代大小,但是调整的时候还是要遵守这些规则。 \ No newline at end of file diff --git a/src/JVM/308.md b/src/JVM/308.md new file mode 100644 index 0000000..ec6b808 --- /dev/null +++ b/src/JVM/308.md @@ -0,0 +1,8 @@ +按照同样的思路对老年代进行调优,同样分析FullGC 频率和停顿时间,按照优化设定的目标进行老年代大小调整。 + +**老年代调优流程** + +- 分析每次MinorGC 之后老年代空间占用变化,计算每次MinorGC之后晋升到老年代的对象大小 +- 按照MinorGC频率和晋升老年代对象大小计算提升率即每秒钟能有多少对象晋升到老年代 +- FullGC之后统计老年代空间被占用大小计算老年带空闲空间,再按照第2部计算的晋升率计算该老年代空闲空间多久会被填满而再次发生FullGC,同样观察FullGC 日志信息,计算FullGC频率,如果频率过高则可以增大老年代空间大小老解决,增大老年代空间大小应保持年轻代空间大小不变 +- 如果在FullGC 频率满足优化目标而停顿时间比较长的情况下可以考虑使用CMS、G1收集器。并发收集减少停顿时间 \ No newline at end of file diff --git a/src/JVM/309.md b/src/JVM/309.md new file mode 100644 index 0000000..4f6731f --- /dev/null +++ b/src/JVM/309.md @@ -0,0 +1,3 @@ +栈溢出异常的排查(包括**虚拟机栈、本地方法栈**)基本和OOM的一场排查是一样的,导出异常的堆栈信息,然后使用mat或者Visual VM工具进行线下分析,找到出现异常的代码或者方法。 + +当线程请求的栈深度大于虚拟机栈所允许的大小时,就会出现**StackOverflowError**异常,二从代码的角度来看,导致线程请求的深度过大的原因可能有:**方法栈中对象过大,或者过多,方法过长从而导致局部变量表过大,超过了-Xss参数的设置**。 \ No newline at end of file diff --git a/src/JVM/310.md b/src/JVM/310.md new file mode 100644 index 0000000..081c895 --- /dev/null +++ b/src/JVM/310.md @@ -0,0 +1,94 @@ +死锁的案例演示的代码如下: + +```java +public class DeadLock { + + public static Object lock1 = new Object(); + public static Object lock2 = new Object(); + + public static void main(String[] args){ + Thread a = new Thread(new Lock1(),"DeadLock1"); + Thread b = new Thread(new Lock2(),"DeadLock2"); + a.start(); + b.start(); + } +} +class Lock1 implements Runnable{ + @Override + public void run(){ + try{ + while(true){ + synchronized(DeadLock.lock1){ + System.out.println("Waiting for lock2"); + Thread.sleep(3000); + synchronized(DeadLock.lock2){ + System.out.println("Lock1 acquired lock1 and lock2 "); + } + } + } + }catch(Exception e){ + e.printStackTrace(); + } + } +} +class Lock2 implements Runnable{ + @Override + public void run(){ + try{ + while(true){ + synchronized(DeadLock.lock2){ + System.out.println("Waiting for lock1"); + Thread.sleep(3000); + synchronized(DeadLock.lock1){ + System.out.println("Lock2 acquired lock1 and lock2"); + } + } + } + }catch(Exception e){ + e.printStackTrace(); + } + } +} +``` + +上面的代码非常的简单,就是两个类的实例作为锁资源,然后分别开启两个线程,不同顺序的对锁资源资源进行加锁,并且获取一个锁资源后,等待三秒,是为了让另一个线程有足够的时间获取另一个锁对象。 + +运行上面的代码后,就会陷入死锁的僵局: + +![死锁排查-死锁运行结果示例](images/JVM/死锁排查-死锁运行结果示例.jpg) + +对于死锁的排查,若是在测试环境或者本地,直接就可以使用Visual VM连接到该进程,如下界面就会自动检测到死锁的存在 + +![死锁排查-检测死锁](images/JVM/死锁排查-检测死锁.jpg) + +并且查看线程的堆栈信息。就能看到具体的死锁的线程: + +![死锁排查-查看线程堆栈信息](images/JVM/死锁排查-查看线程堆栈信息.jpg) + +线上的话可以上用Arthas也可以使用原始的命令进行排查,原始命令可以先使用**jps**查看具体的Java进程的ID,然后再通过**jstack ID**查看进程的线程堆栈信息,他也会自动给你提示有死锁的存在: + +![死锁排查-jstack查看线程堆栈](images/JVM/死锁排查-jstack查看线程堆栈.jpg) + +Arthas工具可以使用**thread**命令排查死锁,要关注的是**BLOCKED**状态的线程,如下图所示: + +![死锁排查-Arthas查看死锁](images/JVM/死锁排查-Arthas查看死锁.jpg) + +具体thread的详细参数可以参考如下图所示: + +![死锁排查-Thread详细参数](images/JVM/死锁排查-Thread详细参数.jpg) + + + +**如何避免死锁** + +上面我们聊了如何排查死锁,下面我们来聊一聊如何避免死锁的发生,从上面的案例中可以发现,死锁的发生两个线程同时都持有对方不释放的资源进入僵局。所以,在代码层面,要避免死锁的发生,主要可以从下面的四个方面进行入手: + +- **首先避免线程的对于资源的加锁顺序要保持一致** + +- **并且要避免同一个线程对多个资源进行资源的争抢** + +- **另外的话,对于已经获取到的锁资源,尽量设置失效时间,避免异常,没有释放锁资源,可以使用acquire() 方法加锁时可指定 timeout 参数** + +- **最后,就是使用第三方的工具检测死锁,预防线上死锁的发生** + +死锁的排查已经说完了,上面的基本就是问题的排查,也可以算是调优的一部分吧,但是对于JVM调优来说,重头戏应该是在**Java堆**,这部分的调优才是重中之重。 \ No newline at end of file diff --git a/src/JVM/311.md b/src/JVM/311.md new file mode 100644 index 0000000..06cb2cb --- /dev/null +++ b/src/JVM/311.md @@ -0,0 +1,90 @@ +上面说完了调优的目的和调优的指标,那么我们就来实战调优,首先准备我的案例代码,如下: + +```java +import java.util.ArrayList; +import java.util.List; + +class OOM { + + static class User{ + private String name; + private int age; + + public User(String name, int age){ + this.name = name; + this.age = age; + } + + } + + public static void main(String[] args) throws InterruptedException { + List list = new ArrayList<>(); + for (int i = 0; i < Integer.MAX_VALUE; i++) { + Tread.sleep(1000); + System.err.println(Thread.currentThread().getName()); + User user = new User("zhangsan"+i,i); + list.add(user); + } + } +} +``` + +案例代码很简单,就是不断的往一个集合里里面添加对象,首先初次我们启动的命令为: + +```shell +java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:+PrintHeapAtGC -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=50M -Xloggc:./logs/emps-gc-%t.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./logs/emps-heap.dump OOM +``` + +就是纯粹的设置了一些GC的打印日志,然后通过Visual VM来看GC的显示如下: + +![调优实战-VisualVM查看GC显示](images/JVM/调优实战-VisualVM查看GC显示.jpg) + +可以看到一段时间后出现4次Minor GC,使用的时间是29.648ms,发生一次Full GC使用的时间是41.944ms。 + +Minor GC非常频繁,Full GC也是,在短时间内就发生了几次,观察输出的日志发现以及Visual VM的显示来看,都是因为内存没有设置,太小,导致Minor GC频繁。 + +因此,我们第二次适当的增大Java堆的大小,调优设置的参数为: + +```shell +java -Xmx2048m -Xms2048m -Xmn1024m -Xss256k -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:+PrintHeapAtGC -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=50M -Xloggc:./logs/emps-gc-%t.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./logs/emps-heap.dump OOM +``` + +观察一段时间后,结果如下图所示: + +![调优实战-一段时间后VisualVM查看GC显示](images/JVM/调优实战-一段时间后VisualVM查看GC显示.jpg) + +可以发现Minor GC次数明显下降,但是还是发生了Full GC,根据打印的日志来看,是因为元空间的内存不足,看了上面的Visual VM元空间的内存图,也是一样,基本都到顶了: + +![调优实战-元空间不足](images/JVM/调优实战-元空间不足.jpg) + +因此第三次对于元空间的区域设置大一些,并且将GC回收器换成是CMS的,设置的参数如下: + +```shell +java -Xmx2048m -Xms2048m -Xmn1024m -Xss256k -XX:MetaspaceSize=100m -XX:MaxMetaspaceSize=100m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:+PrintHeapAtGC -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=50M -Xloggc:./logs/emps-gc-%t.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./logs/emps-heap.dump OOM +``` + +观察相同的时间后,Visual VM的显示图如下: + +![调优实战-元空间调后后VisualVM查看GC显示](images/JVM/调优实战-元空间调后后VisualVM查看GC显示.jpg) + +同样的时间,一次Minor GC和Full GC都没有发生,所以这样我觉得也算是已经调优了。 + +但是调优并不是一味的调大内存,是要在各个区域之间取得平衡,可以适当的调大内存,以及更换GC种类,举个例子,当把上面的案例代码的Thread.sleep(1000)给去掉。 + +然后再来看Visual VM的图,如下: + +![调优实战-去掉线程休眠VisualVM显示](images/JVM/调优实战-去掉线程休眠VisualVM显示.jpg) + +可以看到Minor GC也是非常频繁的,因为这段代码本身就是不断的增大内存,直到OOM异常,真正的实际并不会这样,可能当内存增大到一定两级后,就会在一段范围平衡。 + +当我们将上面的情况,再适当的增大内存,JVM参数如下: + +```shell +java -Xmx4048m -Xms4048m -Xmn2024m -XX:SurvivorRatio=7 -Xss256k -XX:MetaspaceSize=300m -XX:MaxMetaspaceSize=100m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:+PrintHeapAtGC -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=50M -Xloggc:./logs/emps-gc-%t.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./logs/emps-heap.dump OOM +``` + +可以看到相同时间内,确实Minor GC减少了,但是时间增大了,因为复制算法,基本都是存活的,复制需要耗费大量的性能和时间: + +![调优实战-减少MinorGC后VisualVM显示](images/JVM/调优实战-减少MinorGC后VisualVM显示.jpg) + +所以,调优要有取舍,取得一个平衡点,性能、状态达到佳就OK了,并没最佳的状态,这就是调优的基本法则,而且调优也是一个细活,所谓慢工出细活,需要耗费大量的时间,慢慢调,不断的做对比。 \ No newline at end of file diff --git a/src/JVM/312.md b/src/JVM/312.md new file mode 100644 index 0000000..da0ff9f --- /dev/null +++ b/src/JVM/312.md @@ -0,0 +1,99 @@ +### 堆 + +- -Xms1024m 设置堆的初始大小 +- -Xmx1024m 设置堆的最大大小 +- -XX:NewSize=1024m 设置年轻代的初始大小 +- -XX:MaxNewSize=1024m 设置年轻代的最大值 +- -XX:SurvivorRatio=8 Eden和S区的比例 +- -XX:NewRatio=4 设置老年代和新生代的比例 +- -XX:MaxTenuringThreshold=10 设置晋升老年代的年龄条件 + + + +### 栈 + +- -Xss128k + + + +### 元空间 + +- -XX:MetasapceSize=200m 设置初始元空间大小 +- -XX:MaxMatespaceSize=200m 设置最大元空间大小 默认无限制 + + + +### 直接内存 + +- -XX:MaxDirectMemorySize 设置直接内存的容量,默认与堆最大值一样 + + + +### 日志 + +- -Xloggc:/opt/app/ard-user/ard-user-gc-%t.log 设置日志目录和日志名称 +- -XX:+UseGCLogFileRotation 开启滚动生成日志 +- -XX:NumberOfGCLogFiles=5 滚动GC日志文件数,默认0,不滚动 +- -XX:GCLogFileSize=20M GC文件滚动大小,需开 UseGCLogFileRotation +- -XX:+PrintGCDetails 开启记录GC日志详细信息(包括GC类型、各个操作使用的时间),并且在程序运行结束打印出JVM的内存占用情况 +- -XX:+ PrintGCDateStamps 记录系统的GC时间 +- -XX:+PrintGCCause 产生GC的原因(默认开启) + + + +### GC + +#### Serial垃圾收集器(新生代) + +开启 + +- -XX:+UseSerialGC + +关闭: + +- -XX:-UseSerialGC //新生代使用Serial 老年代则使用SerialOld + + + +#### Parallel Scavenge收集器(新生代)开启 + +- -XX:+UseParallelOldGC 关闭 +- -XX:-UseParallelOldGC 新生代使用功能Parallel Scavenge 老年代将会使用Parallel Old收集器 + + + +#### ParallelOl垃圾收集器(老年代)开启 + +- -XX:+UseParallelGC 关闭 +- -XX:-UseParallelGC 新生代使用功能Parallel Scavenge 老年代将会使用Parallel Old收集器 + + + +#### ParNew垃圾收集器(新生代)开启 + +- -XX:+UseParNewGC 关闭 +- -XX:-UseParNewGC //新生代使用功能ParNew 老年代则使用功能CMS + + + +#### CMS垃圾收集器(老年代)开启 + +- -XX:+UseConcMarkSweepGC 关闭 +- -XX:-UseConcMarkSweepGC +- -XX:MaxGCPauseMillis GC停顿时间,垃圾收集器会尝试用各种手段达到这个时间,比如减小年轻代 +- -XX:+UseCMSCompactAtFullCollection 用于在CMS收集器不得不进行FullGC时开启内存碎片的合并整理过程,由于这个内存整理必须移动存活对象,(在Shenandoah和ZGC出现前)是无法并发的 +- -XX:CMSFullGCsBefore-Compaction 多少次FullGC之后压缩一次,默认值为0,表示每次进入FullGC时都进行碎片整理) +- -XX:CMSInitiatingOccupancyFraction 当老年代使用达到该比例时会触发FullGC,默认是92 +- -XX:+UseCMSInitiatingOccupancyOnly 这个参数搭配上面那个用,表示是不是要一直使用上面的比例触发FullGC,如果设置则只会在第一次FullGC的时候使用-XX:CMSInitiatingOccupancyFraction的值,之后会进行自动调整 +- -XX:+CMSScavengeBeforeRemark 在FullGC前启动一次MinorGC,目的在于减少老年代对年轻代的引用,降低CMSGC的标记阶段时的开销,一般CMS的GC耗时80%都在标记阶段 +- -XX:+CMSParallellnitialMarkEnabled 默认情况下初始标记是单线程的,这个参数可以让他多线程执行,可以减少STW +- -XX:+CMSParallelRemarkEnabled 使用多线程进行重新标记,目的也是为了减少STW + + + +#### G1垃圾收集器开启 + +- -XX:+UseG1GC 关闭 +- -XX:-UseG1GC +- -XX:G1HeapRegionSize 设置每个Region的大小,取值范围为1MB~32MB +- -XX:MaxGCPauseMillis 设置垃圾收集器的停顿时间,默认值是200毫秒,通常把期望停顿时间设置为一两百毫秒或者两三百毫秒会是比较合理的 \ No newline at end of file diff --git a/src/JVM/401.md b/src/JVM/401.md new file mode 100644 index 0000000..5932041 --- /dev/null +++ b/src/JVM/401.md @@ -0,0 +1,10 @@ +用于显示当前用户下的所有java进程信息: + +```shell +# jps [options] [hostid] +# q:仅输出VM标识符, m: 输出main method的参数,l:输出完全的包名, v:输出jvm参数 +[root@localhost ~]# jps -l +28729 sun.tools.jps.Jps +23789 cn.ms.test.DemoMain +23651 cn.ms.test.TestMain +``` \ No newline at end of file diff --git a/src/JVM/402.md b/src/JVM/402.md new file mode 100644 index 0000000..39b4efc --- /dev/null +++ b/src/JVM/402.md @@ -0,0 +1,92 @@ +用于监视虚拟机运行时状态信息(类装载、内存、垃圾收集、JIT编译等运行数据): + +**-gc**:垃圾回收统计(大小) + +```shell +# 每隔2000ms输出进程的gc情况,一共输出2次 +[root@localhost ~]# jstat -gc 2000 2 +# 每隔2s输出进程的gc情况,每个3条记录就打印隐藏列标题 +[root@localhost ~]# jstat -gc -t -h3 2s +Timestamp S0C S1C S0U S1U ... YGC YGCT FGC FGCT GCT + 1021.6 1024.0 1024.0 0.0 1024.0 ... 1 0.012 0 0.000 0.012 + 1023.7 1024.0 1024.0 0.0 1024.0 ... 1 0.012 0 0.000 0.012 + 1025.7 1024.0 1024.0 0.0 1024.0 ... 1 0.012 0 0.000 0.012 +Timestamp S0C S1C S0U S1U ... YGC YGCT FGC FGCT GCT + 1027.7 1024.0 1024.0 0.0 1024.0 ... 1 0.012 0 0.000 0.012 + 1029.7 1024.0 1024.0 0.0 1024.0 ... 1 0.012 0 0.000 0.012 +# 结果说明: C即Capacity 总容量,U即Used 已使用的容量 +########################## +# S0C:年轻代中第一个survivor(幸存区)的容量 (kb) +# S1C:年轻代中第二个survivor(幸存区)的容量 (kb) +# S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (kb) +# S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (kb) +# EC:年轻代中Eden(伊甸园)的容量 (kb) +# EU:年轻代中Eden(伊甸园)目前已使用空间 (kb) +# OC:Old代的容量 (kb) +# OU:Old代目前已使用空间 (kb) +# PC:Perm(持久代)的容量 (kb) +# PU:Perm(持久代)目前已使用空间 (kb) +# YGC:从应用程序启动到采样时年轻代中gc次数 +# YGCT:从应用程序启动到采样时年轻代中gc所用时间(s) +# FGC:从应用程序启动到采样时old代(全gc)gc次数 +# FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s) +# GCT:从应用程序启动到采样时gc用的总时间(s) +``` + +**-gcutil**:垃圾回收统计(百分比) + +```shell +[root@localhost bin]# jstat -gcutil + S0 S1 E O M CCS YGC YGCT FGC FGCT GCT + 0.00 99.80 16.21 26.18 93.34 90.74 9 0.056 2 0.045 0.102 +# 结果说明 +########################## +# S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比 +# S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比 +# E:年轻代中Eden(伊甸园)已使用的占当前容量百分比 +# O:old代已使用的占当前容量百分比 +# P:perm代已使用的占当前容量百分比 +# YGC:从应用程序启动到采样时年轻代中gc次数 +# YGCT:从应用程序启动到采样时年轻代中gc所用时间(s) +# FGC:从应用程序启动到采样时old代(全gc)gc次数 +# FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s) +# GCT:从应用程序启动到采样时gc用的总时间(s) +``` + +**-gccapacity**:堆内存统计 + +```shell +[root@localhost ~]# jstat -gccapacity + NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC + 84480.0 1349632.0 913408.0 54272.0 51200.0 502784.0 168448.0 2699264.0 168448.0 168448.0 21504.0 83968.0 51712.0 51712.0 9 0 +# 结果说明 +########################## +# NGCMN:年轻代(young)中初始化(最小)的大小 (kb) +# NGCMX:年轻代(young)的最大容量 (kb) +# NGC:年轻代(young)中当前的容量 (kb) +# S0C:年轻代中第一个survivor(幸存区)的容量 (kb) +# S1C:年轻代中第二个survivor(幸存区)的容量 (kb) +# EC:年轻代中Eden(伊甸园)的容量 (kb) +# OGCMN:old代中初始化(最小)的大小 (kb) +# OGCMX:old代的最大容量 (kb) +# OGC:old代当前新生成的容量 (kb) +# OC:Old代的容量 (kb) +# PGCMN:perm代中初始化(最小)的大小 (kb) +# PGCMX:perm代的最大容量 (kb) +# PGC:perm代当前新生成的容量 (kb) +# PC:Perm(持久代)的容量 (kb) +# YGC:从应用程序启动到采样时年轻代中gc次数 +# GCT:从应用程序启动到采样时gc用的总时间(s) +``` + +**-gccause**:垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因 + +```shell +[root@localhost ~]# jstat -gccause + S0 S1 E O P YGC YGCT FGC FGCT GCT LGCC GCC + 0.00 79.23 39.37 39.92 99.74 9 0.198 0 0.000 0.198 Allocation Failure No GC +# 结果说明 +########################## +# LGCC:最近垃圾回收的原因 +# GCC:当前垃圾回收的原因 +``` \ No newline at end of file diff --git a/src/JVM/403.md b/src/JVM/403.md new file mode 100644 index 0000000..421af84 --- /dev/null +++ b/src/JVM/403.md @@ -0,0 +1,66 @@ +jstack(Java Stack Trace)主要用于打印线程的堆栈信息,是JDK自带的很强大的线程分析工具,可以帮助我们排查程序运行时的线程状态、死锁状态等。 + +```shell +# dump出进程的线程堆栈快照至/data/1.log文件中 +jstack -l >/data/1.log + +# 参数说明: +# -F:如果正常执行jstack命令没有响应(比如进程hung住了),可以加上此参数强制执行thread dump +# -m:除了打印Java的方法调用栈之外,还会输出native方法的栈帧 +# -l:打印与锁有关的附加信息。使用此参数会导致JVM停止时间变长,在生产环境需慎用 +``` + +jstack dump文件中值得关注的线程状态有: + +- **死锁(Deadlock) —— 重点关注** +- 执行中(Runnable) +- **等待资源(Waiting on condition) —— 重点关注** + - 等待某个资源或条件发生来唤醒自己。具体需结合jstacktrace来分析,如线程正在sleep,网络读写繁忙而等待 + - 如果大量线程在“waiting on condition”,并且在等待网络资源,可能是网络瓶颈的征兆 +- **等待获取监视器(Waiting on monitor entry) —— 重点关注** + - 如果大量线程在“waiting for monitor entry”,可能是一个全局锁阻塞住了大量线程 +- 暂停(Suspended) +- 对象等待中(Object.wait() 或 TIMED_WAITING) +- **阻塞(Blocked) —— 重点关注** +- 停止(Parked) + + + +**注意**:如果某个相同的call stack经常出现, 我们有80%的以上的理由确定这个代码存在性能问题(读网络的部分除外)。 + + + +**场景一:分析BLOCKED问题** + +```shell +"RMI TCP Connection(267865)-172.16.5.25" daemon prio=10 tid=0x00007fd508371000 nid=0x55ae waiting for monitor entry [0x00007fd4f8684000] + java.lang.Thread.State: BLOCKED (on object monitor) +at org.apache.log4j.Category.callAppenders(Category.java:201) +- waiting to lock <0x00000000acf4d0c0> (a org.apache.log4j.Logger) +at org.apache.log4j.Category.forcedLog(Category.java:388) +at org.apache.log4j.Category.log(Category.java:853) +at org.apache.commons.logging.impl.Log4JLogger.warn(Log4JLogger.java:234) +at com.tuan.core.common.lang.cache.remote.SpyMemcachedClient.get(SpyMemcachedClient.java:110) +``` + +- 线程状态是 Blocked,阻塞状态。说明线程等待资源超时 +- “ waiting to lock <0x00000000acf4d0c0>”指,线程在等待给这个 0x00000000acf4d0c0 地址上锁(英文可描述为:trying to obtain 0x00000000acf4d0c0 lock) +- 在 dump 日志里查找字符串 0x00000000acf4d0c0,发现有大量线程都在等待给这个地址上锁。如果能在日志里找到谁获得了这个锁(如locked < 0x00000000acf4d0c0 >),就可以顺藤摸瓜了 +- “waiting for monitor entry”说明此线程通过 synchronized(obj) {……} 申请进入了临界区,从而进入了下图1中的“Entry Set”队列,但该 obj 对应的 monitor 被其他线程拥有,所以本线程在 Entry Set 队列中等待 +- 第一行里,"RMI TCP Connection(267865)-172.16.5.25"是 Thread Name 。tid指Java Thread id。nid指native线程的id。prio是线程优先级。[0x00007fd4f8684000]是线程栈起始地址。 + + + +**场景二:分析CPU过高问题** + +1.top命令找出最高占用的进程(Shift+P) + +2.查看高负载进程下的高负载线程(top -Hp 或ps -mp -o THREAD,tid,time) + +3.找出最高占用的线程并记录thread_id,把线程号进行换算成16进制编号(printf "%X\n" thread_id) + +4.(可选)执行查看高负载的线程名称(jstack 16143 | grep 3fb6) + +5.导出进程的堆栈日志,找到3fb6 这个线程号(jstack 16143 >/home/16143.log) + +6.根据找到的堆栈信息关联到代码进行定位分析即可 \ No newline at end of file diff --git a/src/JVM/404.md b/src/JVM/404.md new file mode 100644 index 0000000..6acf72d --- /dev/null +++ b/src/JVM/404.md @@ -0,0 +1,162 @@ +jmap(Java Memory Map)主要用于打印内存映射。常用命令: + +`jmap -dump:live,format=b,file=xxx.hprof ` + +**查看JVM堆栈的使用情况** + +```powershell +[root@localhost ~]# jmap -heap 7243 +Attaching to process ID 27900, please wait... +Debugger attached successfully. +Client compiler detected. +JVM version is 20.45-b01 +using thread-local object allocation. +Mark Sweep Compact GC +Heap Configuration: #堆内存初始化配置 + MinHeapFreeRatio = 40 #-XX:MinHeapFreeRatio设置JVM堆最小空闲比率 + MaxHeapFreeRatio = 70 #-XX:MaxHeapFreeRatio设置JVM堆最大空闲比率 + MaxHeapSize = 100663296 (96.0MB) #-XX:MaxHeapSize=设置JVM堆的最大大小 + NewSize = 1048576 (1.0MB) #-XX:NewSize=设置JVM堆的‘新生代’的默认大小 + MaxNewSize = 4294901760 (4095.9375MB) #-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小 + OldSize = 4194304 (4.0MB) #-XX:OldSize=设置JVM堆的‘老生代’的大小 + NewRatio = 2 #-XX:NewRatio=:‘新生代’和‘老生代’的大小比率 + SurvivorRatio = 8 #-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值 + PermSize = 12582912 (12.0MB) #-XX:PermSize=:设置JVM堆的‘持久代’的初始大小 + MaxPermSize = 67108864 (64.0MB) #-XX:MaxPermSize=:设置JVM堆的‘持久代’的最大大小 +Heap Usage: +New Generation (Eden + 1 Survivor Space): #新生代区内存分布,包含伊甸园区+1个Survivor区 + capacity = 30212096 (28.8125MB) + used = 27103784 (25.848182678222656MB) + free = 3108312 (2.9643173217773438MB) + 89.71169693092462% used +Eden Space: #Eden区内存分布 + capacity = 26869760 (25.625MB) + used = 26869760 (25.625MB) + free = 0 (0.0MB) + 100.0% used +From Space: #其中一个Survivor区的内存分布 + capacity = 3342336 (3.1875MB) + used = 234024 (0.22318267822265625MB) + free = 3108312 (2.9643173217773438MB) + 7.001809512867647% used +To Space: #另一个Survivor区的内存分布 + capacity = 3342336 (3.1875MB) + used = 0 (0.0MB) + free = 3342336 (3.1875MB) + 0.0% used +PS Old Generation: #当前的Old区内存分布 + capacity = 67108864 (64.0MB) + used = 67108816 (63.99995422363281MB) + free = 48 (4.57763671875E-5MB) + 99.99992847442627% used +PS Perm Generation: #当前的 “持久代” 内存分布 + capacity = 14417920 (13.75MB) + used = 14339216 (13.674942016601562MB) + free = 78704 (0.0750579833984375MB) + 99.45412375710227% used +``` + +新生代内存回收就是采用空间换时间方式;如果from区使用率一直是100% 说明程序创建大量的短生命周期的实例,使用jstat统计jvm在内存回收中发生的频率耗时以及是否有full gc,使用这个数据来评估一内存配置参数、gc参数是否合理。 + +**统计一【jmap -histo】**:统计所有类的实例数量和所占用的内存容量 + +```powershell +[root@localhost ~]# jmap -histo 7243 + num #instances #bytes class name +---------------------------------------------- + 1: 8969 19781168 [B + 2: 1835 2296720 [I + 3: 19735 2050688 [C + 4: 3448 385608 java.lang.Class + 5: 3829 371456 [Ljava.lang.Object; + 6: 14634 351216 java.lang.String + 7: 6695 214240 java.util.concurrent.ConcurrentHashMap$Node + 8: 6257 100112 java.lang.Object + 9: 2155 68960 java.util.HashMap$Node + 10: 723 63624 java.lang.reflect.Method + 11: 49 56368 [Ljava.util.concurrent.ConcurrentHashMap$Node; + 12: 830 46480 java.util.zip.ZipFile$ZipFileInputStream + 13: 1146 45840 java.lang.ref.Finalizer + ...... +``` + +**统计二【jmap -histo】**:查看对象数最多的对象,并过滤Map关键词,然后按降序排序输出 + +```shell +[root@localhost ~]# jmap -histo 7243 |grep Map|sort -k 2 -g -r|less +Total 96237 26875560 + 7: 6695 214240 java.util.concurrent.ConcurrentHashMap$Node + 9: 2155 68960 java.util.HashMap$Node + 18: 563 27024 java.util.HashMap + 21: 505 20200 java.util.LinkedHashMap$Entry + 16: 337 34880 [Ljava.util.HashMap$Node; + 27: 336 16128 gnu.trove.THashMap + 56: 163 6520 java.util.WeakHashMap$Entry + 60: 127 6096 java.util.WeakHashMap + 38: 127 10144 [Ljava.util.WeakHashMap$Entry; + 53: 126 7056 java.util.LinkedHashMap +...... +``` + + + +**统计三【jmap -histo】**:统计实例数量最多的前10个类 + +```shell +[root@localhost ~]# jmap -histo 7243 | sort -n -r -k 2 | head -10 + num #instances #bytes class name +---------------------------------------------- +Total 96237 26875560 + 3: 19735 2050688 [C + 6: 14634 351216 java.lang.String + 1: 8969 19781168 [B + 7: 6695 214240 java.util.concurrent.ConcurrentHashMap$Node + 8: 6257 100112 java.lang.Object + 5: 3829 371456 [Ljava.lang.Object; + 4: 3448 385608 java.lang.Class + 9: 2155 68960 java.util.HashMap$Node + 2: 1835 2296720 [I +``` + + + +**统计四【jmap -histo】**:统计合计容量最多的前10个类 + +```shell +[root@localhost ~]# jmap -histo 7243 | sort -n -r -k 3 | head -10 + num #instances #bytes class name +---------------------------------------------- +Total 96237 26875560 + 1: 8969 19781168 [B + 2: 1835 2296720 [I + 3: 19735 2050688 [C + 4: 3448 385608 java.lang.Class + 5: 3829 371456 [Ljava.lang.Object; + 6: 14634 351216 java.lang.String + 7: 6695 214240 java.util.concurrent.ConcurrentHashMap$Node + 8: 6257 100112 java.lang.Object + 9: 2155 68960 java.util.HashMap$Node +``` + +**dump注意事项** + +- 在应用快要发生FGC的时候把堆数据导出来 + + ​ 老年代或新生代used接近100%时,就表示即将发生GC,也可以再JVM参数中指定触发GC的阈值。 + + - 查看快要发生FGC使用命令:jmap -heap < pid > + - 数据导出:jmap -dump:format=b,file=heap.bin < pid > + +- 通过命令查看大对象:jmap -histo < pid >|less + + + +**使用总结** + +- 如果程序内存不足或者频繁GC,很有可能存在内存泄露情况,这时候就要借助Java堆Dump查看对象的情况 +- 要制作堆Dump可以直接使用jvm自带的jmap命令 +- 可以先使用`jmap -heap`命令查看堆的使用情况,看一下各个堆空间的占用情况 +- 使用`jmap -histo:[live]`查看堆内存中的对象的情况。如果有大量对象在持续被引用,并没有被释放掉,那就产生了内存泄露,就要结合代码,把不用的对象释放掉 +- 也可以使用 `jmap -dump:format=b,file=`命令将堆信息保存到一个文件中,再借助jhat命令查看详细内容 +- 在内存出现泄露、溢出或者其它前提条件下,建议多dump几次内存,把内存文件进行编号归档,便于后续内存整理分析 +- 在用cms gc的情况下,执行jmap -heap有些时候会导致进程变T,因此强烈建议别执行这个命令,如果想获取内存目前每个区域的使用状况,可通过jstat -gc或jstat -gccapacity来拿到 \ No newline at end of file diff --git a/src/JVM/405.md b/src/JVM/405.md new file mode 100644 index 0000000..bc431d8 --- /dev/null +++ b/src/JVM/405.md @@ -0,0 +1,6 @@ +jhat(JVM Heap Analysis Tool)命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看。在此要注意,一般不会直接在服务器上进行分析,因为jhat是一个耗时并且耗费硬件资源的过程,一般把服务器生成的dump文件复制到本地或其他机器上进行分析。 + +```powershell +# 解析Java堆转储文件,并启动一个 web server +jhat heapDump.dump +``` \ No newline at end of file diff --git a/src/JVM/406.md b/src/JVM/406.md new file mode 100644 index 0000000..8539623 --- /dev/null +++ b/src/JVM/406.md @@ -0,0 +1,46 @@ +jconsole(Java Monitoring and Management Console)是一个Java GUI监视工具,可以以图表化的形式显示各种数据,并可通过远程连接监视远程的服务器VM。用java写的GUI程序,用来监控VM,并可监控远程的VM,非常易用,而且功能非常强。命令行里打jconsole,选则进程就可以了。 + +**第一步**:在远程机的tomcat的catalina.sh中加入配置: + +```powershell +JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=192.168.202.121 -Dcom.sun.management.jmxremote" +JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=12345" +JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=true" +JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false" +JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.pwd.file=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.101-3.b13.el7_2.x86_64/jre/lib/management/jmxremote.password" +``` + + + +**第二步**:配置权限文件 + +```powershell +[root@localhost bin]# cd /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.101-3.b13.el7_2.x86_64/jre/lib/management/ +[root@localhost management]# cp jmxremote.password.template jmxremote.password +[root@localhost management]# vi jmxremote.password +``` + +monitorRole QED +controlRole chenqimiao + + + +**第三步**:配置权限文件为600 + +```powershell +[root@localhost management]# chmod 600 jmxremote.password jmxremote.access +``` + +这样基本配置就结束了,下面说两个坑,第一个就是防火墙的问题,要开放指定端口的防火墙,我这里配置的是12345端口,第二个是hostname的问题: + +![jconsole-ip2](images/JVM/jconsole-ip2.png) + +请将127.0.0.1修改为本地真实的IP,我的服务器IP是192.168.202.121: + +![jconsole-ip](images/JVM/jconsole-ip.png) + + **第四步**:查看JConsole + +![JConsole-新建连接](images/JVM/JConsole-新建连接.png) + +![JConsole-Console](images/JVM/JConsole-Console.png) \ No newline at end of file diff --git a/src/JVM/407.md b/src/JVM/407.md new file mode 100644 index 0000000..fb0607a --- /dev/null +++ b/src/JVM/407.md @@ -0,0 +1,23 @@ +jvisualvm(JVM Monitoring/Troubleshooting/Profiling Tool)同jconsole都是一个基于图形化界面的、可以查看本地及远程的JAVA GUI监控工具,Jvisualvm同jconsole的使用方式一样,直接在命令行打入Jvisualvm即可启动,不过Jvisualvm相比,界面更美观一些,数据更实时。 jvisualvm的使用VisualVM进行远程连接的配置和JConsole是一摸一样的,最终效果图如下 + +![jvisualvm](images/JVM/jvisualvm.png) + + + +**Visual GC(监控垃圾回收器)** + +Java VisualVM默认没有安装Visual GC插件,需要手动安装,JDK的安装目录的bin目露下双击 jvisualvm.sh,即可打开Java VisualVM,点击菜单栏: **工具->插件** 安装Visual GC,最终效果如下图所示: + +![Visual-GC](images/JVM/Visual-GC.png) + + + +**大dump文件** + +从服务器dump堆内存后文件比较大(5.5G左右),加载文件、查看实例对象都很慢,还提示配置xmx大小。表明给VisualVM分配的堆内存不够,找到$JAVA_HOME/lib/visualvm}/etc/visualvm.conf这个文件,修改: + +```shell +default_options="-J-Xms24m -J-Xmx192m" +``` + +再重启VisualVM就行了。 \ No newline at end of file diff --git a/src/JVM/408.md b/src/JVM/408.md new file mode 100644 index 0000000..7f7d163 --- /dev/null +++ b/src/JVM/408.md @@ -0,0 +1,133 @@ +jmc(Java Mission Control)是JDK自带的一个图形界面监控工具,监控信息非常全面。JMC打开性能日志后,主要包括**一般信息、内存、代码、线程、I/O、系统、事件** 功能。 + +![jmc-main](images/JVM/jmc-main.jpg) + +JMC的最主要的特征就是JFR(Java Flight Recorder),是基于JAVA的飞行记录器,JFR的数据是一些列JVM事件的历史纪录,可以用来诊断JVM的性能和操作,收集后的数据可以使用JMC来分析。 + + + +### 启动JFR + +在商业版本上面,JFR默认是关闭的,可以通过在启动时增加参数 `-XX:+UnlockCommercialFeatures -XX:+FlightRecorder` 来启动应用。启动之后,也只是开启了JFR特性,但是还没有开始进行事件记录。这就要通过GUI和命令行了。 + +- **通过Java Mission Control启动JFR** + + 打开Java Mission Control点击对应的JVM启动即可,事件记录有两种模式(如果选择第2种模式,那么JVM会使用一个循环使用的缓存来存放事件数据): + + - 记录固定一段时间的事件(比如:1分钟) + - 持续进行记录 + +- **通过命令行启动JFR** + + 通过在启动的时候,增加参数:`-XX:+FlightRecorderOptions=string` 来启动真正地事件记录,这里的 `string` 可以是以下值(下列参数都可以使用jcmd命令,在JVM运行的时候进行动态调整,[参考地址](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html)): + + - `name=name`:标识recording的名字(一个进程可以有多个recording存在,它们使用名字来进行区分) + - `defaultrecording=`:是否启动recording,默认是false,我们要分析,必须要设置为true + - `setting=paths`:包含JFR配置的文件名字 + - `delay=time`:启动之后,经过多长时间(比如:30s,1h)开始进行recording + - `duration=time`:做多长时间的recording + - `filename=path`:recordding记录到那个文件里面 + - `compress=`:是否对recording进行压缩(gzip),默认为false + - `maxage=time`:在循环使用的缓存中,事件数据保存的最大时长 + - `maxsize=size`:事件数据缓存的最大大小(比如:1024k,1M) + + + +### 常用JFR命令 + +- 启动recording + + 命令格式:`jcmd process_id JFR.start [options_list]`,其中options_list就是上述的参数值。 + +- dump出循环缓存中的数据 + + 命令格式:`jcmd process_id JFR.dump [options_list]`,其中options_list参数的可选值如下: + + - `name=name`:recording的名字 + - `recording=n`:JFR recording的数字(一个标识recording的随机数) + - `filename=path`:dump文件的保存路径 + +- 查看进程中所有recording + + 命令格式:` jcmd process_id JFR.check [verbose]`,不同recording使用名字进行区分,同时JVM还为它分配一个随机数。 + +- 停止recording + + 命令格式:` jcmd process_id JFR.stop [options_list]`,其中options_list参数的可选值如下: + + - `name=name`:要停止的recording名字 + - `recording=n`:要停止的recording的标识数字 + - `discard=boolean`:如果为true,数据被丢弃,而不是写入下面指定的文件当中 + - `filename=path`:写入数据的文件名称 + + + +### 命令启动JFR案例 + +- **第一步**:创建一个包含了你自己配置的JFR模板文件(`template.jfc`)。运行jmc, 然后Window->Flight Recording Template Manage菜单。准备好档案后,就可以导出文件,并移动到要排查问题的环境中 + + ![jmc-jfc](images/JVM/jmc-jfc.png) + +- **第二步**:由于JFR需要JDK的商业证书,这一步需要解锁jdk的商业特性 + + ```powershell + [root@localhost bin]# jcmd 12234 VM.unlock_commercial_features + 12234: Commercial Features already unlocked. + ``` + +- **第三步**:最后你就可以启动JFR,命令格式如下: + + ```powershell + jcmd JFR.start name=test duration=60s [settings=template.jfc] filename=output.jfr + ``` + + ​ 上述命令立即启动JFR并开始使用 `template.jfc`(在 `$JAVA_HOME/jre/lib/jfr` 下有 `default.jfc` 和 `profile.jfc` 模板)的配置收集 `60s` 的JVM信息,输出到 `output.jfr` 中。一旦记录完成之后,就可以复制.jfr文件到你的工作环境使用jmc GUI来分析。它几乎包含了排查jvm问题需要的所有信息,包括堆dump时的异常信息。使用案例如下: + + ```powershell + [root@localhost bin]# jcmd 12234 JFR.start name=test duration=60s filename=output.jfr + 12234: Started recording 6. The result will be written to: /root/zookeeper-3.4.12/bin/output.jfr + [root@localhost bin]# ls -l + -rw-r--r-- 1 root root 298585 6月 29 11:09 output.jfr + ``` + + + +**JFR(Java Flight Recorder)** + +- Java Mission Control的最主要的特征就是Java Flight Recorder。正如它的名字所示,JFR的数据是一些列JVM事件的历史纪录,可以用来诊断JVM的性能和操作 +- JFR的基本操作就是开启哪些事件(比如:线程由于等待锁而阻塞的事件)。当开启的事件发生了,事件相关的数据会记录到内存或磁盘文件上。记录事件数据的缓存是循环使用的,只有最近发生的事件才能够从缓存中找到,之前的都因为缓存的限制被删除了。Java Mission Control能够对这些事件在界面上进行展示(从JVM的内存中读取或从事件数据文件中读取),我们可以通过这些事件来对JVM的性能进行诊断 +- 事件的类型、缓存的大小、事件数据的存储方式等等都是通过JVM参数、Java Mission Control的GUI界面、jcmd命令来控制的。JFR默认是编译进程序的,因为它的开销很小,一般来说对应用的影响小于1%。不过,如果我们增加了事件的数目、修改了记录事件的阈值,都有可能增加JFR的开销 + + + +### JFR概况 + +​ 下面对GlassFish web服务器进行JFR记录的例子,在这个服务器上面运行着在第2章介绍的股票servlet。Java Mission Control加载完JFR获取的事件之后,大概是下面这个样子: + +![jfr-main](images/JVM/jfr-main.jpg) + +我们可以看到,通过上图可以看到:CPU使用率,Heap使用率,JVM信息,System Properties,JFR的记录情况等等。 + + + +### JFR内存视图 + +Java Mission Control 可以看到非常多的信息,下图只显示了一个标签的内容。下图显示了JVM 的内存波动非常频繁,因为新生代经常被清除(有意思的是,head的大小并没有增长)。下面左边的面板显示了最近一段时间的垃圾回收情况,包括:GC的时长和垃圾回收的类型。如果我们点击一个事件,右边的面板会展示这个事件的具体情况,包括:垃圾垃圾回收的各个阶段及其统计信息。从面板的标签可以看到,还有很多其它信息,比如:有多少对象被清除了,花了多长时间;GC算法的配置;分配的对象信息等等。在第5章和第6章中,我们会详细介绍。 + +![jfr-memory](images/JVM/jfr-memory.jpg) + + + +### JFR 代码视图 + +这张图也有很多tab,可以看到各个包的使用频率和类的使用情况、异常、编译、代码缓存、类加载情况等等: + +![jfr-code](images/JVM/jfr-code.jpg) + + + +### JFR事件视图 + +下图显示了事件的概述视图: + +![jfr-event](images/JVM/jfr-event.jpg) \ No newline at end of file diff --git a/src/JVM/409.md b/src/JVM/409.md new file mode 100644 index 0000000..b32203d --- /dev/null +++ b/src/JVM/409.md @@ -0,0 +1,252 @@ +虽然Java虚拟机可以帮我们对内存进行回收,但是其回收的是Java虚拟机不再引用的对象。很多时候我们使用系统的IO流、Cursor、Receiver如果不及时释放,就会导致内存泄漏(OOM)。但是,很多时候内存泄漏的现象不是很明显,比如内部类、Handler相关的使用导致的内存泄漏,或者你使用了第三方library的一些引用,比较消耗资源,但又不是像系统资源那样会引起你足够的注意去手动释放它们。以下通过内存泄漏分析、集合使用率、Hash性能分析和OQL快读定位空集合来使用MAT。 + + + +**GC Roots** + +JAVA虚拟机通过可达性(Reachability)来判断对象是否存活,基本思想:`以”GC Roots”的对象作为起始点向下搜索,搜索形成的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(即不可达的),则该对象被判定为可以被回收的对象,反之不能被回收`。GC Roots可以是以下任意对象 + +- 一个在current thread(当前线程)的call stack(调用栈)上的对象(如方法参数和局部变量) +- 线程自身或者system class loader(系统类加载器)加载的类 +- native code(本地代码)保留的活动对象 + + + +**内存泄漏** + +当对象无用了,但仍然可达(未释放),垃圾回收器无法回收。 + + + +**Java四种引用类型** + +- Strong References(强引用) + + 普通的java引用,我们通常new的对象就是:`StringBuffer buffer = new StringBuffer();` 如果一个对象通过一串强引用链可达,那么它就不会被垃圾回收。你肯定不希望自己正在使用的引用被垃圾回收器回收吧。但对于集合中的对象,应在不使用的时候移除掉,否则会占用更多的内存,导致内存泄漏。 + +- Soft Reference(软引用) + + 当对象是Soft Reference可达时,gc会向系统申请更多内存,而不是直接回收它,当内存不足的时候才回收它。因此Soft Reference适合用于构建一些缓存系统,比如图片缓存。 + +- Weak Reference(弱引用) + + WeakReference不会强制对象保存在内存中。它拥有比较短暂的生命周期,允许你使用垃圾回收器的能力去权衡一个对象的可达性。在垃圾回收器扫描它所管辖的内存区域过程中,一旦gc发现对象是Weak Reference可达,就会把它放到 `Reference Queue` 中,等下次gc时回收它。 + + 系统为我们提供了WeakHashMap,和HashMap类似,只是其key使用了weak reference。如果WeakHashMap的某个key被垃圾回收器回收,那么entity也会自动被remove。由于WeakReference被GC回收的可能性较大,因此,在使用它之前,你需要通过weakObj.get()去判断目的对象引用是否已经被回收。一旦WeakReference.get()返回null,它指向的对象就会被垃圾回收,那么WeakReference对象就没有用了,意味着你应该进行一些清理。比如在WeakHashMap中要把回收过的key从Map中删除掉,避免无用的的weakReference不断增长。 + + ReferenceQueue可以让你很容易地跟踪dead references。WeakReference类的构造函数有一个ReferenceQueue参数,当指向的对象被垃圾回收时,会把WeakReference对象放到ReferenceQueue中。这样,遍历ReferenceQueue可以得到所有回收过的WeakReference。 + +- Phantom Reference(虚引用) + + 其余Soft/Weak Reference区别较大是它的get()方法总是返回null。这意味着你只能用Phantom Reference本身,而得不到它指向的对象。当Weak Reference指向的对象变得弱可达(weakly reachable)时会立即被放到ReferenceQueue中,这在finalization、garbage collection之前发生。理论上,你可以在finalize()方法中使对象“复活”(使一个强引用指向它就行了,gc不会回收它)。但没法复活PhantomReference指向的对象。而PhantomReference是在garbage collection之后被放到ReferenceQueue中的,没法复活。 + + + +**MAT视图与概念** + +- **Shallow Heap** + + Shallow Size就是对象本身占用内存的大小,不包含其引用的对象内存,实际分析中作用不大。 常规对象(非数组)的Shallow Size由其成员变量的数量和类型决定。数组的Shallow Size有数组元素的类型(对象类型、基本类型)和数组长度决定。案例如下: + +```java +public class String { + public final class String {8 Bytes header + private char value[]; 4 Bytes + private int offset; 4 Bytes + private int count; 4 Bytes + private int hash = 0; 4 Bytes + // ...... +} +// "Shallow size“ of a String ==24 Bytes12345678 +``` + +Java的对象成员都是些引用。真正的内存都在堆上,看起来是一堆原生的byte[]、char[]、int[],对象本身的内存都很小。所以我们可以看到以Shallow Heap进行排序的Histogram图中,排在第一位第二位的是byte和char。 + + + +- **Retained Heap** + + Retained Heap值的计算方式是将Retained Set中的所有对象大小叠加。或者说,由于X被释放,导致其它所有被释放对象(包括被递归释放的)所占的Heap大小。当X被回收时哪些将被GC回收的对象集合。比如: + + 一个ArrayList持有100000个对象,每一个占用16 bytes,移除这些ArrayList可以释放16×100000+X,X代表ArrayList的Shallow大小。相对于Shallow Heap,Retained Heap可以更精确的反映一个对象实际占用的大小(因为如果该对象释放,Retained Heap都可以被释放)。 + + + +- **Histogram** + + 可列出每一个类的实例数。支持正则表达式查找,也可以计算出该类所有对象的Retained Size。 + +![mat-histogram](images/JVM/mat-histogram.jpg) + + + +- **Dominator Tree** + + 对象之间dominator关系树。如果从GC Root到达Y的的所有path都经过X,那么我们称X dominates Y,或者X是Y的Dominator Dominator Tree由系统中复杂的对象图计算而来。从MAT的dominator tree中可以看到占用内存最大的对象以及每个对象的dominator。 我们也可以右键选择Immediate Dominator”来查看某个对象的dominator。 + +![mat-dominator-tree](images/JVM/mat-dominator-tree.jpg) + + + +- **Path to GC Roots** + + ​ 查看一个对象到RC Roots的引用链通常在排查内存泄漏的时候,我们会选择exclude all phantom/weak/soft etc.references, + 意思是查看排除虚引用/弱引用/软引用等的引用链,因为被虚引用/弱引用/软引用的对象可以直接被GC给回收,我们要看的就是某个对象否还存在Strong 引用链(在导出HeapDump之前要手动出发GC来保证),如果有,则说明存在内存泄漏,然后再去排查具体引用。 + + ![mat-path-to-gc-roots](images/JVM/mat-path-to-gc-roots.jpg) + + 查看当前Object所有引用,被引用的对象: + + - List objects with (以Dominator Tree的方式查看) + - incoming references 引用到该对象的对象 + - outcoming references 被该对象引用的对象 + - Show objects by class (以class的方式查看) + - incoming references 引用到该对象的对象 + - outcoming references 被该对象引用的对象 + + + +- **OQL(Object Query Language)** + +类似SQL查询语言:Classes:Table、Objects:Rows、Fileds:Cols + +```mysql +select * from com.example.mat.Listener +# 查找size=0并且未使用过的ArrayList +select * from java.util.ArrayList where size=0 and modCount=01 +# 查找所有的Activity +select * from instanceof android.app.Activity +``` + + + +- **内存快照对比** + +方式一:Compare To Another Heap Dump(直接进行比较) + +![mat-compare-to-another-heap-dump-1](images/JVM/mat-compare-to-another-heap-dump-1.jpg) + +![mat-compare-to-another-heap-dump-2](images/JVM/mat-compare-to-another-heap-dump-2.jpg) + +![mat-compare-to-another-heap-dump-3](images/JVM/mat-compare-to-another-heap-dump-3.jpg) + + + +方式二:Compare Baseket(更全面,可以直接给出百分比) + +![mat-compare-baseket-1](images/JVM/mat-compare-baseket-1.jpg) + +![mat-compare-baseket-2](images/JVM/mat-compare-baseket-2.jpg) + +![mat-compare-baseket-3](images/JVM/mat-compare-baseket-3.jpg) + +![mat-compare-baseket-4](images/JVM/mat-compare-baseket-4.jpg) + + + +**MAT内存分析实战** + +- **实战一:内存泄漏分析** + + 查找导致内存泄漏的类。既然环境已经搭好,heap dump也成功倒入,接下来就去分析问题。 + + - 查找目标类 + 如果在开发过程中,你的目标很明确,比如就是查找自己负责的服务,那么通过包名或者Class筛选,OQL搜索都可以快速定位到。点击OQL图标,在窗口输入,并按Ctrl + F5或者!按钮执行: + + `select * from instanceof android.app.Activity` + + - Paths to GC Roots:exclude all phantom/weak/soft etc.references + + 查看一个对象到RC Roots是否存在引用链。要将虚引用/弱引用/软引用等排除,因为被虚引用/弱引用/软引用的对象可以直接被GC给回收 + + - 分析具体的引用为何没有被释放,并进行修复 + + + +**小技巧:** + +- 当目的不明确时,可以直接定位到RetainedHeap最大的Object,Select incoming references,查看引用链,定位到可疑的对象然后Path to GC Roots进行引用链分析 +- 如果大对象筛选看不出区别,可以试试按照class分组,再寻找可疑对象进行GC引用链分析 +- 直接按照包名直接查看GC引用链,可以一次性筛选多个类,但是如下图所示,选项是 Merge Shortest Path to GCRoots,这个选项具体不是很明白,不过也能筛选出存在GC引用链的类,这种方式的准确性还待验证 + +![mat-实践一](images/JVM/mat-实践一.jpg) + +所以有时候进行MAT分析还是需要一些经验,能够帮你更快更准确的定位。 + + + +- **实战二:集合使用率分析** + + 集合在开发中会经常使用到,如何选择合适的数据结构的集合,初始容量是多少(太小,可能导致频繁扩容),太大,又会开销跟多内存。当这些问题不是很明确时或者想查看集合的使用情况时,可以通过MAT来进行分析。 + + - **筛选目标对象** + + ![mat-实践二-1](images/JVM/mat-实践二-1.jpg) + + - **Show Retained Set(查找当X被回收时那些将被GC回收的对象集合)** + + ![mat-实践二-2](images/JVM/mat-实践二-2.jpg) + + - **筛选指定的Object(Hash Map,ArrayList)并按照大小进行分组** + + ![mat-实践二-3](images/JVM/mat-实践二-3.jpg) + + - **查看指定类的Immediate dominators** + + ![mat-实践二-4](images/JVM/mat-实践二-4.jpg) + + + +**Collections fill ratio** + +这种方式只能查看那些具有预分配内存能力的集合,比如HashMap,ArrayList。计算方式:”size / capacity” + +![mat-实践二-5](images/JVM/mat-实践二-5.jpg) + +![mat-实践二-6](images/JVM/mat-实践二-6.jpg) + + + +- **实战三:Hash相关性能分析** + + 当Hash集合中过多的对象返回相同Hash值的时候,会严重影响性能(Hash算法原理自行搜索),这里来查找导致Hash集合的碰撞率较高的罪魁祸首。 + + - **Map Collision Ratio** + + 检测每一个HashMap或者HashTable实例并按照碰撞率排序:**碰撞率 = 碰撞的实体/Hash表中所有实体** + + ![mat-实践三-1](images/JVM/mat-实践三-1.jpg) + + - **查看Immediate dominators** + + ![mat-实践三-2](images/JVM/mat-实践三-2.jpg) + + ![mat-实践三-3](images/JVM/mat-实践三-3.jpg) + + - **通过HashEntries查看key value** + + ![mat-实践三-4](images/JVM/mat-实践三-4.jpg) + + - **Array等其它集合分析方法类似** + + + +- **实战四:通过OQL快速定位未使用的集合** + + - **通过OQL查询empty并且未修改过的集合:** + + ```mysql + select * from java.util.ArrayList where size=0 and modCount=01 + select * from java.util.HashMap where size=0 and modCount=0 + select * from java.util.Hashtable where count=0 and modCount=012 + ``` + + ![mat-实践四-1](images/JVM/mat-实践四-1.jpg) + + - **Immediate dominators(查看引用者)** + + ![mat-实践四-2](images/JVM/mat-实践四-2.jpg) + + - **计算空集合的Retained Size值,查看浪费了多少内存** + + ![mat-实践四-3](images/JVM/mat-实践四-3.jpg) \ No newline at end of file diff --git a/src/JVM/410.md b/src/JVM/410.md new file mode 100644 index 0000000..07005bc --- /dev/null +++ b/src/JVM/410.md @@ -0,0 +1,125 @@ +火焰图是用来分析程序运行瓶颈的工具。火焰图也可以用来分析 Java 应用。 + +### 环境安装 + +确认你的机器已经安装了**git、jdk、perl、c++编译器**。 + +#### 安装Perl + +```shell +wget http://www.cpan.org/src/5.0/perl-5.26.1.tar.gz +tar zxvf perl-5.26.1.tar.gz +cd perl-5.26.1 +./Configure -de +make +make test +make install +``` + +wget后面的路径可以按需更改。安装过程比较耗时间,安装完成后可通过**perl -version**查看是否安装成功。 + + + +#### C++编译器 + +```shell +apt-get install g++ +``` + +一般用于编译c++程序,缺少这个编译器进行make编译c++代码时,会报“g++: not found”的错误。 + + + +#### clone相关项目 + +下载下来所需要的两个项目(这里建议放到data目录下): + +```shell +git clone https://github.com/jvm-profiling-tools/async-profiler +git clone https://github.com/brendangregg/FlameGraph +``` + + + +#### 编译项目 + +下载好以后,需要打开async-profiler文件,输入make指令进行编译: + +```shell +cd async-profiler +make +``` + + + +### 生成文件 + +#### 生成火焰图数据 + +可以从 github 上下载 [async-profiler](https://github.com/jvm-profiling-tools/async-profiler) 的压缩包进行相关操作。进入async-profiler项目的目录下,然后输入如下指令: + +```shell +./profiler.sh -d 60 -o collapsed -f /tmp/test_01.txt ${pid} +``` + +上面的-d表示的是持续时长,后面60代表持续采集时间60s,-o表示的是采集规范,这里用的是collapsed,-f后面的路径,表示的是数据采集后生成的数据存放的文件路径(这里放在了/tmp/test_01.txt),${pid}表示的是采集目标进程的pid,回车运行,运行期间阻塞,知道约定时间完成。运行完成后去tmp下看看有没有对应文件。 + + + +#### 生成svg文件 + +上一步产生的文件里的内容,肉眼是很难看懂的,所以现在[FlameGraph](https://github.com/brendangregg/FlameGraph)的作用就体现出来了,它可以读取该文件并生成直观的火焰图,现在进入该项目目录下面,执行如下语句: + +```shell +perl flamegraph.pl --colors=java /tmp/test_01.txt > test_01.svg +``` + +因为是perl文件,这里使用perl指令运行该文件,后面--colors表示着色风格,这里是java,后面的是数据文件的路径,这里是刚刚上面生成的那个文件/tmp/test_01.txt,最后的test_01.svg就是最终生成的火焰图文件存放的路径和文件命名,这里是命名为test_01.svg并保存在当前路径,运行后看到该文件已经存在于当前目录下。 + + + +#### 展示火焰图 + +现在下载下来该文件,使用浏览器打开,效果如下: + +![火焰图案例](images/JVM/火焰图案例.svg) + + + +### 火焰图案例 + +生成的[火焰图案例](images/DevOps/火焰图案例.svg)如下: + +![火焰图案例](images/JVM/火焰图案例.jpg) + +#### 瓶颈点1 + +CoohuaAnalytics$KafkaConsumer:::send方法中Gzip压缩占比较高。已经定位到方法级别,再看代码就快速很多,直接找到具体位置,找到第一个消耗大户:**Gzip压缩** + +![火焰图-瓶颈点1](images/JVM/火焰图-瓶颈点1.jpg) + + + +#### 瓶颈点2 + +展开2这个波峰,查看到这个getOurStackTrace方法占用了大比例的CPU,怀疑代码里面频繁用丢异常的方式获取当前代码栈: + +![火焰图-瓶颈点2](images/JVM/火焰图-瓶颈点2.jpg) + +直接看代码: + +![火焰图-瓶颈点2-代码](images/JVM/火焰图-瓶颈点2-代码.jpg) + +果然如推断,找到第二个CPU消耗大户:new Exception().getStackTrace()。 + + + +#### 瓶颈点3 + +展开波峰3,可以看到是这个Gzip解压缩: + +![火焰图-瓶颈点3](images/JVM/火焰图-瓶颈点3.jpg) + +定位到具体的代码,可以看到对每个请求的参数进行了gzip解压缩: + +![火焰图-瓶颈点3-代码](images/JVM/火焰图-瓶颈点3-代码.jpg) \ No newline at end of file diff --git a/src/JVM/README.md b/src/JVM/README.md new file mode 100644 index 0000000..40f9db8 --- /dev/null +++ b/src/JVM/README.md @@ -0,0 +1,9 @@ +
JVM
+ +Introduction:收纳技术相关的JVM知识等总结! + +心法:`数据结构` + `算法` + `操作系统` + `计网` + `底层`Tools`、`Linux Tools`、`Git` 等总结! + +[大吉大利 :空投十个JVM核心知识点,速度捡包](https://mp.weixin.qq.com/s?__biz=MzI4NjI1OTI4Nw==&mid=2247489183&idx=1&sn=02ab3551c473bd2c8429862e3689a94b&chksm=ebdef7a7dca97eb17194c3d935c86ade240d3d96bbeaf036233a712832fb94af07adeafa098b&mpshare=1&scene=23&srcid=0812OQ78gD47QJEguFGixUVa&sharer_sharetime=1628761112690&sharer_shareid=0f9991a2eb945ab493c13ed9bfb8bf4b#rd) + +## 🚀点击左侧菜单栏开始吧! \ No newline at end of file diff --git a/src/JVM/_sidebar.md b/src/JVM/_sidebar.md new file mode 100644 index 0000000..98d76b8 --- /dev/null +++ b/src/JVM/_sidebar.md @@ -0,0 +1,41 @@ +* 🏁 Classloader + * [✍ 类加载机制](src/JVM/1 "类加载机制") + * [✍ 类加载器](src/JVM/2 "类加载器") + * [✍ 双亲委派](src/JVM/3 "双亲委派") +* 🏁 JVM + * [✍ JAVA内存模型](src/JVM/101 "JAVA内存模型") + * [✍ JVM内存结构](src/JVM/102 "JVM内存结构") + * [✍ JVM内存模型](src/JVM/103 "JVM内存模型") + * [✍ JVM运行时内存](src/JVM/104 "JVM运行时内存") + * [✍ 引用级别](src/JVM/105 "引用级别") + * [✍ OOM](src/JVM/106 "OOM") +* 🏁 GC + * [✍ 寻找垃圾算法](src/JVM/201 "寻找垃圾算法") + * [✍ 清理垃圾算法](src/JVM/202 "清理垃圾算法") + * [✍ GC垃圾收集器](src/JVM/203 "GC垃圾收集器") + * [✍ GC日志](src/JVM/204 "GC日志") + * [✍ GC场景](src/JVM/205 "GC场景") +* 🏁 JVM性能调优 + * [✍ 磁盘不足排查](src/JVM/301 "磁盘不足排查") + * [✍ CPU过高排查](src/JVM/302 "CPU过高排查") + * [✍ 内存打满排查](src/JVM/303 "内存打满排查") + * [✍ OOM异常排查](src/JVM/304 "OOM异常排查") + * [✍ Jvisualvm](src/JVM/305 "Jvisualvm") + * [✍ 调优堆内存分配](src/JVM/306 "调优堆内存分配") + * [✍ 年轻代调优](src/JVM/307 "年轻代调优") + * [✍ 老年代调优](src/JVM/308 "老年代调优") + * [✍ 栈溢出](src/JVM/309 "栈溢出") + * [✍ 死锁排查](src/JVM/310 "死锁排查") + * [✍ 调优实战](src/JVM/311 "调优实战") + * [✍ 调优参数](src/JVM/312 "调优参数") +* 🏁 JDK Tools + * [✍ jps](src/JVM/401 "jps") + * [✍ jstat](src/JVM/402 "jstat") + * [✍ jstack](src/JVM/403 "jstack") + * [✍ jmap](src/JVM/404 "jmap") + * [✍ jhat](src/JVM/405 "jhat") + * [✍ jconsole](src/JVM/406 "jconsole") + * [✍ jvisualvm](src/JVM/407 "jvisualvm") + * [✍ jmc](src/JVM/408 "jmc") + * [✍ EclipseMAT](src/JVM/409 "EclipseMAT") + * [✍ 🔥火焰图](src/JVM/410 "🔥火焰图") \ No newline at end of file diff --git a/src/JVM/images/JVM/20200119164633443.png b/src/JVM/images/JVM/20200119164633443.png new file mode 100644 index 0000000..0d5ae79 Binary files /dev/null and b/src/JVM/images/JVM/20200119164633443.png differ diff --git a/src/JVM/images/JVM/20200119164639576.png b/src/JVM/images/JVM/20200119164639576.png new file mode 100644 index 0000000..7d51f97 Binary files /dev/null and b/src/JVM/images/JVM/20200119164639576.png differ diff --git a/src/JVM/images/JVM/20200119164640148.png b/src/JVM/images/JVM/20200119164640148.png new file mode 100644 index 0000000..b4b5118 Binary files /dev/null and b/src/JVM/images/JVM/20200119164640148.png differ diff --git a/src/JVM/images/JVM/20200119164641390.png b/src/JVM/images/JVM/20200119164641390.png new file mode 100644 index 0000000..7801ea2 Binary files /dev/null and b/src/JVM/images/JVM/20200119164641390.png differ diff --git a/src/JVM/images/JVM/20200119164749513.png b/src/JVM/images/JVM/20200119164749513.png new file mode 100644 index 0000000..693f1b0 Binary files /dev/null and b/src/JVM/images/JVM/20200119164749513.png differ diff --git a/src/JVM/images/JVM/20200119164751943.png b/src/JVM/images/JVM/20200119164751943.png new file mode 100644 index 0000000..c6d0f32 Binary files /dev/null and b/src/JVM/images/JVM/20200119164751943.png differ diff --git a/src/JVM/images/JVM/20200119164752266.png b/src/JVM/images/JVM/20200119164752266.png new file mode 100644 index 0000000..52971a2 Binary files /dev/null and b/src/JVM/images/JVM/20200119164752266.png differ diff --git a/src/JVM/images/JVM/2020011916475242.png b/src/JVM/images/JVM/2020011916475242.png new file mode 100644 index 0000000..cceb92c Binary files /dev/null and b/src/JVM/images/JVM/2020011916475242.png differ diff --git a/src/JVM/images/JVM/2020011916490666.png b/src/JVM/images/JVM/2020011916490666.png new file mode 100644 index 0000000..0738830 Binary files /dev/null and b/src/JVM/images/JVM/2020011916490666.png differ diff --git a/src/JVM/images/JVM/20200119164911457.png b/src/JVM/images/JVM/20200119164911457.png new file mode 100644 index 0000000..3406749 Binary files /dev/null and b/src/JVM/images/JVM/20200119164911457.png differ diff --git a/src/JVM/images/JVM/20200119164911559.png b/src/JVM/images/JVM/20200119164911559.png new file mode 100644 index 0000000..127d5a9 Binary files /dev/null and b/src/JVM/images/JVM/20200119164911559.png differ diff --git a/src/JVM/images/JVM/20200119164911817.png b/src/JVM/images/JVM/20200119164911817.png new file mode 100644 index 0000000..3bee7e1 Binary files /dev/null and b/src/JVM/images/JVM/20200119164911817.png differ diff --git a/src/JVM/images/JVM/20200119164912355.png b/src/JVM/images/JVM/20200119164912355.png new file mode 100644 index 0000000..5c01bae Binary files /dev/null and b/src/JVM/images/JVM/20200119164912355.png differ diff --git a/src/JVM/images/JVM/20200119164912847.png b/src/JVM/images/JVM/20200119164912847.png new file mode 100644 index 0000000..09040c4 Binary files /dev/null and b/src/JVM/images/JVM/20200119164912847.png differ diff --git a/src/JVM/images/JVM/20200119164913228.png b/src/JVM/images/JVM/20200119164913228.png new file mode 100644 index 0000000..38e6e2a Binary files /dev/null and b/src/JVM/images/JVM/20200119164913228.png differ diff --git a/src/JVM/images/JVM/CMSGC单次STW长.png b/src/JVM/images/JVM/CMSGC单次STW长.png new file mode 100644 index 0000000..adc9d88 Binary files /dev/null and b/src/JVM/images/JVM/CMSGC单次STW长.png differ diff --git a/src/JVM/images/JVM/CMSOldGC频繁.png b/src/JVM/images/JVM/CMSOldGC频繁.png new file mode 100644 index 0000000..b4ca2f7 Binary files /dev/null and b/src/JVM/images/JVM/CMSOldGC频繁.png differ diff --git a/src/JVM/images/JVM/CMS收集器.png b/src/JVM/images/JVM/CMS收集器.png new file mode 100644 index 0000000..667910a Binary files /dev/null and b/src/JVM/images/JVM/CMS收集器.png differ diff --git a/src/JVM/images/JVM/CPU过高排查-jstack.jpg b/src/JVM/images/JVM/CPU过高排查-jstack.jpg new file mode 100644 index 0000000..b07c101 Binary files /dev/null and b/src/JVM/images/JVM/CPU过高排查-jstack.jpg differ diff --git a/src/JVM/images/JVM/CPU过高排查-printf.jpg b/src/JVM/images/JVM/CPU过高排查-printf.jpg new file mode 100644 index 0000000..cf0311c Binary files /dev/null and b/src/JVM/images/JVM/CPU过高排查-printf.jpg differ diff --git a/src/JVM/images/JVM/CPU过高排查-top-Hp-pid.jpg b/src/JVM/images/JVM/CPU过高排查-top-Hp-pid.jpg new file mode 100644 index 0000000..786a4eb Binary files /dev/null and b/src/JVM/images/JVM/CPU过高排查-top-Hp-pid.jpg differ diff --git a/src/JVM/images/JVM/CPU过高排查-top.jpg b/src/JVM/images/JVM/CPU过高排查-top.jpg new file mode 100644 index 0000000..4a50542 Binary files /dev/null and b/src/JVM/images/JVM/CPU过高排查-top.jpg differ diff --git a/src/JVM/images/JVM/Classloader.png b/src/JVM/images/JVM/Classloader.png new file mode 100644 index 0000000..138e0bd Binary files /dev/null and b/src/JVM/images/JVM/Classloader.png differ diff --git a/src/JVM/images/JVM/FullGC变化比例大.png b/src/JVM/images/JVM/FullGC变化比例大.png new file mode 100644 index 0000000..3aefbd8 Binary files /dev/null and b/src/JVM/images/JVM/FullGC变化比例大.png differ diff --git a/src/JVM/images/JVM/G1-Region.png b/src/JVM/images/JVM/G1-Region.png new file mode 100644 index 0000000..8e5dd78 Binary files /dev/null and b/src/JVM/images/JVM/G1-Region.png differ diff --git a/src/JVM/images/JVM/G1收集器.jpg b/src/JVM/images/JVM/G1收集器.jpg new file mode 100644 index 0000000..c1f08cf Binary files /dev/null and b/src/JVM/images/JVM/G1收集器.jpg differ diff --git a/src/JVM/images/JVM/JAVA内存模型.jpg b/src/JVM/images/JVM/JAVA内存模型.jpg new file mode 100644 index 0000000..7229a98 Binary files /dev/null and b/src/JVM/images/JVM/JAVA内存模型.jpg differ diff --git a/src/JVM/images/JVM/JAVA虚拟机栈.png b/src/JVM/images/JVM/JAVA虚拟机栈.png new file mode 100644 index 0000000..386f5a7 Binary files /dev/null and b/src/JVM/images/JVM/JAVA虚拟机栈.png differ diff --git a/src/JVM/images/JVM/JConsole-Console.png b/src/JVM/images/JVM/JConsole-Console.png new file mode 100644 index 0000000..bb2b907 Binary files /dev/null and b/src/JVM/images/JVM/JConsole-Console.png differ diff --git a/src/JVM/images/JVM/JConsole-新建连接.png b/src/JVM/images/JVM/JConsole-新建连接.png new file mode 100644 index 0000000..71787b7 Binary files /dev/null and b/src/JVM/images/JVM/JConsole-新建连接.png differ diff --git a/src/JVM/images/JVM/JMM.png b/src/JVM/images/JVM/JMM.png new file mode 100644 index 0000000..4cdf8fb Binary files /dev/null and b/src/JVM/images/JVM/JMM.png differ diff --git a/src/JVM/images/JVM/JVM-磁盘不足排查-du-sh.jpg b/src/JVM/images/JVM/JVM-磁盘不足排查-du-sh.jpg new file mode 100644 index 0000000..b16d6a2 Binary files /dev/null and b/src/JVM/images/JVM/JVM-磁盘不足排查-du-sh.jpg differ diff --git a/src/JVM/images/JVM/JVM-磁盘不足排查.jpg b/src/JVM/images/JVM/JVM-磁盘不足排查.jpg new file mode 100644 index 0000000..b87a8cb Binary files /dev/null and b/src/JVM/images/JVM/JVM-磁盘不足排查.jpg differ diff --git a/src/JVM/images/JVM/JVM内存伸缩模型.png b/src/JVM/images/JVM/JVM内存伸缩模型.png new file mode 100644 index 0000000..dfff727 Binary files /dev/null and b/src/JVM/images/JVM/JVM内存伸缩模型.png differ diff --git a/src/JVM/images/JVM/JVM内存结构(JDK1.6).png b/src/JVM/images/JVM/JVM内存结构(JDK1.6).png new file mode 100644 index 0000000..7459e45 Binary files /dev/null and b/src/JVM/images/JVM/JVM内存结构(JDK1.6).png differ diff --git a/src/JVM/images/JVM/JVM内存结构(JDK1.7).png b/src/JVM/images/JVM/JVM内存结构(JDK1.7).png new file mode 100644 index 0000000..c953132 Binary files /dev/null and b/src/JVM/images/JVM/JVM内存结构(JDK1.7).png differ diff --git a/src/JVM/images/JVM/JVM内存结构(JDK1.8).png b/src/JVM/images/JVM/JVM内存结构(JDK1.8).png new file mode 100644 index 0000000..f5abeae Binary files /dev/null and b/src/JVM/images/JVM/JVM内存结构(JDK1.8).png differ diff --git a/src/JVM/images/JVM/JVM堆内存划分.png b/src/JVM/images/JVM/JVM堆内存划分.png new file mode 100644 index 0000000..7dbbdb9 Binary files /dev/null and b/src/JVM/images/JVM/JVM堆内存划分.png differ diff --git a/src/JVM/images/JVM/JVM对象申请空间流程.png b/src/JVM/images/JVM/JVM对象申请空间流程.png new file mode 100644 index 0000000..2e1a568 Binary files /dev/null and b/src/JVM/images/JVM/JVM对象申请空间流程.png differ diff --git a/src/JVM/images/JVM/JVM架构.png b/src/JVM/images/JVM/JVM架构.png new file mode 100644 index 0000000..c0a7c8b Binary files /dev/null and b/src/JVM/images/JVM/JVM架构.png differ diff --git a/src/JVM/images/JVM/JVM类加载机制.png b/src/JVM/images/JVM/JVM类加载机制.png new file mode 100644 index 0000000..6312a67 Binary files /dev/null and b/src/JVM/images/JVM/JVM类加载机制.png differ diff --git a/src/JVM/images/JVM/OOM异常排查-查看实例最多的类.jpg b/src/JVM/images/JVM/OOM异常排查-查看实例最多的类.jpg new file mode 100644 index 0000000..148ec22 Binary files /dev/null and b/src/JVM/images/JVM/OOM异常排查-查看实例最多的类.jpg differ diff --git a/src/JVM/images/JVM/OOM异常排查-查看异常代码.jpg b/src/JVM/images/JVM/OOM异常排查-查看异常代码.jpg new file mode 100644 index 0000000..9e2b0bd Binary files /dev/null and b/src/JVM/images/JVM/OOM异常排查-查看异常代码.jpg differ diff --git a/src/JVM/images/JVM/OOM异常排查-查看异常代码堆栈.jpg b/src/JVM/images/JVM/OOM异常排查-查看异常代码堆栈.jpg new file mode 100644 index 0000000..109fe41 Binary files /dev/null and b/src/JVM/images/JVM/OOM异常排查-查看异常代码堆栈.jpg differ diff --git a/src/JVM/images/JVM/ParNew收集器.jpg b/src/JVM/images/JVM/ParNew收集器.jpg new file mode 100644 index 0000000..57aeefc Binary files /dev/null and b/src/JVM/images/JVM/ParNew收集器.jpg differ diff --git a/src/JVM/images/JVM/ParallelGCFullGC日志.jpg b/src/JVM/images/JVM/ParallelGCFullGC日志.jpg new file mode 100644 index 0000000..60d4f98 Binary files /dev/null and b/src/JVM/images/JVM/ParallelGCFullGC日志.jpg differ diff --git a/src/JVM/images/JVM/ParallelGCYoungGC日志.jpg b/src/JVM/images/JVM/ParallelGCYoungGC日志.jpg new file mode 100644 index 0000000..077e855 Binary files /dev/null and b/src/JVM/images/JVM/ParallelGCYoungGC日志.jpg differ diff --git a/src/JVM/images/JVM/ParallelOld收集器.jpg b/src/JVM/images/JVM/ParallelOld收集器.jpg new file mode 100644 index 0000000..70fce8c Binary files /dev/null and b/src/JVM/images/JVM/ParallelOld收集器.jpg differ diff --git a/src/JVM/images/JVM/RuntimeDataArea.png b/src/JVM/images/JVM/RuntimeDataArea.png new file mode 100644 index 0000000..8c35e73 Binary files /dev/null and b/src/JVM/images/JVM/RuntimeDataArea.png differ diff --git a/src/JVM/images/JVM/SerialOld收集器.jpg b/src/JVM/images/JVM/SerialOld收集器.jpg new file mode 100644 index 0000000..ee11c7b Binary files /dev/null and b/src/JVM/images/JVM/SerialOld收集器.jpg differ diff --git a/src/JVM/images/JVM/Serial收集器.jpg b/src/JVM/images/JVM/Serial收集器.jpg new file mode 100644 index 0000000..ee11c7b Binary files /dev/null and b/src/JVM/images/JVM/Serial收集器.jpg differ diff --git a/src/JVM/images/JVM/Shenandoah收集器运行流程.jpg b/src/JVM/images/JVM/Shenandoah收集器运行流程.jpg new file mode 100644 index 0000000..c6b089b Binary files /dev/null and b/src/JVM/images/JVM/Shenandoah收集器运行流程.jpg differ diff --git a/src/JVM/images/JVM/Visual-GC.png b/src/JVM/images/JVM/Visual-GC.png new file mode 100644 index 0000000..23d964c Binary files /dev/null and b/src/JVM/images/JVM/Visual-GC.png differ diff --git a/src/JVM/images/JVM/ZGC内存布局.jpg b/src/JVM/images/JVM/ZGC内存布局.jpg new file mode 100644 index 0000000..c005f18 Binary files /dev/null and b/src/JVM/images/JVM/ZGC内存布局.jpg differ diff --git a/src/JVM/images/JVM/ZGC收集器.jpg b/src/JVM/images/JVM/ZGC收集器.jpg new file mode 100644 index 0000000..749c025 Binary files /dev/null and b/src/JVM/images/JVM/ZGC收集器.jpg differ diff --git a/src/JVM/images/JVM/jconsole-ip.png b/src/JVM/images/JVM/jconsole-ip.png new file mode 100644 index 0000000..7af597d Binary files /dev/null and b/src/JVM/images/JVM/jconsole-ip.png differ diff --git a/src/JVM/images/JVM/jconsole-ip2.png b/src/JVM/images/JVM/jconsole-ip2.png new file mode 100644 index 0000000..8ec4463 Binary files /dev/null and b/src/JVM/images/JVM/jconsole-ip2.png differ diff --git a/src/JVM/images/JVM/jfr-code.jpg b/src/JVM/images/JVM/jfr-code.jpg new file mode 100644 index 0000000..420ae6e Binary files /dev/null and b/src/JVM/images/JVM/jfr-code.jpg differ diff --git a/src/JVM/images/JVM/jfr-event.jpg b/src/JVM/images/JVM/jfr-event.jpg new file mode 100644 index 0000000..2d43aa2 Binary files /dev/null and b/src/JVM/images/JVM/jfr-event.jpg differ diff --git a/src/JVM/images/JVM/jfr-main.jpg b/src/JVM/images/JVM/jfr-main.jpg new file mode 100644 index 0000000..3d2d92d Binary files /dev/null and b/src/JVM/images/JVM/jfr-main.jpg differ diff --git a/src/JVM/images/JVM/jfr-memory.jpg b/src/JVM/images/JVM/jfr-memory.jpg new file mode 100644 index 0000000..d8ee8ca Binary files /dev/null and b/src/JVM/images/JVM/jfr-memory.jpg differ diff --git a/src/JVM/images/JVM/jmc-jfc.png b/src/JVM/images/JVM/jmc-jfc.png new file mode 100644 index 0000000..1b9f04d Binary files /dev/null and b/src/JVM/images/JVM/jmc-jfc.png differ diff --git a/src/JVM/images/JVM/jmc-main.jpg b/src/JVM/images/JVM/jmc-main.jpg new file mode 100644 index 0000000..3c21183 Binary files /dev/null and b/src/JVM/images/JVM/jmc-main.jpg differ diff --git a/src/JVM/images/JVM/jvisualvm.png b/src/JVM/images/JVM/jvisualvm.png new file mode 100644 index 0000000..ed26f7f Binary files /dev/null and b/src/JVM/images/JVM/jvisualvm.png differ diff --git a/src/JVM/images/JVM/mat-compare-baseket-1.jpg b/src/JVM/images/JVM/mat-compare-baseket-1.jpg new file mode 100644 index 0000000..91524e1 Binary files /dev/null and b/src/JVM/images/JVM/mat-compare-baseket-1.jpg differ diff --git a/src/JVM/images/JVM/mat-compare-baseket-2.jpg b/src/JVM/images/JVM/mat-compare-baseket-2.jpg new file mode 100644 index 0000000..d83b9de Binary files /dev/null and b/src/JVM/images/JVM/mat-compare-baseket-2.jpg differ diff --git a/src/JVM/images/JVM/mat-compare-baseket-3.jpg b/src/JVM/images/JVM/mat-compare-baseket-3.jpg new file mode 100644 index 0000000..bfd4f24 Binary files /dev/null and b/src/JVM/images/JVM/mat-compare-baseket-3.jpg differ diff --git a/src/JVM/images/JVM/mat-compare-baseket-4.jpg b/src/JVM/images/JVM/mat-compare-baseket-4.jpg new file mode 100644 index 0000000..240fb41 Binary files /dev/null and b/src/JVM/images/JVM/mat-compare-baseket-4.jpg differ diff --git a/src/JVM/images/JVM/mat-compare-to-another-heap-dump-1.jpg b/src/JVM/images/JVM/mat-compare-to-another-heap-dump-1.jpg new file mode 100644 index 0000000..9f82eed Binary files /dev/null and b/src/JVM/images/JVM/mat-compare-to-another-heap-dump-1.jpg differ diff --git a/src/JVM/images/JVM/mat-compare-to-another-heap-dump-2.jpg b/src/JVM/images/JVM/mat-compare-to-another-heap-dump-2.jpg new file mode 100644 index 0000000..c022099 Binary files /dev/null and b/src/JVM/images/JVM/mat-compare-to-another-heap-dump-2.jpg differ diff --git a/src/JVM/images/JVM/mat-compare-to-another-heap-dump-3.jpg b/src/JVM/images/JVM/mat-compare-to-another-heap-dump-3.jpg new file mode 100644 index 0000000..aa7d4f5 Binary files /dev/null and b/src/JVM/images/JVM/mat-compare-to-another-heap-dump-3.jpg differ diff --git a/src/JVM/images/JVM/mat-dominator-tree.jpg b/src/JVM/images/JVM/mat-dominator-tree.jpg new file mode 100644 index 0000000..84842c1 Binary files /dev/null and b/src/JVM/images/JVM/mat-dominator-tree.jpg differ diff --git a/src/JVM/images/JVM/mat-histogram.jpg b/src/JVM/images/JVM/mat-histogram.jpg new file mode 100644 index 0000000..4c639e0 Binary files /dev/null and b/src/JVM/images/JVM/mat-histogram.jpg differ diff --git a/src/JVM/images/JVM/mat-path-to-gc-roots.jpg b/src/JVM/images/JVM/mat-path-to-gc-roots.jpg new file mode 100644 index 0000000..0df760e Binary files /dev/null and b/src/JVM/images/JVM/mat-path-to-gc-roots.jpg differ diff --git a/src/JVM/images/JVM/mat-实践一.jpg b/src/JVM/images/JVM/mat-实践一.jpg new file mode 100644 index 0000000..b3b7219 Binary files /dev/null and b/src/JVM/images/JVM/mat-实践一.jpg differ diff --git a/src/JVM/images/JVM/mat-实践三-1.jpg b/src/JVM/images/JVM/mat-实践三-1.jpg new file mode 100644 index 0000000..d44b009 Binary files /dev/null and b/src/JVM/images/JVM/mat-实践三-1.jpg differ diff --git a/src/JVM/images/JVM/mat-实践三-2.jpg b/src/JVM/images/JVM/mat-实践三-2.jpg new file mode 100644 index 0000000..a92588c Binary files /dev/null and b/src/JVM/images/JVM/mat-实践三-2.jpg differ diff --git a/src/JVM/images/JVM/mat-实践三-3.jpg b/src/JVM/images/JVM/mat-实践三-3.jpg new file mode 100644 index 0000000..6650db0 Binary files /dev/null and b/src/JVM/images/JVM/mat-实践三-3.jpg differ diff --git a/src/JVM/images/JVM/mat-实践三-4.jpg b/src/JVM/images/JVM/mat-实践三-4.jpg new file mode 100644 index 0000000..3655a27 Binary files /dev/null and b/src/JVM/images/JVM/mat-实践三-4.jpg differ diff --git a/src/JVM/images/JVM/mat-实践二-1.jpg b/src/JVM/images/JVM/mat-实践二-1.jpg new file mode 100644 index 0000000..b58ae96 Binary files /dev/null and b/src/JVM/images/JVM/mat-实践二-1.jpg differ diff --git a/src/JVM/images/JVM/mat-实践二-2.jpg b/src/JVM/images/JVM/mat-实践二-2.jpg new file mode 100644 index 0000000..d35bc84 Binary files /dev/null and b/src/JVM/images/JVM/mat-实践二-2.jpg differ diff --git a/src/JVM/images/JVM/mat-实践二-3.jpg b/src/JVM/images/JVM/mat-实践二-3.jpg new file mode 100644 index 0000000..997d8ca Binary files /dev/null and b/src/JVM/images/JVM/mat-实践二-3.jpg differ diff --git a/src/JVM/images/JVM/mat-实践二-4.jpg b/src/JVM/images/JVM/mat-实践二-4.jpg new file mode 100644 index 0000000..3cd75e3 Binary files /dev/null and b/src/JVM/images/JVM/mat-实践二-4.jpg differ diff --git a/src/JVM/images/JVM/mat-实践二-5.jpg b/src/JVM/images/JVM/mat-实践二-5.jpg new file mode 100644 index 0000000..2cb7c26 Binary files /dev/null and b/src/JVM/images/JVM/mat-实践二-5.jpg differ diff --git a/src/JVM/images/JVM/mat-实践二-6.jpg b/src/JVM/images/JVM/mat-实践二-6.jpg new file mode 100644 index 0000000..a622be6 Binary files /dev/null and b/src/JVM/images/JVM/mat-实践二-6.jpg differ diff --git a/src/JVM/images/JVM/mat-实践四-1.jpg b/src/JVM/images/JVM/mat-实践四-1.jpg new file mode 100644 index 0000000..4737da5 Binary files /dev/null and b/src/JVM/images/JVM/mat-实践四-1.jpg differ diff --git a/src/JVM/images/JVM/mat-实践四-2.jpg b/src/JVM/images/JVM/mat-实践四-2.jpg new file mode 100644 index 0000000..0cdf6e7 Binary files /dev/null and b/src/JVM/images/JVM/mat-实践四-2.jpg differ diff --git a/src/JVM/images/JVM/mat-实践四-3.jpg b/src/JVM/images/JVM/mat-实践四-3.jpg new file mode 100644 index 0000000..6d630cb Binary files /dev/null and b/src/JVM/images/JVM/mat-实践四-3.jpg differ diff --git a/src/JVM/images/JVM/分析Unreachable.png b/src/JVM/images/JVM/分析Unreachable.png new file mode 100644 index 0000000..62e66c9 Binary files /dev/null and b/src/JVM/images/JVM/分析Unreachable.png differ diff --git a/src/JVM/images/JVM/动态扩容引起的空间震荡.png b/src/JVM/images/JVM/动态扩容引起的空间震荡.png new file mode 100644 index 0000000..46a7e59 Binary files /dev/null and b/src/JVM/images/JVM/动态扩容引起的空间震荡.png differ diff --git a/src/JVM/images/JVM/双亲委派.png b/src/JVM/images/JVM/双亲委派.png new file mode 100644 index 0000000..262210d Binary files /dev/null and b/src/JVM/images/JVM/双亲委派.png differ diff --git a/src/JVM/images/JVM/复制(Copying)算法.png b/src/JVM/images/JVM/复制(Copying)算法.png new file mode 100644 index 0000000..789416b Binary files /dev/null and b/src/JVM/images/JVM/复制(Copying)算法.png differ diff --git a/src/JVM/images/JVM/寻找垃圾算法.png b/src/JVM/images/JVM/寻找垃圾算法.png new file mode 100644 index 0000000..969cdf7 Binary files /dev/null and b/src/JVM/images/JVM/寻找垃圾算法.png differ diff --git a/src/JVM/images/JVM/年轻代.jpg b/src/JVM/images/JVM/年轻代.jpg new file mode 100644 index 0000000..4d803b4 Binary files /dev/null and b/src/JVM/images/JVM/年轻代.jpg differ diff --git a/src/JVM/images/JVM/引用级别.png b/src/JVM/images/JVM/引用级别.png new file mode 100644 index 0000000..cc5ebb1 Binary files /dev/null and b/src/JVM/images/JVM/引用级别.png differ diff --git a/src/JVM/images/JVM/引用计数法-问题.png b/src/JVM/images/JVM/引用计数法-问题.png new file mode 100644 index 0000000..e2a15b3 Binary files /dev/null and b/src/JVM/images/JVM/引用计数法-问题.png differ diff --git a/src/JVM/images/JVM/引用计数法.png b/src/JVM/images/JVM/引用计数法.png new file mode 100644 index 0000000..ec2f0f9 Binary files /dev/null and b/src/JVM/images/JVM/引用计数法.png differ diff --git a/src/JVM/images/JVM/收集器.jpg b/src/JVM/images/JVM/收集器.jpg new file mode 100644 index 0000000..1b3aa37 Binary files /dev/null and b/src/JVM/images/JVM/收集器.jpg differ diff --git a/src/JVM/images/JVM/收集器停顿时间和系统开销对比.png b/src/JVM/images/JVM/收集器停顿时间和系统开销对比.png new file mode 100644 index 0000000..ceee9d0 Binary files /dev/null and b/src/JVM/images/JVM/收集器停顿时间和系统开销对比.png differ diff --git a/src/JVM/images/JVM/收集算法.png b/src/JVM/images/JVM/收集算法.png new file mode 100644 index 0000000..023e6b2 Binary files /dev/null and b/src/JVM/images/JVM/收集算法.png differ diff --git a/src/JVM/images/JVM/整理(Compact).png b/src/JVM/images/JVM/整理(Compact).png new file mode 100644 index 0000000..c046017 Binary files /dev/null and b/src/JVM/images/JVM/整理(Compact).png differ diff --git a/src/JVM/images/JVM/标记复制.jpg b/src/JVM/images/JVM/标记复制.jpg new file mode 100644 index 0000000..f6c5f56 Binary files /dev/null and b/src/JVM/images/JVM/标记复制.jpg differ diff --git a/src/JVM/images/JVM/标记整理(Mark-Compact)算法.png b/src/JVM/images/JVM/标记整理(Mark-Compact)算法.png new file mode 100644 index 0000000..8f7ffa9 Binary files /dev/null and b/src/JVM/images/JVM/标记整理(Mark-Compact)算法.png differ diff --git a/src/JVM/images/JVM/标记清除(Mark-Sweep)算法.png b/src/JVM/images/JVM/标记清除(Mark-Sweep)算法.png new file mode 100644 index 0000000..d052dcf Binary files /dev/null and b/src/JVM/images/JVM/标记清除(Mark-Sweep)算法.png differ diff --git a/src/JVM/images/JVM/标记(Mark).png b/src/JVM/images/JVM/标记(Mark).png new file mode 100644 index 0000000..723bba4 Binary files /dev/null and b/src/JVM/images/JVM/标记(Mark).png differ diff --git a/src/JVM/images/JVM/根可达算法.png b/src/JVM/images/JVM/根可达算法.png new file mode 100644 index 0000000..f71be42 Binary files /dev/null and b/src/JVM/images/JVM/根可达算法.png differ diff --git a/src/JVM/images/JVM/死锁排查-Arthas查看死锁.jpg b/src/JVM/images/JVM/死锁排查-Arthas查看死锁.jpg new file mode 100644 index 0000000..2f3f768 Binary files /dev/null and b/src/JVM/images/JVM/死锁排查-Arthas查看死锁.jpg differ diff --git a/src/JVM/images/JVM/死锁排查-Thread详细参数.jpg b/src/JVM/images/JVM/死锁排查-Thread详细参数.jpg new file mode 100644 index 0000000..d28bb54 Binary files /dev/null and b/src/JVM/images/JVM/死锁排查-Thread详细参数.jpg differ diff --git a/src/JVM/images/JVM/死锁排查-jstack查看线程堆栈.jpg b/src/JVM/images/JVM/死锁排查-jstack查看线程堆栈.jpg new file mode 100644 index 0000000..4f07233 Binary files /dev/null and b/src/JVM/images/JVM/死锁排查-jstack查看线程堆栈.jpg differ diff --git a/src/JVM/images/JVM/死锁排查-查看线程堆栈信息.jpg b/src/JVM/images/JVM/死锁排查-查看线程堆栈信息.jpg new file mode 100644 index 0000000..1e70f75 Binary files /dev/null and b/src/JVM/images/JVM/死锁排查-查看线程堆栈信息.jpg differ diff --git a/src/JVM/images/JVM/死锁排查-检测死锁.jpg b/src/JVM/images/JVM/死锁排查-检测死锁.jpg new file mode 100644 index 0000000..b5d3e02 Binary files /dev/null and b/src/JVM/images/JVM/死锁排查-检测死锁.jpg differ diff --git a/src/JVM/images/JVM/死锁排查-死锁运行结果示例.jpg b/src/JVM/images/JVM/死锁排查-死锁运行结果示例.jpg new file mode 100644 index 0000000..e1bcfcb Binary files /dev/null and b/src/JVM/images/JVM/死锁排查-死锁运行结果示例.jpg differ diff --git a/src/JVM/images/JVM/清除(Sweep)-内存.jpg b/src/JVM/images/JVM/清除(Sweep)-内存.jpg new file mode 100644 index 0000000..73ce7bf Binary files /dev/null and b/src/JVM/images/JVM/清除(Sweep)-内存.jpg differ diff --git a/src/JVM/images/JVM/清除(Sweep)-回收.jpg b/src/JVM/images/JVM/清除(Sweep)-回收.jpg new file mode 100644 index 0000000..84c30a2 Binary files /dev/null and b/src/JVM/images/JVM/清除(Sweep)-回收.jpg differ diff --git a/src/JVM/images/JVM/清除(Sweep).png b/src/JVM/images/JVM/清除(Sweep).png new file mode 100644 index 0000000..a8a940c Binary files /dev/null and b/src/JVM/images/JVM/清除(Sweep).png differ diff --git a/src/JVM/images/JVM/火焰图-瓶颈点1.jpg b/src/JVM/images/JVM/火焰图-瓶颈点1.jpg new file mode 100644 index 0000000..5d42beb Binary files /dev/null and b/src/JVM/images/JVM/火焰图-瓶颈点1.jpg differ diff --git a/src/JVM/images/JVM/火焰图-瓶颈点2-代码.jpg b/src/JVM/images/JVM/火焰图-瓶颈点2-代码.jpg new file mode 100644 index 0000000..48673fd Binary files /dev/null and b/src/JVM/images/JVM/火焰图-瓶颈点2-代码.jpg differ diff --git a/src/JVM/images/JVM/火焰图-瓶颈点2.jpg b/src/JVM/images/JVM/火焰图-瓶颈点2.jpg new file mode 100644 index 0000000..41b81aa Binary files /dev/null and b/src/JVM/images/JVM/火焰图-瓶颈点2.jpg differ diff --git a/src/JVM/images/JVM/火焰图-瓶颈点3-代码.jpg b/src/JVM/images/JVM/火焰图-瓶颈点3-代码.jpg new file mode 100644 index 0000000..7d09c2a Binary files /dev/null and b/src/JVM/images/JVM/火焰图-瓶颈点3-代码.jpg differ diff --git a/src/JVM/images/JVM/火焰图-瓶颈点3.jpg b/src/JVM/images/JVM/火焰图-瓶颈点3.jpg new file mode 100644 index 0000000..0b389d5 Binary files /dev/null and b/src/JVM/images/JVM/火焰图-瓶颈点3.jpg differ diff --git a/src/JVM/images/JVM/火焰图案例.jpg b/src/JVM/images/JVM/火焰图案例.jpg new file mode 100644 index 0000000..6eb1190 Binary files /dev/null and b/src/JVM/images/JVM/火焰图案例.jpg differ diff --git a/src/JVM/images/JVM/火焰图案例.svg b/src/JVM/images/JVM/火焰图案例.svg new file mode 100644 index 0000000..3459a2d --- /dev/null +++ b/src/JVM/images/JVM/火焰图案例.svg @@ -0,0 +1,18917 @@ + + + + + + + + + + + + + + +Flame Graph + +Reset Zoom +Search + + + +java/lang/String:::toUpperCase (1 samples, 0.02%) + + + +java/lang/ThreadLocal:::setInitialValue (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +java/lang/ThreadLocal$ThreadLocalMap:::remove (1 samples, 0.02%) + + + +smp_apic_timer_interrupt (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/ArrayOf:::write (2 samples, 0.04%) + + + +net_rx_action (1 samples, 0.02%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +java/util/GregorianCalendar:::computeTime (2 samples, 0.04%) + + + +org/apache/kafka/common/metrics/stats/Meter:::record (3 samples, 0.06%) + + + +PhaseIdealLoop::build_and_optimize (12 samples, 0.23%) + + + +java/io/RandomAccessFile:::writeBytes (41 samples, 0.80%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +java/net/URI$Parser:::parseAuthority (1 samples, 0.02%) + + + +java/util/LinkedHashMap:::get (1 samples, 0.02%) + + + +__block_write_begin (1 samples, 0.02%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +java/util/regex/Pattern$BranchConn:::match (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +smp_apic_timer_interrupt (1 samples, 0.02%) + + + +Node::clone (1 samples, 0.02%) + + + +Unsafe_Park (25 samples, 0.49%) + + + +pipe_read (1 samples, 0.02%) + + + +sk_reset_timer (1 samples, 0.02%) + + + +__lll_unlock_wake (2 samples, 0.04%) + + + +file_remove_privs (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +generic_exec_single (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/condition/ProducesRequestCondition:::getMatchingCondition (16 samples, 0.31%) + + + +sun/security/provider/DigestBase:::engineDigest (6 samples, 0.12%) + + + +org/springframework/web/util/UrlPathHelper:::getRemainingPath (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +__audit_syscall_exit (2 samples, 0.04%) + + + +java/util/LinkedHashMap:::forEach (1 samples, 0.02%) + + + +com/coohua/caf/core/sentinel/SentinelHttpInterceptor:::preHandle (28 samples, 0.54%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ser/std/BooleanSerializer:::serialize (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy49:::annotationType (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +__vdso_clock_gettime (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11Processor:::prepareResponse (14 samples, 0.27%) + + + +org/apache/catalina/connector/Request:::doGetSession (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +CodeBlob::is_zombie (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/Type$8:::write (1 samples, 0.02%) + + + +java/util/Calendar$Builder:::build (1 samples, 0.02%) + + + +CollectedHeap::common_mem_allocate_init (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +org/apache/coyote/AbstractProcessor:::action (6 samples, 0.12%) + + + +java/text/DigitList:::getLong (1 samples, 0.02%) + + + +com/google/gson/internal/$Gson$Types:::canonicalize (2 samples, 0.04%) + + + +generic_write_end (5 samples, 0.10%) + + + +process_backlog (1 samples, 0.02%) + + + +org/springframework/web/method/annotation/AbstractNamedValueMethodArgumentResolver:::resolveArgument (2 samples, 0.04%) + + + +java/util/ArrayList:::toArray (1 samples, 0.02%) + + + +try_to_wake_up (3 samples, 0.06%) + + + +updateBytesCRC32 (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/CtSph:::entryWithPriority (17 samples, 0.33%) + + + +com/sun/crypto/provider/CipherCore:::init (19 samples, 0.37%) + + + +org/springframework/boot/actuate/web/trace/servlet/TraceableHttpServletRequest:::extractHeaders (5 samples, 0.10%) + + + +com/google/gson/internal/bind/ArrayTypeAdapter:::write (1 samples, 0.02%) + + + +itable stub (3 samples, 0.06%) + + + +ip_rcv (1 samples, 0.02%) + + + +com/coohuadata/analytics/javasdk/util/KafkaProducer:::send (59 samples, 1.15%) + + + +java/lang/StringBuffer:::append (1 samples, 0.02%) + + + +schedule_hrtimeout_range (14 samples, 0.27%) + + + +jni_GetObjectField (5 samples, 0.10%) + + + +futex_wake_op (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +org/springframework/beans/TypeConverterSupport:::doConvert (2 samples, 0.04%) + + + +org/apache/catalina/connector/Request:::getAttribute (3 samples, 0.06%) + + + +java/util/LinkedHashMap:::removeEldestEntry (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +sun/nio/ch/FileDispatcherImpl:::write0 (48 samples, 0.93%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +ParseGenerator::generate (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +CollectedHeap::allocate_from_tlab_slow (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils:::isInJavaLangAnnotationPackage (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +schedule (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::setAttribute (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +java/util/HashMap:::put (2 samples, 0.04%) + + + +io/micrometer/shaded/org/pcollections/IntTree:::get (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +org/apache/kafka/common/requests/RequestHeader:::toStruct (2 samples, 0.04%) + + + +io/micrometer/shaded/org/pcollections/IntTree:::get (1 samples, 0.02%) + + + +java/util/concurrent/ConcurrentHashMap:::get (2 samples, 0.04%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +tcp_event_new_data_sent (2 samples, 0.04%) + + + +org/apache/catalina/connector/RequestFacade:::getRequestURL (1 samples, 0.02%) + + + +JVM_GetArrayElement (2 samples, 0.04%) + + + +CodeHeap::find_start (1 samples, 0.02%) + + + +grab_cache_page_write_begin (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy5:::annotationType (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils$AnnotationCollector:::process (1 samples, 0.02%) + + + +java/util/regex/Pattern$Curly:::match (1 samples, 0.02%) + + + +org/apache/logging/log4j/spi/AbstractLogger:::logMessage (7 samples, 0.14%) + + + +sun/nio/cs/UTF_8$Decoder:::decodeArrayLoop (6 samples, 0.12%) + + + +schedule (10 samples, 0.19%) + + + +SYSC_sendto (6 samples, 0.12%) + + + +ret_from_intr (1 samples, 0.02%) + + + +sys_write (31 samples, 0.60%) + + + +org/apache/logging/slf4j/Log4jLogger:::isTraceEnabled (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +start_xmit (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11OutputBuffer:::write (9 samples, 0.18%) + + + +kmem_cache_free (1 samples, 0.02%) + + + +sock_poll (1 samples, 0.02%) + + + +java/util/regex/Pattern$Begin:::match (3 samples, 0.06%) + + + +frame::sender_for_compiled_frame (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/apache/logging/log4j/spi/AbstractLogger:::logMessage (60 samples, 1.17%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::nextToken (8 samples, 0.16%) + + + +java/lang/String:::hashCode (1 samples, 0.02%) + + + +tcp_poll (1 samples, 0.02%) + + + +JVM_GetStackTraceElement (4 samples, 0.08%) + + + +java/io/FilterOutputStream:::close (1 samples, 0.02%) + + + +org/springframework/util/ReflectionUtils:::makeAccessible (2 samples, 0.04%) + + + +com/coohua/caf/core/util/HttpUtil:::getPatternUrl (5 samples, 0.10%) + + + +org/apache/kafka/common/protocol/types/Type$3:::validate (1 samples, 0.02%) + + + +_new_array_Java (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +java/util/regex/Pattern$BmpCharProperty:::match (1 samples, 0.02%) + + + +deflate_slow (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +Parse::Parse (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ObjectMapper:::writeValueAsString (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (203 samples, 3.95%) +org/.. + + +do_softirq (1 samples, 0.02%) + + + +do_sync_readv_writev (16 samples, 0.31%) + + + +com/alibaba/csp/sentinel/slots/logger/LogSlot:::exit (15 samples, 0.29%) + + + +__do_softirq (1 samples, 0.02%) + + + +Node::in (1 samples, 0.02%) + + + +vfs_write (2 samples, 0.04%) + + + +sys_poll (1 samples, 0.02%) + + + +pthread_mutex_trylock (1 samples, 0.02%) + + + +kvm_clock_get_cycles (1 samples, 0.02%) + + + +java/util/ArrayList$Itr:::next (1 samples, 0.02%) + + + +org/jboss/netty/util/internal/LinkedTransferQueue:::xfer (1 samples, 0.02%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (2 samples, 0.04%) + + + +do_sync_write (1 samples, 0.02%) + + + +sys_futex (2 samples, 0.04%) + + + +kmem_cache_alloc (1 samples, 0.02%) + + + +java/lang/ref/Finalizer:::runFinalizer (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +org/springframework/web/servlet/handler/AbstractHandlerMethodMapping:::lookupHandlerMethod (126 samples, 2.45%) +or.. + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +redis/clients/jedis/JedisClusterCommand:::runWithRetries (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +java/lang/String:::hashCode (2 samples, 0.04%) + + + +JavaThread::thread_from_jni_environment (2 samples, 0.04%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::nextToken (1 samples, 0.02%) + + + +java/util/concurrent/ConcurrentHashMap:::putVal (2 samples, 0.04%) + + + +ip_queue_xmit (6 samples, 0.12%) + + + +mod_timer (1 samples, 0.02%) + + + +java/util/Collections$UnmodifiableCollection:::isEmpty (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +native_send_call_func_single_ipi (2 samples, 0.04%) + + + +java/lang/StringBuffer:::append (1 samples, 0.02%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (2 samples, 0.04%) + + + +JavaCallWrapper::JavaCallWrapper (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +sock_poll (1 samples, 0.02%) + + + +org/apache/catalina/core/StandardWrapper:::allocate (1 samples, 0.02%) + + + +YoungList::rs_length_sampling_next (3 samples, 0.06%) + + + +alloc_pages_current (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/deserializer/FieldDeserializer:::setValue (2 samples, 0.04%) + + + +java/lang/Throwable:::getOurStackTrace (31 samples, 0.60%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (2 samples, 0.04%) + + + +wake_up_state (29 samples, 0.56%) + + + +org/springframework/web/servlet/resource/ResourceUrlProviderExposingInterceptor:::preHandle (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +__schedule (1 samples, 0.02%) + + + +java/lang/StringBuilder:::append (2 samples, 0.04%) + + + +org/apache/coyote/Response:::getWriteListener (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::nextToken (1 samples, 0.02%) + + + +InstanceKlass::allocate_instance (1 samples, 0.02%) + + + +wake_up_state (15 samples, 0.29%) + + + +java/util/zip/Deflater:::deflateBytes (1 samples, 0.02%) + + + +org/springframework/boot/actuate/web/trace/servlet/TraceableHttpServletRequest:::getUri (1 samples, 0.02%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics:::addEvent (60 samples, 1.17%) + + + +kvm_sched_clock_read (1 samples, 0.02%) + + + +org/springframework/http/converter/AbstractHttpMessageConverter:::canWrite (1 samples, 0.02%) + + + +java/util/regex/Pattern$CharProperty:::match (3 samples, 0.06%) + + + +do_softirq (1 samples, 0.02%) + + + +ktime_get_real (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +com/coohua/caf/core/util/HttpUtil:::getPatternUrl (9 samples, 0.18%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +tcp_event_new_data_sent (1 samples, 0.02%) + + + +org/apache/kafka/common/utils/ByteUtils:::writeVarint (1 samples, 0.02%) + + + +com/fasterxml/jackson/core/json/WriterBasedJsonGenerator:::writeStartObject (1 samples, 0.02%) + + + +ClassLoaderDataGraph::roots_cld_do (1 samples, 0.02%) + + + +Matcher::match (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +java/util/AbstractList:::hashCode (1 samples, 0.02%) + + + +tcp_rcv_state_process (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor53:::invoke (1 samples, 0.02%) + + + +virtnet_select_queue (1 samples, 0.02%) + + + +java/net/URI:::<init> (3 samples, 0.06%) + + + +java/util/regex/Pattern:::compile (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils:::findAnnotation (2 samples, 0.04%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +tcp_recvmsg (8 samples, 0.16%) + + + +java/util/LinkedList:::unlink (1 samples, 0.02%) + + + +java/text/DateFormatSymbols:::initializeData (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +apic_timer_interrupt (1 samples, 0.02%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +sock_def_readable (1 samples, 0.02%) + + + +org/springframework/web/servlet/handler/AbstractHandlerMethodMapping:::addMatchingMappings (4 samples, 0.08%) + + + +dev_queue_xmit (19 samples, 0.37%) + + + +java/util/HashMap:::putMapEntries (1 samples, 0.02%) + + + +com/sun/crypto/provider/CipherCore:::doFinal (3 samples, 0.06%) + + + +org/apache/catalina/connector/RequestFacade:::getHeader (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +jni_fast_GetIntField (1 samples, 0.02%) + + + +java/util/HashSet:::iterator (16 samples, 0.31%) + + + +do_softirq (1 samples, 0.02%) + + + +tcp_stream_memory_free (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupTail:::match (3 samples, 0.06%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (2 samples, 0.04%) + + + +JvmtiVMObjectAllocEventCollector::JvmtiVMObjectAllocEventCollector (1 samples, 0.02%) + + + +jni_GetPrimitiveArrayCritical (1 samples, 0.02%) + + + +_new_array_Java (1 samples, 0.02%) + + + +deflateReset (3 samples, 0.06%) + + + +__do_softirq (1 samples, 0.02%) + + + +java/nio/charset/CharsetEncoder:::encode (5 samples, 0.10%) + + + +call_softirq (1 samples, 0.02%) + + + +java/util/Formatter$FormatSpecifier:::print (3 samples, 0.06%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +java/lang/StringCoding:::encode (1 samples, 0.02%) + + + +[libpthread-2.17.so] (3 samples, 0.06%) + + + +sun/nio/ch/SocketChannelImpl:::write (1 samples, 0.02%) + + + +sock_def_readable (1 samples, 0.02%) + + + +java/util/AbstractList$Itr:::<init> (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor94:::invoke (1 samples, 0.02%) + + + +hrtimer_cancel (4 samples, 0.08%) + + + +call_softirq (1 samples, 0.02%) + + + +do_softirq (2 samples, 0.04%) + + + +sun/security/jca/ProviderList$ServiceList:::tryGet (2 samples, 0.04%) + + + +org/springframework/web/method/HandlerMethod:::<init> (2 samples, 0.04%) + + + +irq_exit (1 samples, 0.02%) + + + +inflateStateCheck (4 samples, 0.08%) + + + +netif_receive_skb_internal (1 samples, 0.02%) + + + +java/util/AbstractList:::equals (2 samples, 0.04%) + + + +io/micrometer/core/instrument/MeterRegistry:::registerMeterIfNecessary (2 samples, 0.04%) + + + +org/springframework/web/filter/FormContentFilter:::doFilterInternal (205 samples, 3.99%) +org/.. + + +CompileBroker::invoke_compiler_on_method (48 samples, 0.93%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +Parse::do_field_access (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (5 samples, 0.10%) + + + +java/util/Formatter:::format (17 samples, 0.33%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/deserializer/FieldDeserializer:::setValue (2 samples, 0.04%) + + + +java/util/ArrayList:::iterator (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +org/jboss/netty/channel/socket/nio/SelectorUtil:::select (1 samples, 0.02%) + + + +java/lang/StringBuffer:::append (1 samples, 0.02%) + + + +StringTable::intern (8 samples, 0.16%) + + + +add_wait_queue (2 samples, 0.04%) + + + +org/springframework/core/annotation/AnnotatedElementUtils:::searchWithFindSemantics (26 samples, 0.51%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +ip_queue_xmit (3 samples, 0.06%) + + + +java/lang/reflect/Method:::hashCode (1 samples, 0.02%) + + + +CodeCache::find_blob (8 samples, 0.16%) + + + +path_put (1 samples, 0.02%) + + + +Parse::do_one_bytecode (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/context/ContextUtil:::trueEnter (1 samples, 0.02%) + + + +I2C/C2I adapters (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11Processor:::recycle (4 samples, 0.08%) + + + +org/apache/kafka/common/protocol/types/Type$7:::write (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::scanNumber (1 samples, 0.02%) + + + +__skb_clone (1 samples, 0.02%) + + + +__netdev_alloc_skb (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +__ext4_handle_dirty_metadata (1 samples, 0.02%) + + + +pipe_read (1 samples, 0.02%) + + + +__page_cache_alloc (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/RequestMappingInfo:::getMatchingCondition (3 samples, 0.06%) + + + +call_softirq (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +java/text/DecimalFormat:::parse (3 samples, 0.06%) + + + +java/util/regex/Pattern$3:::isSatisfiedBy (2 samples, 0.04%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +block_write_end (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slotchain/DefaultProcessorSlotChain$1:::exit (15 samples, 0.29%) + + + +G1CollectedHeap::mem_allocate (1 samples, 0.02%) + + + +ep_poll (24 samples, 0.47%) + + + +com/coohua/caf/core/metrics/LatencyStat$Timer:::observeDuration (2 samples, 0.04%) + + + +AddPNode::Ideal (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +pthread_getspecific (1 samples, 0.02%) + + + +OopMapCache::lookup (1 samples, 0.02%) + + + +java/util/stream/ReduceOps$3ReducingSink:::accept (4 samples, 0.08%) + + + +tcp_ack (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +deflate (166 samples, 3.23%) +def.. + + +jni_SetBooleanField (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::subFormat (3 samples, 0.06%) + + + +ip_output (1 samples, 0.02%) + + + +G1SATBCardTableLoggingModRefBS::write_ref_field_work (3 samples, 0.06%) + + + +fsnotify (3 samples, 0.06%) + + + +_new_array_nozero_Java (1 samples, 0.02%) + + + +JvmtiVMObjectAllocEventCollector::JvmtiVMObjectAllocEventCollector (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupHead:::match (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupHead:::match (1 samples, 0.02%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +com/coohua/ad/data/manager/AdDataManager:::setUserAdClickIntervalTimeStamp (2 samples, 0.04%) + + + +tcp_send_ack (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +org/springframework/boot/actuate/trace/http/HttpTrace$Request:::<init> (6 samples, 0.12%) + + + +ip_rcv (1 samples, 0.02%) + + + +JVM_IHashCode (2 samples, 0.04%) + + + +vtable stub (1 samples, 0.02%) + + + +java/lang/ThreadLocal:::setInitialValue (3 samples, 0.06%) + + + +_raw_spin_lock (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +_int_malloc (13 samples, 0.25%) + + + +call_softirq (1 samples, 0.02%) + + + +JavaThread::handle_special_suspend_equivalent_condition (1 samples, 0.02%) + + + +schedule (2 samples, 0.04%) + + + +jni_ReleasePrimitiveArrayCritical (6 samples, 0.12%) + + + +sys_futex (14 samples, 0.27%) + + + +java/util/regex/Pattern$Branch:::match (3 samples, 0.06%) + + + +rw_verify_area (2 samples, 0.04%) + + + +org/apache/kafka/clients/producer/internals/Sender:::sendProduceRequests (47 samples, 0.91%) + + + +security_file_permission (1 samples, 0.02%) + + + +__do_softirq (2 samples, 0.04%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +HeapRegion::block_size (1 samples, 0.02%) + + + +java/util/LinkedHashMap$LinkedKeyIterator:::next (2 samples, 0.04%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics:::getLibProperties (578 samples, 11.25%) +com/coohuadata/a.. + + +ret_from_intr (1 samples, 0.02%) + + + +JavaThread::last_frame (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils$AnnotationCollector:::<init> (4 samples, 0.08%) + + + +net_rx_action (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (14 samples, 0.27%) + + + +__do_softirq (1 samples, 0.02%) + + + +java/util/zip/Inflater:::init (2 samples, 0.04%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +__alloc_pages_nodemask (1 samples, 0.02%) + + + +java/util/zip/Deflater:::deflateBytes (171 samples, 3.33%) +jav.. + + +com/alibaba/fastjson/parser/JSONScanner:::next (1 samples, 0.02%) + + + +java/lang/Object:::toString (2 samples, 0.04%) + + + +org/springframework/web/servlet/mvc/method/RequestMappingInfo:::hashCode (2 samples, 0.04%) + + + +__fsnotify_parent (1 samples, 0.02%) + + + +org/apache/tomcat/util/threads/TaskQueue:::offer (26 samples, 0.51%) + + + +virtnet_poll (1 samples, 0.02%) + + + +java/lang/StringCoding:::encode (3 samples, 0.06%) + + + +Interpreter (4,903 samples, 95.39%) +Interpreter + + +irq_exit (1 samples, 0.02%) + + + +java/util/LinkedHashMap:::get (11 samples, 0.21%) + + + +sun/nio/ch/EPollArrayWrapper:::epollCtl (16 samples, 0.31%) + + + +org/springframework/http/converter/AbstractGenericHttpMessageConverter:::canWrite (1 samples, 0.02%) + + + +compress_block (4 samples, 0.08%) + + + +redis/clients/jedis/JedisCluster$25:::execute (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor62:::invoke (1 samples, 0.02%) + + + +__libc_writev (1 samples, 0.02%) + + + +org/apache/catalina/core/StandardContextValve:::invoke (216 samples, 4.20%) +org/a.. + + +ParseGenerator::generate (1 samples, 0.02%) + + + +java/lang/StringBuilder:::append (1 samples, 0.02%) + + + +org/springframework/util/NumberUtils:::parseNumber (3 samples, 0.06%) + + + +java/lang/StringBuffer:::append (1 samples, 0.02%) + + + +com/coohua/caf/core/metrics/LatencyStat:::setMax (1 samples, 0.02%) + + + +java/nio/charset/Charset:::atBugLevel (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +ep_poll (19 samples, 0.37%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +org/apache/catalina/connector/CoyoteAdapter:::normalize (3 samples, 0.06%) + + + +sun/nio/cs/ISO_8859_1$Encoder:::encodeBufferLoop (3 samples, 0.06%) + + + +java/security/Provider:::getService (2 samples, 0.04%) + + + +copy_user_enhanced_fast_string (1 samples, 0.02%) + + + +kmem_cache_free (1 samples, 0.02%) + + + +org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter:::canWrite (3 samples, 0.06%) + + + +java/util/regex/Pattern$BmpCharProperty:::match (4 samples, 0.08%) + + + +do_sync_write (21 samples, 0.41%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +com/google/gson/stream/JsonWriter:::string (21 samples, 0.41%) + + + +__fsnotify_parent (1 samples, 0.02%) + + + +java/util/regex/Pattern:::matcher (2 samples, 0.04%) + + + +java/lang/StringBuffer:::append (1 samples, 0.02%) + + + +CollectedHeap::post_allocation_setup_array (4 samples, 0.08%) + + + +sun/nio/ch/EPollArrayWrapper:::poll (46 samples, 0.89%) + + + +tcp_current_mss (1 samples, 0.02%) + + + +sys_epoll_wait (1 samples, 0.02%) + + + +javax/crypto/Cipher:::chooseProvider (30 samples, 0.58%) + + + +SharedRuntime::complete_monitor_locking_C (2 samples, 0.04%) + + + +java/security/Provider:::getService (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::interrupt (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +_new_array_Java (2 samples, 0.04%) + + + +org/springframework/web/servlet/DispatcherServlet:::doDispatch (187 samples, 3.64%) +org/.. + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +com/coohua/ad/data/interceptor/UserInterceptor:::afterCompletion (143 samples, 2.78%) +co.. + + +PhaseIdealLoop::split_if_with_blocks (1 samples, 0.02%) + + + +java/lang/String:::toUpperCase (2 samples, 0.04%) + + + +org/apache/catalina/core/StandardContext:::getApplicationEventListeners (1 samples, 0.02%) + + + +java/lang/ThreadLocal$ThreadLocalMap:::set (1 samples, 0.02%) + + + +java_lang_Thread::is_alive (1 samples, 0.02%) + + + +com/coohua/ad/data/manager/AdLogTrackManager:::ecpTrack (9 samples, 0.18%) + + + +schedule_hrtimeout_range_clock (14 samples, 0.27%) + + + +redis/clients/jedis/JedisClusterCommand:::runWithRetries (1 samples, 0.02%) + + + +java/lang/String:::hashCode (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/B2CConverter:::convert (2 samples, 0.04%) + + + +do_softirq (2 samples, 0.04%) + + + +org/apache/kafka/common/metrics/stats/Meter:::record (2 samples, 0.04%) + + + +java/lang/Integer:::toString (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/AbstractEndpoint:::processSocket (27 samples, 0.53%) + + + +vfs_write (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +sun/misc/Unsafe:::unpark (34 samples, 0.66%) + + + +tcp_poll (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor:::writeWithMessageConverters (40 samples, 0.78%) + + + +do_softirq (1 samples, 0.02%) + + + +futex_wake_op (20 samples, 0.39%) + + + +pqdownheap (1 samples, 0.02%) + + + +org/springframework/web/servlet/FrameworkServlet:::service (192 samples, 3.74%) +org/.. + + +__call_rcu (1 samples, 0.02%) + + + +java/util/HashMap:::resize (1 samples, 0.02%) + + + +os::javaTimeMillis (2 samples, 0.04%) + + + +java/lang/Thread:::sleep (12 samples, 0.23%) + + + +ip_queue_xmit (1 samples, 0.02%) + + + +Symbol::as_klass_external_name (37 samples, 0.72%) + + + +sock_def_readable (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/apache/coyote/AbstractProcessor:::action (1 samples, 0.02%) + + + +ThreadStateTransition::trans_from_native (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +BarrierSet::static_write_ref_array_pre (2 samples, 0.04%) + + + +net_rx_action (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/StringCache:::toString (1 samples, 0.02%) + + + +G1CollectedHeap::can_elide_initializing_store_barrier (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +jbyte_disjoint_arraycopy (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy48:::annotationType (1 samples, 0.02%) + + + +Compile::Process_OopMap_Node (2 samples, 0.04%) + + + +kmem_cache_alloc (1 samples, 0.02%) + + + +__irqentry_text_start (2 samples, 0.04%) + + + +org/springframework/http/CacheControl:::getHeaderValue (1 samples, 0.02%) + + + +sys_futex (2 samples, 0.04%) + + + +com/coohuadata/analytics/javasdk/util/KafkaProducerHandler:::run (82 samples, 1.60%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +sock_def_readable (1 samples, 0.02%) + + + +sch_direct_xmit (1 samples, 0.02%) + + + +Klass::external_name (52 samples, 1.01%) + + + +JVM_GetStackTraceElement (463 samples, 9.01%) +JVM_GetStackT.. + + +generic_exec_single (2 samples, 0.04%) + + + +sysret_audit (1 samples, 0.02%) + + + +com/coohuadata/analytics/javasdk/util/KafkaProducer$1:::onCompletion (31 samples, 0.60%) + + + +Compile::Compile (48 samples, 0.93%) + + + +generic_file_aio_write (21 samples, 0.41%) + + + +get_futex_key (1 samples, 0.02%) + + + +release_sock (1 samples, 0.02%) + + + +__schedule (16 samples, 0.31%) + + + +org/apache/kafka/common/network/Selector$SelectorMetrics:::recordBytesReceived (5 samples, 0.10%) + + + +org/springframework/core/annotation/AnnotatedElementUtils:::searchWithFindSemantics (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +java/util/AbstractList:::equals (1 samples, 0.02%) + + + +PhaseCFG::build_dominator_tree (1 samples, 0.02%) + + + +java/lang/String:::toLowerCase (1 samples, 0.02%) + + + +OptoRuntime::new_array_C (1 samples, 0.02%) + + + +java/util/Formatter:::format (15 samples, 0.29%) + + + +HandleMarkCleaner::~HandleMarkCleaner (1 samples, 0.02%) + + + +RegMask::smear_to_sets (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +pqdownheap (2 samples, 0.04%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +mod_timer (1 samples, 0.02%) + + + +java/util/regex/Pattern$Neg:::match (106 samples, 2.06%) +j.. + + +__skb_checksum (1 samples, 0.02%) + + + +java/lang/Boolean:::equals (1 samples, 0.02%) + + + +inet_gro_receive (1 samples, 0.02%) + + + +ClassLoaderData::oops_do (1 samples, 0.02%) + + + +OptoRuntime::register_finalizer (8 samples, 0.16%) + + + +sun/nio/ch/FileDispatcherImpl:::writev0 (21 samples, 0.41%) + + + +jni_GetObjectField (4 samples, 0.08%) + + + +do_softirq (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +update_time (1 samples, 0.02%) + + + +_multianewarray2_Java (11 samples, 0.21%) + + + +IndexSetIterator::advance_and_next (2 samples, 0.04%) + + + +__ext4_journal_stop (1 samples, 0.02%) + + + +__pollwait (1 samples, 0.02%) + + + +org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter:::canWrite (1 samples, 0.02%) + + + +Parse::do_one_bytecode (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +tcp_sendmsg (5 samples, 0.10%) + + + +jni_GetObjectField (92 samples, 1.79%) + + + +PhaseAggressiveCoalesce::insert_copies (1 samples, 0.02%) + + + +Compile::Optimize (16 samples, 0.31%) + + + +sk_reset_timer (1 samples, 0.02%) + + + +java/net/URI$Parser:::parseServer (3 samples, 0.06%) + + + +wake_futex (2 samples, 0.04%) + + + +org/springframework/boot/actuate/trace/http/HttpTrace$Request:::<init> (73 samples, 1.42%) + + + +org/apache/kafka/common/network/Selector:::attemptRead (21 samples, 0.41%) + + + +java/util/Formatter$Conversion:::isValid (1 samples, 0.02%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +java/lang/Long:::getChars (1 samples, 0.02%) + + + +OptoRuntime::new_array_C (1 samples, 0.02%) + + + +pthread_mutex_trylock (1 samples, 0.02%) + + + +irq_exit (2 samples, 0.04%) + + + +net_rx_action (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +java/lang/ref/Reference$ReferenceHandler:::run (2 samples, 0.04%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics:::assertProperties (131 samples, 2.55%) +co.. + + +org/springframework/core/annotation/AnnotatedElementUtils:::searchWithFindSemantics (11 samples, 0.21%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +pthread_getspecific (2 samples, 0.04%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +sys_write (12 samples, 0.23%) + + + +generic_exec_single (1 samples, 0.02%) + + + +ep_poll (18 samples, 0.35%) + + + +__do_softirq (1 samples, 0.02%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::doFilter (211 samples, 4.11%) +org/.. + + +call_function_single_interrupt (1 samples, 0.02%) + + + +tcp_recvmsg (1 samples, 0.02%) + + + +java/util/regex/Pattern$Begin:::match (15 samples, 0.29%) + + + +system_call_fastpath (12 samples, 0.23%) + + + +org/apache/tomcat/util/buf/StringCache:::toString (2 samples, 0.04%) + + + +java/lang/String:::hashCode (1 samples, 0.02%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics$KafkaConsumer:::send (490 samples, 9.53%) +com/coohuadat.. + + +java/lang/ThreadLocal$ThreadLocalMap:::set (1 samples, 0.02%) + + + +sg_next (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping:::handleMatch (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +checkcast_arraycopy (1 samples, 0.02%) + + + +do_futex (3 samples, 0.06%) + + + +org/jboss/netty/channel/socket/nio/NioWorker:::write0 (1 samples, 0.02%) + + + +pipe_write (21 samples, 0.41%) + + + +pthread_getspecific (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +java/util/HashMap:::resize (1 samples, 0.02%) + + + +vfs_write (30 samples, 0.58%) + + + +system_call_fastpath (25 samples, 0.49%) + + + +Java_java_net_SocketInputStream_socketRead0 (1 samples, 0.02%) + + + +io/micrometer/core/instrument/Tags:::and (2 samples, 0.04%) + + + +com/coohua/ad/data/service/impl/AdDataServiceImpl:::checkAdValid (3 samples, 0.06%) + + + +call_softirq (1 samples, 0.02%) + + + +com/sun/crypto/provider/AESCrypt:::makeSessionKey (17 samples, 0.33%) + + + +sys_epoll_wait (20 samples, 0.39%) + + + +fget_light (1 samples, 0.02%) + + + +__fsnotify_parent (1 samples, 0.02%) + + + +finish_task_switch (16 samples, 0.31%) + + + +java/util/concurrent/locks/LockSupport:::parkNanos (5 samples, 0.10%) + + + +ret_from_intr (2 samples, 0.04%) + + + +ThreadInVMfromNative::~ThreadInVMfromNative (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/config/LoggerConfig:::log (3 samples, 0.06%) + + + +itable stub (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (18 samples, 0.35%) + + + +__srcu_read_unlock (2 samples, 0.04%) + + + +sys_poll (1 samples, 0.02%) + + + +java/util/Formatter$FixedString:::print (1 samples, 0.02%) + + + +java/net/URI$Parser:::parseServer (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +tcp_send_mss (2 samples, 0.04%) + + + +__ext4_journal_get_write_access (1 samples, 0.02%) + + + +detach_buf (1 samples, 0.02%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +poll_schedule_timeout (1 samples, 0.02%) + + + +sys_futex (2 samples, 0.04%) + + + +ThreadBlockInVM::ThreadBlockInVM (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ser/std/StdKeySerializers$StringKeySerializer:::serialize (7 samples, 0.14%) + + + +com/coohua/caf/core/rpc/MotanConfigPrintSpringListener:::onApplicationEvent (13 samples, 0.25%) + + + +com/fasterxml/jackson/databind/ser/std/MapSerializer:::serialize (37 samples, 0.72%) + + + +java/lang/Object:::hashCode (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +inet_csk_destroy_sock (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +tcp_rearm_rto (1 samples, 0.02%) + + + +com/google/gson/Gson:::getAdapter (3 samples, 0.06%) + + + +tcp_sendmsg (36 samples, 0.70%) + + + +net_rx_action (1 samples, 0.02%) + + + +sun/nio/cs/ISO_8859_1$Decoder:::decodeLoop (1 samples, 0.02%) + + + +org/springframework/web/multipart/support/MultipartResolutionDelegate:::resolveMultipartArgument (4 samples, 0.08%) + + + +java/lang/AbstractStringBuilder:::append (4 samples, 0.08%) + + + +org/springframework/core/convert/TypeDescriptor:::equals (17 samples, 0.33%) + + + +org/springframework/core/convert/support/GenericConversionService$ConverterCacheKey:::equals (19 samples, 0.37%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +sun/nio/ch/EPollSelectorImpl:::putEventOps (1 samples, 0.02%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +ConcurrentG1RefineThread::sample_young_list_rs_lengths (3 samples, 0.06%) + + + +itable stub (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/pattern/LoggerPatternConverter:::format (1 samples, 0.02%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +org/apache/kafka/common/metrics/Sensor:::record (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +java/util/ArrayList:::add (1 samples, 0.02%) + + + +OptoRuntime::new_array_C (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::subFormat (3 samples, 0.06%) + + + +jshort_disjoint_arraycopy (6 samples, 0.12%) + + + +java/util/zip/DeflaterOutputStream:::write (89 samples, 1.73%) + + + +call_softirq (1 samples, 0.02%) + + + +netif_skb_features (1 samples, 0.02%) + + + +java/util/concurrent/locks/ReentrantReadWriteLock$Sync:::tryAcquireShared (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/beans/TypeConverterDelegate:::convertIfNecessary (27 samples, 0.53%) + + + +java/lang/String:::hashCode (1 samples, 0.02%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +GangWorker::loop (19 samples, 0.37%) + + + +Monitor::ILock (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +java/util/regex/Pattern$Begin:::match (1 samples, 0.02%) + + + +java/text/DateFormatSymbols:::getProviderInstance (2 samples, 0.04%) + + + +java/util/HashMap:::resize (5 samples, 0.10%) + + + +ip_rcv (1 samples, 0.02%) + + + +__schedule (10 samples, 0.19%) + + + +java/lang/ThreadLocal:::getMap (1 samples, 0.02%) + + + +get_rps_cpu (1 samples, 0.02%) + + + +org/apache/logging/log4j/spi/AbstractLogger:::logMessageSafely (3 samples, 0.06%) + + + +TypeArrayKlass::allocate_common (1 samples, 0.02%) + + + +org/apache/kafka/common/metrics/Sensor:::record (5 samples, 0.10%) + + + +Unsafe_Unpark (2 samples, 0.04%) + + + +org/joda/time/format/FormatUtils:::appendPaddedInteger (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +_raw_spin_lock (1 samples, 0.02%) + + + +jbd2_journal_stop (1 samples, 0.02%) + + + +java/util/zip/Deflater:::deflateBytes (1 samples, 0.02%) + + + +futex_wait (19 samples, 0.37%) + + + +wake_up_state (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11Processor:::prepareRequest (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +fget_light (2 samples, 0.04%) + + + +Interpreter (1 samples, 0.02%) + + + +java/util/concurrent/FutureTask:::run (82 samples, 1.60%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/joda/time/field/PreciseDateTimeField:::get (1 samples, 0.02%) + + + +org/springframework/core/convert/TypeDescriptor:::valueOf (2 samples, 0.04%) + + + +do_softirq (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +java/util/HashMap$HashIterator:::hasNext (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject:::awaitNanos (5 samples, 0.10%) + + + +irq_exit (1 samples, 0.02%) + + + +JavaThread::run (5,080 samples, 98.83%) +JavaThread::run + + +call_function_single_interrupt (1 samples, 0.02%) + + + +__mark_inode_dirty (9 samples, 0.18%) + + + +irq_exit (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils:::isInJavaLangAnnotationPackage (1 samples, 0.02%) + + + +Interpreter (2 samples, 0.04%) + + + +G1SATBCardTableLoggingModRefBS::invalidate (1 samples, 0.02%) + + + +java/text/DateFormatSymbols:::getProviderInstance (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::parseField (1 samples, 0.02%) + + + +[libpthread-2.17.so] (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +deflate (9 samples, 0.18%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +PhaseIterGVN::optimize (4 samples, 0.08%) + + + +ret_from_intr (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor86:::invoke (1 samples, 0.02%) + + + +__GI___libc_poll (1 samples, 0.02%) + + + +io/micrometer/core/instrument/Timer$Builder:::register (6 samples, 0.12%) + + + +java/lang/ref/Finalizer:::register (1 samples, 0.02%) + + + +__lll_unlock_wake (1 samples, 0.02%) + + + +HandleMarkCleaner::~HandleMarkCleaner (2 samples, 0.04%) + + + +java/util/ArrayList:::size (1 samples, 0.02%) + + + +java/util/zip/Deflater:::deflateBytes (89 samples, 1.73%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +skb_checksum (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/pattern/LevelPatternConverter:::format (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/block/degrade/DegradeSlot:::exit (1 samples, 0.02%) + + + +java/util/AbstractList:::equals (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::smartMatch (18 samples, 0.35%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +jbyte_disjoint_arraycopy (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +Java_java_util_zip_Deflater_deflateBytes (87 samples, 1.69%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (2 samples, 0.04%) + + + +lock_sock_nested (1 samples, 0.02%) + + + +frame::oops_interpreted_do (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +com/coohua/caf/core/metrics/LatencyStat:::setMax (6 samples, 0.12%) + + + +__do_softirq (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +java/lang/Class:::getDeclaringClass0 (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +java/util/Formatter$FormatSpecifier:::print (5 samples, 0.10%) + + + +com/coohua/caf/core/metrics/LatencyStat:::observe (17 samples, 0.33%) + + + +deflateStateCheck (1 samples, 0.02%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +ep_scan_ready_list.isra.7 (4 samples, 0.08%) + + + +apic_timer_interrupt (1 samples, 0.02%) + + + +skb_put (1 samples, 0.02%) + + + +java/io/ByteArrayOutputStream:::write (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +org/springframework/web/util/UrlPathHelper:::getRemainingPath (1 samples, 0.02%) + + + +__vdso_gettimeofday (2 samples, 0.04%) + + + +do_softirq (1 samples, 0.02%) + + + +java/lang/StringBuilder:::append (2 samples, 0.04%) + + + +java/util/Calendar:::<init> (1 samples, 0.02%) + + + +sock_def_readable (1 samples, 0.02%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics$KafkaConsumer:::send (2 samples, 0.04%) + + + +virtqueue_add_inbuf (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::parseField (68 samples, 1.32%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +org/springframework/web/method/annotation/ModelFactory:::findSessionAttributeArguments (2 samples, 0.04%) + + + +CompressedReadStream::read_signed_int (4 samples, 0.08%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/core/DefaultParameterNameDiscoverer:::<init> (3 samples, 0.06%) + + + +com/weibo/api/motan/proxy/AbstractRefererHandler:::invokeRequest (10 samples, 0.19%) + + + +ret_from_intr (2 samples, 0.04%) + + + +ret_from_intr (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +org/springframework/web/method/support/InvocableHandlerMethod:::invokeForRequest (141 samples, 2.74%) +or.. + + +CollectedHeap::new_store_pre_barrier (1 samples, 0.02%) + + + +Parker::park (4 samples, 0.08%) + + + +org/springframework/core/annotation/AnnotationUtils$AnnotationCollector:::<init> (5 samples, 0.10%) + + + +org/apache/kafka/common/metrics/stats/Meter:::record (1 samples, 0.02%) + + + +generic_exec_single (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +java/lang/reflect/Method:::invoke (138 samples, 2.68%) +ja.. + + +java/util/GregorianCalendar:::computeFields (2 samples, 0.04%) + + + +java_lang_Throwable::fill_in_stack_trace (4 samples, 0.08%) + + + +com/coohua/caf/core/sentinel/SentinelHttpInterceptor:::preHandle (2 samples, 0.04%) + + + +java/io/DataOutputStream:::write (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupHead:::match (4 samples, 0.08%) + + + +org/apache/coyote/Response:::recycle (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +java/net/SocketInputStream:::socketRead0 (1 samples, 0.02%) + + + +org/springframework/util/AntPathMatcher:::match (49 samples, 0.95%) + + + +__vdso_gettimeofday (2 samples, 0.04%) + + + +G1BlockOffsetArrayContigSpace::zero_bottom_entry_raw (1 samples, 0.02%) + + + +java_lang_StackTraceElement::create (420 samples, 8.17%) +java_lang_S.. + + +ip_rcv (1 samples, 0.02%) + + + +sysret_audit (1 samples, 0.02%) + + + +ObjArrayKlass::allocate (1 samples, 0.02%) + + + +G1AllocRegion::new_alloc_region_and_allocate (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils$AnnotationCollector:::process (9 samples, 0.18%) + + + +do_softirq (1 samples, 0.02%) + + + +_copy_from_user (1 samples, 0.02%) + + + +sys_write (43 samples, 0.84%) + + + +do_softirq (1 samples, 0.02%) + + + +PhaseRegAlloc::is_oop (1 samples, 0.02%) + + + +netif_receive_skb_internal (1 samples, 0.02%) + + + +java/lang/StringCoding:::decode (1 samples, 0.02%) + + + +java/util/HashMap$HashIterator:::hasNext (1 samples, 0.02%) + + + +java/lang/ThreadLocal:::getMap (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +java/util/regex/Pattern$Begin:::match (2 samples, 0.04%) + + + +org/springframework/web/filter/HiddenHttpMethodFilter:::doFilterInternal (211 samples, 4.11%) +org/.. + + +java/util/regex/Pattern$GroupHead:::match (1 samples, 0.02%) + + + +java/lang/Integer:::toString (2 samples, 0.04%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +_raw_spin_lock_irqsave (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/pattern/NameAbbreviator$PatternAbbreviator:::abbreviate (1 samples, 0.02%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +vfs_write (12 samples, 0.23%) + + + +com/coohua/caf/core/kv/JedisClusterClient$$FastClassBySpringCGLIB$$1bc9b45c:::invoke (2 samples, 0.04%) + + + +org/springframework/cglib/proxy/MethodProxy:::invoke (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +UTF8::convert_to_unicode (22 samples, 0.43%) + + + +G1UpdateRSOrPushRefOopClosure::do_oop (1 samples, 0.02%) + + + +org/springframework/web/util/UrlPathHelper:::decodeInternal (6 samples, 0.12%) + + + +org/apache/tomcat/websocket/server/WsFilter:::doFilter (3,448 samples, 67.08%) +org/apache/tomcat/websocket/server/WsFilter:::doFilter + + +__audit_syscall_entry (1 samples, 0.02%) + + + +java/util/regex/Pattern$Dollar:::match (1 samples, 0.02%) + + + +__skb_gro_checksum_complete (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +CodeCache::find_blob (1 samples, 0.02%) + + + +java/util/Formatter$FormatSpecifier:::print (6 samples, 0.12%) + + + +__libc_writev (20 samples, 0.39%) + + + +org/springframework/core/annotation/SynthesizedAnnotationInvocationHandler:::invoke (12 samples, 0.23%) + + + +tcp_sendmsg (15 samples, 0.29%) + + + +org/apache/kafka/clients/producer/internals/BufferPool:::allocate (3 samples, 0.06%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/web/context/request/ServletWebRequest:::getNativeRequest (1 samples, 0.02%) + + + +com/alibaba/fastjson/serializer/StringCodec:::deserialze (7 samples, 0.14%) + + + +org/springframework/core/convert/support/GenericConversionService:::getConverter (22 samples, 0.43%) + + + +BarrierSet::static_write_ref_array_post (1 samples, 0.02%) + + + +ReferenceProcessor::process_discovered_references (3 samples, 0.06%) + + + +__skb_checksum (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils$AnnotationCollector:::process (22 samples, 0.43%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +netif_receive_skb_internal (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils:::isInJavaLangAnnotationPackage (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +TypeArrayKlass::allocate_common (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +JVM_IHashCode (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +__irqentry_text_start (2 samples, 0.04%) + + + +org/springframework/aop/aspectj/AbstractAspectJAdvice:::invokeAdviceMethod (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +_new_instance_Java (1 samples, 0.02%) + + + +java/util/regex/Pattern:::matcher (2 samples, 0.04%) + + + +sock_aio_read (9 samples, 0.18%) + + + +x2apic_send_IPI_mask (2 samples, 0.04%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +skb_release_all (1 samples, 0.02%) + + + +Java_java_util_zip_Deflater_deflateBytes (1 samples, 0.02%) + + + +redis/clients/jedis/JedisCluster$21:::execute (1 samples, 0.02%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics:::assertProperties (4 samples, 0.08%) + + + +call_softirq (1 samples, 0.02%) + + + +Monitor::ILock (1 samples, 0.02%) + + + +java/util/GregorianCalendar:::computeTime (3 samples, 0.06%) + + + +do_futex (6 samples, 0.12%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +try_to_wake_up (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +__lll_unlock_wake (3 samples, 0.06%) + + + +frame::is_interpreted_frame (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (206 samples, 4.01%) +org/.. + + +java_lang_Throwable::fill_in_stack_trace (74 samples, 1.44%) + + + +Monitor::unlock (1 samples, 0.02%) + + + +java/lang/String:::equals (2 samples, 0.04%) + + + +com/sun/proxy/$Proxy77:::annotationType (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +csum_partial_ext (1 samples, 0.02%) + + + +org/springframework/util/MimeType$SpecificityComparator:::compare (1 samples, 0.02%) + + + +itable stub (5 samples, 0.10%) + + + +PhaseIdealLoop::build_loop_late (4 samples, 0.08%) + + + +send_tree (9 samples, 0.18%) + + + +java/nio/Buffer:::limit (1 samples, 0.02%) + + + +java/util/concurrent/ThreadPoolExecutor:::execute (26 samples, 0.51%) + + + +sys_epoll_wait (25 samples, 0.49%) + + + +__memset_sse2 (1 samples, 0.02%) + + + +java/security/Provider$ServiceKey:::<init> (9 samples, 0.18%) + + + +java/lang/StringCoding:::decode (3 samples, 0.06%) + + + +javax/crypto/Cipher:::tokenizeTransformation (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/appender/AsyncAppender$AsyncThread:::run (99 samples, 1.93%) +o.. + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +sys_write (2 samples, 0.04%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +Java_java_util_zip_Deflater_init (37 samples, 0.72%) + + + +auditsys (1 samples, 0.02%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +io/micrometer/core/instrument/config/MeterFilter:::map (1 samples, 0.02%) + + + +pthread_getspecific (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +retint_careful (1 samples, 0.02%) + + + +rcu_process_callbacks (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +pipe_poll (1 samples, 0.02%) + + + +sun/nio/cs/UTF_8$Decoder:::decodeLoop (1 samples, 0.02%) + + + +java/util/HashMap:::resize (2 samples, 0.04%) + + + +smp_apic_timer_interrupt (1 samples, 0.02%) + + + +java/net/SocketInputStream:::socketRead0 (1 samples, 0.02%) + + + +tcp_event_data_recv (1 samples, 0.02%) + + + +com/alibaba/fastjson/serializer/IntegerCodec:::deserialze (3 samples, 0.06%) + + + +DirtyCardQueueSet::apply_closure_to_completed_buffer (5 samples, 0.10%) + + + +irq_exit (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::initialize (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +ipv4_mtu (1 samples, 0.02%) + + + +java/util/Formatter:::format (23 samples, 0.45%) + + + +sun/misc/Unsafe:::unpark (25 samples, 0.49%) + + + +sun/nio/ch/SelectorImpl:::select (25 samples, 0.49%) + + + +Interpreter (4,346 samples, 84.55%) +Interpreter + + +org/apache/logging/log4j/core/impl/Log4jLogEvent:::<init> (5 samples, 0.10%) + + + +os::javaTimeMillis (2 samples, 0.04%) + + + +dev_hard_start_xmit (3 samples, 0.06%) + + + +pthread_mutex_unlock (1 samples, 0.02%) + + + +java/util/HashSet:::iterator (2 samples, 0.04%) + + + +do_sys_poll (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/util/regex/Pattern$CharProperty:::match (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +java/util/HashMap:::newNode (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (204 samples, 3.97%) +org/.. + + +com/alibaba/csp/sentinel/slots/statistic/base/LeapArray:::currentWindow (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +jbd2__journal_start (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor61:::invoke (1 samples, 0.02%) + + + +tcp_data_queue (1 samples, 0.02%) + + + +java/util/concurrent/LinkedBlockingQueue:::offer (22 samples, 0.43%) + + + +java/lang/Throwable:::<init> (78 samples, 1.52%) + + + +ip_queue_xmit (23 samples, 0.45%) + + + +org/springframework/context/support/AbstractApplicationContext:::publishEvent (3 samples, 0.06%) + + + +arrayOopDesc::base (1 samples, 0.02%) + + + +OptoRuntime::new_array_C (1 samples, 0.02%) + + + +org/springframework/context/event/SimpleApplicationEventMulticaster:::multicastEvent (22 samples, 0.43%) + + + +org/jboss/netty/channel/DefaultChannelPipeline$DefaultChannelHandlerContext:::sendDownstream (2 samples, 0.04%) + + + +pthread_cond_signal@@GLIBC_2.3.2 (1 samples, 0.02%) + + + +OptoRuntime::new_instance_C (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +java/util/LinkedHashMap:::get (4 samples, 0.08%) + + + +call_rcu_sched (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +ip_finish_output (5 samples, 0.10%) + + + +org/apache/tomcat/util/net/NioBlockingSelector:::write (85 samples, 1.65%) + + + +org/apache/kafka/common/protocol/types/ArrayOf:::validate (1 samples, 0.02%) + + + +org/joda/time/DateTimeFieldType$StandardDateTimeFieldType:::getField (1 samples, 0.02%) + + + +system_call_after_swapgs (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +os::javaTimeMillis (2 samples, 0.04%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +java/util/HashMap:::putMapEntries (5 samples, 0.10%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics$KafkaConsumer:::send (1 samples, 0.02%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +dev_gro_receive (1 samples, 0.02%) + + + +MachNode::ideal_reg (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor63:::invoke (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +java/util/regex/Pattern:::matcher (1 samples, 0.02%) + + + +VM_Operation::evaluate (4 samples, 0.08%) + + + +itable stub (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +HandleMarkCleaner::~HandleMarkCleaner (2 samples, 0.04%) + + + +skb_copy_datagram_iovec (5 samples, 0.10%) + + + +org/springframework/core/annotation/AnnotationUtils:::findAnnotation (3 samples, 0.06%) + + + +java/util/concurrent/ConcurrentHashMap:::putVal (1 samples, 0.02%) + + + +java/util/regex/Pattern$Begin:::match (108 samples, 2.10%) +j.. + + +com/alibaba/fastjson/parser/JSONLexerBase:::scanSymbol (16 samples, 0.31%) + + + +tcp_v4_early_demux (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/SymbolTable:::addSymbol (2 samples, 0.04%) + + + +java/nio/charset/CharsetDecoder:::implReset (1 samples, 0.02%) + + + +com/coohua/caf/core/rpc/MotanTracingFilter:::filter (8 samples, 0.16%) + + + +inet_gro_receive (1 samples, 0.02%) + + + +org/springframework/web/method/annotation/ModelAttributeMethodProcessor:::supportsReturnType (2 samples, 0.04%) + + + +JavaThread::handle_special_suspend_equivalent_condition (3 samples, 0.06%) + + + +org/springframework/boot/actuate/trace/http/HttpTrace$Request:::<init> (6 samples, 0.12%) + + + +pthread_getspecific (1 samples, 0.02%) + + + +com/google/gson/internal/bind/ArrayTypeAdapter:::write (1 samples, 0.02%) + + + +try_fill_recv (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +java/util/ComparableTimSort:::binarySort (3 samples, 0.06%) + + + +java/lang/StringCoding:::encode (8 samples, 0.16%) + + + +run_timer_softirq (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor55:::invoke (2,635 samples, 51.26%) +sun/reflect/GeneratedMethodAccessor55:::invoke + + +OopMapSet::all_do (1 samples, 0.02%) + + + +java/util/regex/Pattern:::matcher (8 samples, 0.16%) + + + +bictcp_cong_avoid (1 samples, 0.02%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +__fsnotify_parent (1 samples, 0.02%) + + + +org/apache/catalina/mapper/Mapper:::internalMap (9 samples, 0.18%) + + + +schedule (11 samples, 0.21%) + + + +jshort_disjoint_arraycopy (2 samples, 0.04%) + + + +jshort_disjoint_arraycopy (2 samples, 0.04%) + + + +sun/nio/ch/NativeThread:::current (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (5 samples, 0.10%) + + + +sun/reflect/GeneratedMethodAccessor94:::invoke (1 samples, 0.02%) + + + +PhaseIterGVN::remove_globally_dead_node (1 samples, 0.02%) + + + +generic_exec_single (1 samples, 0.02%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject:::doSignal (1 samples, 0.02%) + + + +JVM_GetStackTraceDepth (3 samples, 0.06%) + + + +java/lang/StringBuffer:::append (11 samples, 0.21%) + + + +InterpreterRuntime::ldc (1 samples, 0.02%) + + + +ipv4_mtu (1 samples, 0.02%) + + + +G1RemSet::oops_into_collection_set_do (5 samples, 0.10%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +org/springframework/boot/actuate/trace/http/HttpTrace$Request:::<init> (73 samples, 1.42%) + + + +java/lang/StringBuilder:::append (1 samples, 0.02%) + + + +org/apache/catalina/connector/InputBuffer:::read (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +jbyte_disjoint_arraycopy (1 samples, 0.02%) + + + +InterpreterRuntime::method (1 samples, 0.02%) + + + +Parse::do_all_blocks (1 samples, 0.02%) + + + +Klass::external_name (5 samples, 0.10%) + + + +com/fasterxml/jackson/databind/ObjectMapper:::_configAndWriteValue (60 samples, 1.17%) + + + +java/util/ArrayList:::toArray (1 samples, 0.02%) + + + +java/util/Arrays:::sort (3 samples, 0.06%) + + + +__schedule (12 samples, 0.23%) + + + +_new_instance_Java (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +system_call_fastpath (6 samples, 0.12%) + + + +org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping$PartialMatchHelper:::<init> (67 samples, 1.30%) + + + +tcp_data_queue (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/AbstractChunk:::indexOf (3 samples, 0.06%) + + + +call_softirq (1 samples, 0.02%) + + + +__audit_syscall_entry (1 samples, 0.02%) + + + +G1CollectedHeap::do_collection_pause_at_safepoint (4 samples, 0.08%) + + + +sys_futex (4 samples, 0.08%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +vfs_read (3 samples, 0.06%) + + + +org/springframework/beans/factory/support/AbstractBeanFactory:::getBeanExpressionResolver (1 samples, 0.02%) + + + +__dev_kfree_skb_any (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::deserialze (1 samples, 0.02%) + + + +org/apache/catalina/connector/RequestFacade:::getRequestURL (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +com/coohua/ad/data/utils/GzipUtil:::deCompress (1,033 samples, 20.10%) +com/coohua/ad/data/utils/GzipUt.. + + +ResourceMark::~ResourceMark (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping$PartialMatchHelper:::<init> (4 samples, 0.08%) + + + +sun/nio/ch/SocketChannelImpl:::read (16 samples, 0.31%) + + + +org/springframework/util/StringUtils:::tokenizeToStringArray (1 samples, 0.02%) + + + +ext4_dirty_inode (2 samples, 0.04%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +org/apache/kafka/common/metrics/stats/Count:::update (1 samples, 0.02%) + + + +java/util/concurrent/ThreadPoolExecutor:::runWorker (124 samples, 2.41%) +ja.. + + +jni_GetPrimitiveArrayCritical (148 samples, 2.88%) +jn.. + + +org/apache/coyote/AbstractProcessor:::parseHost (1 samples, 0.02%) + + + +system_call_fastpath (31 samples, 0.60%) + + + +OptoRuntime::is_deoptimized_caller_frame (1 samples, 0.02%) + + + +futex_wake_op (5 samples, 0.10%) + + + +tcp4_gro_receive (1 samples, 0.02%) + + + +__inet_lookup_established (1 samples, 0.02%) + + + +org/springframework/web/method/support/HandlerMethodReturnValueHandlerComposite:::selectHandler (2 samples, 0.04%) + + + +java/lang/Class:::getEnclosingMethod0 (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::initialize (4 samples, 0.08%) + + + +HandleMarkCleaner::~HandleMarkCleaner (32 samples, 0.62%) + + + +com/google/gson/internal/bind/MapTypeAdapterFactory$Adapter:::write (56 samples, 1.09%) + + + +com/alibaba/csp/sentinel/slots/statistic/base/LeapArray:::currentWindow (4 samples, 0.08%) + + + +__libc_calloc (4 samples, 0.08%) + + + +org/apache/kafka/common/requests/ProduceRequest:::toStruct (7 samples, 0.14%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +BarrierSet::static_write_ref_array_post (1 samples, 0.02%) + + + +ObjectSynchronizer::FastHashCode (1 samples, 0.02%) + + + +vfs_read (12 samples, 0.23%) + + + +java/io/ByteArrayInputStream:::read (1 samples, 0.02%) + + + +org/apache/logging/log4j/message/ParameterFormatter:::recursiveDeepToString (3 samples, 0.06%) + + + +java/util/regex/Pattern$Branch:::match (6 samples, 0.12%) + + + +com/google/gson/internal/bind/TypeAdapters$16:::write (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +hrtimer_try_to_cancel.part.25 (3 samples, 0.06%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +java/lang/reflect/Array:::get (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +do_sync_write (11 samples, 0.21%) + + + +Interpreter (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +java/lang/Throwable:::getOurStackTrace (473 samples, 9.20%) +java/lang/Thr.. + + +G1ParEvacuateFollowersClosure::do_void (11 samples, 0.21%) + + + +call_softirq (2 samples, 0.04%) + + + +inet_gro_receive (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/AbstractEndpoint:::processSocket (2 samples, 0.04%) + + + +org/springframework/http/MediaType:::isCompatibleWith (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +com/alibaba/fastjson/serializer/StringCodec:::getFastMatchToken (1 samples, 0.02%) + + + +java/util/regex/Pattern$Slice:::match (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +Method::bci_from (1 samples, 0.02%) + + + +JNIHandleBlock::allocate_handle (2 samples, 0.04%) + + + +jni_GetPrimitiveArrayCritical (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/clusterbuilder/ClusterBuilderSlot:::exit (15 samples, 0.29%) + + + +com/coohua/caf/core/sentinel/SentinelHttpFilter:::doFilter (3,548 samples, 69.03%) +com/coohua/caf/core/sentinel/SentinelHttpFilter:::doFilter + + +tcp_rcv_established (1 samples, 0.02%) + + + +skb_checksum (1 samples, 0.02%) + + + +java/util/concurrent/locks/ReentrantLock$NonfairSync:::lock (1 samples, 0.02%) + + + +Type::meet_helper (2 samples, 0.04%) + + + +org/springframework/web/util/UrlPathHelper:::getPathWithinApplication (5 samples, 0.10%) + + + +org/apache/catalina/connector/RequestFacade:::getHeader (4 samples, 0.08%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +epoll_ctl (2 samples, 0.04%) + + + +java/util/zip/GZIPOutputStream:::<init> (49 samples, 0.95%) + + + +hrtimer_try_to_cancel.part.25 (1 samples, 0.02%) + + + +os::stack_shadow_pages_available (1 samples, 0.02%) + + + +org/springframework/context/event/AbstractApplicationEventMulticaster$ListenerCacheKey:::hashCode (1 samples, 0.02%) + + + +org/springframework/web/servlet/handler/AbstractHandlerMethodMapping:::getHandlerInternal (10 samples, 0.19%) + + + +tcp_ack (1 samples, 0.02%) + + + +dput (1 samples, 0.02%) + + + +__wake_up_sync_key (16 samples, 0.31%) + + + +org/apache/kafka/common/protocol/types/ArrayOf:::validate (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +HandleArea::allocate_handle (1 samples, 0.02%) + + + +org/springframework/core/MethodParameter:::getNestedParameterType (1 samples, 0.02%) + + + +Java_java_util_zip_Inflater_end (1 samples, 0.02%) + + + +org/apache/catalina/connector/CoyoteAdapter:::service (224 samples, 4.36%) +org/a.. + + +G1CollectedHeap::evacuate_collection_set (3 samples, 0.06%) + + + +__sb_start_write (1 samples, 0.02%) + + + +irq_exit (2 samples, 0.04%) + + + +Parse::Parse (1 samples, 0.02%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics:::addEvent (1,243 samples, 24.18%) +com/coohuadata/analytics/javasdk/Coohu.. + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +HandleMarkCleaner::~HandleMarkCleaner (36 samples, 0.70%) + + + +java/util/GregorianCalendar:::computeFields (1 samples, 0.02%) + + + +sun/nio/ch/IOUtil:::drain (1 samples, 0.02%) + + + +java/util/HashSet:::iterator (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +org/apache/catalina/mapper/Mapper:::internalMap (1 samples, 0.02%) + + + +org/springframework/boot/actuate/metrics/web/servlet/LongTaskTimingHandlerInterceptor:::afterCompletion (2 samples, 0.04%) + + + +pthread_cond_signal@@GLIBC_2.3.2 (2 samples, 0.04%) + + + +org/apache/tomcat/util/http/NamesEnumerator:::findNext (1 samples, 0.02%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +java/util/ArrayList:::toArray (1 samples, 0.02%) + + + +do_futex (23 samples, 0.45%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11Processor:::endRequest (1 samples, 0.02%) + + + +org/apache/commons/lang3/StringUtils:::splitWorker (7 samples, 0.14%) + + + +java/util/zip/Inflater:::end (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/util/HashMap:::put (2 samples, 0.04%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/springframework/web/servlet/handler/AbstractHandlerMethodMapping:::lookupHandlerMethod (9 samples, 0.18%) + + + +org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler:::supportsReturnType (1 samples, 0.02%) + + + +fill_window (4 samples, 0.08%) + + + +java/util/GregorianCalendar:::computeFields (1 samples, 0.02%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics:::addEvent (6 samples, 0.12%) + + + +sun/reflect/GeneratedMethodAccessor76:::invoke (1 samples, 0.02%) + + + +sys_futex (24 samples, 0.47%) + + + +org/springframework/core/ResolvableType:::forMethodParameter (1 samples, 0.02%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +org/springframework/aop/aspectj/AbstractAspectJAdvice:::invokeAdviceMethod (1 samples, 0.02%) + + + +__generic_file_aio_write (20 samples, 0.39%) + + + +java/util/zip/Deflater:::end (1 samples, 0.02%) + + + +java/util/concurrent/ThreadPoolExecutor:::execute (23 samples, 0.45%) + + + +sun/reflect/GeneratedMethodAccessor68:::invoke (1 samples, 0.02%) + + + +tcp_schedule_loss_probe (1 samples, 0.02%) + + + +java/lang/String:::toLowerCase (1 samples, 0.02%) + + + +tcp_transmit_skb (1 samples, 0.02%) + + + +system_call_fastpath (24 samples, 0.47%) + + + +smp_apic_timer_interrupt (1 samples, 0.02%) + + + +pthread_cond_signal@@GLIBC_2.3.2 (21 samples, 0.41%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +alloc_pages_current (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +java/lang/Object:::toString (5 samples, 0.10%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +java/lang/StringCoding:::decode (1 samples, 0.02%) + + + +java/util/regex/Pattern$BitClass:::isSatisfiedBy (1 samples, 0.02%) + + + +_complete_monitor_locking_Java (1 samples, 0.02%) + + + +itable stub (1 samples, 0.02%) + + + +org/springframework/web/method/annotation/ModelFactory:::initModel (2 samples, 0.04%) + + + +java/text/SimpleDateFormat:::subParse (4 samples, 0.08%) + + + +sun/misc/Unsafe:::park (5 samples, 0.10%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy5:::annotationType (1 samples, 0.02%) + + + +org/springframework/util/ConcurrentReferenceHashMap$Segment:::restructureIfNecessary (1 samples, 0.02%) + + + +org/springframework/web/servlet/DispatcherServlet:::processDispatchResult (9 samples, 0.18%) + + + +__do_softirq (1 samples, 0.02%) + + + +deflateInit2_ (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/condition/RequestMethodsRequestCondition:::matchRequestMethod (5 samples, 0.10%) + + + +sun/nio/ch/EPollArrayWrapper:::epollWait (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::intValue (1 samples, 0.02%) + + + +java/text/DigitList:::getLong (1 samples, 0.02%) + + + +PhaseChaitin::interfere_with_live (3 samples, 0.06%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +OptoRuntime::register_finalizer (1 samples, 0.02%) + + + +Unsafe_Unpark (1 samples, 0.02%) + + + +mutex_unlock (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +futex_wait_queue_me (4 samples, 0.08%) + + + +org/apache/catalina/connector/Request:::setAttribute (4 samples, 0.08%) + + + +pthread_cond_signal@@GLIBC_2.3.2 (2 samples, 0.04%) + + + +BacktraceBuilder::expand (3 samples, 0.06%) + + + +do_softirq (1 samples, 0.02%) + + + +ObjectMonitor::enter (1 samples, 0.02%) + + + +java/util/zip/Deflater:::deflateBytes (9 samples, 0.18%) + + + +org/springframework/web/servlet/handler/AbstractHandlerMapping:::getHandler (10 samples, 0.19%) + + + +org/apache/catalina/connector/RequestFacade:::getAttribute (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +generic_exec_single (1 samples, 0.02%) + + + +deflateResetKeep (2 samples, 0.04%) + + + +tcp_rearm_rto (1 samples, 0.02%) + + + +__mark_inode_dirty (3 samples, 0.06%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +java/util/HashMap:::get (1 samples, 0.02%) + + + +Node::replace_edge (1 samples, 0.02%) + + + +copy_user_enhanced_fast_string (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +java/util/HashMap:::put (2 samples, 0.04%) + + + +do_softirq (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +arrayof_jint_fill (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::interrupt (26 samples, 0.51%) + + + +G1ParScanThreadState::copy_to_survivor_space (3 samples, 0.06%) + + + +InstanceRefKlass::oop_oop_iterate_backwards_nv (1 samples, 0.02%) + + + +jni_GetPrimitiveArrayCritical (4 samples, 0.08%) + + + +hrtimer_start_range_ns (1 samples, 0.02%) + + + +schedule (3 samples, 0.06%) + + + +sys_read (5 samples, 0.10%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +[libc-2.17.so] (20 samples, 0.39%) + + + +org/apache/kafka/common/requests/ProduceRequest:::<init> (3 samples, 0.06%) + + + +process_backlog (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +__libc_calloc (1 samples, 0.02%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +tcp_poll (1 samples, 0.02%) + + + +checkcast_arraycopy (1 samples, 0.02%) + + + +java/util/concurrent/ArrayBlockingQueue:::offer (2 samples, 0.04%) + + + +sun/reflect/GeneratedMethodAccessor92:::invoke (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/NioEndpoint$Poller:::run (128 samples, 2.49%) +or.. + + +java/util/Vector:::addElement (1 samples, 0.02%) + + + +ip_queue_xmit (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +AddNode::Identity (2 samples, 0.04%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +rcu_process_callbacks (1 samples, 0.02%) + + + +call_stub (5,032 samples, 97.90%) +call_stub + + +java/util/regex/Pattern$5:::isSatisfiedBy (7 samples, 0.14%) + + + +JvmtiVMObjectAllocEventCollector::~JvmtiVMObjectAllocEventCollector (1 samples, 0.02%) + + + +ep_remove (3 samples, 0.06%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/logger/LogSlot:::entry (9 samples, 0.18%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +JavaCalls::call_helper (5 samples, 0.10%) + + + +clock_gettime (1 samples, 0.02%) + + + +sys_poll (1 samples, 0.02%) + + + +all (5,140 samples, 100%) + + + +irq_exit (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +tcp_push (11 samples, 0.21%) + + + +com/coohua/caf/core/kv/JedisClusterClient:::expire (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +java/util/ArrayList:::toArray (1 samples, 0.02%) + + + +org/apache/kafka/common/utils/AbstractIterator:::hasNext (1 samples, 0.02%) + + + +updatewindow (6 samples, 0.12%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::poll (1 samples, 0.02%) + + + +java/util/GregorianCalendar:::computeFields (1 samples, 0.02%) + + + +java/util/LinkedHashMap:::afterNodeAccess (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getParameterMap (11 samples, 0.21%) + + + +do_softirq (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +com/coohua/ad/data/controller/AdDataController:::process (138 samples, 2.68%) +co.. + + +try_to_wake_up (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (16 samples, 0.31%) + + + +org/springframework/web/method/annotation/AbstractNamedValueMethodArgumentResolver:::resolveArgument (56 samples, 1.09%) + + + +itable stub (4 samples, 0.08%) + + + +net_rx_action (1 samples, 0.02%) + + + +com/coohua/caf/core/metrics/LatencyStat:::observe (1 samples, 0.02%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +updatewindow (18 samples, 0.35%) + + + +do_softirq (2 samples, 0.04%) + + + +tcp_transmit_skb (1 samples, 0.02%) + + + +wake_futex (2 samples, 0.04%) + + + +auditsys (1 samples, 0.02%) + + + +tcp4_gro_receive (1 samples, 0.02%) + + + +__tcp_push_pending_frames (29 samples, 0.56%) + + + +org/springframework/boot/actuate/trace/http/HttpExchangeTracer$$Lambda$656/561830191:::test (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping:::handleMatch (7 samples, 0.14%) + + + +java/util/regex/Pattern$Curly:::match (1 samples, 0.02%) + + + +Parse::do_all_blocks (1 samples, 0.02%) + + + +JavaThread::last_frame (1 samples, 0.02%) + + + +java/lang/String:::toLowerCase (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/clusterbuilder/ClusterBuilderSlot:::entry (10 samples, 0.19%) + + + +call_softirq (1 samples, 0.02%) + + + +LShiftLNode::Identity (1 samples, 0.02%) + + + +java/util/zip/Inflater:::inflateBytes (45 samples, 0.88%) + + + +net_rx_action (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/NioEndpoint$Poller:::add (27 samples, 0.53%) + + + +org/springframework/web/servlet/HandlerInterceptor:::postHandle (1 samples, 0.02%) + + + +org/springframework/http/MediaType:::isCompatibleWith (1 samples, 0.02%) + + + +wake_futex (3 samples, 0.06%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +java/nio/ByteBuffer:::get (1 samples, 0.02%) + + + +java/util/LinkedHashMap$LinkedHashIterator:::hasNext (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +try_fill_recv (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11Processor:::prepareResponse (1 samples, 0.02%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilter:::doFilterInternal (3,748 samples, 72.92%) +org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilter:::doFilterInternal + + +_new_array_Java (1 samples, 0.02%) + + + +java/util/HashMap:::resize (2 samples, 0.04%) + + + +G1CollectedHeap::new_mutator_alloc_region (1 samples, 0.02%) + + + +org/springframework/core/annotation/SynthesizedAnnotationInvocationHandler:::invoke (2 samples, 0.04%) + + + +jni_fast_GetIntField (1 samples, 0.02%) + + + +Type::hashcons (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +java/util/ArrayList:::iterator (1 samples, 0.02%) + + + +schedule (12 samples, 0.23%) + + + +com/coohua/ad/data/interceptor/UserInterceptor:::preHandle (9 samples, 0.18%) + + + +org/apache/catalina/connector/RequestFacade:::getAttribute (1 samples, 0.02%) + + + +java/security/Provider$ServiceKey:::<init> (1 samples, 0.02%) + + + +sock_def_readable (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (3,613 samples, 70.29%) +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter + + +com/alibaba/fastjson/serializer/IntegerCodec:::deserialze (1 samples, 0.02%) + + + +java/util/stream/ReferencePipeline:::collect (15 samples, 0.29%) + + + +__do_softirq (1 samples, 0.02%) + + + +sun/nio/ch/SelectorImpl:::select (31 samples, 0.60%) + + + +org/apache/catalina/authenticator/AuthenticatorBase:::invoke (3,778 samples, 73.50%) +org/apache/catalina/authenticator/AuthenticatorBase:::invoke + + +com/coohua/caf/core/kv/JedisClusterClient:::incrBy (1 samples, 0.02%) + + + +__strlen_sse2_pminub (4 samples, 0.08%) + + + +org/apache/tomcat/util/net/NioBlockingSelector$BlockPoller:::events (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +wake_futex (15 samples, 0.29%) + + + +Java_sun_nio_ch_EPollArrayWrapper_interrupt (1 samples, 0.02%) + + + +java/util/AbstractList$Itr:::hasNext (1 samples, 0.02%) + + + +smp_apic_timer_interrupt (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +org/springframework/util/StringUtils:::uriDecode (3 samples, 0.06%) + + + +java/io/ObjectOutputStream:::writeArray (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/logger/LogSlot:::entry (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +TypeArrayKlass::allocate_common (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (3,448 samples, 67.08%) +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter + + +pthread_getspecific (2 samples, 0.04%) + + + +UTF8::convert_to_unicode (2 samples, 0.04%) + + + +java/lang/String:::equals (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/impl/Log4jLogEvent:::getTimeMillis (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (192 samples, 3.74%) +org/.. + + +__do_softirq (1 samples, 0.02%) + + + +_new_array_nozero_Java (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (3,605 samples, 70.14%) +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter + + +pthread_getspecific (1 samples, 0.02%) + + + +deflate (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy0:::annotationType (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::nextToken (1 samples, 0.02%) + + + +java_lang_Thread::park_event (1 samples, 0.02%) + + + +kfree (1 samples, 0.02%) + + + +__vdso_gettimeofday (2 samples, 0.04%) + + + +generic_exec_single (1 samples, 0.02%) + + + +Interpreter (236 samples, 4.59%) +Inter.. + + +__do_softirq (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +writeBytes (40 samples, 0.78%) + + + +sys_futex (2 samples, 0.04%) + + + +ep_ptable_queue_proc (2 samples, 0.04%) + + + +Java_java_net_SocketOutputStream_socketWrite0 (3 samples, 0.06%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +com/sun/crypto/provider/AESCrypt:::init (17 samples, 0.33%) + + + +epoll_wait (1 samples, 0.02%) + + + +fsnotify (1 samples, 0.02%) + + + +java/lang/String:::charAt (3 samples, 0.06%) + + + +call_softirq (2 samples, 0.04%) + + + +tcp_transmit_skb (4 samples, 0.08%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +vfs_write (24 samples, 0.47%) + + + +call_softirq (1 samples, 0.02%) + + + +checkcast_arraycopy_uninit (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::setAttribute (1 samples, 0.02%) + + + +ThreadInVMfromNative::~ThreadInVMfromNative (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +futex_wait_queue_me (21 samples, 0.41%) + + + +javax/crypto/Cipher$Transform:::matches (2 samples, 0.04%) + + + +Parse::do_one_block (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ser/std/NumberSerializers$LongSerializer:::serialize (1 samples, 0.02%) + + + +JavaThread::thread_main_inner (5,080 samples, 98.83%) +JavaThread::thread_main_inner + + +__do_softirq (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/StringCache:::toString (2 samples, 0.04%) + + + +java/util/regex/Pattern$Curly:::match (4 samples, 0.08%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/web/method/HandlerMethod:::<init> (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +resource_allocate_bytes (4 samples, 0.08%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::initialize (15 samples, 0.29%) + + + +java/text/SimpleDateFormat:::compile (1 samples, 0.02%) + + + +Java_java_net_SocketInputStream_socketRead0 (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11Processor:::service (3,985 samples, 77.53%) +org/apache/coyote/http11/Http11Processor:::service + + +getnstimeofday64 (1 samples, 0.02%) + + + +itable stub (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +ConstantPool::klass_at_impl (1 samples, 0.02%) + + + +java/util/HashMap:::newNode (4 samples, 0.08%) + + + +sun/reflect/GeneratedMethodAccessor75:::invoke (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11InputBuffer:::parseRequestLine (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +org/springframework/web/bind/support/WebBindingInitializer:::initBinder (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (3,548 samples, 69.03%) +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/ArrayOf:::validate (1 samples, 0.02%) + + + +org/springframework/boot/actuate/trace/http/HttpExchangeTracer$$Lambda$699/710427695:::get (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +sysret_audit (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +tcp4_gro_receive (1 samples, 0.02%) + + + +__lll_unlock_wake (2 samples, 0.04%) + + + +do_softirq (1 samples, 0.02%) + + + +java/util/zip/GZIPOutputStream:::finish (9 samples, 0.18%) + + + +vtable stub (2 samples, 0.04%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +G1CollectedHeap::allocate_new_tlab (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::recycle (1 samples, 0.02%) + + + +jbd2_journal_get_write_access (1 samples, 0.02%) + + + +generic_exec_single (1 samples, 0.02%) + + + +do_softirq (2 samples, 0.04%) + + + +java/util/Formatter$FormatSpecifier:::print (7 samples, 0.14%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/NioEndpoint$SocketProcessor:::doRun (227 samples, 4.42%) +org/a.. + + +java/util/regex/Pattern$GroupHead:::match (3 samples, 0.06%) + + + +org/apache/logging/log4j/core/pattern/MessagePatternConverter:::format (3 samples, 0.06%) + + + +java/util/Formatter$FormatSpecifier:::print (4 samples, 0.08%) + + + +do_softirq (1 samples, 0.02%) + + + +oopDesc::obj_field_put (7 samples, 0.14%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +Parker::park (1 samples, 0.02%) + + + +org/springframework/util/AntPathMatcher:::doMatch (5 samples, 0.10%) + + + +tcp_done (1 samples, 0.02%) + + + +CollectedHeap::common_mem_allocate_init (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupHead:::match (106 samples, 2.06%) +j.. + + +org/apache/logging/log4j/core/filter/AbstractFilterable:::isFiltered (1 samples, 0.02%) + + + +_new_instance_Java (2 samples, 0.04%) + + + +org/apache/kafka/common/protocol/types/Type$7:::write (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +security_socket_recvmsg (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +finish_task_switch (1 samples, 0.02%) + + + +__schedule (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +JVM_FillInStackTrace (4 samples, 0.08%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +java/util/Comparator$$Lambda$213/1325144078:::compare (2 samples, 0.04%) + + + +do_futex (1 samples, 0.02%) + + + +java/lang/AbstractStringBuilder:::append (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/DefaultJSONParser:::parse (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupHead:::match (2 samples, 0.04%) + + + +org/apache/logging/log4j/message/ParameterizedMessage:::getFormattedMessage (6 samples, 0.12%) + + + +validate_xmit_skb.part.93 (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +itable stub (3 samples, 0.06%) + + + +call_softirq (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +java/util/AbstractList$Itr:::hasNext (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +ext4_mark_inode_dirty (2 samples, 0.04%) + + + +java/util/concurrent/ConcurrentHashMap:::replaceNode (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +tcp_push (4 samples, 0.08%) + + + +org/springframework/beans/factory/support/AbstractBeanFactory:::getBean (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/web/filter/HiddenHttpMethodFilter:::doFilterInternal (3,679 samples, 71.58%) +org/springframework/web/filter/HiddenHttpMethodFilter:::doFilterInternal + + +JVM_GetStackTraceElement (29 samples, 0.56%) + + + +_raw_spin_lock_bh (1 samples, 0.02%) + + + +ParseGenerator::generate (1 samples, 0.02%) + + + +com/coohua/platform/security/AESCoder:::decrypt (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +java/net/SocketOutputStream:::socketWrite0 (3 samples, 0.06%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +HandleMarkCleaner::~HandleMarkCleaner (1 samples, 0.02%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (6 samples, 0.12%) + + + +os::javaTimeNanos (1 samples, 0.02%) + + + +netif_skb_features (1 samples, 0.02%) + + + +JNIHandleBlock::allocate_handle (1 samples, 0.02%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (216 samples, 4.20%) +org/s.. + + +lock_hrtimer_base.isra.20 (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +java/util/StringTokenizer:::nextToken (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +__vdso_gettimeofday (2 samples, 0.04%) + + + +inet_sendmsg (16 samples, 0.31%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +java_lang_Throwable::fill_in_stack_trace (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +org/springframework/web/context/request/AbstractRequestAttributes:::executeRequestDestructionCallbacks (1 samples, 0.02%) + + + +tcp_recvmsg (3 samples, 0.06%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/appender/AsyncAppender$AsyncThread:::callAppenders (60 samples, 1.17%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +org/joda/time/tz/CachedDateTimeZone:::getInfo (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +org/jboss/netty/channel/SimpleChannelHandler:::writeRequested (2 samples, 0.04%) + + + +java/util/concurrent/ConcurrentHashMap:::putVal (2 samples, 0.04%) + + + +com/alibaba/csp/sentinel/slots/statistic/StatisticSlot:::entry (1 samples, 0.02%) + + + +G1CollectedHeap::process_discovered_references (3 samples, 0.06%) + + + +_new_array_nozero_Java (1 samples, 0.02%) + + + +__alloc_pages_nodemask (1 samples, 0.02%) + + + +org/springframework/util/AntPathMatcher:::doMatch (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/Schema:::read (5 samples, 0.10%) + + + +netif_receive_skb_internal (1 samples, 0.02%) + + + +java/util/HashMap$HashIterator:::hasNext (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +tcp_check_req (1 samples, 0.02%) + + + +java_lang_StackTraceElement::create (3 samples, 0.06%) + + + +java/util/concurrent/ArrayBlockingQueue:::offer (3 samples, 0.06%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +org/apache/kafka/clients/producer/internals/RecordAccumulator:::expiredBatches (2 samples, 0.04%) + + + +__inet_lookup_established (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor51:::invoke (3 samples, 0.06%) + + + +org/apache/catalina/connector/CoyoteAdapter:::postParseRequest (1 samples, 0.02%) + + + +java/nio/charset/Charset:::atBugLevel (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::poll (3 samples, 0.06%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +frame::sender_for_compiled_frame (15 samples, 0.29%) + + + +org/springframework/boot/actuate/web/trace/servlet/TraceableHttpServletRequest:::extractHeaders (29 samples, 0.56%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (1 samples, 0.02%) + + + +com/coohua/ad/data/manager/AdLogTrackManager:::logTrack (6 samples, 0.12%) + + + +free_old_xmit_skbs.isra.32 (1 samples, 0.02%) + + + +sun/nio/cs/UTF_8$Decoder:::decode (1 samples, 0.02%) + + + +do_sync_read (9 samples, 0.18%) + + + +org/springframework/context/event/SimpleApplicationEventMulticaster:::multicastEvent (3 samples, 0.06%) + + + +org/apache/catalina/connector/CoyoteAdapter:::parseSessionCookiesId (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +irq_exit (2 samples, 0.04%) + + + +napi_complete_done (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +finish_task_switch (12 samples, 0.23%) + + + +os::javaTimeMillis (3 samples, 0.06%) + + + +java/util/Collections$UnmodifiableSet:::hashCode (1 samples, 0.02%) + + + +Parse::do_all_blocks (1 samples, 0.02%) + + + +run_timer_softirq (1 samples, 0.02%) + + + +futex_wake_op (2 samples, 0.04%) + + + +_new_array_Java (1 samples, 0.02%) + + + +tcp_v4_early_demux (1 samples, 0.02%) + + + +java/util/concurrent/ThreadPoolExecutor:::runWorker (4,105 samples, 79.86%) +java/util/concurrent/ThreadPoolExecutor:::runWorker + + +os::javaTimeMillis (1 samples, 0.02%) + + + +hash_futex (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ser/impl/PropertySerializerMap$Multi:::serializerFor (1 samples, 0.02%) + + + +java/util/LinkedHashMap$LinkedHashIterator:::hasNext (1 samples, 0.02%) + + + +java/util/HashMap:::putMapEntries (18 samples, 0.35%) + + + +wake_futex (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +G1SATBCardTableLoggingModRefBS::write_ref_array_work (2 samples, 0.04%) + + + +G1SATBCardTableLoggingModRefBS::invalidate (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/condition/AbstractMediaTypeExpression:::compareTo (3 samples, 0.06%) + + + +checkcast_arraycopy (3 samples, 0.06%) + + + +java/lang/ThreadLocal:::set (4 samples, 0.08%) + + + +Compile::Code_Gen (30 samples, 0.58%) + + + +ret_from_intr (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +jbd2_journal_dirty_metadata (1 samples, 0.02%) + + + +com/coohua/ad/data/manager/AdDataManager:::incrMiniProgramClickLimit (1 samples, 0.02%) + + + +set_skb_frag (1 samples, 0.02%) + + + +mutex_unlock (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy40:::annotationType (1 samples, 0.02%) + + + +sun/nio/cs/UTF_8$Decoder:::decodeArrayLoop (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +OptoRuntime::new_array_C (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/ArrayOf:::sizeOf (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor60:::invoke (1 samples, 0.02%) + + + +_raw_spin_lock (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +UTF8::unicode_length (19 samples, 0.37%) + + + +org/apache/logging/log4j/message/ParameterizedMessage:::getFormattedMessage (1 samples, 0.02%) + + + +com/coohua/ad/data/interceptor/UserInterceptor$BaseKeyUglyUtil:::getBaseKey (97 samples, 1.89%) +c.. + + +com/alibaba/fastjson/parser/deserializer/FieldDeserializer:::setValue (1 samples, 0.02%) + + + +MemNode::Ideal_common (1 samples, 0.02%) + + + +__ext4_get_inode_loc (1 samples, 0.02%) + + + +com/alibaba/fastjson/JSON:::parseObject (13 samples, 0.25%) + + + +org/springframework/beans/TypeConverterSupport:::doConvert (33 samples, 0.64%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +org/apache/kafka/clients/NodeApiVersions:::latestUsableVersion (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ser/std/NumberSerializers$LongSerializer:::serialize (1 samples, 0.02%) + + + +file_update_time (3 samples, 0.06%) + + + +__do_softirq (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +sch_direct_xmit (3 samples, 0.06%) + + + +run_timer_softirq (1 samples, 0.02%) + + + +sys_futex (1 samples, 0.02%) + + + +java/util/stream/ReduceOps$3:::getOpFlags (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +java/util/concurrent/ConcurrentHashMap:::get (7 samples, 0.14%) + + + +process_backlog (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11Processor:::prepareResponse (1 samples, 0.02%) + + + +futex_wait_queue_me (5 samples, 0.10%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +InstanceKlass::allocate_instance (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (192 samples, 3.74%) +org/.. + + +java/util/ArrayList:::isEmpty (1 samples, 0.02%) + + + +clock_gettime (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::smartMatch (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +ep_scan_ready_list.isra.7 (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +JVM_GetStackTraceDepth (1 samples, 0.02%) + + + +io/micrometer/core/instrument/Clock$1:::monotonicTime (1 samples, 0.02%) + + + +do_sync_read (2 samples, 0.04%) + + + +__skb_gro_checksum_complete (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +local_bh_disable (1 samples, 0.02%) + + + +com/coohua/platform/security/AESCoder:::decrypt (7 samples, 0.14%) + + + +ret_from_intr (1 samples, 0.02%) + + + +org/apache/tomcat/util/http/ValuesEnumerator:::findNext (7 samples, 0.14%) + + + +unlock_page (1 samples, 0.02%) + + + +java/lang/String:::toLowerCase (7 samples, 0.14%) + + + +org/apache/kafka/common/protocol/types/ArrayOf:::read (5 samples, 0.10%) + + + +CollectedHeap::common_mem_allocate_init (6 samples, 0.12%) + + + +smp_apic_timer_interrupt (1 samples, 0.02%) + + + +auditsys (1 samples, 0.02%) + + + +Java_java_util_zip_Deflater_deflateBytes (169 samples, 3.29%) +Jav.. + + +java/util/regex/Pattern:::matcher (2 samples, 0.04%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +sk_reset_timer (1 samples, 0.02%) + + + +java/lang/StringBuffer:::append (3 samples, 0.06%) + + + +kvm_clock_get_cycles (1 samples, 0.02%) + + + +skb_checksum (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +org/apache/tomcat/util/http/MimeHeaders:::getUniqueValue (1 samples, 0.02%) + + + +tcp4_gro_receive (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +itable stub (1 samples, 0.02%) + + + +jni_SetIntField (5 samples, 0.10%) + + + +sun/nio/cs/ISO_8859_1$Decoder:::decodeLoop (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +set_skb_frag (1 samples, 0.02%) + + + +JVM_IHashCode (1 samples, 0.02%) + + + +itable stub (2 samples, 0.04%) + + + +org/springframework/web/util/UrlPathHelper:::getPathWithinApplication (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +org/apache/coyote/AbstractProtocol$ConnectionHandler:::process (225 samples, 4.38%) +org/a.. + + +com/alibaba/csp/sentinel/slots/nodeselector/NodeSelectorSlot:::entry (2 samples, 0.04%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +java/util/zip/InflaterInputStream:::read (48 samples, 0.93%) + + + +do_softirq (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +__tcp_push_pending_frames (11 samples, 0.21%) + + + +do_futex (31 samples, 0.60%) + + + +org/springframework/core/annotation/AnnotationUtils:::getAnnotation (2 samples, 0.04%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/apache/kafka/common/utils/Checksums:::update (8 samples, 0.16%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +org/springframework/web/servlet/FrameworkServlet:::publishRequestHandledEvent (29 samples, 0.56%) + + + +do_softirq (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11InputBuffer:::parseRequestLine (32 samples, 0.62%) + + + +sun/nio/ch/EPollArrayWrapper:::interrupt (12 samples, 0.23%) + + + +ip_rcv (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +java/util/ArrayList:::toArray (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +ConstantPool::klass_at_impl (1 samples, 0.02%) + + + +org/apache/kafka/clients/InFlightRequests:::nodesWithTimedOutRequests (3 samples, 0.06%) + + + +org/apache/logging/log4j/core/appender/AsyncAppender:::append (47 samples, 0.91%) + + + +[libpthread-2.17.so] (6 samples, 0.12%) + + + +sun/misc/Unsafe:::unpark (2 samples, 0.04%) + + + +org/apache/kafka/clients/producer/internals/RecordAccumulator:::append (13 samples, 0.25%) + + + +frame::sender (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +java/util/Formatter$FormatSpecifier:::print (2 samples, 0.04%) + + + +org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping:::handleMatch (1 samples, 0.02%) + + + +os::is_interrupted (1 samples, 0.02%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +[libpthread-2.17.so] (1 samples, 0.02%) + + + +org/springframework/util/PropertyPlaceholderHelper:::parseStringValue (2 samples, 0.04%) + + + +Klass::external_name (2 samples, 0.04%) + + + +g1_post_barrier_slow Runtime1 stub (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/CtSph:::entryWithPriority (1 samples, 0.02%) + + + +tcp_transmit_skb (1 samples, 0.02%) + + + +G1CollectedHeap::allocate_new_tlab (1 samples, 0.02%) + + + +try_to_wake_up (15 samples, 0.29%) + + + +packet_rcv (3 samples, 0.06%) + + + +java/util/stream/ReferencePipeline:::collect (3 samples, 0.06%) + + + +java/util/zip/Deflater:::init (43 samples, 0.84%) + + + +process_backlog (1 samples, 0.02%) + + + +try_to_wake_up (5 samples, 0.10%) + + + +com/alibaba/csp/sentinel/slots/nodeselector/NodeSelectorSlot:::entry (12 samples, 0.23%) + + + +com/coohua/caf/core/sentinel/SentinelHttpInterceptor:::afterCompletion (18 samples, 0.35%) + + + +org/springframework/boot/actuate/web/trace/servlet/TraceableHttpServletRequest:::getUri (10 samples, 0.19%) + + + +sysret_audit (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +ext4_mark_inode_dirty (7 samples, 0.14%) + + + +call_softirq (1 samples, 0.02%) + + + +sysret_audit (1 samples, 0.02%) + + + +org/springframework/web/servlet/FrameworkServlet:::publishRequestHandledEvent (3 samples, 0.06%) + + + +StringTable::intern (242 samples, 4.71%) +Strin.. + + +fsnotify (1 samples, 0.02%) + + + +vfs_write (41 samples, 0.80%) + + + +com/sun/proxy/$Proxy109:::annotationType (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter:::format (1 samples, 0.02%) + + + +java/util/ArrayList:::toArray (2 samples, 0.04%) + + + +__x2apic_send_IPI_mask (2 samples, 0.04%) + + + +java/util/GregorianCalendar:::getFixedDate (1 samples, 0.02%) + + + +inet_recvmsg (3 samples, 0.06%) + + + +org/springframework/web/servlet/mvc/method/RequestMappingInfo:::getMatchingCondition (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/NioEndpoint$NioSocketWrapper:::doWrite (5 samples, 0.10%) + + + +com/sun/proxy/$Proxy77:::annotationType (2 samples, 0.04%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +tcp_v4_early_demux (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +sun/nio/ch/SocketChannelImpl:::read (1 samples, 0.02%) + + + +InstanceKlass::allocate_objArray (1 samples, 0.02%) + + + +java/lang/String:::hashCode (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (3 samples, 0.06%) + + + +java/net/URI$Parser:::parseAuthority (2 samples, 0.04%) + + + +org/apache/catalina/connector/CoyoteAdapter:::parsePathParameters (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor103:::invoke (1 samples, 0.02%) + + + +sys_futex (2 samples, 0.04%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +tcp_write_xmit (1 samples, 0.02%) + + + +java/lang/ThreadLocal$ThreadLocalMap:::set (3 samples, 0.06%) + + + +do_softirq (1 samples, 0.02%) + + + +__do_softirq (2 samples, 0.04%) + + + +java_lang_StackTraceElement::set_fileName (1 samples, 0.02%) + + + +java/util/regex/Pattern$Slice:::match (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy0:::annotationType (1 samples, 0.02%) + + + +sys_futex (5 samples, 0.10%) + + + +CodeHeap::find_start (1 samples, 0.02%) + + + +__audit_syscall_exit (2 samples, 0.04%) + + + +SYSC_recvfrom (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::recycle (1 samples, 0.02%) + + + +do_futex (19 samples, 0.37%) + + + +java/util/regex/Pattern:::matcher (2 samples, 0.04%) + + + +org/apache/tomcat/util/buf/StringCache:::toString (12 samples, 0.23%) + + + +G1SATBCardTableLoggingModRefBS::write_ref_array_work (1 samples, 0.02%) + + + +objArrayOopDesc::obj_at (1 samples, 0.02%) + + + +[libpthread-2.17.so] (47 samples, 0.91%) + + + +ret_from_intr (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +[libc-2.17.so] (18 samples, 0.35%) + + + +java_lang_StackTraceElement::create (2 samples, 0.04%) + + + +[libpthread-2.17.so] (12 samples, 0.23%) + + + +process_backlog (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +java/util/Arrays:::sort (1 samples, 0.02%) + + + +java/text/DecimalFormat:::subparse (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/http/converter/AbstractHttpMessageConverter:::canWrite (4 samples, 0.08%) + + + +irq_exit (1 samples, 0.02%) + + + +system_call_fastpath (3 samples, 0.06%) + + + +java/util/concurrent/ArrayBlockingQueue:::offer (35 samples, 0.68%) + + + +org/apache/kafka/common/protocol/types/ArrayOf:::validate (1 samples, 0.02%) + + + +com/alibaba/fastjson/serializer/StringCodec:::deserialze (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::interrupt (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +com/alibaba/fastjson/JSON:::parseObject (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +irq_exit (2 samples, 0.04%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +generic_exec_single (1 samples, 0.02%) + + + +Parse::do_one_block (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +page_to_skb (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +jni_GetByteArrayRegion (1 samples, 0.02%) + + + +LoadNode::Ideal (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/ArrayOf:::sizeOf (2 samples, 0.04%) + + + +java/util/concurrent/ConcurrentHashMap:::replaceNode (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +org/apache/kafka/common/metrics/Sensor:::record (6 samples, 0.12%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +java/util/Formatter$FormatSpecifier:::print (3 samples, 0.06%) + + + +Unsafe_Unpark (2 samples, 0.04%) + + + +dev_gro_receive (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +map_id_up (1 samples, 0.02%) + + + +__audit_syscall_exit (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy49:::annotationType (1 samples, 0.02%) + + + +java/util/concurrent/ThreadPoolExecutor:::getTask (5 samples, 0.10%) + + + +org/apache/kafka/common/protocol/types/ArrayOf:::sizeOf (4 samples, 0.08%) + + + +__do_softirq (1 samples, 0.02%) + + + +com/coohua/caf/core/kv/JedisClusterClient$$FastClassBySpringCGLIB$$1bc9b45c:::invoke (1 samples, 0.02%) + + + +Unsafe_Park (38 samples, 0.74%) + + + +org/apache/logging/log4j/core/pattern/LiteralPatternConverter:::format (1 samples, 0.02%) + + + +java/text/DateFormatSymbols:::copyMembers (2 samples, 0.04%) + + + +sun/nio/cs/UTF_8$Encoder:::encode (10 samples, 0.19%) + + + +java/util/regex/Pattern$Branch:::match (4 samples, 0.08%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +tcp_send_ack (1 samples, 0.02%) + + + +generic_exec_single (1 samples, 0.02%) + + + +sun/nio/cs/ISO_8859_1$Decoder:::decodeLoop (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +cap_file_permission (1 samples, 0.02%) + + + +tcp_rearm_rto (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONScanner:::scanFieldLong (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +apic_timer_interrupt (1 samples, 0.02%) + + + +java_lang_String::equals (37 samples, 0.72%) + + + +_raw_spin_unlock_irqrestore (2 samples, 0.04%) + + + +org/springframework/util/StringUtils:::uriDecode (2 samples, 0.04%) + + + +build_tree (3 samples, 0.06%) + + + +ktime_get_real (1 samples, 0.02%) + + + +do_futex (2 samples, 0.04%) + + + +ret_from_intr (1 samples, 0.02%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +java/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1:::next (2 samples, 0.04%) + + + +schedule_hrtimeout_range (16 samples, 0.31%) + + + +G1CollectedHeap::unsafe_max_tlab_alloc (1 samples, 0.02%) + + + +com/coohua/caf/core/kv/JedisClusterClientAspect:::around (4 samples, 0.08%) + + + +sk_stream_alloc_skb (2 samples, 0.04%) + + + +inet_recvmsg (9 samples, 0.18%) + + + +java/lang/StringBuffer:::append (1 samples, 0.02%) + + + +org/apache/kafka/common/metrics/stats/SampledStat:::record (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +__skb_to_sgvec (2 samples, 0.04%) + + + +org/apache/tomcat/util/http/NamesEnumerator:::findNext (1 samples, 0.02%) + + + +org/springframework/util/StringUtils:::tokenizeToStringArray (23 samples, 0.45%) + + + +sun/nio/ch/IOUtil:::drain (3 samples, 0.06%) + + + +sun/nio/cs/UTF_8$Decoder:::decode (1 samples, 0.02%) + + + +java/util/regex/Pattern$BmpCharProperty:::match (1 samples, 0.02%) + + + +vfs_read (5 samples, 0.10%) + + + +net_rx_action (1 samples, 0.02%) + + + +try_to_wake_up (2 samples, 0.04%) + + + +org/springframework/util/ConcurrentReferenceHashMap$Segment:::restructureIfNecessary (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::parseParameters (63 samples, 1.23%) + + + +sun/misc/Unsafe:::park (33 samples, 0.64%) + + + +Unsafe_Unpark (2 samples, 0.04%) + + + +java_lang_Throwable::get_stack_trace_element (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +CodeBlob::is_zombie (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +org/apache/kafka/common/metrics/Sensor:::record (8 samples, 0.16%) + + + +objArrayOopDesc::obj_at (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +CodeHeap::find_start (7 samples, 0.14%) + + + +org/apache/kafka/common/requests/ProduceResponse:::<init> (1 samples, 0.02%) + + + +java/util/regex/Pattern:::sequence (1 samples, 0.02%) + + + +_raw_spin_lock (1 samples, 0.02%) + + + +java/util/stream/ReferencePipeline$2$1:::accept (7 samples, 0.14%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +itable stub (1 samples, 0.02%) + + + +org/springframework/web/method/annotation/InitBinderDataBinderFactory:::initBinder (1 samples, 0.02%) + + + +java/util/HashMap:::newNode (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +javax/crypto/Cipher:::getInstance (5 samples, 0.10%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +StringTable::intern (14 samples, 0.27%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +java/util/LinkedHashMap:::get (1 samples, 0.02%) + + + +org/springframework/boot/actuate/metrics/web/servlet/LongTaskTimingHandlerInterceptor:::afterCompletion (1 samples, 0.02%) + + + +sys_futex (19 samples, 0.37%) + + + +net_rx_action (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +java/util/Locale:::getLanguage (1 samples, 0.02%) + + + +JavaThread::thread_from_jni_environment (22 samples, 0.43%) + + + +do_futex (2 samples, 0.04%) + + + +HandleMarkCleaner::~HandleMarkCleaner (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +sun/nio/cs/UTF_8$Encoder:::encode (1 samples, 0.02%) + + + +futex_wake_op (3 samples, 0.06%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +pipe_write (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +pthread_self (1 samples, 0.02%) + + + +org/apache/kafka/common/network/NetworkReceive:::readFrom (18 samples, 0.35%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +__schedule (1 samples, 0.02%) + + + +__schedule (1 samples, 0.02%) + + + +sys_write (25 samples, 0.49%) + + + +org/apache/logging/log4j/core/config/AwaitCompletionReliabilityStrategy:::afterLogEvent (1 samples, 0.02%) + + + +ext4_get_inode_loc (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/text/DateFormatSymbols:::initializeData (2 samples, 0.04%) + + + +java/util/LinkedHashMap:::clear (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (200 samples, 3.89%) +org/.. + + +org/apache/tomcat/util/http/MimeHeaders:::getValue (2 samples, 0.04%) + + + +org/apache/kafka/clients/producer/internals/Sender$SenderMetrics:::maybeRegisterTopicMetrics (1 samples, 0.02%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +pthread_cond_timedwait@@GLIBC_2.3.2 (29 samples, 0.56%) + + + +java/util/Calendar:::<init> (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +frame::oops_do_internal (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor66:::invoke (1 samples, 0.02%) + + + +itable stub (1 samples, 0.02%) + + + +org/springframework/web/servlet/support/WebContentGenerator:::prepareResponse (1 samples, 0.02%) + + + +org/springframework/web/util/UrlPathHelper:::getLookupPathForRequest (9 samples, 0.18%) + + + +itable stub (1 samples, 0.02%) + + + +java/lang/Throwable:::getStackTraceDepth (4 samples, 0.08%) + + + +do_sync_write (1 samples, 0.02%) + + + +com/coohua/ad/data/interceptor/UserInterceptor$BaseKeyUglyUtil:::getBaseKey (9 samples, 0.18%) + + + +com/fasterxml/jackson/databind/ser/impl/PropertySerializerMap$Double:::serializerFor (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +java/util/Formatter:::format (23 samples, 0.45%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::matchField (3 samples, 0.06%) + + + +com/sun/crypto/provider/AESCrypt:::makeSessionKey (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +rw_verify_area (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +ext4_get_inode_loc (1 samples, 0.02%) + + + +java/net/URI$Parser:::parseHostname (1 samples, 0.02%) + + + +do_sync_write (38 samples, 0.74%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +tcp_data_queue (1 samples, 0.02%) + + + +os::javaTimeMillis (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (3,765 samples, 73.25%) +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter + + +ip_local_out_sk (1 samples, 0.02%) + + + +apic_timer_interrupt (1 samples, 0.02%) + + + +PhaseIdealLoop::split_if_with_blocks_post (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +start_thread (5,106 samples, 99.34%) +start_thread + + +do_futex (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +__libc_send (6 samples, 0.12%) + + + +com/coohua/caf/core/sentinel/SentinelHttpInterceptor:::afterCompletion (1 samples, 0.02%) + + + +_raw_spin_unlock (1 samples, 0.02%) + + + +wake_futex (1 samples, 0.02%) + + + +tcp_poll (4 samples, 0.08%) + + + +java/util/regex/Pattern$BranchConn:::match (3 samples, 0.06%) + + + +dev_gro_receive (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +org/springframework/boot/actuate/trace/http/HttpExchangeTracer:::getHeadersIfIncluded (4 samples, 0.08%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +Interpreter (12 samples, 0.23%) + + + +futex_wake_op (31 samples, 0.60%) + + + +com/fasterxml/jackson/databind/ser/std/MapSerializer:::serializeFields (34 samples, 0.66%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +com/coohua/caf/core/metrics/LatencyStat:::setMin (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +java/util/GregorianCalendar:::computeFields (2 samples, 0.04%) + + + +com/coohua/ad/data/manager/AdLogTrackManager:::logTrack (60 samples, 1.17%) + + + +java/util/regex/Pattern$BranchConn:::match (1 samples, 0.02%) + + + +_new_array_nozero_Java (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/appender/RollingRandomAccessFileAppender:::append (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +call_stub (1 samples, 0.02%) + + + +java/util/HashMap:::newNode (1 samples, 0.02%) + + + +pvclock_clocksource_read (1 samples, 0.02%) + + + +page_waitqueue (1 samples, 0.02%) + + + +file_update_time (1 samples, 0.02%) + + + +java/lang/StringBuilder:::append (1 samples, 0.02%) + + + +java/util/HashMap:::put (3 samples, 0.06%) + + + +com/weibo/api/motan/filter/AccessLogFilter:::logAccess (5 samples, 0.10%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +tcp_send_ack (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils$AnnotationCollector:::process (11 samples, 0.21%) + + + +call_stub (1 samples, 0.02%) + + + +sun/security/jca/ProviderList$ServiceList:::tryGet (23 samples, 0.45%) + + + +sys_epoll_ctl (13 samples, 0.25%) + + + +java/lang/ref/Reference:::tryHandlePending (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +Reflection::array_get (2 samples, 0.04%) + + + +net_rx_action (1 samples, 0.02%) + + + +get_page_from_freelist (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +com/coohua/ad/data/manager/AdDataManager:::incrUserDayClickLimit (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (200 samples, 3.89%) +org/.. + + +__do_softirq (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ser/std/NumberSerializers$IntegerSerializer:::serialize (1 samples, 0.02%) + + + +JNIHandleBlock::allocate_handle (4 samples, 0.08%) + + + +UTF8::unicode_length (1 samples, 0.02%) + + + +io/micrometer/core/instrument/Tags$ArrayIterator:::<init> (1 samples, 0.02%) + + + +org/springframework/web/util/UrlPathHelper:::decodeInternal (3 samples, 0.06%) + + + +WeakPreserveExceptionMark::WeakPreserveExceptionMark (14 samples, 0.27%) + + + +java/util/GregorianCalendar:::computeTime (1 samples, 0.02%) + + + +Java_java_net_SocketInputStream_socketRead0 (1 samples, 0.02%) + + + +com/coohua/caf/core/kv/JedisClusterClient$$EnhancerBySpringCGLIB$$b8ee9ffc:::incrBy (1 samples, 0.02%) + + + +com/coohua/caf/core/sentinel/SentinelHttpFilter:::doFilter (200 samples, 3.89%) +com/.. + + +java/util/HashMap:::put (2 samples, 0.04%) + + + +hrtimer_start_range_ns (1 samples, 0.02%) + + + +JNIHandleBlock::allocate_handle (19 samples, 0.37%) + + + +org/springframework/aop/aspectj/AbstractAspectJAdvice:::invokeAdviceMethod (2 samples, 0.04%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +inet_gro_receive (1 samples, 0.02%) + + + +__ext4_handle_dirty_metadata (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +java/util/regex/Pattern$Curly:::match (47 samples, 0.91%) + + + +java/net/URI$Parser:::parseHostname (1 samples, 0.02%) + + + +org/apache/kafka/clients/NetworkClient:::canSendRequest (1 samples, 0.02%) + + + +hrtimer_cancel (2 samples, 0.04%) + + + +WeakPreserveExceptionMark::WeakPreserveExceptionMark (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +java/util/ArrayList:::toArray (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::subParse (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +G1ParScanThreadState::trim_queue (3 samples, 0.06%) + + + +java/lang/StringBuilder:::append (1 samples, 0.02%) + + + +PhaseChaitin::Split (4 samples, 0.08%) + + + +org/apache/kafka/clients/producer/internals/Sender$SenderMetrics:::updateProduceRequestMetrics (13 samples, 0.25%) + + + +IndexSetIterator::IndexSetIterator (1 samples, 0.02%) + + + +InstanceKlass::allocate_instance (2 samples, 0.04%) + + + +ret_from_intr (1 samples, 0.02%) + + + +pipe_write (11 samples, 0.21%) + + + +virtnet_poll (1 samples, 0.02%) + + + +ep_send_events_proc (3 samples, 0.06%) + + + +do_readv_writev (17 samples, 0.33%) + + + +org/springframework/core/annotation/AnnotatedElementUtils:::searchWithFindSemantics (4 samples, 0.08%) + + + +do_softirq (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getAttribute (2 samples, 0.04%) + + + +java/util/LinkedHashMap:::afterNodeInsertion (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/tomcat/util/http/ValuesEnumerator:::findNext (1 samples, 0.02%) + + + +sock_def_readable (1 samples, 0.02%) + + + +do_futex (2 samples, 0.04%) + + + +java/util/concurrent/ArrayBlockingQueue:::offer (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy5:::annotationType (2 samples, 0.04%) + + + +org/apache/kafka/clients/producer/internals/ProducerInterceptors:::onAcknowledgement (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +java/lang/String:::equals (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +sys_epoll_ctl (2 samples, 0.04%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/Type$8:::sizeOf (2 samples, 0.04%) + + + +org/apache/kafka/common/protocol/types/Type$7:::read (2 samples, 0.04%) + + + +java/text/DateFormatSymbols:::getProviderInstance (1 samples, 0.02%) + + + +java/lang/Throwable:::getStackTraceDepth (1 samples, 0.02%) + + + +itable stub (1 samples, 0.02%) + + + +system_call_fastpath (5 samples, 0.10%) + + + +system_call_fastpath (5 samples, 0.10%) + + + +JavaThread::last_frame (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +apic_timer_interrupt (1 samples, 0.02%) + + + +java/util/HashMap$EntrySet:::iterator (1 samples, 0.02%) + + + +lock_timer_base.isra.33 (1 samples, 0.02%) + + + +pthread_cond_signal@@GLIBC_2.3.2 (2 samples, 0.04%) + + + +org/apache/tomcat/util/http/Parameters:::processParameters (5 samples, 0.10%) + + + +call_softirq (1 samples, 0.02%) + + + +deflate (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +Symbol::as_klass_external_name (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy47:::annotationType (1 samples, 0.02%) + + + +org/springframework/web/accept/ContentNegotiationManager:::resolveMediaTypes (1 samples, 0.02%) + + + +java/lang/StringCoding:::encode (1 samples, 0.02%) + + + +schedule_hrtimeout_range_clock (1 samples, 0.02%) + + + +java/util/Formatter$FormatSpecifier:::localizedMagnitude (2 samples, 0.04%) + + + +java/util/HashSet:::contains (2 samples, 0.04%) + + + +do_softirq (1 samples, 0.02%) + + + +ObjectMonitor::enter (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/statistic/StatisticSlot:::exit (14 samples, 0.27%) + + + +sun/reflect/GeneratedMethodAccessor50:::invoke (1 samples, 0.02%) + + + +org/apache/catalina/connector/RequestFacade:::getHeader (1 samples, 0.02%) + + + +sysret_audit (2 samples, 0.04%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +BarrierSet::static_write_ref_array_post (2 samples, 0.04%) + + + +java/util/Formatter$FormatSpecifier:::print (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/springframework/web/method/support/InvocableHandlerMethod:::<init> (5 samples, 0.10%) + + + +os::javaTimeMillis (2 samples, 0.04%) + + + +com/coohua/caf/core/metrics/ProfilerHttpFilter:::doFilter (203 samples, 3.95%) +com/.. + + +arrayof_jint_fill (1 samples, 0.02%) + + + +java/util/regex/Pattern$3:::isSatisfiedBy (1 samples, 0.02%) + + + +java/util/GregorianCalendar:::computeFields (1 samples, 0.02%) + + + +schedule (1 samples, 0.02%) + + + +sun/nio/ch/EPollSelectorImpl:::putEventOps (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/CtSph:::entryWithPriority (2 samples, 0.04%) + + + +lock_sock_nested (1 samples, 0.02%) + + + +java/lang/Class:::reflectionData (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +smp_apic_timer_interrupt (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupHead:::match (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/StreamingResponseBodyReturnValueHandler:::supportsReturnType (1 samples, 0.02%) + + + +finish_task_switch (17 samples, 0.33%) + + + +org/springframework/context/event/AbstractApplicationEventMulticaster$ListenerCacheKey:::hashCode (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +itable stub (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/NioBlockingSelector:::write (5 samples, 0.10%) + + + +frame::sender (16 samples, 0.31%) + + + +inet_sendmsg (2 samples, 0.04%) + + + +com/coohua/ad/data/interceptor/UserInterceptor:::buildLogMessage (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +org/apache/kafka/common/network/Selector$SelectorMetrics:::recordBytesSent (7 samples, 0.14%) + + + +HandleMarkCleaner::~HandleMarkCleaner (1 samples, 0.02%) + + + +com/coohua/ad/data/manager/AdLogTrackManager:::logTrack (1,261 samples, 24.53%) +com/coohua/ad/data/manager/AdLogTrackM.. + + +__do_softirq (1 samples, 0.02%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics:::assertKey (1 samples, 0.02%) + + + +system_call_fastpath (18 samples, 0.35%) + + + +kfree (1 samples, 0.02%) + + + +JNIHandleBlock::allocate_handle (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +checkcast_arraycopy_uninit (2 samples, 0.04%) + + + +java/net/SocketInputStream:::read (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +com/alibaba/fastjson/JSON:::parseObject (1 samples, 0.02%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +BacktraceBuilder::push (1 samples, 0.02%) + + + +__lll_unlock_wake (1 samples, 0.02%) + + + +getnstimeofday64 (1 samples, 0.02%) + + + +ip_finish_output (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +java/util/Spliterators$IteratorSpliterator:::forEachRemaining (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +G1RootProcessor::scan_remembered_sets (5 samples, 0.10%) + + + +java/util/concurrent/ConcurrentHashMap:::putVal (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +sk_run_filter (2 samples, 0.04%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +checkcast_arraycopy (2 samples, 0.04%) + + + +deflateEnd (1 samples, 0.02%) + + + +org/apache/kafka/clients/NetworkClient:::handleInitiateApiVersionRequests (2 samples, 0.04%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +java/lang/String:::indexOf (1 samples, 0.02%) + + + +dev_hard_start_xmit (15 samples, 0.29%) + + + +java/util/Calendar:::setTimeInMillis (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +OptoRuntime::register_finalizer (4 samples, 0.08%) + + + +java/util/stream/ReduceOps$3:::getOpFlags (1 samples, 0.02%) + + + +_complete_monitor_locking_Java (2 samples, 0.04%) + + + +org/apache/catalina/connector/Request:::setAttribute (2 samples, 0.04%) + + + +com/alibaba/fastjson/serializer/IntegerCodec:::deserialze (2 samples, 0.04%) + + + +java/util/concurrent/ConcurrentHashMap:::replaceNode (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +sysret_audit (2 samples, 0.04%) + + + +CollectedHeap::allocate_from_tlab_slow (1 samples, 0.02%) + + + +Compile::get_alias_index (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (4 samples, 0.08%) + + + +tcp_current_mss (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::matchField (2 samples, 0.04%) + + + +LatestMethodCache::get_method (1 samples, 0.02%) + + + +HandleMarkCleaner::~HandleMarkCleaner (11 samples, 0.21%) + + + +java/security/Provider:::getService (22 samples, 0.43%) + + + +PhaseLive::add_liveout (3 samples, 0.06%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (1 samples, 0.02%) + + + +PhaseIterGVN::optimize (3 samples, 0.06%) + + + +com/fasterxml/jackson/databind/ser/std/StdKeySerializers$StringKeySerializer:::serialize (6 samples, 0.12%) + + + +vtable stub (2 samples, 0.04%) + + + +run_timer_softirq (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +G1AllocRegion::retire (1 samples, 0.02%) + + + +com/coohua/platform/security/AESCoder:::decrypt (83 samples, 1.61%) + + + +org/apache/kafka/clients/producer/internals/RecordAccumulator:::tryAppend (2 samples, 0.04%) + + + +__vdso_gettimeofday (2 samples, 0.04%) + + + +do_softirq (1 samples, 0.02%) + + + +__tcp_push_pending_frames (4 samples, 0.08%) + + + +RefineRecordRefsIntoCSCardTableEntryClosure::do_card_ptr (3 samples, 0.06%) + + + +ret_from_intr (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +java/util/LinkedHashMap:::newNode (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +inet_sendmsg (6 samples, 0.12%) + + + +sys_futex (6 samples, 0.12%) + + + +java_lang_Throwable::fill_in_stack_trace (67 samples, 1.30%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ObjectMapper:::writeValueAsString (1 samples, 0.02%) + + + +sun/misc/Unsafe:::unpark (2 samples, 0.04%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +run_timer_softirq (1 samples, 0.02%) + + + +__lll_unlock_wake (2 samples, 0.04%) + + + +CollectedHeap::common_mem_allocate_init (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +java/math/BigDecimal:::<init> (1 samples, 0.02%) + + + +objArrayOopDesc::obj_at (11 samples, 0.21%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/springframework/context/expression/StandardBeanExpressionResolver:::evaluate (2 samples, 0.04%) + + + +org/LatencyUtils/TimeCappedMovingAverageIntervalEstimator:::recordInterval (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +Parse::do_one_bytecode (1 samples, 0.02%) + + + +skb_to_sgvec (2 samples, 0.04%) + + + +__vdso_gettimeofday (2 samples, 0.04%) + + + +page_to_skb (1 samples, 0.02%) + + + +sun/nio/ch/SelectionKeyImpl:::nioInterestOps (1 samples, 0.02%) + + + +PhaseIdealLoop::build_loop_late_post (3 samples, 0.06%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +skb_copy_datagram_iovec (1 samples, 0.02%) + + + +java/util/regex/Pattern$Single:::isSatisfiedBy (1 samples, 0.02%) + + + +io/micrometer/core/instrument/Timer$Builder:::register (3 samples, 0.06%) + + + +io/micrometer/shaded/org/pcollections/HashPMap:::get (2 samples, 0.04%) + + + +ret_from_intr (1 samples, 0.02%) + + + +G1CollectorPolicy::predict_region_elapsed_time_ms (1 samples, 0.02%) + + + +java/lang/ThreadLocal$ThreadLocalMap:::remove (1 samples, 0.02%) + + + +do_sys_poll (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +apic_timer_interrupt (1 samples, 0.02%) + + + +__skb_gro_checksum_complete (1 samples, 0.02%) + + + +TaskQueueSetSuper::randomParkAndMiller (1 samples, 0.02%) + + + +Type::hashcons (1 samples, 0.02%) + + + +inet_gro_receive (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +sun/nio/ch/FileDispatcherImpl:::read0 (6 samples, 0.12%) + + + +sock_aio_read.part.7 (9 samples, 0.18%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +java/text/DateFormatSymbols:::getProviderInstance (2 samples, 0.04%) + + + +do_softirq (1 samples, 0.02%) + + + +org/apache/catalina/mapper/MappingData:::recycle (1 samples, 0.02%) + + + +system_call_fastpath (14 samples, 0.27%) + + + +org/apache/kafka/common/requests/ProduceRequest:::createPartitionSizes (2 samples, 0.04%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/Type$8:::validate (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +java/util/concurrent/ThreadPoolExecutor:::getTask (55 samples, 1.07%) + + + +irq_exit (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (2 samples, 0.04%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +_int_free (2 samples, 0.04%) + + + +java/util/Formatter$FixedString:::print (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/catalina/core/StandardHostValve:::invoke (3,781 samples, 73.56%) +org/apache/catalina/core/StandardHostValve:::invoke + + +CollectedHeap::post_allocation_setup_array (1 samples, 0.02%) + + + +javax/crypto/Cipher:::tokenizeTransformation (3 samples, 0.06%) + + + +java/text/DecimalFormat:::equals (1 samples, 0.02%) + + + +redis/clients/jedis/Protocol:::process (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +com/alibaba/fastjson/serializer/LongCodec:::deserialze (6 samples, 0.12%) + + + +java/util/regex/Pattern$Curly:::match (3 samples, 0.06%) + + + +__do_softirq (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (2 samples, 0.04%) + + + +java/util/GregorianCalendar:::computeTime (2 samples, 0.04%) + + + +generic_exec_single (1 samples, 0.02%) + + + +try_to_wake_up (1 samples, 0.02%) + + + +start_this_handle (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +__memset_sse2 (32 samples, 0.62%) + + + +__libc_calloc (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::scanString (6 samples, 0.12%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (1 samples, 0.02%) + + + +sun/nio/ch/SelectorImpl:::select (55 samples, 1.07%) + + + +JNIHandleBlock::allocate_block (1 samples, 0.02%) + + + +CodeCache::find_blob (1 samples, 0.02%) + + + +java/util/LinkedHashMap$LinkedKeyIterator:::next (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/MessageBytes:::isNull (1 samples, 0.02%) + + + +system_call_fastpath (2 samples, 0.04%) + + + +org/springframework/aop/framework/ReflectiveMethodInvocation:::proceed (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +java/util/zip/Inflater:::init (2 samples, 0.04%) + + + +java/util/stream/ForEachOps$ForEachOp$OfRef:::evaluateSequential (2 samples, 0.04%) + + + +sock_sendmsg (6 samples, 0.12%) + + + +call_softirq (1 samples, 0.02%) + + + +java/lang/Class:::reflectionData (1 samples, 0.02%) + + + +ext4_mark_iloc_dirty (3 samples, 0.06%) + + + +Parse::do_one_block (1 samples, 0.02%) + + + +org/springframework/aop/framework/ReflectiveMethodInvocation:::proceed (1 samples, 0.02%) + + + +jni_ReleasePrimitiveArrayCritical (105 samples, 2.04%) +j.. + + +[libc-2.17.so] (1 samples, 0.02%) + + + +OptoRuntime::is_deoptimized_caller_frame (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/impl/Log4jLogEvent:::serialize (3 samples, 0.06%) + + + +org/apache/kafka/common/protocol/types/Schema:::read (2 samples, 0.04%) + + + +TypeArrayKlass::allocate_common (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +java/util/concurrent/ConcurrentHashMap$MapEntry:::getValue (1 samples, 0.02%) + + + +java/util/Calendar:::createCalendar (1 samples, 0.02%) + + + +IndexSetIterator::advance_and_next (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy0:::annotationType (1 samples, 0.02%) + + + +org/apache/kafka/clients/NetworkClient:::pollDelayMs (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +virtqueue_kick_prepare (2 samples, 0.04%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (1 samples, 0.02%) + + + +CollectedHeap::allocate_from_tlab_slow (1 samples, 0.02%) + + + +sun/nio/cs/ThreadLocalCoders$Cache:::forName (2 samples, 0.04%) + + + +ip_output (6 samples, 0.12%) + + + +java/text/SimpleDateFormat:::format (5 samples, 0.10%) + + + +longest_match (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +org/apache/tomcat/websocket/server/WsFilter:::doFilter (192 samples, 3.74%) +org/.. + + +java/io/SequenceInputStream:::read (1 samples, 0.02%) + + + +system_call_fastpath (31 samples, 0.60%) + + + +__mnt_want_write (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::initialize (2 samples, 0.04%) + + + +java/lang/Throwable:::getStackTraceElement (466 samples, 9.07%) +java/lang/Thr.. + + +fget_light (1 samples, 0.02%) + + + +java/util/regex/Pattern$Curly:::match (3 samples, 0.06%) + + + +sun/nio/ch/IOVecWrapper:::get (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::intValue (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +sun/nio/ch/SocketChannelImpl:::write (54 samples, 1.05%) + + + +java/lang/System:::identityHashCode (1 samples, 0.02%) + + + +java/lang/Throwable:::fillInStackTrace (77 samples, 1.50%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +InstanceKlass::register_finalizer (4 samples, 0.08%) + + + +__pthread_enable_asynccancel (1 samples, 0.02%) + + + +futex_wait (4 samples, 0.08%) + + + +checkcast_arraycopy (1 samples, 0.02%) + + + +java/lang/Object:::toString (1 samples, 0.02%) + + + +java/util/HashMap:::resize (1 samples, 0.02%) + + + +java/lang/ThreadLocal$ThreadLocalMap:::set (3 samples, 0.06%) + + + +do_futex (5 samples, 0.10%) + + + +sun/misc/Unsafe:::unpark (2 samples, 0.04%) + + + +fget_light (3 samples, 0.06%) + + + +irq_exit (1 samples, 0.02%) + + + +org/springframework/aop/framework/CglibAopProxy$DynamicAdvisedInterceptor:::intercept (2 samples, 0.04%) + + + +ip_rcv (1 samples, 0.02%) + + + +pthread_mutex_unlock (1 samples, 0.02%) + + + +java/util/HashMap:::containsKey (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/config/LoggerConfig:::log (7 samples, 0.14%) + + + +memcpy_toiovec (1 samples, 0.02%) + + + +JVM_Sleep (11 samples, 0.21%) + + + +java/lang/AbstractStringBuilder:::append (1 samples, 0.02%) + + + +java/util/Formatter$FormatSpecifier:::print (2 samples, 0.04%) + + + +ip_output (3 samples, 0.06%) + + + +smp_call_function_single_async (2 samples, 0.04%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (3,684 samples, 71.67%) +org/springframework/web/filter/OncePerRequestFilter:::doFilter + + +JavaThread::handle_special_suspend_equivalent_condition (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +java/io/ByteArrayInputStream:::read (1 samples, 0.02%) + + + +rw_verify_area (1 samples, 0.02%) + + + +sys_recvfrom (1 samples, 0.02%) + + + +__memset (1 samples, 0.02%) + + + +org/springframework/aop/framework/ReflectiveMethodInvocation:::proceed (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +pthread_cond_timedwait@@GLIBC_2.3.2 (6 samples, 0.12%) + + + +sun/security/provider/SHA:::implCompress (4 samples, 0.08%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/appender/AbstractOutputStreamAppender:::directEncodeEvent (52 samples, 1.01%) + + + +inflate (13 samples, 0.25%) + + + +Parker::unpark (1 samples, 0.02%) + + + +jni_SetBooleanField (2 samples, 0.04%) + + + +JVM_FillInStackTrace (74 samples, 1.44%) + + + +java/util/HashMap$EntrySet:::iterator (2 samples, 0.04%) + + + +java/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1:::next (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +org/springframework/web/util/UrlPathHelper:::getRemainingPath (1 samples, 0.02%) + + + +java/util/concurrent/ConcurrentHashMap:::get (2 samples, 0.04%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +tcp_v4_syn_recv_sock (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/SerializerProvider:::<init> (1 samples, 0.02%) + + + +org/apache/tomcat/util/http/ValuesEnumerator:::findNext (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +sys_futex (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +system_call_fastpath (15 samples, 0.29%) + + + +org/apache/kafka/clients/NetworkClient:::handleCompletedReceives (1 samples, 0.02%) + + + +sys_futex (1 samples, 0.02%) + + + +PhaseIFG::remove_node (2 samples, 0.04%) + + + +system_call_fastpath (2 samples, 0.04%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (206 samples, 4.01%) +org/.. + + +JNIHandles::make_local (1 samples, 0.02%) + + + +org/apache/kafka/clients/producer/internals/Sender:::handleProduceResponse (34 samples, 0.66%) + + + +sk_run_filter (1 samples, 0.02%) + + + +com/alibaba/fastjson/JSON:::parseObject (185 samples, 3.60%) +com.. + + +do_softirq (1 samples, 0.02%) + + + +__skb_gro_checksum_complete (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor65:::invoke (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11InputBuffer:::doRead (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +java/util/Arrays:::sort (4 samples, 0.08%) + + + +do_softirq (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +__getnstimeofday64 (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +HandleMarkCleaner::~HandleMarkCleaner (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupHead:::match (2 samples, 0.04%) + + + +org/joda/time/format/DateTimeFormatter:::printTo (2 samples, 0.04%) + + + +com/coohua/caf/core/rpc/MotanProfilerFilter:::filter (10 samples, 0.19%) + + + +ip_output (23 samples, 0.45%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +net_rx_action (2 samples, 0.04%) + + + +org/apache/kafka/common/network/Selector$SelectorMetrics:::maybeRegisterConnectionMetrics (1 samples, 0.02%) + + + +javax/crypto/Cipher:::getInstance (46 samples, 0.89%) + + + +java/text/DateFormatSymbols:::initializeData (2 samples, 0.04%) + + + +skb_clone (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy50:::annotationType (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::nextToken (1 samples, 0.02%) + + + +java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject:::await (33 samples, 0.64%) + + + +do_softirq (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor90:::invoke (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +local_clock (1 samples, 0.02%) + + + +org/springframework/boot/actuate/trace/http/HttpExchangeTracer$FilteredTraceableResponse:::<init> (1 samples, 0.02%) + + + +org/jboss/netty/channel/socket/nio/NioWorker:::run (2 samples, 0.04%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +tcp_schedule_loss_probe (2 samples, 0.04%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +CollectedHeap::common_mem_allocate_init (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +tcp_md5_do_lookup (1 samples, 0.02%) + + + +pthread_getspecific (1 samples, 0.02%) + + + +ReferenceProcessor::process_discovered_reflist (3 samples, 0.06%) + + + +system_call_fastpath (4 samples, 0.08%) + + + +CollectedHeap::new_store_pre_barrier (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy50:::annotationType (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +Parse::do_one_bytecode (1 samples, 0.02%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (2 samples, 0.04%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +java/util/concurrent/ConcurrentHashMap$BaseIterator:::hasNext (3 samples, 0.06%) + + + +VM_G1IncCollectionPause::doit (4 samples, 0.08%) + + + +org/apache/catalina/connector/Request:::setAttribute (3 samples, 0.06%) + + + +java/util/regex/Pattern$Branch:::match (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/context/event/SimpleApplicationEventMulticaster:::multicastEvent (1 samples, 0.02%) + + + +Compile::fill_buffer (2 samples, 0.04%) + + + +org/springframework/core/annotation/AnnotatedElementUtils:::searchWithFindSemantics (9 samples, 0.18%) + + + +java/lang/Long:::getChars (1 samples, 0.02%) + + + +InstanceKlass::register_finalizer (2 samples, 0.04%) + + + +updateBytesCRC32 (8 samples, 0.16%) + + + +org/apache/tomcat/util/buf/B2CConverter:::convert (1 samples, 0.02%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (4 samples, 0.08%) + + + +net_rx_action (2 samples, 0.04%) + + + +sun/nio/ch/EPollArrayWrapper:::epollWait (23 samples, 0.45%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +java/util/regex/Pattern$Dollar:::match (1 samples, 0.02%) + + + +sun/nio/ch/SelectionKeyImpl:::nioInterestOps (1 samples, 0.02%) + + + +java/util/HashMap:::put (2 samples, 0.04%) + + + +Java_java_io_RandomAccessFile_writeBytes (41 samples, 0.80%) + + + +com/coohua/ad/data/service/impl/AdDataServiceImpl:::ecpProcess (54 samples, 1.05%) + + + +get_rps_cpu (1 samples, 0.02%) + + + +java/util/HashMap:::afterNodeInsertion (1 samples, 0.02%) + + + +org/apache/kafka/common/network/Selector:::pollSelectionKeys (60 samples, 1.17%) + + + +java/util/Calendar$Builder:::build (1 samples, 0.02%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +org/apache/catalina/connector/RequestFacade:::setAttribute (2 samples, 0.04%) + + + +do_sync_read (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +tcp4_gro_receive (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor103:::invoke (4 samples, 0.08%) + + + +Java_java_util_zip_Deflater_deflateBytes (9 samples, 0.18%) + + + +com/google/gson/internal/bind/TypeAdapters$16:::write (22 samples, 0.43%) + + + +org/springframework/web/servlet/handler/AbstractHandlerMethodMapping:::addMatchingMappings (46 samples, 0.89%) + + + +__block_write_begin (1 samples, 0.02%) + + + +tcp_push (30 samples, 0.58%) + + + +java/util/HashMap:::get (1 samples, 0.02%) + + + +[libpthread-2.17.so] (16 samples, 0.31%) + + + +checkcast_arraycopy (1 samples, 0.02%) + + + +PhaseIFG::SquareUp (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupHead:::match (1 samples, 0.02%) + + + +do_sync_readv_writev (1 samples, 0.02%) + + + +rw_verify_area (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +org/apache/coyote/Request:::recycle (3 samples, 0.06%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (3,765 samples, 73.25%) +org/springframework/web/filter/OncePerRequestFilter:::doFilter + + +futex_wake (1 samples, 0.02%) + + + +java/util/zip/InflaterInputStream:::read (917 samples, 17.84%) +java/util/zip/InflaterInput.. + + +java/security/Provider$ServiceKey:::equals (1 samples, 0.02%) + + + +compress_block (30 samples, 0.58%) + + + +call_softirq (1 samples, 0.02%) + + + +java/util/regex/Pattern$Node:::match (2 samples, 0.04%) + + + +java/util/regex/Pattern$GroupHead:::match (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +tcp_write_xmit (11 samples, 0.21%) + + + +HeapRegion::oops_on_card_seq_iterate_careful (3 samples, 0.06%) + + + +org/springframework/aop/framework/CglibAopProxy$DynamicAdvisedInterceptor:::intercept (1 samples, 0.02%) + + + +VMThread::loop (4 samples, 0.08%) + + + +PhaseChaitin::gather_lrg_masks (3 samples, 0.06%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +com/coohua/platform/security/Base64$Decoder:::process (3 samples, 0.06%) + + + +redis/clients/jedis/Pipeline:::sync (4 samples, 0.08%) + + + +java/text/SimpleDateFormat:::compile (1 samples, 0.02%) + + + +com/coohua/ad/data/utils/GzipUtil:::deCompress (56 samples, 1.09%) + + + +java_lang_Throwable::get_stack_trace_element (3 samples, 0.06%) + + + +process_backlog (1 samples, 0.02%) + + + +apic_timer_interrupt (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (2 samples, 0.04%) + + + +java/util/regex/Pattern$GroupHead:::match (5 samples, 0.10%) + + + +ext4_da_write_begin (4 samples, 0.08%) + + + +org/springframework/http/converter/xml/SourceHttpMessageConverter:::supports (1 samples, 0.02%) + + + +futex_wait (23 samples, 0.45%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (211 samples, 4.11%) +org/.. + + +PhaseIterGVN::add_users_to_worklist (1 samples, 0.02%) + + + +JfrBackend::is_event_enabled (1 samples, 0.02%) + + + +org/springframework/core/ResolvableType:::forMethodParameter (5 samples, 0.10%) + + + +java/util/AbstractList:::hashCode (1 samples, 0.02%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +local_bh_enable_ip (1 samples, 0.02%) + + + +java_lang_StackTraceElement::create (26 samples, 0.51%) + + + +virtnet_poll (1 samples, 0.02%) + + + +java/util/AbstractList:::hashCode (3 samples, 0.06%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +ipv4_mtu (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/appender/RollingRandomAccessFileAppender:::append (56 samples, 1.09%) + + + +org/springframework/web/util/UrlPathHelper:::decodeInternal (3 samples, 0.06%) + + + +org/springframework/web/context/request/async/StandardServletAsyncWebRequest:::<init> (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/apache/logging/log4j/spi/AbstractLogger:::logMessage (3 samples, 0.06%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (1 samples, 0.02%) + + + +org/springframework/util/AntPathMatcher:::doMatch (11 samples, 0.21%) + + + +try_to_wake_up (2 samples, 0.04%) + + + +Java_java_util_zip_Inflater_inflateBytes (4 samples, 0.08%) + + + +java/lang/reflect/Array:::get (3 samples, 0.06%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +ext4_mark_iloc_dirty (1 samples, 0.02%) + + + +sun/security/provider/SecureRandom:::engineNextBytes (7 samples, 0.14%) + + + +system_call_fastpath (2 samples, 0.04%) + + + +java/util/regex/Pattern$Single:::isSatisfiedBy (1 samples, 0.02%) + + + +InterpreterRuntime::ldc (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessor:::supportsReturnType (1 samples, 0.02%) + + + +try_to_wake_up (29 samples, 0.56%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +Java_java_util_zip_Inflater_inflateBytes (37 samples, 0.72%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +futex_wait (5 samples, 0.10%) + + + +do_softirq (1 samples, 0.02%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +ThreadBlockInVM::ThreadBlockInVM (1 samples, 0.02%) + + + +java/lang/AbstractStringBuilder:::append (10 samples, 0.19%) + + + +java/util/HashSet:::iterator (1 samples, 0.02%) + + + +com/alibaba/fastjson/serializer/IntegerCodec:::getFastMatchToken (1 samples, 0.02%) + + + +tcp_gro_receive (1 samples, 0.02%) + + + +java/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1:::next (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +nmethod::is_nmethod (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +org/apache/kafka/clients/producer/internals/RecordAccumulator:::expiredBatches (9 samples, 0.18%) + + + +java/security/Provider$Service:::newInstance (1 samples, 0.02%) + + + +fsnotify (1 samples, 0.02%) + + + +_raw_spin_lock_irqsave (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/NioEndpoint$Poller:::timeout (2 samples, 0.04%) + + + +java/lang/Object:::hashCode (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +_raw_spin_unlock_bh (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupTail:::match (2 samples, 0.04%) + + + +java/lang/String:::toLowerCase (3 samples, 0.06%) + + + +virtnet_poll (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +sun/nio/cs/UTF_8$Decoder:::decodeLoop (6 samples, 0.12%) + + + +OptoRuntime::new_instance_C (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ser/std/StringSerializer:::serialize (9 samples, 0.18%) + + + +org/springframework/web/servlet/handler/HandlerInterceptorAdapter:::postHandle (1 samples, 0.02%) + + + +__memmove_ssse3_back (3 samples, 0.06%) + + + +java/util/zip/InflaterInputStream:::read (6 samples, 0.12%) + + + +java/net/URI$Parser:::parseHostname (3 samples, 0.06%) + + + +__schedule (3 samples, 0.06%) + + + +[libpthread-2.17.so] (3 samples, 0.06%) + + + +java/util/HashMap$HashIterator:::hasNext (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/appender/AsyncAppender:::append (3 samples, 0.06%) + + + +G1SATBCardTableLoggingModRefBS::write_ref_array_work (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +ParseGenerator::generate (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +pipe_poll (1 samples, 0.02%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (17 samples, 0.33%) + + + +__do_softirq (1 samples, 0.02%) + + + +JNIHandleBlock::allocate_handle (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (3,753 samples, 73.02%) +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter + + +__dev_queue_xmit (5 samples, 0.10%) + + + +com/coohua/caf/core/kv/JedisClusterClient:::setex (1 samples, 0.02%) + + + +do_futex (1 samples, 0.02%) + + + +OptoRuntime::is_deoptimized_caller_frame (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotatedElementUtils:::searchWithFindSemantics (16 samples, 0.31%) + + + +vtable stub (1 samples, 0.02%) + + + +com/coohua/platform/security/Base64:::decode (1 samples, 0.02%) + + + +tcp_write_xmit (28 samples, 0.54%) + + + +__build_skb (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +java/util/Spliterator:::getExactSizeIfKnown (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +finish_task_switch (9 samples, 0.18%) + + + +Dict::Insert (1 samples, 0.02%) + + + +ep_poll (1 samples, 0.02%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +__audit_syscall_exit (1 samples, 0.02%) + + + +pthread_cond_signal@@GLIBC_2.3.2 (7 samples, 0.14%) + + + +wake_futex (5 samples, 0.10%) + + + +org/apache/catalina/connector/Request:::setAttribute (2 samples, 0.04%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +futex_wake_op (2 samples, 0.04%) + + + +ip_local_out_sk (1 samples, 0.02%) + + + +finish_task_switch (3 samples, 0.06%) + + + +sock_aio_write (16 samples, 0.31%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +org/springframework/web/util/UrlPathHelper:::decodeInternal (1 samples, 0.02%) + + + +org/apache/catalina/core/StandardContextValve:::invoke (3,777 samples, 73.48%) +org/apache/catalina/core/StandardContextValve:::invoke + + +itable stub (3 samples, 0.06%) + + + +ObjArrayKlass::multi_allocate (9 samples, 0.18%) + + + +InterpreterRuntime::frequency_counter_overflow_inner (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +tcp_stream_memory_free (1 samples, 0.02%) + + + +java/util/ArrayList:::add (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +sun/misc/Unsafe:::park (27 samples, 0.53%) + + + +CollectedHeap::allocate_from_tlab_slow (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +_new_array_Java (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +java/lang/ref/Finalizer$FinalizerThread:::run (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +java/text/DateFormatSymbols:::copyMembers (2 samples, 0.04%) + + + +do_futex (14 samples, 0.27%) + + + +org/apache/coyote/http11/Http11OutputBuffer:::end (5 samples, 0.10%) + + + +net_rx_action (1 samples, 0.02%) + + + +org/jboss/netty/channel/DefaultChannelPipeline:::sendDownstream (2 samples, 0.04%) + + + +JVM_GetDeclaringClass (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/condition/PatternsRequestCondition:::getMatchingPatterns (1 samples, 0.02%) + + + +OptoRuntime::new_array_nozero_C (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/Utf8Decoder:::decodeHasArray (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/context/i18n/LocaleContextHolder:::setLocale (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy0:::annotationType (1 samples, 0.02%) + + + +ObjArrayKlass::allocate (1 samples, 0.02%) + + + +[libpthread-2.17.so] (1 samples, 0.02%) + + + +sun/nio/ch/IOUtil:::write (23 samples, 0.45%) + + + +jshort_arraycopy (1 samples, 0.02%) + + + +java/util/HashSet:::iterator (1 samples, 0.02%) + + + +do_futex (21 samples, 0.41%) + + + +irq_exit (2 samples, 0.04%) + + + +sun/nio/ch/FileDispatcherImpl:::write0 (3 samples, 0.06%) + + + +ret_from_intr (1 samples, 0.02%) + + + +sys_epoll_wait (18 samples, 0.35%) + + + +java/lang/String:::charAt (2 samples, 0.04%) + + + +OptoRuntime::new_array_C (1 samples, 0.02%) + + + +__libc_read (1 samples, 0.02%) + + + +jni_GetByteArrayRegion (3 samples, 0.06%) + + + +TypeArrayKlass::allocate_common (6 samples, 0.12%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::nextToken (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/MessageBytes:::toString (2 samples, 0.04%) + + + +OptoRuntime::new_array_nozero_C (1 samples, 0.02%) + + + +sys_writev (18 samples, 0.35%) + + + +com/weibo/api/motan/transport/netty/NettyClient:::request (2 samples, 0.04%) + + + +[libpthread-2.17.so] (31 samples, 0.60%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +futex_wake (2 samples, 0.04%) + + + +InstanceKlass::register_finalizer (5 samples, 0.10%) + + + +ip_finish_output (21 samples, 0.41%) + + + +com/coohua/platform/security/Base64:::decode (3 samples, 0.06%) + + + +generic_file_buffered_write (10 samples, 0.19%) + + + +do_softirq (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +sys_futex (18 samples, 0.35%) + + + +hrtimer_start_range_ns (2 samples, 0.04%) + + + +org/springframework/boot/actuate/trace/http/HttpExchangeTracer:::getHeadersIfIncluded (47 samples, 0.91%) + + + +java/util/regex/Pattern$Node:::match (3 samples, 0.06%) + + + +irq_exit (1 samples, 0.02%) + + + +InstanceKlass::allocate_instance (1 samples, 0.02%) + + + +com/coohua/ad/data/interceptor/UserInterceptor:::buildLogMessage (136 samples, 2.65%) +co.. + + +java/lang/String:::hashCode (2 samples, 0.04%) + + + +org/springframework/beans/TypeConverterDelegate:::convertIfNecessary (1 samples, 0.02%) + + + +ipv4_dst_check (1 samples, 0.02%) + + + +java/util/HashMap:::putMapEntries (1 samples, 0.02%) + + + +JavaThread::oops_do (2 samples, 0.04%) + + + +org/joda/time/chrono/BasicYearDateTimeField:::get (2 samples, 0.04%) + + + +Interpreter (176 samples, 3.42%) +Int.. + + +__netif_receive_skb (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/block/authority/AuthoritySlot:::entry (1 samples, 0.02%) + + + +PhaseIterGVN::transform_old (4 samples, 0.08%) + + + +java/util/LinkedHashMap:::newNode (1 samples, 0.02%) + + + +org/springframework/web/servlet/FrameworkServlet:::service (3,446 samples, 67.04%) +org/springframework/web/servlet/FrameworkServlet:::service + + +smp_call_function_single_async (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/web/util/UrlPathHelper:::getLookupPathForRequest (8 samples, 0.16%) + + + +generic_exec_single (1 samples, 0.02%) + + + +system_call_fastpath (19 samples, 0.37%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +sun/nio/ch/IOUtil:::drain (4 samples, 0.08%) + + + +generic_pipe_buf_unmap (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/appender/AsyncAppender:::append (6 samples, 0.12%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::epollWait (18 samples, 0.35%) + + + +kmem_cache_free (1 samples, 0.02%) + + + +java/util/Formatter$FormatSpecifier:::localizedMagnitude (2 samples, 0.04%) + + + +sun/nio/cs/ISO_8859_1$Decoder:::decodeLoop (5 samples, 0.10%) + + + +com/coohua/caf/core/kv/JedisClusterClient$$FastClassBySpringCGLIB$$1bc9b45c:::invoke (1 samples, 0.02%) + + + +TypeArrayKlass::multi_allocate (6 samples, 0.12%) + + + +org/springframework/web/servlet/mvc/method/annotation/StreamingResponseBodyReturnValueHandler:::supportsReturnType (2 samples, 0.04%) + + + +com/coohua/ad/data/interceptor/UserInterceptor:::preHandle (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils:::getAnnotation (2 samples, 0.04%) + + + +java/util/regex/Pattern$Neg:::match (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy8:::annotationType (1 samples, 0.02%) + + + +pthread_cond_wait@@GLIBC_2.3.2 (20 samples, 0.39%) + + + +vtable stub (11 samples, 0.21%) + + + +process_backlog (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::poll (19 samples, 0.37%) + + + +java/util/Formatter$Conversion:::isValid (2 samples, 0.04%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +PhaseIFG::init (1 samples, 0.02%) + + + +org/springframework/boot/actuate/trace/http/HttpExchangeTracer:::sendingResponse (10 samples, 0.19%) + + + +java/text/SimpleDateFormat:::subFormat (1 samples, 0.02%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +itable stub (5 samples, 0.10%) + + + +org/apache/kafka/common/record/ByteBufferLogInputStream:::nextBatch (1 samples, 0.02%) + + + +sock_aio_write (37 samples, 0.72%) + + + +pthread_self@plt (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +org/springframework/web/context/request/ServletWebRequest:::getParameterValues (8 samples, 0.16%) + + + +jshort_disjoint_arraycopy (5 samples, 0.10%) + + + +java/util/HashMap:::resize (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/block/authority/AuthoritySlot:::exit (1 samples, 0.02%) + + + +ip_local_out_sk (3 samples, 0.06%) + + + +OptoRuntime::new_array_nozero_C (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils$AnnotationCollector:::process (24 samples, 0.47%) + + + +G1CollectedHeap::attempt_allocation_slow (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (200 samples, 3.89%) +org/.. + + +__irqentry_text_start (1 samples, 0.02%) + + + +tcp_cleanup_rbuf (1 samples, 0.02%) + + + +CodeHeap::find_start (1 samples, 0.02%) + + + +InterpreterRuntime::ldc (3 samples, 0.06%) + + + +java/util/LinkedHashSet:::spliterator (1 samples, 0.02%) + + + +do_futex (17 samples, 0.33%) + + + +Java_java_lang_Throwable_fillInStackTrace (75 samples, 1.46%) + + + +irq_exit (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +do_sync_read (1 samples, 0.02%) + + + +dev_queue_xmit (5 samples, 0.10%) + + + +java/lang/Throwable:::fillInStackTrace (4 samples, 0.08%) + + + +org/springframework/web/filter/FormContentFilter:::doFilterInternal (3,609 samples, 70.21%) +org/springframework/web/filter/FormContentFilter:::doFilterInternal + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (3,548 samples, 69.03%) +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter + + +ret_from_intr (1 samples, 0.02%) + + + +org/apache/kafka/clients/producer/internals/Sender:::sendProducerData (108 samples, 2.10%) +o.. + + +do_futex (2 samples, 0.04%) + + + +java/util/zip/GZIPInputStream:::skipBytes (1 samples, 0.02%) + + + +__memmove_ssse3_back (1 samples, 0.02%) + + + +org/apache/catalina/mapper/Mapper:::internalMapWrapper (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +InstanceKlass::method_with_orig_idnum (1 samples, 0.02%) + + + +OptoRuntime::is_deoptimized_caller_frame (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor:::writeWithMessageConverters (5 samples, 0.10%) + + + +java/lang/ThreadLocal:::set (1 samples, 0.02%) + + + +com/coohua/ad/data/interceptor/UserInterceptor:::buildLogMessage (7 samples, 0.14%) + + + +java/util/stream/Sink:::end (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +system_call_fastpath (20 samples, 0.39%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/condition/ProducesRequestCondition:::getMatchingCondition (2 samples, 0.04%) + + + +InstanceKlass::oop_oop_iterate_nv (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +sock_poll (1 samples, 0.02%) + + + +Handle::Handle (1 samples, 0.02%) + + + +org/springframework/util/AntPathMatcher:::doMatch (3 samples, 0.06%) + + + +sun/misc/Unsafe:::unpark (3 samples, 0.06%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::epollCtl (2 samples, 0.04%) + + + +Unsafe_Unpark (24 samples, 0.47%) + + + +org/apache/kafka/clients/NetworkClient:::handleCompletedReceives (12 samples, 0.23%) + + + +java/util/regex/Pattern:::closure (1 samples, 0.02%) + + + +pthread_cond_signal@@GLIBC_2.3.2 (21 samples, 0.41%) + + + +java_lang_StackTraceElement::set_methodName (1 samples, 0.02%) + + + +system_call_fastpath (6 samples, 0.12%) + + + +InstanceKlass::method_with_orig_idnum (11 samples, 0.21%) + + + +com/coohua/caf/core/base/SpringApplicationEventListenerAutoConfiguration:::onApplicationEvent (5 samples, 0.10%) + + + +java/util/concurrent/locks/ReentrantLock$NonfairSync:::lock (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +com/coohua/caf/core/kv/JedisClusterClientAspect:::around (1 samples, 0.02%) + + + +PhaseGVN::transform_no_reclaim (1 samples, 0.02%) + + + +java/util/regex/Pattern$Slice:::match (2 samples, 0.04%) + + + +oopDesc::size_given_klass (1 samples, 0.02%) + + + +org/apache/juli/logging/DirectJDKLog:::isDebugEnabled (1 samples, 0.02%) + + + +futex_wait_queue_me (16 samples, 0.31%) + + + +com/coohua/ad/data/interceptor/UserInterceptor:::afterCompletion (2 samples, 0.04%) + + + +validate_xmit_skb.part.93 (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +__vdso_clock_gettime (2 samples, 0.04%) + + + +_raw_spin_unlock_irqrestore (2 samples, 0.04%) + + + +org/apache/logging/log4j/core/AbstractLifeCycle:::isStarted (1 samples, 0.02%) + + + +tcp_ack (1 samples, 0.02%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +Parse::do_call (1 samples, 0.02%) + + + +org/joda/time/format/DateTimeFormatter:::printTo (6 samples, 0.12%) + + + +org/apache/tomcat/util/buf/StringCache:::toString (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::setAttribute (2 samples, 0.04%) + + + +__libc_write (1 samples, 0.02%) + + + +deflate (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +Monitor::lock_without_safepoint_check (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +org/springframework/web/filter/HiddenHttpMethodFilter:::doFilterInternal (1 samples, 0.02%) + + + +java/lang/Thread:::isAlive (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +CodeBlob::is_nmethod (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (1 samples, 0.02%) + + + +JavaCallWrapper::JavaCallWrapper (1 samples, 0.02%) + + + +com/coohua/caf/core/web/HttpTracingInterceptor:::preHandle (2 samples, 0.04%) + + + +net_rx_action (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/kafka/clients/producer/KafkaProducer:::doSend (45 samples, 0.88%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (3,753 samples, 73.02%) +org/springframework/web/filter/OncePerRequestFilter:::doFilter + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +java/security/Provider:::getService (2 samples, 0.04%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +com/alibaba/fastjson/serializer/IntegerCodec:::getFastMatchToken (2 samples, 0.04%) + + + +org/springframework/aop/framework/ReflectiveMethodInvocation:::proceed (1 samples, 0.02%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +JavaThread::last_frame (1 samples, 0.02%) + + + +com/coohua/caf/core/kv/JedisClusterClientAspect:::around (2 samples, 0.04%) + + + +Unsafe_Unpark (3 samples, 0.06%) + + + +org/apache/kafka/clients/producer/internals/Sender:::run (286 samples, 5.56%) +org/apa.. + + +java/util/GregorianCalendar:::computeFields (2 samples, 0.04%) + + + +org/springframework/util/StringUtils:::uriDecode (1 samples, 0.02%) + + + +tcp_transmit_skb (7 samples, 0.14%) + + + +ip_rcv (1 samples, 0.02%) + + + +pthread_cond_signal@@GLIBC_2.3.2 (32 samples, 0.62%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +sk_run_filter (1 samples, 0.02%) + + + +__schedule (11 samples, 0.21%) + + + +org/apache/tomcat/websocket/server/WsFilter:::doFilter (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (2 samples, 0.04%) + + + +org/apache/catalina/connector/Request:::parseParameters (5 samples, 0.10%) + + + +ConvI2LNode::Value (1 samples, 0.02%) + + + +JavaCalls::call_virtual (5,032 samples, 97.90%) +JavaCalls::call_virtual + + +java/util/LinkedHashMap:::get (5 samples, 0.10%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +org/springframework/aop/aspectj/AbstractAspectJAdvice:::getJoinPointMatch (1 samples, 0.02%) + + + +schedule (18 samples, 0.35%) + + + +futex_wake (1 samples, 0.02%) + + + +sock_aio_read (4 samples, 0.08%) + + + +com/coohua/caf/core/kv/JedisClusterClient:::incrBy (1 samples, 0.02%) + + + +clock_gettime (2 samples, 0.04%) + + + +vtable stub (3 samples, 0.06%) + + + +__x2apic_send_IPI_mask (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (3 samples, 0.06%) + + + +java/util/AbstractList:::equals (1 samples, 0.02%) + + + +HandleMarkCleaner::~HandleMarkCleaner (11 samples, 0.21%) + + + +java/lang/String:::hashCode (1 samples, 0.02%) + + + +deflate_slow (9 samples, 0.18%) + + + +sock_def_readable (1 samples, 0.02%) + + + +sch_direct_xmit (15 samples, 0.29%) + + + +InstanceKlass::allocate_instance (1 samples, 0.02%) + + + +sun/nio/ch/FileDispatcherImpl:::read0 (18 samples, 0.35%) + + + +java/util/HashMap:::put (2 samples, 0.04%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +dev_gro_receive (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::decimalValue (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +com/fasterxml/jackson/core/io/NumberOutput:::_outputFullBillion (1 samples, 0.02%) + + + +wake_up_state (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +BarrierSet::static_write_ref_array_pre (1 samples, 0.02%) + + + +org/joda/time/tz/CachedDateTimeZone:::getInfo (1 samples, 0.02%) + + + +Parse::Parse (1 samples, 0.02%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +CollectedHeap::post_allocation_setup_array (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/kafka/clients/producer/internals/RecordAccumulator:::drain (11 samples, 0.21%) + + + +checkcast_arraycopy_uninit (2 samples, 0.04%) + + + +do_softirq (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor105:::invoke (1 samples, 0.02%) + + + +itable stub (4 samples, 0.08%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +java/lang/ThreadLocal$ThreadLocalMap:::set (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy47:::annotationType (1 samples, 0.02%) + + + +java/util/LinkedList:::unlink (1 samples, 0.02%) + + + +org/springframework/web/servlet/support/WebContentGenerator:::checkRequest (1 samples, 0.02%) + + + +ConcurrentG1RefineThread::run (3 samples, 0.06%) + + + +deflate (85 samples, 1.65%) + + + +org/apache/catalina/connector/RequestFacade:::getHeader (3 samples, 0.06%) + + + +java/util/regex/Pattern$GroupTail:::match (1 samples, 0.02%) + + + +__inet_lookup_established (1 samples, 0.02%) + + + +javax/crypto/Cipher$Transform:::matches (2 samples, 0.04%) + + + +itable stub (2 samples, 0.04%) + + + +_new_array_nozero_Java (1 samples, 0.02%) + + + +PhaseChaitin::build_ifg_physical (6 samples, 0.12%) + + + +java/lang/StringCoding:::decode (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupTail:::match (4 samples, 0.08%) + + + +system_call_fastpath (25 samples, 0.49%) + + + +java/util/HashMap:::newNode (1 samples, 0.02%) + + + +org/apache/coyote/Request:::getContentType (5 samples, 0.10%) + + + +CompressedReadStream::read_int_mb (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (3 samples, 0.06%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/StringCache:::toString (2 samples, 0.04%) + + + +sun/reflect/GeneratedMethodAccessor55:::invoke (138 samples, 2.68%) +su.. + + +virtnet_poll (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +try_to_wake_up (19 samples, 0.37%) + + + +net_rx_action (1 samples, 0.02%) + + + +skb_release_all (1 samples, 0.02%) + + + +com/coohua/caf/core/metrics/ProfilerHttpFilter:::doFilter (3,588 samples, 69.81%) +com/coohua/caf/core/metrics/ProfilerHttpFilter:::doFilter + + +Method::line_number_from_bci (1 samples, 0.02%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +java/util/regex/Pattern$Neg:::match (3 samples, 0.06%) + + + +com/alibaba/fastjson/parser/JSONScanner:::scanFieldString (5 samples, 0.10%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +longest_match (27 samples, 0.53%) + + + +org/springframework/aop/framework/CglibAopProxy$DynamicAdvisedInterceptor:::intercept (5 samples, 0.10%) + + + +irq_exit (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +java/util/Collections$UnmodifiableCollection:::isEmpty (1 samples, 0.02%) + + + +TypeInt::xmeet (1 samples, 0.02%) + + + +java/util/Calendar:::createCalendar (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessor:::supportsReturnType (12 samples, 0.23%) + + + +org/apache/kafka/clients/producer/internals/Sender$SenderMetrics:::updateProduceRequestMetrics (1 samples, 0.02%) + + + +org/springframework/web/servlet/DispatcherServlet:::doService (189 samples, 3.68%) +org/.. + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +pthread_mutex_unlock (1 samples, 0.02%) + + + +csum_partial (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +java/lang/ThreadLocal:::set (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +org/apache/commons/pool2/impl/GenericObjectPool:::borrowObject (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +call_softirq (2 samples, 0.04%) + + + +system_call_fastpath (18 samples, 0.35%) + + + +generic_exec_single (1 samples, 0.02%) + + + +org/springframework/web/cors/CorsUtils:::isPreFlightRequest (4 samples, 0.08%) + + + +do_softirq (1 samples, 0.02%) + + + +BarrierSet::static_write_ref_array_pre (1 samples, 0.02%) + + + +java/util/ArrayList:::toArray (1 samples, 0.02%) + + + +java/util/concurrent/ArrayBlockingQueue:::offer (3 samples, 0.06%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy8:::annotationType (1 samples, 0.02%) + + + +java/util/HashMap:::afterNodeInsertion (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +org/springframework/web/accept/ContentNegotiationManager:::resolveMediaTypes (1 samples, 0.02%) + + + +current_kernel_time (1 samples, 0.02%) + + + +java/net/URI:::<init> (8 samples, 0.16%) + + + +inflate (3 samples, 0.06%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/LoggerContext:::getLogger (1 samples, 0.02%) + + + +java/util/HashMap:::put (3 samples, 0.06%) + + + +java/lang/Enum:::hashCode (1 samples, 0.02%) + + + +__pthread_enable_asynccancel (1 samples, 0.02%) + + + +generic_exec_single (1 samples, 0.02%) + + + +Java_java_lang_reflect_Array_get (1 samples, 0.02%) + + + +BarrierSet::static_write_ref_array_pre (2 samples, 0.04%) + + + +wake_futex (30 samples, 0.58%) + + + +java/util/HashMap:::put (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/web/filter/RequestContextFilter:::doFilterInternal (3,600 samples, 70.04%) +org/springframework/web/filter/RequestContextFilter:::doFilterInternal + + +free (1 samples, 0.02%) + + + +do_sync_write (25 samples, 0.49%) + + + +sun/misc/Unsafe:::unpark (8 samples, 0.16%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +java/util/HashMap:::put (3 samples, 0.06%) + + + +java/text/DateFormatSymbols:::getProviderInstance (1 samples, 0.02%) + + + +java/util/zip/Inflater:::inflateBytes (2 samples, 0.04%) + + + +ep_scan_ready_list.isra.7 (3 samples, 0.06%) + + + +G1CollectedHeap::can_elide_initializing_store_barrier (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +Unsafe_Unpark (1 samples, 0.02%) + + + +__sb_start_write (1 samples, 0.02%) + + + +sched_clock (1 samples, 0.02%) + + + +smp_apic_timer_interrupt (1 samples, 0.02%) + + + +inflate (219 samples, 4.26%) +inflate + + +com/coohua/caf/core/sentinel/SentinelHttpFilter:::doFilter (1 samples, 0.02%) + + + +java/lang/reflect/Method:::invoke (2,644 samples, 51.44%) +java/lang/reflect/Method:::invoke + + +do_futex (4 samples, 0.08%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +CompressedReadStream::read_signed_int (2 samples, 0.04%) + + + +java/util/HashMap:::newNode (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::subParse (1 samples, 0.02%) + + + +java/security/Provider$ServiceKey:::equals (2 samples, 0.04%) + + + +[libc-2.17.so] (1 samples, 0.02%) + + + +wake_futex (1 samples, 0.02%) + + + +java_lang_Throwable::get_stack_trace_element (27 samples, 0.53%) + + + +__schedule (10 samples, 0.19%) + + + +org/apache/kafka/common/requests/ProduceRequest:::<init> (2 samples, 0.04%) + + + +com/alibaba/csp/sentinel/slots/statistic/base/LeapArray:::currentWindow (2 samples, 0.04%) + + + +do_softirq (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/util/regex/Pattern$Begin:::match (3 samples, 0.06%) + + + +ConcurrentG1RefineThread::run_young_rs_sampling (3 samples, 0.06%) + + + +org/apache/coyote/http11/Http11OutputBuffer:::end (88 samples, 1.71%) + + + +do_sync_read (4 samples, 0.08%) + + + +JavaThread::thread_from_jni_environment (2 samples, 0.04%) + + + +java/text/SimpleDateFormat:::parse (2 samples, 0.04%) + + + +InstanceKlass::mask_for (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy49:::annotationType (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/HttpHeadersReturnValueHandler:::supportsReturnType (1 samples, 0.02%) + + + +inflate_table (2 samples, 0.04%) + + + +net_rx_action (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +io/micrometer/core/instrument/MeterRegistry:::registerMeterIfNecessary (6 samples, 0.12%) + + + +schedule_hrtimeout_range (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +G1ParScanThreadState::copy_to_survivor_space (1 samples, 0.02%) + + + +OptoRuntime::multianewarray2_C (10 samples, 0.19%) + + + +org/apache/kafka/common/Cluster:::leaderFor (5 samples, 0.10%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/condition/PatternsRequestCondition:::getMatchingPatterns (55 samples, 1.07%) + + + +_register_finalizer_Java (4 samples, 0.08%) + + + +java/text/SimpleDateFormat:::parse (5 samples, 0.10%) + + + +OptoRuntime::new_array_nozero_C (1 samples, 0.02%) + + + +call_softirq (2 samples, 0.04%) + + + +vfs_write (24 samples, 0.47%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +BarrierSet::static_write_ref_array_post (2 samples, 0.04%) + + + +irq_exit (1 samples, 0.02%) + + + +com/google/gson/internal/bind/MapTypeAdapterFactory$Adapter:::write (1 samples, 0.02%) + + + +__do_softirq (2 samples, 0.04%) + + + +org/springframework/web/method/annotation/ModelFactory:::initModel (1 samples, 0.02%) + + + +redis/clients/jedis/Protocol:::process (1 samples, 0.02%) + + + +org/apache/kafka/common/network/Selector:::addToCompletedReceives (5 samples, 0.10%) + + + +fill_window (3 samples, 0.06%) + + + +java/text/DateFormatSymbols:::getProviderInstance (2 samples, 0.04%) + + + +java/util/Collections$UnmodifiableMap:::size (1 samples, 0.02%) + + + +frame::sender (1 samples, 0.02%) + + + +TypeArrayKlass::allocate_common (1 samples, 0.02%) + + + +com/coohua/ad/data/service/impl/AdDataServiceImpl:::ecpProcess (4 samples, 0.08%) + + + +UTF8::unicode_length (3 samples, 0.06%) + + + +_new_array_nozero_Java (1 samples, 0.02%) + + + +pipe_read (1 samples, 0.02%) + + + +java/net/URI:::<init> (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +java/util/regex/Pattern$GroupTail:::match (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/StringCache:::toString (4 samples, 0.08%) + + + +[libpthread-2.17.so] (1 samples, 0.02%) + + + +com/coohua/ad/data/domain/AdDataDomain:::getAdId (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +security_file_permission (2 samples, 0.04%) + + + +org/springframework/web/util/UrlPathHelper:::getPathWithinServletMapping (2 samples, 0.04%) + + + +java/util/regex/Pattern$CharProperty:::match (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +java/lang/StringBuilder:::append (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/condition/AbstractMediaTypeExpression:::hashCode (3 samples, 0.06%) + + + +com/sun/proxy/$Proxy109:::annotationType (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor51:::invoke (1 samples, 0.02%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics:::addEvent (1 samples, 0.02%) + + + +JavaCallWrapper::~JavaCallWrapper (1 samples, 0.02%) + + + +rb_erase (1 samples, 0.02%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (2 samples, 0.04%) + + + +process_backlog (1 samples, 0.02%) + + + +G1SATBCardTableModRefBS::write_ref_array_pre (1 samples, 0.02%) + + + +I2C/C2I adapters (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +[libc-2.17.so] (27 samples, 0.53%) + + + +[libpthread-2.17.so] (25 samples, 0.49%) + + + +Interpreter (4,470 samples, 86.96%) +Interpreter + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +sun/nio/ch/SelectorImpl:::lockAndDoSelect (6 samples, 0.12%) + + + +__irqentry_text_start (2 samples, 0.04%) + + + +jni_fast_GetBooleanField (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +java/lang/ThreadLocal$ThreadLocalMap:::getEntryAfterMiss (1 samples, 0.02%) + + + +StringTable::intern (128 samples, 2.49%) +St.. + + +JVM_GetArrayElement (2 samples, 0.04%) + + + +Java_java_util_zip_Inflater_end (1 samples, 0.02%) + + + +java/util/regex/Pattern$BmpCharProperty:::match (1 samples, 0.02%) + + + +org/apache/kafka/clients/producer/KafkaProducer:::waitOnMetadata (2 samples, 0.04%) + + + +__skb_to_sgvec (1 samples, 0.02%) + + + +sock_def_readable (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/impl/Log4jLogEvent:::<init> (1 samples, 0.02%) + + + +fsnotify (2 samples, 0.04%) + + + +java/util/regex/Pattern$CharProperty:::match (1 samples, 0.02%) + + + +com/coohua/ad/data/manager/AdDataManager:::incrUserDayClickLimit (6 samples, 0.12%) + + + +__skb_checksum (1 samples, 0.02%) + + + +G1CollectedHeap::attempt_allocation_slow (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +Java_java_util_zip_Deflater_deflateBytes (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +hrtimer_try_to_cancel.part.25 (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter:::invokeHandlerMethod (153 samples, 2.98%) +or.. + + +org/springframework/web/method/support/InvocableHandlerMethod:::invokeForRequest (2,706 samples, 52.65%) +org/springframework/web/method/support/InvocableHandlerMethod:::invokeForRequest + + +skb_release_head_state (1 samples, 0.02%) + + + +java/util/regex/Pattern$Neg:::match (2 samples, 0.04%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (2 samples, 0.04%) + + + +com/fasterxml/jackson/databind/ObjectMapper:::_configAndWriteValue (1 samples, 0.02%) + + + +auditsys (1 samples, 0.02%) + + + +java/util/concurrent/ConcurrentHashMap:::putVal (7 samples, 0.14%) + + + +__do_softirq (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +finish_task_switch (1 samples, 0.02%) + + + +inet_sendmsg (1 samples, 0.02%) + + + +java/lang/Throwable:::<init> (1 samples, 0.02%) + + + +system_call_fastpath (24 samples, 0.47%) + + + +com/sun/proxy/$Proxy8:::annotationType (2 samples, 0.04%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics:::getLibProperties (4 samples, 0.08%) + + + +redis/clients/jedis/Connection:::getStatusCodeReply (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +java/util/HashMap:::resize (1 samples, 0.02%) + + + +com/coohua/ad/data/controller/AdDataController:::process (2,634 samples, 51.25%) +com/coohua/ad/data/controller/AdDataController:::process + + +call_function_single_interrupt (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/DefaultJSONParser:::getResolveStatus (1 samples, 0.02%) + + + +__mnt_want_write_file (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/util/TimeUtil$1:::run (13 samples, 0.25%) + + + +frame::sender (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/web/context/request/ServletWebRequest:::getHeaderValues (1 samples, 0.02%) + + + +run_timer_softirq (1 samples, 0.02%) + + + +tcp_v4_early_demux (1 samples, 0.02%) + + + +wake_up_state (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getLocale (3 samples, 0.06%) + + + +system_call_fastpath (19 samples, 0.37%) + + + +redis/clients/jedis/JedisSlotBasedConnectionHandler:::getConnectionFromSlot (1 samples, 0.02%) + + + +skb_release_data (1 samples, 0.02%) + + + +java/util/HashMap:::put (5 samples, 0.10%) + + + +vtable stub (1 samples, 0.02%) + + + +org/apache/kafka/clients/InFlightRequests:::nodesWithTimedOutRequests (1 samples, 0.02%) + + + +Method::line_number_from_bci (49 samples, 0.95%) + + + +java/lang/ThreadLocal:::set (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::initialize (1 samples, 0.02%) + + + +copy_user_enhanced_fast_string (3 samples, 0.06%) + + + +pthread_cond_signal@@GLIBC_2.3.2 (2 samples, 0.04%) + + + +java/util/HashMap:::resize (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +CompressedReadStream::read_signed_int (2 samples, 0.04%) + + + +org/apache/kafka/clients/NetworkClient:::canSendRequest (1 samples, 0.02%) + + + +sys_read (1 samples, 0.02%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +JVM_IsThreadAlive (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +CompileBroker::compiler_thread_loop (48 samples, 0.93%) + + + +java/lang/String:::toLowerCase (1 samples, 0.02%) + + + +java/util/HashMap:::put (2 samples, 0.04%) + + + +java_lang_Throwable::get_stack_trace_element (444 samples, 8.64%) +java_lang_Th.. + + +__dev_queue_xmit (1 samples, 0.02%) + + + +G1CollectorPolicy::add_region_to_incremental_cset_lhs (1 samples, 0.02%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (3 samples, 0.06%) + + + +call_softirq (1 samples, 0.02%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +I2C/C2I adapters (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +DebugInformationRecorder::dump_object_pool (1 samples, 0.02%) + + + +G1CollectedHeap::allocate_new_tlab (1 samples, 0.02%) + + + +__wake_up_sync_key (18 samples, 0.35%) + + + +OptoRuntime::new_array_nozero_C (1 samples, 0.02%) + + + +BarrierSet::static_write_ref_array_post (2 samples, 0.04%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +__memmove_ssse3_back (8 samples, 0.16%) + + + +jni_ExceptionOccurred (1 samples, 0.02%) + + + +PhaseIdealLoop::build_loop_early (3 samples, 0.06%) + + + +do_softirq (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +ep_scan_ready_list.isra.7 (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +Parse::do_one_block (1 samples, 0.02%) + + + +tcp_fin (1 samples, 0.02%) + + + +org/springframework/web/method/support/HandlerMethodReturnValueHandlerComposite:::selectHandler (50 samples, 0.97%) + + + +java/util/HashMap:::resize (8 samples, 0.16%) + + + +org/apache/catalina/connector/Request:::setAttribute (1 samples, 0.02%) + + + +java/util/regex/Matcher:::replaceAll (1 samples, 0.02%) + + + +jbyte_disjoint_arraycopy (1 samples, 0.02%) + + + +__pthread_mutex_cond_lock (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/LoggerContext:::getLogger (1 samples, 0.02%) + + + +__block_commit_write.isra.19 (1 samples, 0.02%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +Dict::Insert (1 samples, 0.02%) + + + +G1SATBCardTableModRefBS::enqueue (1 samples, 0.02%) + + + +com/coohua/ad/data/domain/AdDataDomain:::setAnonymous (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +org/apache/tomcat/util/threads/ThreadPoolExecutor:::currentThreadShouldBeStopped (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +java/util/ArrayList:::toArray (3 samples, 0.06%) + + + +org/springframework/util/LinkedCaseInsensitiveMap:::hashCode (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (1 samples, 0.02%) + + + +fdval (1 samples, 0.02%) + + + +IndexSet::IndexSet (1 samples, 0.02%) + + + +com/fasterxml/jackson/core/json/WriterBasedJsonGenerator:::writeEndObject (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (9 samples, 0.18%) + + + +Java_java_lang_Throwable_fillInStackTrace (4 samples, 0.08%) + + + +java/lang/Class:::getConstructor0 (1 samples, 0.02%) + + + +org/springframework/core/convert/support/GenericConversionService$ConverterCacheKey:::equals (1 samples, 0.02%) + + + +sys_sendto (6 samples, 0.12%) + + + +java/util/GregorianCalendar:::computeTime (1 samples, 0.02%) + + + +rw_verify_area (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/context/ContextUtil:::trueEnter (2 samples, 0.04%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +TypeArrayKlass::allocate_common (1 samples, 0.02%) + + + +org/apache/catalina/connector/CoyoteAdapter:::postParseRequest (1 samples, 0.02%) + + + +java/util/ArrayList:::add (1 samples, 0.02%) + + + +__GI___libc_poll (1 samples, 0.02%) + + + +CodeBlob::is_zombie (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +deflate_slow (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +system_call_fastpath (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +org/springframework/context/i18n/LocaleContextHolder:::setLocale (4 samples, 0.08%) + + + +PhaseIdealLoop::get_early_ctrl (1 samples, 0.02%) + + + +sun/nio/ch/SocketChannelImpl:::write (4 samples, 0.08%) + + + +PhaseCFG::do_global_code_motion (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/DefaultJSONParser:::parse (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +oopDesc::obj_field_put (1 samples, 0.02%) + + + +java/util/Calendar:::createCalendar (5 samples, 0.10%) + + + +do_softirq (1 samples, 0.02%) + + + +java_start (5,106 samples, 99.34%) +java_start + + +InstanceRefKlass::oop_oop_iterate_nv (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ObjectMapper:::_configAndWriteValue (1 samples, 0.02%) + + + +sun/misc/Unsafe:::unpark (21 samples, 0.41%) + + + +sun/reflect/GeneratedMethodAccessor95:::invoke (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/NioEndpoint$NioSocketWrapper:::doWrite (86 samples, 1.67%) + + + +net_rx_action (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy77:::annotationType (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +AbsSeq::davg (1 samples, 0.02%) + + + +JVM_GetStackTraceElement (1 samples, 0.02%) + + + +org/springframework/web/servlet/FrameworkServlet:::processRequest (192 samples, 3.74%) +org/.. + + +org/springframework/boot/actuate/trace/http/HttpExchangeTracer$$Lambda$656/561830191:::test (1 samples, 0.02%) + + + +java/lang/ref/Finalizer:::register (1 samples, 0.02%) + + + +java/util/HashSet:::isEmpty (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +java/util/LinkedHashMap:::get (2 samples, 0.04%) + + + +schedule_hrtimeout_range (11 samples, 0.21%) + + + +call_softirq (1 samples, 0.02%) + + + +mod_timer (1 samples, 0.02%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +com/coohua/caf/core/metrics/LatencyStat:::setMin (2 samples, 0.04%) + + + +org/apache/catalina/connector/CoyoteAdapter:::parseSessionSslId (1 samples, 0.02%) + + + +thread_entry (5,032 samples, 97.90%) +thread_entry + + +com/google/gson/stream/JsonWriter:::close (1 samples, 0.02%) + + + +tcp4_gro_receive (1 samples, 0.02%) + + + +Unsafe_Unpark (8 samples, 0.16%) + + + +netdev_pick_tx (1 samples, 0.02%) + + + +__audit_syscall_entry (1 samples, 0.02%) + + + +java/util/regex/Pattern$Ctype:::isSatisfiedBy (1 samples, 0.02%) + + + +Java_sun_nio_ch_EPollArrayWrapper_epollWait (1 samples, 0.02%) + + + +ep_send_events_proc (1 samples, 0.02%) + + + +getnstimeofday64 (1 samples, 0.02%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +pthread_getspecific (4 samples, 0.08%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +_tr_flush_block (7 samples, 0.14%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/util/AntPathMatcher:::doMatch (10 samples, 0.19%) + + + +org/springframework/web/util/UrlPathHelper:::getPathWithinApplication (4 samples, 0.08%) + + + +org/springframework/web/filter/CharacterEncodingFilter:::doFilterInternal (3,756 samples, 73.07%) +org/springframework/web/filter/CharacterEncodingFilter:::doFilterInternal + + +org/springframework/cglib/proxy/MethodProxy:::invoke (2 samples, 0.04%) + + + +java/util/HashMap:::newNode (1 samples, 0.02%) + + + +build_tree (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/util/HashMap:::put (2 samples, 0.04%) + + + +java/security/Provider$ServiceKey:::hashCode (1 samples, 0.02%) + + + +build_tree (81 samples, 1.58%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +malloc (1 samples, 0.02%) + + + +java/text/DateFormatSymbols:::getInstance (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +pvclock_clocksource_read (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ObjectMapper:::writeValueAsString (68 samples, 1.32%) + + + +org/springframework/context/event/AbstractApplicationEventMulticaster$ListenerRetriever:::getApplicationListeners (2 samples, 0.04%) + + + +InterpreterRuntime::frequency_counter_overflow (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +jni_fast_GetIntField (2 samples, 0.04%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +epoll_ctl (15 samples, 0.29%) + + + +com/sun/proxy/$Proxy48:::annotationType (1 samples, 0.02%) + + + +TypeArrayKlass::allocate_common (1 samples, 0.02%) + + + +org/apache/kafka/common/metrics/Sensor:::record (5 samples, 0.10%) + + + +org/springframework/web/servlet/FrameworkServlet:::logResult (1 samples, 0.02%) + + + +org/apache/coyote/AbstractProcessor:::action (103 samples, 2.00%) +o.. + + +oopDesc::obj_field_put (2 samples, 0.04%) + + + +virtnet_poll (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/config/LoggerConfig:::log (3 samples, 0.06%) + + + +ret_from_intr (1 samples, 0.02%) + + + +org/springframework/util/StringUtils:::trimAllWhitespace (1 samples, 0.02%) + + + +G1SATBCardTableModRefBS::write_ref_field_pre_work (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +org/springframework/web/servlet/DispatcherServlet:::processDispatchResult (165 samples, 3.21%) +org.. + + +__do_softirq (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/Type$11:::sizeOf (2 samples, 0.04%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter:::getSessionAttributesHandler (1 samples, 0.02%) + + + +pthread_self (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/impl/Log4jLogEvent:::<init> (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +get_futex_key (1 samples, 0.02%) + + + +java/util/regex/Pattern$Curly:::match (1 samples, 0.02%) + + + +x2apic_send_IPI_mask (2 samples, 0.04%) + + + +consume_skb (1 samples, 0.02%) + + + +java/lang/Throwable:::<init> (4 samples, 0.08%) + + + +free_old_xmit_skbs.isra.32 (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +dev_gro_receive (1 samples, 0.02%) + + + +OptoRuntime::new_instance_C (2 samples, 0.04%) + + + +org/springframework/context/support/AbstractApplicationContext:::publishEvent (22 samples, 0.43%) + + + +do_softirq (1 samples, 0.02%) + + + +_raw_spin_lock (1 samples, 0.02%) + + + +java/net/URI$Parser:::parseServer (1 samples, 0.02%) + + + +Symbol::as_unicode (2 samples, 0.04%) + + + +hrtimer_cancel (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::scanSymbol (1 samples, 0.02%) + + + +org/apache/kafka/clients/producer/internals/RecordAccumulator:::ready (21 samples, 0.41%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +sun/misc/Unsafe:::park (39 samples, 0.76%) + + + +java/util/regex/Pattern$Node:::match (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils$AnnotationCollector:::process (1 samples, 0.02%) + + + +system_call_fastpath (2 samples, 0.04%) + + + +apic_timer_interrupt (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/config/LoggerConfig:::log (5 samples, 0.10%) + + + +file_update_time (9 samples, 0.18%) + + + +Unsafe_Unpark (21 samples, 0.41%) + + + +java/util/LinkedHashMap:::newNode (1 samples, 0.02%) + + + +javax/crypto/Cipher$Transform:::matches (2 samples, 0.04%) + + + +apic_timer_interrupt (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +org/springframework/web/method/annotation/AbstractNamedValueMethodArgumentResolver:::resolveArgument (1 samples, 0.02%) + + + +JavaCalls::call_virtual (5,032 samples, 97.90%) +JavaCalls::call_virtual + + +org/apache/catalina/connector/RequestFacade:::removeAttribute (3 samples, 0.06%) + + + +JfrBackend::is_event_enabled (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::epollCtl (2 samples, 0.04%) + + + +org/apache/catalina/webresources/Cache:::getResource (4 samples, 0.08%) + + + +java/lang/String:::hashCode (1 samples, 0.02%) + + + +__pthread_disable_asynccancel (1 samples, 0.02%) + + + +do_sync_write (2 samples, 0.04%) + + + +auditsys (1 samples, 0.02%) + + + +_new_array_Java (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +StringTable::intern (1 samples, 0.02%) + + + +java/util/AbstractList:::hashCode (1 samples, 0.02%) + + + +_raw_spin_unlock (1 samples, 0.02%) + + + +unroll_tree_refs (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/util/HashMap$HashIterator:::hasNext (2 samples, 0.04%) + + + +org/springframework/util/StringUtils:::uriDecode (6 samples, 0.12%) + + + +arrayOopDesc::base (7 samples, 0.14%) + + + +__sb_end_write (1 samples, 0.02%) + + + +com/coohua/caf/core/rpc/MotanConfigPrintSpringListener:::onApplicationEvent (2 samples, 0.04%) + + + +jni_ReleasePrimitiveArrayCritical (7 samples, 0.14%) + + + +irq_exit (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::intValue (2 samples, 0.04%) + + + +sys_read (15 samples, 0.29%) + + + +java/io/StringWriter:::write (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11Processor:::prepareRequest (1 samples, 0.02%) + + + +java/util/concurrent/locks/ReentrantLock$NonfairSync:::lock (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::parseRest (1 samples, 0.02%) + + + +org/springframework/beans/TypeConverterSupport:::doConvert (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils:::findAnnotation (1 samples, 0.02%) + + + +hrtimer_start_range_ns (2 samples, 0.04%) + + + +process_backlog (1 samples, 0.02%) + + + +jbd2_journal_put_journal_head (1 samples, 0.02%) + + + +sys_write (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +__schedule (18 samples, 0.35%) + + + +Type::hashcons (1 samples, 0.02%) + + + +java/util/HashMap:::merge (3 samples, 0.06%) + + + +net_rx_action (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils:::isInJavaLangAnnotationPackage (2 samples, 0.04%) + + + +ret_from_intr (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::setAttribute (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getAttribute (2 samples, 0.04%) + + + +java_lang_String::equals (3 samples, 0.06%) + + + +net_rx_action (1 samples, 0.02%) + + + +ext4_da_write_end (5 samples, 0.10%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +java/util/zip/Inflater:::ensureOpen (1 samples, 0.02%) + + + +BarrierSet::static_write_ref_array_pre (1 samples, 0.02%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/Schema:::read (1 samples, 0.02%) + + + +skb_clone (1 samples, 0.02%) + + + +org/springframework/web/servlet/support/WebContentGenerator:::prepareResponse (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/Type$7:::sizeOf (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +com/coohua/caf/core/web/HttpTracingInterceptor:::preHandle (9 samples, 0.18%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +java_lang_StackTraceElement::set_declaringClass (1 samples, 0.02%) + + + +__dev_queue_xmit (2 samples, 0.04%) + + + +org/springframework/core/annotation/SynthesizedAnnotationInvocationHandler:::getAttributeValue (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +com/weibo/api/motan/filter/AccessLogFilter:::filter (8 samples, 0.16%) + + + +org/apache/kafka/common/protocol/types/ArrayOf:::read (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +sys_write (24 samples, 0.47%) + + + +org/apache/catalina/connector/Request:::setAttribute (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +org/springframework/core/annotation/SynthesizedAnnotationInvocationHandler:::getAttributeValue (1 samples, 0.02%) + + + +BacktraceBuilder::push (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/system/SystemSlot:::entry (2 samples, 0.04%) + + + +irq_exit (1 samples, 0.02%) + + + +java/net/SocketInputStream:::read (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/MessageBytes:::toString (1 samples, 0.02%) + + + +ObjectSynchronizer::FastHashCode (1 samples, 0.02%) + + + +java/util/zip/GZIPOutputStream:::finish (174 samples, 3.39%) +jav.. + + +java/lang/ThreadLocal:::set (3 samples, 0.06%) + + + +do_softirq (1 samples, 0.02%) + + + +__do_softirq (2 samples, 0.04%) + + + +org/springframework/core/MethodParameter:::hashCode (1 samples, 0.02%) + + + +java/text/DateFormatSymbols:::copyMembers (1 samples, 0.02%) + + + +java/net/SocketInputStream:::socketRead0 (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +java/util/LinkedHashMap:::get (3 samples, 0.06%) + + + +java/util/GregorianCalendar:::computeFields (1 samples, 0.02%) + + + +PhaseChaitin::fixup_spills (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +org/apache/catalina/connector/ResponseFacade:::containsHeader (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::setAttribute (1 samples, 0.02%) + + + +tcp_md5_do_lookup (1 samples, 0.02%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +org/apache/kafka/clients/producer/internals/Sender:::sendProduceRequest (46 samples, 0.89%) + + + +javax/crypto/Cipher$Transform:::matches (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +__wake_up_sync_key (9 samples, 0.18%) + + + +irq_exit (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotatedElementUtils:::searchWithFindSemantics (2 samples, 0.04%) + + + +jni_SetIntField (77 samples, 1.50%) + + + +ip_rcv (1 samples, 0.02%) + + + +nmethod::is_zombie (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (2 samples, 0.04%) + + + +IndexSet::initialize (1 samples, 0.02%) + + + +java/io/ByteArrayInputStream:::close (2 samples, 0.04%) + + + +__getnstimeofday64 (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/condition/ProducesRequestCondition$ProduceMediaTypeExpression:::matchMediaType (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterFactory:::createFilterChain (6 samples, 0.12%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +G1ParScanThreadState::copy_to_survivor_space (2 samples, 0.04%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (216 samples, 4.20%) +org/a.. + + +java/util/concurrent/ConcurrentHashMap:::putVal (1 samples, 0.02%) + + + +G1CollectedHeap::retire_mutator_alloc_region (1 samples, 0.02%) + + + +sys_read (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy5:::annotationType (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy5:::annotationType (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (3,548 samples, 69.03%) +org/springframework/web/filter/OncePerRequestFilter:::doFilter + + +org/apache/tomcat/util/net/NioEndpoint$NioSocketWrapper:::fillReadBuffer (27 samples, 0.53%) + + + +do_futex (1 samples, 0.02%) + + + +OtherRegionsTable::occupied (1 samples, 0.02%) + + + +com/coohua/caf/core/kv/JedisClient:::incrBy (1 samples, 0.02%) + + + +sun/nio/ch/SocketChannelImpl:::write (26 samples, 0.51%) + + + +sun/nio/cs/ISO_8859_1$Decoder:::decodeLoop (1 samples, 0.02%) + + + +__kfree_skb (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +sys_futex (21 samples, 0.41%) + + + +CollectedHeap::allocate_from_tlab_slow (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +java/lang/StringCoding:::decode (5 samples, 0.10%) + + + +org/springframework/util/CollectionUtils$MultiValueMapAdapter:::getFirst (3 samples, 0.06%) + + + +org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor:::getProducibleMediaTypes (3 samples, 0.06%) + + + +sock_def_readable (1 samples, 0.02%) + + + +ObjArrayKlass::allocate (1 samples, 0.02%) + + + +tcp_poll (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor103:::invoke (2 samples, 0.04%) + + + +com/weibo/api/motan/transport/netty/NettyChannel:::request (2 samples, 0.04%) + + + +__percpu_counter_add (1 samples, 0.02%) + + + +java/util/Formatter$FormatSpecifier:::checkBadFlags (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::recycle (7 samples, 0.14%) + + + +net_rx_action (1 samples, 0.02%) + + + +org/springframework/boot/actuate/web/trace/servlet/HttpTraceFilter:::doFilterInternal (200 samples, 3.89%) +org/.. + + +sun/nio/cs/UTF_8$Encoder:::encode (6 samples, 0.12%) + + + +net_rx_action (1 samples, 0.02%) + + + +longest_match (1 samples, 0.02%) + + + +itable stub (1 samples, 0.02%) + + + +futex_wake_op (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +Java_java_util_zip_Inflater_inflateBytes (760 samples, 14.79%) +Java_java_util_zip_Inf.. + + +do_softirq (1 samples, 0.02%) + + + +org/springframework/aop/aspectj/AbstractAspectJAdvice:::invokeAdviceMethod (4 samples, 0.08%) + + + +java/util/zip/GZIPInputStream:::readUByte (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +ip_output (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::parseRest (120 samples, 2.33%) +c.. + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +org/springframework/web/servlet/FrameworkServlet:::processRequest (3,445 samples, 67.02%) +org/springframework/web/servlet/FrameworkServlet:::processRequest + + +com/alibaba/fastjson/parser/DefaultJSONParser:::parse (2 samples, 0.04%) + + + +G1SATBCardTableLoggingModRefBS::invalidate (1 samples, 0.02%) + + + +CollectedHeap::new_store_pre_barrier (1 samples, 0.02%) + + + +java/util/zip/DeflaterOutputStream:::write (1 samples, 0.02%) + + + +Unsafe_Park (5 samples, 0.10%) + + + +call_softirq (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +inflateInit2_ (1 samples, 0.02%) + + + +checkcast_arraycopy (1 samples, 0.02%) + + + +org/springframework/web/util/UrlPathHelper:::getPathWithinApplication (1 samples, 0.02%) + + + +JVM_GetEnclosingMethodInfo (1 samples, 0.02%) + + + +update_time (9 samples, 0.18%) + + + +JavaThread::thread_from_jni_environment (4 samples, 0.08%) + + + +org/springframework/core/annotation/SynthesizedAnnotationInvocationHandler:::getAttributeValue (3 samples, 0.06%) + + + +irq_exit (1 samples, 0.02%) + + + +_tr_flush_block (127 samples, 2.47%) +_t.. + + +java/util/LinkedHashMap:::get (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +generic_exec_single (2 samples, 0.04%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +__GI___libc_poll (1 samples, 0.02%) + + + +itable stub (1 samples, 0.02%) + + + +os::sleep (8 samples, 0.16%) + + + +__do_softirq (1 samples, 0.02%) + + + +checkcast_arraycopy_uninit (1 samples, 0.02%) + + + +HandleMarkCleaner::~HandleMarkCleaner (1 samples, 0.02%) + + + +java/lang/String:::charAt (3 samples, 0.06%) + + + +ciEnv::register_method (1 samples, 0.02%) + + + +org/apache/catalina/connector/CoyoteAdapter:::postParseRequest (21 samples, 0.41%) + + + +java/util/regex/Pattern$GroupTail:::match (1 samples, 0.02%) + + + +system_call_after_swapgs (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/springframework/web/filter/RequestContextFilter:::doFilterInternal (204 samples, 3.97%) +org/.. + + +sys_read (3 samples, 0.06%) + + + +longest_match (2 samples, 0.04%) + + + +_raw_spin_unlock_irqrestore (2 samples, 0.04%) + + + +org/springframework/boot/actuate/metrics/web/servlet/LongTaskTimingHandlerInterceptor:::getLongTaskTimerSamples (5 samples, 0.10%) + + + +org/apache/catalina/core/ApplicationFilterChain:::doFilter (3,685 samples, 71.69%) +org/apache/catalina/core/ApplicationFilterChain:::doFilter + + +sun/misc/Unsafe:::unpark (3 samples, 0.06%) + + + +org/apache/logging/log4j/message/ParameterizedMessage:::getFormattedMessage (5 samples, 0.10%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +javax/crypto/Cipher:::chooseProvider (2 samples, 0.04%) + + + +Matcher::xform (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/lang/StringBuilder:::append (4 samples, 0.08%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +pqdownheap (60 samples, 1.17%) + + + +org/springframework/util/MimeType$SpecificityComparator:::compare (3 samples, 0.06%) + + + +inflateStateCheck (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (211 samples, 4.11%) +org/.. + + +sun/nio/ch/SelectionKeyImpl:::nioInterestOps (1 samples, 0.02%) + + + +com/coohua/ad/data/interceptor/UserInterceptor:::preHandle (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/SymbolTable:::addSymbol (5 samples, 0.10%) + + + +arrayof_jint_fill (4 samples, 0.08%) + + + +vtable stub (1 samples, 0.02%) + + + +netif_receive_skb_internal (1 samples, 0.02%) + + + +sysret_audit (1 samples, 0.02%) + + + +inet_recvmsg (1 samples, 0.02%) + + + +C2Compiler::compile_method (48 samples, 0.93%) + + + +java/util/regex/Pattern$Curly:::match (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +vfs_writev (18 samples, 0.35%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/Struct:::set (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (4 samples, 0.08%) + + + +call_softirq (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/coyote/AbstractProtocol$ConnectionHandler:::process (4,041 samples, 78.62%) +org/apache/coyote/AbstractProtocol$ConnectionHandler:::process + + +com/coohua/caf/core/web/HttpTracingInterceptor:::postHandle (1 samples, 0.02%) + + + +InstanceRefKlass::oop_oop_iterate_backwards_nv (3 samples, 0.06%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +org/springframework/web/util/UrlPathHelper:::getPathWithinApplication (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::parseField (4 samples, 0.08%) + + + +java/net/SocketInputStream:::read (1 samples, 0.02%) + + + +java/util/LinkedHashMap:::newNode (1 samples, 0.02%) + + + +java/util/concurrent/ConcurrentHashMap$EntryIterator:::next (1 samples, 0.02%) + + + +__audit_syscall_exit (1 samples, 0.02%) + + + +java/util/Formatter$FormatSpecifier:::print (2 samples, 0.04%) + + + +ip_rcv (1 samples, 0.02%) + + + +org/apache/kafka/common/requests/ProduceRequest$Builder:::build (3 samples, 0.06%) + + + +pthread_cond_wait@@GLIBC_2.3.2 (18 samples, 0.35%) + + + +CodeBuffer::free_blob (1 samples, 0.02%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (204 samples, 3.97%) +org/.. + + +org/apache/kafka/common/requests/AbstractResponse:::parseResponse (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/web/servlet/handler/ConversionServiceExposingInterceptor:::preHandle (2 samples, 0.04%) + + + +tcp_time_wait (1 samples, 0.02%) + + + +com/coohua/caf/core/metrics/LatencyStat:::setMax (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +java_lang_Thread::set_thread_status (1 samples, 0.02%) + + + +org/apache/kafka/common/metrics/stats/SampledStat:::record (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +MultiNode::is_CFG (1 samples, 0.02%) + + + +apic_timer_interrupt (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +org/apache/tomcat/util/http/NamesEnumerator:::findNext (12 samples, 0.23%) + + + +com/sun/proxy/$Proxy0:::annotationType (1 samples, 0.02%) + + + +org/springframework/web/servlet/handler/AbstractHandlerMethodMapping:::getHandlerInternal (138 samples, 2.68%) +or.. + + +org/apache/tomcat/util/buf/MessageBytes:::toString (1 samples, 0.02%) + + + +sysret_check (1 samples, 0.02%) + + + +_complete_monitor_locking_Java (1 samples, 0.02%) + + + +vfs_read (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::deserialze (9 samples, 0.18%) + + + +virtnet_poll (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +inet_gro_receive (1 samples, 0.02%) + + + +org/springframework/cglib/proxy/MethodProxy:::invoke (1 samples, 0.02%) + + + +com/weibo/api/motan/proxy/RefererInvocationHandler:::invoke (10 samples, 0.19%) + + + +mark_buffer_dirty (1 samples, 0.02%) + + + +futex_wait_setup (1 samples, 0.02%) + + + +ThreadLocalAllocBuffer::fill (1 samples, 0.02%) + + + +__audit_syscall_entry (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/StringCache:::toString (4 samples, 0.08%) + + + +ret_from_intr (1 samples, 0.02%) + + + +org/apache/coyote/Request:::recycle (8 samples, 0.16%) + + + +java/text/DecimalFormat:::parse (1 samples, 0.02%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +sys_write (1 samples, 0.02%) + + + +futex_wake_op (1 samples, 0.02%) + + + +BacktraceBuilder::expand (2 samples, 0.04%) + + + +tcp_ack (1 samples, 0.02%) + + + +PhaseChaitin::Register_Allocate (25 samples, 0.49%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +updateBytesCRC32 (3 samples, 0.06%) + + + +java/util/regex/Pattern:::RemoveQEQuoting (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy43:::annotationType (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +sys_futex (1 samples, 0.02%) + + + +G1RootProcessor::process_java_roots (3 samples, 0.06%) + + + +malloc (4 samples, 0.08%) + + + +com/google/gson/stream/JsonWriter:::close (1 samples, 0.02%) + + + +tcp_send_mss (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +com/coohua/ad/data/service/impl/AdDataServiceImpl:::dataProcess (8 samples, 0.16%) + + + +org/apache/kafka/clients/producer/internals/ProducerBatch:::completeFutureAndFireCallbacks (32 samples, 0.62%) + + + +__audit_syscall_exit (1 samples, 0.02%) + + + +sun/nio/cs/UTF_8$Decoder:::decode (1 samples, 0.02%) + + + +sun/nio/ch/SocketChannelImpl:::translateReadyOps (1 samples, 0.02%) + + + +IndexSetIterator::advance_and_next (1 samples, 0.02%) + + + +java/util/HashMap$EntrySet:::iterator (2 samples, 0.04%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (3,685 samples, 71.69%) +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter + + +org/springframework/web/servlet/handler/AbstractUrlHandlerMapping:::lookupHandler (12 samples, 0.23%) + + + +vtable stub (2 samples, 0.04%) + + + +process_backlog (1 samples, 0.02%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/nodeselector/NodeSelectorSlot:::exit (15 samples, 0.29%) + + + +org/apache/kafka/clients/NetworkClient:::handleInitiateApiVersionRequests (2 samples, 0.04%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/apache/catalina/core/StandardContext:::getApplicationEventListeners (1 samples, 0.02%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +[unknown] (15 samples, 0.29%) + + + +wake_up_state (2 samples, 0.04%) + + + +__fsnotify_parent (1 samples, 0.02%) + + + +__srcu_read_unlock (1 samples, 0.02%) + + + +java/util/concurrent/ConcurrentHashMap:::putVal (1 samples, 0.02%) + + + +get_page_from_freelist (1 samples, 0.02%) + + + +org/apache/kafka/common/record/ByteBufferLogInputStream:::nextBatch (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +JNIHandleBlock::allocate_block (1 samples, 0.02%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/node/StatisticNode:::addRtAndSuccess (10 samples, 0.19%) + + + +sun/nio/ch/EPollArrayWrapper:::interrupt (24 samples, 0.47%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/util/regex/Pattern$Slice:::match (1 samples, 0.02%) + + + +java/util/regex/Pattern$BmpCharProperty:::match (6 samples, 0.12%) + + + +hrtimer_start_range_ns (1 samples, 0.02%) + + + +java/lang/Throwable:::getStackTraceElement (1 samples, 0.02%) + + + +sun/security/jca/ProviderList$ServiceList:::tryGet (1 samples, 0.02%) + + + +mutex_lock (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +__vdso_clock_gettime (1 samples, 0.02%) + + + +CollectedHeap::allocate_from_tlab_slow (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/CallableMethodReturnValueHandler:::supportsReturnType (1 samples, 0.02%) + + + +java/lang/ThreadLocal$ThreadLocalMap:::getEntryAfterMiss (1 samples, 0.02%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (14 samples, 0.27%) + + + +smp_apic_timer_interrupt (1 samples, 0.02%) + + + +java/util/HashMap:::get (1 samples, 0.02%) + + + +java/util/concurrent/ConcurrentHashMap:::get (1 samples, 0.02%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +consume_skb (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::compile (7 samples, 0.14%) + + + +org/apache/kafka/clients/NetworkClient:::doSend (33 samples, 0.64%) + + + +com/coohua/caf/core/kv/JedisClient$$EnhancerBySpringCGLIB$$712d2b04:::incrBy (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +sock_poll (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +java/util/HashMap:::newNode (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +org/springframework/web/servlet/handler/AbstractHandlerMapping:::getHandlerExecutionChain (15 samples, 0.29%) + + + +java/lang/AbstractStringBuilder:::append (14 samples, 0.27%) + + + +java/util/regex/Pattern$BmpCharProperty:::match (1 samples, 0.02%) + + + +CodeCache::find_blob (1 samples, 0.02%) + + + +sk_stream_alloc_skb (1 samples, 0.02%) + + + +generic_exec_single (1 samples, 0.02%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +nmethod::is_zombie (1 samples, 0.02%) + + + +tcp_data_queue (1 samples, 0.02%) + + + +org/springframework/aop/aspectj/AbstractAspectJAdvice:::invokeAdviceMethod (1 samples, 0.02%) + + + +__srcu_read_lock (3 samples, 0.06%) + + + +java/util/IdentityHashMap:::get (1 samples, 0.02%) + + + +CollectedHeap::common_mem_allocate_init (2 samples, 0.04%) + + + +net_rx_action (1 samples, 0.02%) + + + +tcp_cleanup_rbuf (2 samples, 0.04%) + + + +org/apache/catalina/core/StandardWrapperValve:::invoke (216 samples, 4.20%) +org/a.. + + +GenericTaskQueueSet<OverflowTaskQueue<StarTask, (4 samples, 0.08%) + + + +jni_fast_GetIntField (25 samples, 0.49%) + + + +org/apache/catalina/core/StandardWrapperValve:::invoke (3,775 samples, 73.44%) +org/apache/catalina/core/StandardWrapperValve:::invoke + + +call_function_single_interrupt (1 samples, 0.02%) + + + +ObjArrayKlass::multi_allocate (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (3 samples, 0.06%) + + + +org/springframework/web/servlet/handler/AbstractUrlHandlerMapping:::getHandlerInternal (1 samples, 0.02%) + + + +Parse::do_call (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ser/std/MapSerializer:::serializeFields (2 samples, 0.04%) + + + +com/google/gson/stream/JsonWriter:::string (5 samples, 0.10%) + + + +java/util/concurrent/ConcurrentMap:::computeIfAbsent (1 samples, 0.02%) + + + +java/lang/String:::equals (2 samples, 0.04%) + + + +java/text/SimpleDateFormat:::format (4 samples, 0.08%) + + + +java/util/concurrent/locks/ReentrantLock$NonfairSync:::lock (1 samples, 0.02%) + + + +dev_gro_receive (1 samples, 0.02%) + + + +__alloc_skb (1 samples, 0.02%) + + + +pthread_cond_signal@@GLIBC_2.3.2 (3 samples, 0.06%) + + + +G1CollectorPolicy::update_incremental_cset_info (1 samples, 0.02%) + + + +__skb_checksum (1 samples, 0.02%) + + + +org/apache/catalina/core/StandardHostValve:::invoke (216 samples, 4.20%) +org/a.. + + +wake_up_state (5 samples, 0.10%) + + + +getnstimeofday64 (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +__vdso_gettimeofday (2 samples, 0.04%) + + + +_new_array_nozero_Java (2 samples, 0.04%) + + + +Symbol::as_klass_external_name (4 samples, 0.08%) + + + +sock_def_readable (1 samples, 0.02%) + + + +generic_exec_single (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/StringCache:::toString (8 samples, 0.16%) + + + +com/alibaba/csp/sentinel/slots/logger/LogSlot:::entry (1 samples, 0.02%) + + + +wake_up_state (3 samples, 0.06%) + + + +G1ParTask::work (19 samples, 0.37%) + + + +system_call_fastpath (43 samples, 0.84%) + + + +org/apache/catalina/core/StandardContext:::getApplicationEventListeners (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +org/apache/kafka/clients/producer/internals/Sender:::completeBatch (34 samples, 0.66%) + + + +sun/nio/cs/UTF_8$Encoder:::encode (1 samples, 0.02%) + + + +org/apache/logging/log4j/message/ParameterFormatter:::recursiveDeepToString (1 samples, 0.02%) + + + +finish_task_switch (11 samples, 0.21%) + + + +pthread_getspecific (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/web/method/annotation/ModelFactory:::findSessionAttributeArguments (1 samples, 0.02%) + + + +org/jboss/netty/channel/socket/nio/NioWorker:::writeFromUserCode (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +org/springframework/core/annotation/SynthesizedAnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +_new_array_nozero_Java (1 samples, 0.02%) + + + +__audit_syscall_exit (1 samples, 0.02%) + + + +sun/nio/ch/SelectorImpl:::select (1 samples, 0.02%) + + + +longest_match (12 samples, 0.23%) + + + +schedule_hrtimeout_range_clock (16 samples, 0.31%) + + + +select_estimate_accuracy (1 samples, 0.02%) + + + +org/springframework/beans/factory/support/DefaultSingletonBeanRegistry:::getSingleton (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor:::supportsReturnType (1 samples, 0.02%) + + + +java/util/HashSet:::iterator (1 samples, 0.02%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +OptoRuntime::new_array_nozero_C (1 samples, 0.02%) + + + +sun/nio/ch/NativeThread:::current (1 samples, 0.02%) + + + +OptoRuntime::new_instance_C (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/StringCache:::toString (1 samples, 0.02%) + + + +org/springframework/util/AntPathMatcher:::match (3 samples, 0.06%) + + + +inet_sendmsg (37 samples, 0.72%) + + + +org/springframework/web/accept/ContentNegotiationManager:::resolveMediaTypes (1 samples, 0.02%) + + + +org/springframework/web/method/annotation/ModelAttributeMethodProcessor:::supportsReturnType (31 samples, 0.60%) + + + +anon_pipe_buf_release (1 samples, 0.02%) + + + +jni_SetIntField (6 samples, 0.12%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +sun/nio/ch/IOUtil:::write (3 samples, 0.06%) + + + +sun/security/provider/ByteArrayAccess:::b2iBig64 (1 samples, 0.02%) + + + +jshort_arraycopy (1 samples, 0.02%) + + + +post_allocation_notify (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +G1RootProcessor::evacuate_roots (3 samples, 0.06%) + + + +ret_from_intr (1 samples, 0.02%) + + + +inflateInit2_ (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +ksize (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/pattern/MdcPatternConverter:::format (1 samples, 0.02%) + + + +java/lang/Thread:::sleep (12 samples, 0.23%) + + + +org/springframework/boot/actuate/trace/http/HttpExchangeTracer:::getHeadersIfIncluded (5 samples, 0.10%) + + + +hrtimer_cancel (1 samples, 0.02%) + + + +__fsnotify_parent (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/RequestMappingInfo:::getMatchingCondition (36 samples, 0.70%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +org/springframework/http/MediaType:::isCompatibleWith (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +vfs_read (1 samples, 0.02%) + + + +JVM_IsThreadAlive (1 samples, 0.02%) + + + +system_call_fastpath (14 samples, 0.27%) + + + +java/util/regex/Pattern$GroupHead:::match (3 samples, 0.06%) + + + +org/springframework/core/ResolvableType:::forType (2 samples, 0.04%) + + + +process_backlog (1 samples, 0.02%) + + + +Java_java_util_zip_Deflater_deflateBytes (1 samples, 0.02%) + + + +java/util/ComparableTimSort:::sort (3 samples, 0.06%) + + + +pthread_mutex_unlock@plt (1 samples, 0.02%) + + + +itable stub (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor108:::invoke (9 samples, 0.18%) + + + +org/apache/tomcat/util/http/NamesEnumerator:::findNext (3 samples, 0.06%) + + + +__alloc_skb (1 samples, 0.02%) + + + +java/lang/String:::regionMatches (1 samples, 0.02%) + + + +epoll_ctl (2 samples, 0.04%) + + + +org/jboss/netty/channel/socket/nio/NioSocketChannel$WriteTask:::run (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/system/SystemSlot:::exit (1 samples, 0.02%) + + + +org/joda/time/chrono/BasicYearDateTimeField:::get (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +java/util/AbstractList:::equals (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/lang/String:::hashCode (1 samples, 0.02%) + + + +java/util/regex/Pattern$BmpCharProperty:::match (7 samples, 0.14%) + + + +__do_softirq (1 samples, 0.02%) + + + +Unsafe_Unpark (33 samples, 0.64%) + + + +JavaThread::handle_special_suspend_equivalent_condition (1 samples, 0.02%) + + + +java/lang/AbstractStringBuilder:::append (2 samples, 0.04%) + + + +java/util/zip/Inflater:::inflateBytes (835 samples, 16.25%) +java/util/zip/Inflater:::.. + + +java/util/stream/ReduceOps$ReduceOp:::evaluateSequential (12 samples, 0.23%) + + + +net_rx_action (1 samples, 0.02%) + + + +PhaseChaitin::Simplify (3 samples, 0.06%) + + + +sock_aio_read.part.7 (3 samples, 0.06%) + + + +_raw_spin_unlock_irqrestore (5 samples, 0.10%) + + + +org/springframework/web/util/UrlPathHelper:::getLookupPathForRequest (10 samples, 0.19%) + + + +deflateStateCheck (1 samples, 0.02%) + + + +org/springframework/beans/factory/support/AbstractBeanFactory:::resolveEmbeddedValue (2 samples, 0.04%) + + + +__memmove_ssse3_back (3 samples, 0.06%) + + + +java/util/regex/Pattern$Begin:::match (8 samples, 0.16%) + + + +G1SATBCardTableLoggingModRefBS::write_ref_array_work (1 samples, 0.02%) + + + +java/net/URI$Parser:::parseAuthority (4 samples, 0.08%) + + + +_raw_spin_unlock_irqrestore (4 samples, 0.08%) + + + +com/sun/proxy/$Proxy109:::annotationType (1 samples, 0.02%) + + + +__mnt_want_write_file (1 samples, 0.02%) + + + +com/alibaba/fastjson/serializer/LongCodec:::deserialze (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (31 samples, 0.60%) + + + +com/fasterxml/jackson/databind/ser/std/MapSerializer:::serialize (2 samples, 0.04%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +__x2apic_send_IPI_mask (2 samples, 0.04%) + + + +org/apache/tomcat/util/buf/MessageBytes:::recycle (1 samples, 0.02%) + + + +finish_task_switch (10 samples, 0.19%) + + + +__do_softirq (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +add_transaction_credits (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +arrayof_jint_fill (2 samples, 0.04%) + + + +CollectedHeap::common_mem_allocate_init (1 samples, 0.02%) + + + +org/apache/catalina/connector/CoyoteAdapter:::service (3,927 samples, 76.40%) +org/apache/catalina/connector/CoyoteAdapter:::service + + +enqueue_to_backlog (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/lang/StringBuilder:::append (1 samples, 0.02%) + + + +_tr_init (2 samples, 0.04%) + + + +jshort_arraycopy (2 samples, 0.04%) + + + +_raw_spin_unlock_irqrestore (28 samples, 0.54%) + + + +java/util/ComparableTimSort:::sort (5 samples, 0.10%) + + + +BarrierSet::static_write_ref_array_post (1 samples, 0.02%) + + + +system_call_fastpath (3 samples, 0.06%) + + + +TypeLong::xmeet (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +G1CollectedHeap::unsafe_max_tlab_alloc (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONScanner:::scanFieldInt (3 samples, 0.06%) + + + +resource_allocate_bytes (1 samples, 0.02%) + + + +Symbol::as_unicode (48 samples, 0.93%) + + + +do_softirq (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +start_xmit (8 samples, 0.16%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +ip_queue_xmit (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +org/springframework/http/converter/ByteArrayHttpMessageConverter:::supports (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/block/flow/FlowSlot:::entry (1 samples, 0.02%) + + + +ret_from_intr (2 samples, 0.04%) + + + +copy_user_enhanced_fast_string (1 samples, 0.02%) + + + +org/apache/logging/log4j/message/ParameterFormatter:::appendMap (5 samples, 0.10%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy8:::annotationType (1 samples, 0.02%) + + + +__libc_recv (1 samples, 0.02%) + + + +page_to_skb (1 samples, 0.02%) + + + +ep_unregister_pollwait.isra.6 (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11InputBuffer:::parseHeader (8 samples, 0.16%) + + + +smp_apic_timer_interrupt (2 samples, 0.04%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +java/util/Collections$UnmodifiableMap$UnmodifiableEntrySet:::iterator (1 samples, 0.02%) + + + +java/lang/AbstractStringBuilder:::append (2 samples, 0.04%) + + + +irq_exit (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +java/lang/reflect/Method:::hashCode (1 samples, 0.02%) + + + +ext4_reserve_inode_write (3 samples, 0.06%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +org/springframework/util/StringUtils:::tokenizeToStringArray (8 samples, 0.16%) + + + +CollectedHeap::allocate_from_tlab_slow (1 samples, 0.02%) + + + +org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilter:::doFilterInternal (215 samples, 4.18%) +org/.. + + +org/springframework/util/StringUtils:::tokenizeToStringArray (5 samples, 0.10%) + + + +sys_futex (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/pattern/ThreadNamePatternConverter:::format (1 samples, 0.02%) + + + +org/springframework/util/MimeType$SpecificityComparator:::compare (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/statistic/StatisticSlot:::entry (1 samples, 0.02%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +_int_malloc (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +java/util/Comparator$$Lambda$213/1325144078:::compare (1 samples, 0.02%) + + + +jbd2_journal_put_journal_head (1 samples, 0.02%) + + + +inflateStateCheck (15 samples, 0.29%) + + + +start_xmit (1 samples, 0.02%) + + + +com/coohua/ad/data/service/impl/AdDataServiceImpl:::clickProcess (20 samples, 0.39%) + + + +com/coohua/ad/data/manager/AdDataManager:::adChargeForCreative (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +sun/reflect/GeneratedMethodAccessor73:::invoke (3 samples, 0.06%) + + + +generic_exec_single (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter:::invokeHandlerMethod (2,834 samples, 55.14%) +org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter:::invo.. + + +org/springframework/web/servlet/handler/AbstractHandlerMapping:::getHandler (177 samples, 3.44%) +org.. + + +org/joda/time/chrono/BasicMonthOfYearDateTimeField:::get (1 samples, 0.02%) + + + +call_softirq (2 samples, 0.04%) + + + +UTF8::convert_to_unicode (15 samples, 0.29%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (2 samples, 0.04%) + + + +com/sun/proxy/$Proxy50:::annotationType (1 samples, 0.02%) + + + +sock_recvmsg (1 samples, 0.02%) + + + +apic_timer_interrupt (2 samples, 0.04%) + + + +java/util/regex/Pattern$Branch:::match (3 samples, 0.06%) + + + +__audit_syscall_exit (1 samples, 0.02%) + + + +do_csum (1 samples, 0.02%) + + + +org/apache/coyote/AbstractProtocol$RecycledProcessors:::push (1 samples, 0.02%) + + + +system_call_fastpath (2 samples, 0.04%) + + + +java (5,140 samples, 100.00%) +java + + +org/apache/catalina/mapper/Mapper:::internalMapWrapper (8 samples, 0.16%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics:::getLibProperties (35 samples, 0.68%) + + + +sun/nio/ch/IOUtil:::write (51 samples, 0.99%) + + + +java/util/ArrayList:::toArray (2 samples, 0.04%) + + + +OptoRuntime::multianewarray2_C (1 samples, 0.02%) + + + +packet_rcv (1 samples, 0.02%) + + + +com/alibaba/fastjson/parser/JSONLexerBase:::scanSymbol (1 samples, 0.02%) + + + +java/lang/StringBuffer:::append (1 samples, 0.02%) + + + +java/util/zip/DeflaterOutputStream:::write (1 samples, 0.02%) + + + +com/coohua/caf/core/kv/JedisClient$$FastClassBySpringCGLIB$$11ce05b4:::invoke (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +java/lang/String:::equals (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +epoll_ctl (1 samples, 0.02%) + + + +java/util/zip/GZIPOutputStream:::finish (1 samples, 0.02%) + + + +os::Linux::safe_cond_timedwait (1 samples, 0.02%) + + + +java/lang/String:::indexOf (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +sun/nio/ch/NativeThread:::current (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +__dev_queue_xmit (19 samples, 0.37%) + + + +org/springframework/core/annotation/AnnotationUtils:::isInJavaLangAnnotationPackage (3 samples, 0.06%) + + + +call_softirq (1 samples, 0.02%) + + + +__ext4_journal_start_sb (1 samples, 0.02%) + + + +org/springframework/web/servlet/DispatcherServlet:::doService (3,406 samples, 66.26%) +org/springframework/web/servlet/DispatcherServlet:::doService + + +net_rx_action (1 samples, 0.02%) + + + +virtqueue_get_buf (1 samples, 0.02%) + + + +__alloc_skb (2 samples, 0.04%) + + + +vfs_write (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +Parse::do_get_xxx (1 samples, 0.02%) + + + +java/util/zip/InflaterInputStream:::read (1 samples, 0.02%) + + + +com/coohua/caf/core/metrics/LatencyStat$Timer:::<init> (1 samples, 0.02%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +futex_wait (14 samples, 0.27%) + + + +java/util/regex/Pattern$CharProperty:::match (8 samples, 0.16%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::deserialze (118 samples, 2.30%) +c.. + + +Threads::possibly_parallel_oops_do (2 samples, 0.04%) + + + +org/apache/kafka/common/utils/AbstractIterator:::next (1 samples, 0.02%) + + + +CodeHeap::deallocate (1 samples, 0.02%) + + + +G1ParScanThreadState::trim_queue (4 samples, 0.08%) + + + +__do_softirq (2 samples, 0.04%) + + + +org/springframework/web/servlet/FrameworkServlet:::service (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilter:::record (57 samples, 1.11%) + + + +OptoRuntime::new_array_nozero_C (1 samples, 0.02%) + + + +java/util/concurrent/ThreadPoolExecutor:::getTask (41 samples, 0.80%) + + + +java/util/concurrent/ConcurrentHashMap:::putVal (2 samples, 0.04%) + + + +org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilter:::record (4 samples, 0.08%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (1 samples, 0.02%) + + + +pthread_getspecific@plt (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +java/lang/String:::split (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (2 samples, 0.04%) + + + +clock_gettime (1 samples, 0.02%) + + + +itable stub (1 samples, 0.02%) + + + +sun/reflect/GeneratedConstructorAccessor83:::newInstance (1 samples, 0.02%) + + + +tcp_data_queue (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (3 samples, 0.06%) + + + +com/coohua/caf/core/metrics/LatencyStat:::setMin (9 samples, 0.18%) + + + +schedule_hrtimeout_range_clock (11 samples, 0.21%) + + + +_register_finalizer_Java (10 samples, 0.19%) + + + +org/springframework/aop/framework/CglibAopProxy$DynamicAdvisedInterceptor:::intercept (1 samples, 0.02%) + + + +redis/clients/jedis/Jedis:::close (1 samples, 0.02%) + + + +ext4_dirty_inode (9 samples, 0.18%) + + + +VMThread::evaluate_operation (4 samples, 0.08%) + + + +system_call_fastpath (2 samples, 0.04%) + + + +org/apache/logging/log4j/core/LoggerContext:::getLogger (1 samples, 0.02%) + + + +Monitor::lock_without_safepoint_check (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +VMThread::run (4 samples, 0.08%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy0:::annotationType (1 samples, 0.02%) + + + +JavaCalls::call_helper (3 samples, 0.06%) + + + +redis/clients/jedis/Protocol:::process (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::epollWait (30 samples, 0.58%) + + + +rcu_process_gp_end (1 samples, 0.02%) + + + +java/util/Formatter:::format (3 samples, 0.06%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +java/util/GregorianCalendar:::computeTime (1 samples, 0.02%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +org/apache/kafka/common/record/MemoryRecordsBuilder:::close (8 samples, 0.16%) + + + +org/apache/coyote/http11/Http11OutputBuffer:::write (1 samples, 0.02%) + + + +java/util/TimSort:::sort (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (216 samples, 4.20%) +org/a.. + + +sock_poll (1 samples, 0.02%) + + + +tcp_sendmsg (2 samples, 0.04%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +java/lang/StringCoding:::encode (14 samples, 0.27%) + + + +org/apache/tomcat/util/net/NioEndpoint$Poller:::events (6 samples, 0.12%) + + + +schedule (10 samples, 0.19%) + + + +jshort_disjoint_arraycopy (8 samples, 0.16%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +tcp_transmit_skb (23 samples, 0.45%) + + + +org/apache/logging/log4j/message/ParameterFormatter:::recursiveDeepToString (5 samples, 0.10%) + + + +java/util/HashMap:::get (1 samples, 0.02%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject:::await (37 samples, 0.72%) + + + +call_softirq (1 samples, 0.02%) + + + +java/lang/AbstractStringBuilder:::append (1 samples, 0.02%) + + + +JavaCalls::call_helper (5,032 samples, 97.90%) +JavaCalls::call_helper + + +com/alibaba/csp/sentinel/slots/statistic/StatisticSlot:::entry (9 samples, 0.18%) + + + +ThreadStateTransition::trans_from_native (1 samples, 0.02%) + + + +org/springframework/web/context/request/ServletWebRequest:::getHeaderValues (1 samples, 0.02%) + + + +dev_hard_start_xmit (1 samples, 0.02%) + + + +java/util/LinkedHashMap$LinkedHashIterator:::hasNext (1 samples, 0.02%) + + + +tcp_rcv_established (1 samples, 0.02%) + + + +io/micrometer/core/instrument/Tags$ArrayIterator:::<init> (1 samples, 0.02%) + + + +org/apache/kafka/common/metrics/stats/Meter:::record (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +org/apache/catalina/connector/RequestFacade:::removeAttribute (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +ip_rcv (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/SocketProcessorBase:::run (4,047 samples, 78.74%) +org/apache/tomcat/util/net/SocketProcessorBase:::run + + +ret_from_intr (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +itable stub (1 samples, 0.02%) + + + +com/fasterxml/jackson/databind/ser/std/MapSerializer:::serializeFields (46 samples, 0.89%) + + + +java/util/Collection:::stream (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +copy_user_enhanced_fast_string (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +ReferenceProcessor::process_phase3 (3 samples, 0.06%) + + + +sysret_audit (1 samples, 0.02%) + + + +sock_def_readable (1 samples, 0.02%) + + + +virtnet_poll (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::parse (1 samples, 0.02%) + + + +[libpthread-2.17.so] (24 samples, 0.47%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +Parse::Parse (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/util/LinkedHashMap$LinkedKeyIterator:::next (1 samples, 0.02%) + + + +futex_wait_setup (1 samples, 0.02%) + + + +sys_epoll_ctl (2 samples, 0.04%) + + + +smp_apic_timer_interrupt (1 samples, 0.02%) + + + +Parse::do_all_blocks (1 samples, 0.02%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (3,612 samples, 70.27%) +org/springframework/web/filter/OncePerRequestFilter:::doFilter + + +call_function_single_interrupt (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +org/apache/kafka/clients/NetworkClient:::handleCompletedSends (4 samples, 0.08%) + + + +java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject:::awaitNanos (52 samples, 1.01%) + + + +pipe_write (1 samples, 0.02%) + + + +call_function_single_interrupt (2 samples, 0.04%) + + + +org/springframework/web/servlet/mvc/condition/PatternsRequestCondition:::getMatchingPatterns (1 samples, 0.02%) + + + +Symbol::as_klass_external_name (5 samples, 0.10%) + + + +org/apache/tomcat/util/http/ValuesEnumerator:::findNext (1 samples, 0.02%) + + + +virtqueue_add_outbuf (1 samples, 0.02%) + + + +com/coohua/ad/data/service/impl/AdDataServiceImpl:::clickProcess (1 samples, 0.02%) + + + +org/springframework/boot/actuate/web/trace/servlet/HttpTraceFilter:::doFilterInternal (3,545 samples, 68.97%) +org/springframework/boot/actuate/web/trace/servlet/HttpTraceFilter:::doFilterInternal + + +java/lang/reflect/Method:::equals (1 samples, 0.02%) + + + +Parker::park (1 samples, 0.02%) + + + +java/math/BigDecimal:::layoutChars (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +org/apache/catalina/authenticator/AuthenticatorBase:::invoke (216 samples, 4.20%) +org/a.. + + +skb_release_all (1 samples, 0.02%) + + + +sun/nio/ch/SocketChannelImpl:::read (27 samples, 0.53%) + + + +com/google/gson/Gson:::toJson (60 samples, 1.17%) + + + +BacktraceBuilder::push (25 samples, 0.49%) + + + +Java_java_lang_Throwable_fillInStackTrace (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +tcp_v4_early_demux (1 samples, 0.02%) + + + +com/weibo/api/motan/rpc/AbstractReferer:::call (3 samples, 0.06%) + + + +java/util/Calendar:::createCalendar (4 samples, 0.08%) + + + +JVM_FillInStackTrace (1 samples, 0.02%) + + + +mod_timer (1 samples, 0.02%) + + + +ep_poll (1 samples, 0.02%) + + + +UTF8::unicode_length (28 samples, 0.54%) + + + +itable stub (2 samples, 0.04%) + + + +com/alibaba/csp/sentinel/slots/system/SystemSlot:::exit (1 samples, 0.02%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics:::assertKeyWithRegex (3 samples, 0.06%) + + + +skb_defer_rx_timestamp (1 samples, 0.02%) + + + +com/google/gson/internal/bind/ArrayTypeAdapter:::write (40 samples, 0.78%) + + + +Unsafe_Unpark (2 samples, 0.04%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +org/springframework/web/filter/RequestContextFilter:::doFilterInternal (1 samples, 0.02%) + + + +Unsafe_Park (30 samples, 0.58%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::smartMatch (3 samples, 0.06%) + + + +arrayof_jint_fill (1 samples, 0.02%) + + + +__memmove_ssse3_back (1 samples, 0.02%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +G1RemSet::refine_card (3 samples, 0.06%) + + + +net_rx_action (1 samples, 0.02%) + + + +java/util/LinkedHashMap:::get (2 samples, 0.04%) + + + +tcp_v4_destroy_sock (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (3 samples, 0.06%) + + + +do_sync_write (21 samples, 0.41%) + + + +process_backlog (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +JavaThread::check_and_handle_async_exceptions (1 samples, 0.02%) + + + +CollectedHeap::allocate_from_tlab_slow (1 samples, 0.02%) + + + +_new_instance_Java (1 samples, 0.02%) + + + +native_send_call_func_single_ipi (2 samples, 0.04%) + + + +itable stub (3 samples, 0.06%) + + + +call_softirq (1 samples, 0.02%) + + + +net_rx_action (2 samples, 0.04%) + + + +kfree (1 samples, 0.02%) + + + +HandleArea::allocate_handle (3 samples, 0.06%) + + + +PhaseIterGVN::subsume_node (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotationUtils:::getAnnotation (1 samples, 0.02%) + + + +org/apache/kafka/clients/producer/internals/Sender:::run (290 samples, 5.64%) +org/apa.. + + +java_lang_Throwable::get_stack_trace_depth (1 samples, 0.02%) + + + +deflate_slow (1 samples, 0.02%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +updateBytesCRC32 (4 samples, 0.08%) + + + +local_clock (2 samples, 0.04%) + + + +java/util/concurrent/locks/ReentrantLock$NonfairSync:::lock (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +plist_add (1 samples, 0.02%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (3,603 samples, 70.10%) +org/springframework/web/filter/OncePerRequestFilter:::doFilter + + +java/util/HashMap:::entrySet (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/Type$8:::write (1 samples, 0.02%) + + + +org/apache/kafka/common/utils/PureJavaCrc32C:::update (8 samples, 0.16%) + + + +com/alibaba/csp/sentinel/slots/statistic/StatisticSlot:::entry (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::poll (27 samples, 0.53%) + + + +release_sock (1 samples, 0.02%) + + + +java/util/Formatter:::checkText (1 samples, 0.02%) + + + +org/springframework/web/filter/CharacterEncodingFilter:::doFilterInternal (216 samples, 4.20%) +org/s.. + + +ConstMethod::compressed_linenumber_table (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/NioBlockingSelector$BlockPoller:::run (27 samples, 0.53%) + + + +pthread_mutex_unlock (1 samples, 0.02%) + + + +org/apache/tomcat/util/http/Parameters:::processParameters (55 samples, 1.07%) + + + +ip_rcv (1 samples, 0.02%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +java/util/regex/Matcher:::end (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +vtable stub (2 samples, 0.04%) + + + +java/util/regex/Pattern$3:::isSatisfiedBy (4 samples, 0.08%) + + + +irq_exit (1 samples, 0.02%) + + + +java_lang_Throwable::fill_in_stack_trace (3 samples, 0.06%) + + + +inflate_table (30 samples, 0.58%) + + + +tcp_cleanup_rbuf (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +java/util/Calendar$Builder:::build (3 samples, 0.06%) + + + +call_softirq (1 samples, 0.02%) + + + +com/coohua/ad/data/service/impl/AdDataServiceImpl:::ecpProcess (1 samples, 0.02%) + + + +ret_from_intr (1 samples, 0.02%) + + + +java/net/URI$Parser:::parseAuthority (3 samples, 0.06%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +org/apache/coyote/http11/Http11Processor:::service (225 samples, 4.38%) +org/a.. + + +futex_wake_op (16 samples, 0.31%) + + + +org/apache/logging/log4j/core/appender/AsyncAppender:::append (4 samples, 0.08%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +hrtimer_try_to_cancel.part.25 (2 samples, 0.04%) + + + +java/util/HashMap:::get (1 samples, 0.02%) + + + +sys_futex (31 samples, 0.60%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +wake_up_state (2 samples, 0.04%) + + + +Method::line_number_from_bci (5 samples, 0.10%) + + + +java/lang/Class:::getEnclosingMethod0 (1 samples, 0.02%) + + + +system_call_fastpath (2 samples, 0.04%) + + + +deflate_slow (161 samples, 3.13%) +def.. + + +com/alibaba/fastjson/serializer/LongCodec:::deserialze (1 samples, 0.02%) + + + +adler32 (1 samples, 0.02%) + + + +java/lang/StringBuffer:::append (4 samples, 0.08%) + + + +do_futex (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +java/lang/reflect/Method:::hashCode (1 samples, 0.02%) + + + +org/apache/kafka/common/network/Selector:::poll (117 samples, 2.28%) +o.. + + +G1CollectedHeap::free_collection_set (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy109:::annotationType (1 samples, 0.02%) + + + +apic_timer_interrupt (1 samples, 0.02%) + + + +tcp_ack (1 samples, 0.02%) + + + +org/springframework/web/servlet/handler/AbstractUrlHandlerMapping:::getHandlerInternal (22 samples, 0.43%) + + + +irq_exit (1 samples, 0.02%) + + + +rcu_process_callbacks (1 samples, 0.02%) + + + +org/apache/kafka/common/utils/ByteBufferOutputStream:::write (1 samples, 0.02%) + + + +java/lang/AbstractStringBuilder:::append (1 samples, 0.02%) + + + +do_sys_poll (1 samples, 0.02%) + + + +java/lang/Throwable:::getOurStackTrace (4 samples, 0.08%) + + + +do_softirq (1 samples, 0.02%) + + + +java/util/zip/Inflater:::end (1 samples, 0.02%) + + + +com/coohua/ad/data/interceptor/UserInterceptor:::afterCompletion (9 samples, 0.18%) + + + +wake_up_state (19 samples, 0.37%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/util/ObjectUtils:::unwrapOptional (1 samples, 0.02%) + + + +java/util/regex/Pattern$CharProperty:::match (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +sys_futex (3 samples, 0.06%) + + + +HandleMarkCleaner::~HandleMarkCleaner (2 samples, 0.04%) + + + +ip_finish_output (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (19 samples, 0.37%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +OptoRuntime::new_instance_C (1 samples, 0.02%) + + + +system_call_fastpath (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +org/springframework/cglib/proxy/MethodProxy:::invoke (1 samples, 0.02%) + + + +org/springframework/core/annotation/SynthesizedAnnotationInvocationHandler:::invoke (3 samples, 0.06%) + + + +skb_checksum (1 samples, 0.02%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +java/util/LinkedHashMap:::get (1 samples, 0.02%) + + + +org/springframework/boot/actuate/trace/http/HttpExchangeTracer$$Lambda$701/1778763541:::accept (1 samples, 0.02%) + + + +org/springframework/beans/factory/support/AbstractBeanFactory:::doGetBean (2 samples, 0.04%) + + + +org/springframework/aop/framework/CglibAopProxy$DynamicAdvisedInterceptor:::intercept (1 samples, 0.02%) + + + +java/util/TimSort:::sort (1 samples, 0.02%) + + + +ext4_file_write (22 samples, 0.43%) + + + +oop_disjoint_arraycopy (2 samples, 0.04%) + + + +jlong_disjoint_arraycopy (1 samples, 0.02%) + + + +__mnt_want_write (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +vtable stub (1 samples, 0.02%) + + + +java/util/Spliterators$IteratorSpliterator:::forEachRemaining (11 samples, 0.21%) + + + +Matcher::Matcher (1 samples, 0.02%) + + + +com/alibaba/csp/sentinel/slots/statistic/StatisticSlot:::entry (9 samples, 0.18%) + + + +WeakPreserveExceptionMark::WeakPreserveExceptionMark (1 samples, 0.02%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (2 samples, 0.04%) + + + +irq_exit (1 samples, 0.02%) + + + +ip_local_deliver_finish (1 samples, 0.02%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +org/springframework/core/annotation/AnnotatedElementUtils:::searchWithFindSemantics (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +java/util/zip/Deflater:::deflateBytes (1 samples, 0.02%) + + + +jni_GetPrimitiveArrayCritical (3 samples, 0.06%) + + + +org/apache/catalina/connector/Request:::setAttribute (3 samples, 0.06%) + + + +ep_send_events_proc (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +call_function_single_interrupt (1 samples, 0.02%) + + + +java/nio/Buffer:::limit (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +PhaseIterGVN::transform_old (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/config/LoggerConfig:::log (56 samples, 1.09%) + + + +process_backlog (1 samples, 0.02%) + + + +java/lang/Long:::getChars (1 samples, 0.02%) + + + +JNIHandles::make_local (5 samples, 0.10%) + + + +_new_instance_Java (1 samples, 0.02%) + + + +finish_task_switch (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/condition/PatternsRequestCondition:::getMatchingPatterns (3 samples, 0.06%) + + + +java/util/regex/Pattern$5:::isSatisfiedBy (3 samples, 0.06%) + + + +tcp_child_process (1 samples, 0.02%) + + + +netif_receive_skb_internal (1 samples, 0.02%) + + + +java/util/stream/ReduceOps$ReduceOp:::evaluateSequential (1 samples, 0.02%) + + + +itable stub (2 samples, 0.04%) + + + +__do_softirq (1 samples, 0.02%) + + + +java/lang/ThreadLocal$ThreadLocalMap:::remove (2 samples, 0.04%) + + + +org/apache/tomcat/util/net/NioEndpoint$SocketProcessor:::doRun (4,046 samples, 78.72%) +org/apache/tomcat/util/net/NioEndpoint$SocketProcessor:::doRun + + +java/lang/String:::charAt (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +com/sun/proxy/$Proxy8:::annotationType (1 samples, 0.02%) + + + +pipe_write (21 samples, 0.41%) + + + +jshort_disjoint_arraycopy (2 samples, 0.04%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/SocketProcessorBase:::run (2 samples, 0.04%) + + + +native_send_call_func_single_ipi (1 samples, 0.02%) + + + +smp_apic_timer_interrupt (1 samples, 0.02%) + + + +PhaseChaitin::post_allocate_copy_removal (1 samples, 0.02%) + + + +java/util/TimSort:::sort (1 samples, 0.02%) + + + +G1UpdateRSOrPushRefOopClosure::do_oop (1 samples, 0.02%) + + + +java/lang/Object:::hashCode (1 samples, 0.02%) + + + +LShiftLNode::Ideal (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +__wake_up_sync_key (1 samples, 0.02%) + + + +sk_stream_alloc_skb (1 samples, 0.02%) + + + +schedule_hrtimeout_range_clock (1 samples, 0.02%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (3,447 samples, 67.06%) +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter + + +org/apache/tomcat/util/buf/StringCache:::toString (2 samples, 0.04%) + + + +org/apache/catalina/connector/Connector:::isParseBodyMethod (1 samples, 0.02%) + + + +skb_release_data (1 samples, 0.02%) + + + +InstanceKlass::allocate_instance (12 samples, 0.23%) + + + +llist_add_batch (1 samples, 0.02%) + + + +org/springframework/http/converter/AbstractGenericHttpMessageConverter:::canWrite (1 samples, 0.02%) + + + +org/apache/tomcat/util/buf/MessageBytes:::toString (6 samples, 0.12%) + + + +tcp_v4_do_rcv (1 samples, 0.02%) + + + +java/util/regex/Pattern$3:::isSatisfiedBy (2 samples, 0.04%) + + + +do_softirq (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::getAttribute (1 samples, 0.02%) + + + +G1CollectedHeap::iterate_dirty_card_closure (5 samples, 0.10%) + + + +com/alibaba/csp/sentinel/slots/clusterbuilder/ClusterBuilderSlot:::entry (1 samples, 0.02%) + + + +__vdso_gettimeofday (3 samples, 0.06%) + + + +__do_softirq (1 samples, 0.02%) + + + +org/springframework/web/servlet/DispatcherServlet:::doDispatch (3,386 samples, 65.88%) +org/springframework/web/servlet/DispatcherServlet:::doDispatch + + +java/util/regex/Pattern$GroupHead:::match (2 samples, 0.04%) + + + +Parse::do_call (1 samples, 0.02%) + + + +schedule_hrtimeout_range (1 samples, 0.02%) + + + +java_lang_Thread::set_thread_status (1 samples, 0.02%) + + + +com/alibaba/fastjson/util/TypeUtils:::castToLong (4 samples, 0.08%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +CollectedHeap::new_store_pre_barrier (1 samples, 0.02%) + + + +sun/nio/ch/EPollArrayWrapper:::epollWait (1 samples, 0.02%) + + + +java/util/HashMap:::put (16 samples, 0.31%) + + + +org/springframework/core/MethodParameter:::getNestedParameterType (1 samples, 0.02%) + + + +sys_futex (1 samples, 0.02%) + + + +ip_local_out_sk (6 samples, 0.12%) + + + +net_rps_action_and_irq_enable.isra.91 (1 samples, 0.02%) + + + +wake_futex (20 samples, 0.39%) + + + +org/apache/kafka/common/network/Selector:::send (2 samples, 0.04%) + + + +PhaseCCP::analyze (1 samples, 0.02%) + + + +org/springframework/util/LinkedCaseInsensitiveMap:::hashCode (1 samples, 0.02%) + + + +skb_to_sgvec (1 samples, 0.02%) + + + +__list_del_entry (1 samples, 0.02%) + + + +ip_finish_output (3 samples, 0.06%) + + + +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter (3,589 samples, 69.82%) +org/apache/catalina/core/ApplicationFilterChain:::internalDoFilter + + +ext4_inode_table (1 samples, 0.02%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +com/fasterxml/jackson/core/json/WriterBasedJsonGenerator:::writeStartObject (1 samples, 0.02%) + + + +java/util/regex/Pattern$Branch:::match (5 samples, 0.10%) + + + +fill_window (1 samples, 0.02%) + + + +java/util/HashMap:::putMapEntries (2 samples, 0.04%) + + + +org/springframework/util/AntPathMatcher:::doMatch (49 samples, 0.95%) + + + +com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer:::parseRest (9 samples, 0.18%) + + + +deflate_slow (81 samples, 1.58%) + + + +JavaThread::thread_from_jni_environment (1 samples, 0.02%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +Parker::unpark (1 samples, 0.02%) + + + +tcp_write_xmit (4 samples, 0.08%) + + + +pthread_mutex_lock (1 samples, 0.02%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +[libpthread-2.17.so] (2 samples, 0.04%) + + + +ip_rcv_finish (1 samples, 0.02%) + + + +java/util/GregorianCalendar:::getFixedDate (1 samples, 0.02%) + + + +sock_aio_write (2 samples, 0.04%) + + + +sun/reflect/GeneratedMethodAccessor70:::invoke (2 samples, 0.04%) + + + +java/util/Calendar$Builder:::build (3 samples, 0.06%) + + + +irq_exit (1 samples, 0.02%) + + + +java/lang/ThreadLocal$ThreadLocalMap:::set (2 samples, 0.04%) + + + +ret_from_intr (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +org/apache/catalina/connector/ResponseFacade:::containsHeader (1 samples, 0.02%) + + + +resource_allocate_bytes (4 samples, 0.08%) + + + +do_softirq (1 samples, 0.02%) + + + +java/lang/String:::toUpperCase (8 samples, 0.16%) + + + +jshort_disjoint_arraycopy (2 samples, 0.04%) + + + +ip_rcv (1 samples, 0.02%) + + + +org/apache/tomcat/util/net/SocketProcessorBase:::run (227 samples, 4.42%) +org/a.. + + +__do_softirq (1 samples, 0.02%) + + + +com/coohua/ad/data/manager/AdDataManager:::buildRedisAdClickCounter (2 samples, 0.04%) + + + +java/util/HashMap:::put (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +OptoRuntime::new_array_C (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (2 samples, 0.04%) + + + +__audit_syscall_entry (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +java/util/Formatter$FixedString:::print (1 samples, 0.02%) + + + +org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor:::getProducibleMediaTypes (14 samples, 0.27%) + + + +ip_local_out_sk (23 samples, 0.45%) + + + +java/lang/Object:::toString (3 samples, 0.06%) + + + +os::javaTimeMillis (3 samples, 0.06%) + + + +memcpy@plt (1 samples, 0.02%) + + + +org/springframework/web/servlet/support/WebContentGenerator:::checkRequest (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/boot/actuate/metrics/web/servlet/LongTaskTimingHandlerInterceptor:::preHandle (47 samples, 0.91%) + + + +sock_def_readable (1 samples, 0.02%) + + + +java/lang/Class:::getSimpleName (3 samples, 0.06%) + + + +com/google/gson/Gson:::toJson (1 samples, 0.02%) + + + +org/apache/commons/lang3/StringUtils:::splitWorker (5 samples, 0.10%) + + + +ip_rcv (1 samples, 0.02%) + + + +G1SATBCardTableModRefBS::g1_mark_as_young (1 samples, 0.02%) + + + +Monitor::unlock (1 samples, 0.02%) + + + +dput (1 samples, 0.02%) + + + +org/springframework/web/method/annotation/AbstractNamedValueMethodArgumentResolver:::resolveArgument (1 samples, 0.02%) + + + +Method::mask_for (1 samples, 0.02%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +java/util/regex/Pattern$BranchConn:::match (4 samples, 0.08%) + + + +net_rx_action (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (3 samples, 0.06%) + + + +__netif_receive_skb (1 samples, 0.02%) + + + +sk_reset_timer (1 samples, 0.02%) + + + +sys_epoll_wait (1 samples, 0.02%) + + + +org/springframework/web/servlet/handler/AbstractHandlerMapping:::getHandler (1 samples, 0.02%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +sock_def_readable (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (2 samples, 0.04%) + + + +com/coohuadata/analytics/javasdk/CoohuaAnalytics$KafkaConsumer:::send (19 samples, 0.37%) + + + +kmem_cache_alloc_node (1 samples, 0.02%) + + + +vtable stub (2 samples, 0.04%) + + + +arrayOopDesc::base (5 samples, 0.10%) + + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +futex_wait_queue_me (11 samples, 0.21%) + + + +itable stub (1 samples, 0.02%) + + + +sun/nio/cs/UTF_8$Encoder:::encode (2 samples, 0.04%) + + + +pthread_mutex_lock (1 samples, 0.02%) + + + +scan_tree (5 samples, 0.10%) + + + +tcp_v4_rcv (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/appender/AsyncAppender:::append (3 samples, 0.06%) + + + +call_softirq (1 samples, 0.02%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +jshort_disjoint_arraycopy (1 samples, 0.02%) + + + +ip_local_deliver (1 samples, 0.02%) + + + +napi_gro_receive (1 samples, 0.02%) + + + +java/net/URLEncoder:::encode (2 samples, 0.04%) + + + +org/apache/kafka/common/requests/AbstractRequestResponse:::serialize (16 samples, 0.31%) + + + +java_lang_Throwable::get_stack_trace_depth (1 samples, 0.02%) + + + +java/util/stream/Collectors$$Lambda$421/1176968662:::accept (4 samples, 0.08%) + + + +org/springframework/util/ConcurrentReferenceHashMap$Segment:::restructureIfNecessary (1 samples, 0.02%) + + + +do_softirq (1 samples, 0.02%) + + + +org/apache/kafka/common/protocol/types/ArrayOf:::write (1 samples, 0.02%) + + + +PhaseLive::compute (4 samples, 0.08%) + + + +org/apache/catalina/connector/RequestFacade:::getRequestURL (2 samples, 0.04%) + + + +sk_reset_timer (1 samples, 0.02%) + + + +java/lang/String:::toString (1 samples, 0.02%) + + + +net_rx_action (1 samples, 0.02%) + + + +pthread_cond_timedwait@@GLIBC_2.3.2 (5 samples, 0.10%) + + + +do_softirq (2 samples, 0.04%) + + + +call_softirq (1 samples, 0.02%) + + + +org/springframework/web/filter/OncePerRequestFilter:::doFilter (216 samples, 4.20%) +org/s.. + + +process_backlog (1 samples, 0.02%) + + + +org/springframework/web/util/UrlPathHelper:::getPathWithinApplication (7 samples, 0.14%) + + + +org/springframework/aop/framework/ReflectiveMethodInvocation:::proceed (4 samples, 0.08%) + + + +sun/reflect/annotation/AnnotationInvocationHandler:::invoke (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/util/zip/InflaterInputStream:::fill (1 samples, 0.02%) + + + +java/lang/Throwable:::getStackTraceElement (4 samples, 0.08%) + + + +org/apache/logging/log4j/core/appender/OutputStreamManager:::flushBuffer (42 samples, 0.82%) + + + +java/util/concurrent/locks/LockSupport:::parkNanos (40 samples, 0.78%) + + + +__kfree_skb (1 samples, 0.02%) + + + +os::javaTimeMillis (1 samples, 0.02%) + + + +__mark_inode_dirty (1 samples, 0.02%) + + + +org/apache/catalina/connector/Request:::parseLocales (3 samples, 0.06%) + + + +do_softirq (1 samples, 0.02%) + + + +JVM_GetStackTraceDepth (1 samples, 0.02%) + + + +__netif_receive_skb_core (1 samples, 0.02%) + + + +dev_queue_xmit (2 samples, 0.04%) + + + +skb_clone (1 samples, 0.02%) + + + +call_softirq (1 samples, 0.02%) + + + +irq_exit (1 samples, 0.02%) + + + +java/util/Comparator$$Lambda$213/1325144078:::compare (1 samples, 0.02%) + + + +JNIHandles::make_local (1 samples, 0.02%) + + + +_new_array_nozero_Java (1 samples, 0.02%) + + + +__vdso_gettimeofday (1 samples, 0.02%) + + + +java/text/SimpleDateFormat:::initialize (2 samples, 0.04%) + + + +sock_poll (4 samples, 0.08%) + + + +com/coohua/caf/core/rpc/MotanSentinelFilter:::filter (8 samples, 0.16%) + + + +java/lang/Long:::toString (1 samples, 0.02%) + + + +com/google/gson/reflect/TypeToken:::<init> (3 samples, 0.06%) + + + +java_lang_Throwable::set_backtrace (2 samples, 0.04%) + + + +smp_call_function_single_async (1 samples, 0.02%) + + + +com/coohua/ad/data/interceptor/UserInterceptor:::preHandle (105 samples, 2.04%) +c.. + + +smp_call_function_single_interrupt (1 samples, 0.02%) + + + +Type::cmp (1 samples, 0.02%) + + + +_raw_spin_unlock_irqrestore (2 samples, 0.04%) + + + +irq_exit (1 samples, 0.02%) + + + +java/util/HashMap:::put (2 samples, 0.04%) + + + +x2apic_send_IPI_mask (1 samples, 0.02%) + + + +__do_softirq (1 samples, 0.02%) + + + +java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject:::doSignal (1 samples, 0.02%) + + + +BufferBlob::free (1 samples, 0.02%) + + + +org/apache/logging/log4j/core/pattern/MdcPatternConverter:::format (1 samples, 0.02%) + + + +sun/misc/Unsafe:::unpark (1 samples, 0.02%) + + + +PhaseIterGVN::transform_old (3 samples, 0.06%) + + + +_raw_spin_unlock_irqrestore (3 samples, 0.06%) + + + +vtable stub (1 samples, 0.02%) + + + +_raw_spin_unlock (1 samples, 0.02%) + + + +system_call_fastpath (21 samples, 0.41%) + + + +org/apache/catalina/connector/RequestFacade:::removeAttribute (2 samples, 0.04%) + + + +redis/clients/jedis/JedisClusterCommand:::runWithRetries (1 samples, 0.02%) + + + +sys_read (1 samples, 0.02%) + + + +__irqentry_text_start (1 samples, 0.02%) + + + +java/lang/String:::toUpperCase (2 samples, 0.04%) + + + +java/util/regex/Pattern$Curly:::match (1 samples, 0.02%) + + + +process_backlog (1 samples, 0.02%) + + + +G1CollectedHeap::can_elide_tlab_store_barriers (1 samples, 0.02%) + + + +java/lang/Throwable:::getStackTraceElement (30 samples, 0.58%) + + + +ret_from_intr (1 samples, 0.02%) + + + +schedule (16 samples, 0.31%) + + + +org/springframework/web/context/support/ServletRequestHandledEvent:::<init> (2 samples, 0.04%) + + + + diff --git a/src/JVM/images/JVM/调优实战-VisualVM查看GC显示.jpg b/src/JVM/images/JVM/调优实战-VisualVM查看GC显示.jpg new file mode 100644 index 0000000..c2fabc2 Binary files /dev/null and b/src/JVM/images/JVM/调优实战-VisualVM查看GC显示.jpg differ diff --git a/src/JVM/images/JVM/调优实战-一段时间后VisualVM查看GC显示.jpg b/src/JVM/images/JVM/调优实战-一段时间后VisualVM查看GC显示.jpg new file mode 100644 index 0000000..55b652a Binary files /dev/null and b/src/JVM/images/JVM/调优实战-一段时间后VisualVM查看GC显示.jpg differ diff --git a/src/JVM/images/JVM/调优实战-元空间不足.jpg b/src/JVM/images/JVM/调优实战-元空间不足.jpg new file mode 100644 index 0000000..9bcf68d Binary files /dev/null and b/src/JVM/images/JVM/调优实战-元空间不足.jpg differ diff --git a/src/JVM/images/JVM/调优实战-元空间调后后VisualVM查看GC显示.jpg b/src/JVM/images/JVM/调优实战-元空间调后后VisualVM查看GC显示.jpg new file mode 100644 index 0000000..7029757 Binary files /dev/null and b/src/JVM/images/JVM/调优实战-元空间调后后VisualVM查看GC显示.jpg differ diff --git a/src/JVM/images/JVM/调优实战-减少MinorGC后VisualVM显示.jpg b/src/JVM/images/JVM/调优实战-减少MinorGC后VisualVM显示.jpg new file mode 100644 index 0000000..0b8d1d8 Binary files /dev/null and b/src/JVM/images/JVM/调优实战-减少MinorGC后VisualVM显示.jpg differ diff --git a/src/JVM/images/JVM/调优实战-去掉线程休眠VisualVM显示.jpg b/src/JVM/images/JVM/调优实战-去掉线程休眠VisualVM显示.jpg new file mode 100644 index 0000000..65c4e97 Binary files /dev/null and b/src/JVM/images/JVM/调优实战-去掉线程休眠VisualVM显示.jpg differ diff --git a/src/JVM/images/JVM/过早晋升优化GC.png b/src/JVM/images/JVM/过早晋升优化GC.png new file mode 100644 index 0000000..e02c12e Binary files /dev/null and b/src/JVM/images/JVM/过早晋升优化GC.png differ diff --git a/src/JVM/images/JVM/过早晋升优化Oldgen.png b/src/JVM/images/JVM/过早晋升优化Oldgen.png new file mode 100644 index 0000000..662e1d9 Binary files /dev/null and b/src/JVM/images/JVM/过早晋升优化Oldgen.png differ diff --git a/src/Middleware/1204.md b/src/Middleware/1204.md index e69de29..cafb8b9 100644 --- a/src/Middleware/1204.md +++ b/src/Middleware/1204.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待!有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/Middleware/1205.md b/src/Middleware/1205.md index e69de29..cafb8b9 100644 --- a/src/Middleware/1205.md +++ b/src/Middleware/1205.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待!有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/Middleware/_sidebar.md b/src/Middleware/_sidebar.md index c771f8b..5ee9ff4 100644 --- a/src/Middleware/_sidebar.md +++ b/src/Middleware/_sidebar.md @@ -1,130 +1,130 @@ -* [🏁SPI](src/Middleware/1 "SPI") - * [✍Java SPI](src/Middleware/2 "Java SPI") - * [✍Dubbo SPI](src/Middleware/3 "Dubbo SPI") - * [✍Motan SPI](src/Middleware/4 "Motan SPI") - * [✍SpringBoot SPI](src/Middleware/5 "SpringBoot SPI") -* [🏁Redis](src/Middleware/101 "Redis") - * [✍线程模型](src/Middleware/102 "线程模型") - * [✍数据类型](src/Middleware/103 "数据类型") - * [✍特殊数据结构](src/Middleware/104 "特殊数据结构") - * [✍底层数据结构](src/Middleware/105 "底层数据结构") - * [✍持久化机制](src/Middleware/106 "持久化机制") - * [✍过期策略](src/Middleware/107 "过期策略") - * [✍淘汰策略](src/Middleware/108 "淘汰策略") - * [✍部署架构](src/Middleware/109 "部署架构") - * [✍环境搭建](src/Middleware/110 "环境搭建") - * [✍拓展方案](src/Middleware/111 "拓展方案") - * [✍常见问题](src/Middleware/112 "常见问题") -* 🏁Kafka -* [🏁RocketMQ](src/Middleware/301 "RocketMQ") - * [✍架构设计](src/Middleware/302 "架构设计") - * [✍核心概念](src/Middleware/303 "核心概念") - * [✍核心设计](src/Middleware/304 "核心设计") - * [✍最佳实践](src/Middleware/305 "最佳实践") - * [✍保证顺序](src/Middleware/306 "保证顺序") - * [✍消息不丢失](src/Middleware/307 "消息不丢失") - * [✍消息幂等](src/Middleware/308 "消息幂等") -* [🏁Zookeeper](src/Middleware/401 "Zookeeper") - * [✍ZK特性](src/Middleware/402 "ZK特性") - * [✍ZK角色](src/Middleware/403 "ZK角色") - * [✍数据模型](src/Middleware/404 "数据模型") - * [✍Server工作状态](src/Middleware/405 "Server工作状态") - * [✍运行模式](src/Middleware/406 "运行模式") - * [✍Leader选举](src/Middleware/407 "Leader选举") - * [✍节点(znode)](src/Middleware/408 "节点(znode)") - * [✍关键词](src/Middleware/409 "关键词") - * [✍Watcher监听机制](src/Middleware/410 "Watcher监听机制") - * [✍ZXID](src/Middleware/411 "ZXID") - * [✍工作流程](src/Middleware/412 "工作流程") - * [✍ZAB协议](src/Middleware/413 "ZAB协议") - * [✍ZK选举过程](src/Middleware/414 "ZK选举过程") - * [✍Zookeeper安装](src/Middleware/415 "Zookeeper安装") -* 🏁Netty - * [✍Netty流程](src/Middleware/501 "Netty流程") - * [✍处理事件](src/Middleware/502 "处理事件") - * [✍长连接优化](src/Middleware/503 "长连接优化") - * [✍线程模型](src/Middleware/504 "线程模型") - * [✍HashedWheelTimer](src/Middleware/505 "HashedWheelTimer") - * [✍ByteBuf](src/Middleware/506 "ByteBuf") - * [✍Zero-Copy](src/Middleware/507 "Zero-Copy") - * [✍TCP粘包拆包](src/Middleware/508 "TCP粘包拆包") - * [✍高性能](src/Middleware/509 "高性能") - * [✍操作系统调优](src/Middleware/510 "操作系统调优") - * [✍Netty性能调优](src/Middleware/511 "Netty性能调优") - * [✍案例分析](src/Middleware/512 "案例分析") -* 🏁RabbitMQ - * [✍模式介绍](src/Middleware/601 "模式介绍") -* [🏁Dubbo](src/Middleware/701 "Dubbo") - * [✍RPC](src/Middleware/702 "RPC") - * [✍框架设计](src/Middleware/703 "框架设计") - * [✍SPI机制](src/Middleware/704 "SPI机制") - * [✍服务暴露流程](src/Middleware/705 "服务暴露流程") - * [✍服务引用流程](src/Middleware/706 "服务引用流程") - * [✍调用整体流程](src/Middleware/707 "调用整体流程") - * [✍集群容错负载均衡](src/Middleware/708 "集群容错负载均衡") - * [✍设计RPC](src/Middleware/709 "设计RPC") -* 🏁Nacos - * [✍基本架构](src/Middleware/801 "基本架构") - * [✍逻辑架构](src/Middleware/802 "逻辑架构") - * [✍功能特性](src/Middleware/803 "功能特性") - * [✍安装部署](src/Middleware/804 "安装部署") - * [✍开源案例](src/Middleware/805 "开源案例") -* [🏁Sentinel](src/Middleware/901 "Sentinel") - * [✍主要特性](src/Middleware/902 "主要特性") - * [✍开源生态](src/Middleware/903 "开源生态") - * [✍Quick Start](src/Middleware/904 "Quick Start") -* [🏁Influxdb](src/Middleware/1001 "Influxdb") - * [✍重要特性](src/Middleware/1002 "重要特性") - * [✍存储引擎](src/Middleware/1003 "存储引擎") - * [✍系统架构](src/Middleware/1004 "系统架构") -* [🏁Spring](src/Middleware/1101 "Spring") - * [✍相关概念](src/Middleware/1102 "相关概念") - * [✍Spring原理](src/Middleware/1103 "Spring原理") - * [✍IoC](src/Middleware/1104 "IoC") - * [✍AOP](src/Middleware/1105 "AOP") - * [✍过滤器(Filter)](src/Middleware/1106 "过滤器(Filter)") - * [✍拦截器(Interceptor)](src/Middleware/1107 "拦截器(Interceptor)") - * [✍Spring流程](src/Middleware/1108 "Spring流程") -* [🏁SpringBoot](src/Middleware/1201 "SpringBoot") - * [✍MVC](src/Middleware/1202 "MVC") - * [✍IoC](src/Middleware/1203 "IoC") - * [✍AOP](src/Middleware/1204 "AOP") - * [✍Others](src/Middleware/1205 "Others") -* [🏁SpringCloud](src/Middleware/1301 "SpringCloud") - * [✍Eurake](src/Middleware/1302 "Eurake") - * [✍Zuul](src/Middleware/1303 "Zuul") - * [✍Feign](src/Middleware/1304 "Feign") - * [✍Ribbon](src/Middleware/1305 "Ribbon") - * [✍Hystrix](src/Middleware/1306 "Hystrix") - * [✍Gateway](src/Middleware/1307 "Gateway") - * [✍Config](src/Middleware/1308 "Config") - * [✍Bus](src/Middleware/1309 "Bus") - * [✍OAuth2](src/Middleware/1310 "OAuth2") - * [✍Sleuth](src/Middleware/1311 "Sleuth") -* [🏁MyBatis](src/Middleware/1401 "MyBatis") - * [✍MyBatis架构](src/Middleware/1402 "MyBatis架构") - * [✍MyBatis流程](src/Middleware/1403 "MyBatis流程") - * [✍Dao接口工作原理](src/Middleware/1404 "Dao接口工作原理") - * [✍MyBatis缓存](src/Middleware/1405 "MyBatis缓存") - * [✍MyBatis主要组件](src/Middleware/1406 "MyBatis主要组件") -* 🏁Nginx - * [✍Nginx安装](src/Middleware/1501 "Nginx安装") - * [✍运维命令](src/Middleware/1502 "运维命令") - * [✍配置规则](src/Middleware/1503 "配置规则") - * [✍应用场景](src/Middleware/1504 "应用场景") - * [✍常用配置](src/Middleware/1505 "常用配置") - * [✍日志分析](src/Middleware/1506 "日志分析") -* [🏁LVS](src/Middleware/1601 "LVS") - * [✍工作模式](src/Middleware/1602 "工作模式") - * [✍调度算法](src/Middleware/1603 "调度算法") - * [✍常见问题分析](src/Middleware/1604 "常见问题分析") -* [🏁Keepalived](src/Middleware/1701 "Keepalived") - * [✍功能体系](src/Middleware/1702 "功能体系") - * [✍脑裂问题](src/Middleware/1703 "脑裂问题") - * [✍安装部署](src/Middleware/1704 "安装部署") -* [🏁HAProxy](src/Middleware/1801 "HAProxy") - * [✍四层负载均衡](src/Middleware/1802 "四层负载均衡") - * [✍七层负载均衡](src/Middleware/1803 "七层负载均衡") - * [✍负载均衡策略](src/Middleware/1804 "负载均衡策略") - * [✍HAProxy与LVS的区别](src/Middleware/1805 "HAProxy与LVS的区别") - * [✍安装配置](src/Middleware/1806 "安装配置") \ No newline at end of file +* [🏁 SPI](src/Middleware/1 "SPI") + * [✍ Java SPI](src/Middleware/2 "Java SPI") + * [✍ Dubbo SPI](src/Middleware/3 "Dubbo SPI") + * [✍ Motan SPI](src/Middleware/4 "Motan SPI") + * [✍ SpringBoot SPI](src/Middleware/5 "SpringBoot SPI") +* [🏁 Redis](src/Middleware/101 "Redis") + * [✍ 线程模型](src/Middleware/102 "线程模型") + * [✍ 数据类型](src/Middleware/103 "数据类型") + * [✍ 特殊数据结构](src/Middleware/104 "特殊数据结构") + * [✍ 底层数据结构](src/Middleware/105 "底层数据结构") + * [✍ 持久化机制](src/Middleware/106 "持久化机制") + * [✍ 过期策略](src/Middleware/107 "过期策略") + * [✍ 淘汰策略](src/Middleware/108 "淘汰策略") + * [✍ 部署架构](src/Middleware/109 "部署架构") + * [✍ 环境搭建](src/Middleware/110 "环境搭建") + * [✍ 拓展方案](src/Middleware/111 "拓展方案") + * [✍ 常见问题](src/Middleware/112 "常见问题") +* 🏁 Kafka +* [🏁 RocketMQ](src/Middleware/301 "RocketMQ") + * [✍ 架构设计](src/Middleware/302 "架构设计") + * [✍ 核心概念](src/Middleware/303 "核心概念") + * [✍ 核心设计](src/Middleware/304 "核心设计") + * [✍ 最佳实践](src/Middleware/305 "最佳实践") + * [✍ 保证顺序](src/Middleware/306 "保证顺序") + * [✍ 消息不丢失](src/Middleware/307 "消息不丢失") + * [✍ 消息幂等](src/Middleware/308 "消息幂等") +* [🏁 Zookeeper](src/Middleware/401 "Zookeeper") + * [✍ ZK特性](src/Middleware/402 "ZK特性") + * [✍ ZK角色](src/Middleware/403 "ZK角色") + * [✍ 数据模型](src/Middleware/404 "数据模型") + * [✍ Server工作状态](src/Middleware/405 "Server工作状态") + * [✍ 运行模式](src/Middleware/406 "运行模式") + * [✍ Leader选举](src/Middleware/407 "Leader选举") + * [✍ 节点(znode)](src/Middleware/408 "节点(znode)") + * [✍ 关键词](src/Middleware/409 "关键词") + * [✍ Watcher监听机制](src/Middleware/410 "Watcher监听机制") + * [✍ ZXID](src/Middleware/411 "ZXID") + * [✍ 工作流程](src/Middleware/412 "工作流程") + * [✍ ZAB协议](src/Middleware/413 "ZAB协议") + * [✍ ZK选举过程](src/Middleware/414 "ZK选举过程") + * [✍ Zookeeper安装](src/Middleware/415 "Zookeeper安装") +* 🏁 Netty + * [✍ Netty流程](src/Middleware/501 "Netty流程") + * [✍ 处理事件](src/Middleware/502 "处理事件") + * [✍ 长连接优化](src/Middleware/503 "长连接优化") + * [✍ 线程模型](src/Middleware/504 "线程模型") + * [✍ HashedWheelTimer](src/Middleware/505 "HashedWheelTimer") + * [✍ ByteBuf](src/Middleware/506 "ByteBuf") + * [✍ Zero-Copy](src/Middleware/507 "Zero-Copy") + * [✍ TCP粘包拆包](src/Middleware/508 "TCP粘包拆包") + * [✍ 高性能](src/Middleware/509 "高性能") + * [✍ 操作系统调优](src/Middleware/510 "操作系统调优") + * [✍ Netty性能调优](src/Middleware/511 "Netty性能调优") + * [✍ 案例分析](src/Middleware/512 "案例分析") +* 🏁 RabbitMQ + * [✍ 模式介绍](src/Middleware/601 "模式介绍") +* [🏁 Dubbo](src/Middleware/701 "Dubbo") + * [✍ RPC](src/Middleware/702 "RPC") + * [✍ 框架设计](src/Middleware/703 "框架设计") + * [✍ SPI机制](src/Middleware/704 "SPI机制") + * [✍ 服务暴露流程](src/Middleware/705 "服务暴露流程") + * [✍ 服务引用流程](src/Middleware/706 "服务引用流程") + * [✍ 调用整体流程](src/Middleware/707 "调用整体流程") + * [✍ 集群容错负载均衡](src/Middleware/708 "集群容错负载均衡") + * [✍ 设计RPC](src/Middleware/709 "设计RPC") +* 🏁 Nacos + * [✍ 基本架构](src/Middleware/801 "基本架构") + * [✍ 逻辑架构](src/Middleware/802 "逻辑架构") + * [✍ 功能特性](src/Middleware/803 "功能特性") + * [✍ 安装部署](src/Middleware/804 "安装部署") + * [✍ 开源案例](src/Middleware/805 "开源案例") +* [🏁 Sentinel](src/Middleware/901 "Sentinel") + * [✍ 主要特性](src/Middleware/902 "主要特性") + * [✍ 开源生态](src/Middleware/903 "开源生态") + * [✍ Quick Start](src/Middleware/904 "Quick Start") +* [🏁 Influxdb](src/Middleware/1001 "Influxdb") + * [✍ 重要特性](src/Middleware/1002 "重要特性") + * [✍ 存储引擎](src/Middleware/1003 "存储引擎") + * [✍ 系统架构](src/Middleware/1004 "系统架构") +* [🏁 Spring](src/Middleware/1101 "Spring") + * [✍ 相关概念](src/Middleware/1102 "相关概念") + * [✍ Spring原理](src/Middleware/1103 "Spring原理") + * [✍ IoC](src/Middleware/1104 "IoC") + * [✍ AOP](src/Middleware/1105 "AOP") + * [✍ 过滤器(Filter)](src/Middleware/1106 "过滤器(Filter)") + * [✍ 拦截器(Interceptor)](src/Middleware/1107 "拦截器(Interceptor)") + * [✍ Spring流程](src/Middleware/1108 "Spring流程") +* [🏁 SpringBoot](src/Middleware/1201 "SpringBoot") + * [✍ MVC](src/Middleware/1202 "MVC") + * [✍ IoC](src/Middleware/1203 "IoC") + * [✍ AOP](src/Middleware/1204 "AOP") + * [✍ Others](src/Middleware/1205 "Others") +* [🏁 SpringCloud](src/Middleware/1301 "SpringCloud") + * [✍ Eurake](src/Middleware/1302 "Eurake") + * [✍ Zuul](src/Middleware/1303 "Zuul") + * [✍ Feign](src/Middleware/1304 "Feign") + * [✍ Ribbon](src/Middleware/1305 "Ribbon") + * [✍ Hystrix](src/Middleware/1306 "Hystrix") + * [✍ Gateway](src/Middleware/1307 "Gateway") + * [✍ Config](src/Middleware/1308 "Config") + * [✍ Bus](src/Middleware/1309 "Bus") + * [✍ OAuth2](src/Middleware/1310 "OAuth2") + * [✍ Sleuth](src/Middleware/1311 "Sleuth") +* [🏁 MyBatis](src/Middleware/1401 "MyBatis") + * [✍ MyBatis架构](src/Middleware/1402 "MyBatis架构") + * [✍ MyBatis流程](src/Middleware/1403 "MyBatis流程") + * [✍ Dao接口工作原理](src/Middleware/1404 "Dao接口工作原理") + * [✍ MyBatis缓存](src/Middleware/1405 "MyBatis缓存") + * [✍ MyBatis主要组件](src/Middleware/1406 "MyBatis主要组件") +* 🏁 Nginx + * [✍ Nginx安装](src/Middleware/1501 "Nginx安装") + * [✍ 运维命令](src/Middleware/1502 "运维命令") + * [✍ 配置规则](src/Middleware/1503 "配置规则") + * [✍ 应用场景](src/Middleware/1504 "应用场景") + * [✍ 常用配置](src/Middleware/1505 "常用配置") + * [✍ 日志分析](src/Middleware/1506 "日志分析") +* [🏁 LVS](src/Middleware/1601 "LVS") + * [✍ 工作模式](src/Middleware/1602 "工作模式") + * [✍ 调度算法](src/Middleware/1603 "调度算法") + * [✍ 常见问题分析](src/Middleware/1604 "常见问题分析") +* [🏁 Keepalived](src/Middleware/1701 "Keepalived") + * [✍ 功能体系](src/Middleware/1702 "功能体系") + * [✍ 脑裂问题](src/Middleware/1703 "脑裂问题") + * [✍ 安装部署](src/Middleware/1704 "安装部署") +* [🏁 HAProxy](src/Middleware/1801 "HAProxy") + * [✍ 四层负载均衡](src/Middleware/1802 "四层负载均衡") + * [✍ 七层负载均衡](src/Middleware/1803 "七层负载均衡") + * [✍ 负载均衡策略](src/Middleware/1804 "负载均衡策略") + * [✍ HAProxy与LVS的区别](src/Middleware/1805 "HAProxy与LVS的区别") + * [✍ 安装配置](src/Middleware/1806 "安装配置") \ No newline at end of file diff --git a/src/OS/_sidebar.md b/src/OS/_sidebar.md index 8491a11..d72d6f5 100644 --- a/src/OS/_sidebar.md +++ b/src/OS/_sidebar.md @@ -1,29 +1,29 @@ -* [🏁I/O](src/OS/1 "I/O") - * [✍基础概念](src/OS/2 "基础模式") - * [✍Reactor模式](src/OS/3 "Reactor模式") - * [✍Proactor模式](src/OS/4 "Proactor模式") - * [✍select/poll/epoll](src/OS/5 "select/poll/epoll") - * [✍BIO(同步阻塞I/O)](src/OS/6 "BIO(同步阻塞I/O)") - * [✍NIO(同步非阻塞I/O)](src/OS/7 "NIO(同步非阻塞I/O)") - * [✍IO多路复用(异步阻塞I/O)](src/OS/8 "IO多路复用(异步阻塞I/O)") - * [✍AIO(异步非阻塞I/O)](src/OS/9 "AIO(异步非阻塞I/O)") - * [✍信号驱动式I/O](src/OS/10 "信号驱动式I/O") -* [🏁TCP](src/OS/101 "TCP") - * [✍网络模型](src/OS/102 "网络模型") - * [✍TCP状态](src/OS/103 "TCP状态") - * [✍连接过程](src/OS/104 "连接过程") - * [✍TCP优化](src/OS/105 "TCP优化") - * [✍常见问题](src/OS/106 "常见问题") - * [✍Socket](src/OS/107 "Socket") - * [✍TCP源码](src/OS/108 "TCP源码") -* [🏁HTTP](src/OS/201 "HTTP") - * [✍HTTP缓存](src/OS/202 "HTTP缓存") - * [✍请求方法](src/OS/203 "请求方法") - * [✍头参数](src/OS/204 "头参数") - * [✍状态码](src/OS/205 "状态码") - * [✍请求流程](src/OS/206 "请求流程") - * [✍常见问题](src/OS/207 "常见问题") -* 🏁OS - * [✍处理器](src/OS/301 "处理器") - * [✍内存管理](src/OS/302 "内存管理") - * [✍进程和线程](src/OS/303 "进程和线程") \ No newline at end of file +* [🏁 I/O](src/OS/1 "I/O") + * [✍ 基础概念](src/OS/2 "基础模式") + * [✍ Reactor模式](src/OS/3 "Reactor模式") + * [✍ Proactor模式](src/OS/4 "Proactor模式") + * [✍ select/poll/epoll](src/OS/5 "select/poll/epoll") + * [✍ BIO(同步阻塞I/O)](src/OS/6 "BIO(同步阻塞I/O)") + * [✍ NIO(同步非阻塞I/O)](src/OS/7 "NIO(同步非阻塞I/O)") + * [✍ IO多路复用(异步阻塞I/O)](src/OS/8 "IO多路复用(异步阻塞I/O)") + * [✍ AIO(异步非阻塞I/O)](src/OS/9 "AIO(异步非阻塞I/O)") + * [✍ 信号驱动式I/O](src/OS/10 "信号驱动式I/O") +* [🏁 TCP](src/OS/101 "TCP") + * [✍ 网络模型](src/OS/102 "网络模型") + * [✍ TCP状态](src/OS/103 "TCP状态") + * [✍ 连接过程](src/OS/104 "连接过程") + * [✍ TCP优化](src/OS/105 "TCP优化") + * [✍ 常见问题](src/OS/106 "常见问题") + * [✍ Socket](src/OS/107 "Socket") + * [✍ TCP源码](src/OS/108 "TCP源码") +* [🏁 HTTP](src/OS/201 "HTTP") + * [✍ HTTP缓存](src/OS/202 "HTTP缓存") + * [✍ 请求方法](src/OS/203 "请求方法") + * [✍ 头参数](src/OS/204 "头参数") + * [✍ 状态码](src/OS/205 "状态码") + * [✍ 请求流程](src/OS/206 "请求流程") + * [✍ 常见问题](src/OS/207 "常见问题") +* 🏁 OS + * [✍ 处理器](src/OS/301 "处理器") + * [✍ 内存管理](src/OS/302 "内存管理") + * [✍ 进程和线程](src/OS/303 "进程和线程") \ No newline at end of file diff --git a/src/Others/1.md b/src/Others/1.md new file mode 100644 index 0000000..95b093c --- /dev/null +++ b/src/Others/1.md @@ -0,0 +1,23 @@ +### draw.io + +本地或在线画图地址:https://draw.io + +![draw.io](images/Others/draw.io.jpeg) + +### Excalidraw + +在线画图地址:https://excalidraw.com + +![Excalidraw](images/Others/Excalidraw.png) + +### ProcessOn + +在线画图地址:https://www.processon.com + +![ProcessOn](images/Others/ProcessOn.png) + +### Carbon + +代码截图网址地址:https://carbon.now.sh + +![Carbon](images/Others/Carbon.png) \ No newline at end of file diff --git a/src/Others/101.md b/src/Others/101.md new file mode 100644 index 0000000..018a2d4 --- /dev/null +++ b/src/Others/101.md @@ -0,0 +1,25 @@ +[**Swagger**](https://swagger.io/): API Documentation & Design Tools for Teams + +[**jvm-sandbox**](https://github.com/alibaba/jvm-sandbox):Real - time non-invasive AOP framework container based on JVM + +**[JimuReport](https://github.com/zhangdaiscott/JimuReport)**:这是一款免费的数据可视化工具,报表与大屏设计!类似于excel操作风格,在线拖拽完成报表设计!功能涵盖: 报表设计、图形报表、打印设计、大屏设计等,永久免费! + +**[sa-token](https://github.com/dromara/sa-token)**:这可能是史上功能最全的Java权限认证框架!目前已集成——登录认证、权限认证、分布式Session会话、微服务网关鉴权、单点登录、OAuth2.0、踢人下线、Redis集成、前后台分离、记住我模式、模拟他人账号、临时身份切换、账号封禁、多账号认证体系、注解式鉴权、路由拦截式鉴权、花式token生成、自动续签、同端互斥登录、会话治理、密码加密、jwt集成、Spring集成、WebFlux集成... + +**[soul](https://github.com/dromara/soul)**:应用于所有微服务场景的,可扩展、高性能、响应式的 API 网关解决方案。 + +**[arthas](https://github.com/alibaba/arthas)**:Arthas旨在帮助开发人员解决Java应用程序的生产问题,无需修改代码或重新启动服务器。有了Arthas,你就可以在不重新启动JVM或需要额外的代码更改的情况下实时地对问题进行故障排除。 + +**[miaosha](https://github.com/qiurunze123/miaosha)**:该项目是对高并发大流量如何进行秒杀架构,而做的一个系统整理,如果你完全没接触过 MQ、SpringBoot、Redis、Dubbo、ZK 、Maven,lua等,那么我建议你可以先在网上搜一下每一块知识的快速入门。 + +[**Guava**](https://github.com/google/guava):Google core libraries for Java + +[**TransmittableThreadLocal**](https://github.com/alibaba/transmittable-thread-local):The missing Java™ std lib(simple & 0-dependency) for framework/middleware, provide an enhanced InheritableThreadLocal that transmits ThreadLocal values between threads even using thread pooling components. + +[**FastJSON**](https://github.com/alibaba/fastjson):A fast JSON parser/generator for Java. + +[**Druid**](https://github.com/alibaba/druid):阿里巴巴计算平台事业部出品,为监控而生的数据库连接池 + +[**JetCache**](https://github.com/alibaba/jetcache):JetCache is a Java cache framework. + +[**Metrics**](https://github.com/alibaba/metrics):The metrics library for Apache Dubbo and any frameworks or systems. \ No newline at end of file diff --git a/src/Others/2.md b/src/Others/2.md new file mode 100644 index 0000000..0e333b0 --- /dev/null +++ b/src/Others/2.md @@ -0,0 +1,215 @@ +### Fiddler + +Fiddler是一个蛮好用的抓包工具,可以将网络传输发送与接受的数据包进行截获、重发、编辑、转存等操作。也可以用来检测网络安全。反正好处多多,举之不尽呀!当年学习的时候也蛮费劲,一些蛮实用隐藏的小功能用了之后就忘记了,每次去网站上找也很麻烦,所以搜集各大网络的资料,总结了一些常用的功能。 + +Fiddler 下载地址 :https://www.telerik.com/download/fiddler + +win8之后用“Fiddler for .NET4”而win8之前用“Fiidler for .NET2”比较好。 + +#### Fiddler抓包简介 + +##### 代理设置 + +Fiddler是通过改写HTTP代理,让数据从它那通过,来监控并且截取到数据。当然Fiddler很屌,在打开它的那一瞬间,它就已经设置好了浏览器的代理了。当你关闭的时候,它又帮你把代理还原了,是不是很贴心。 + +![Fiddler抓包简介](images/Others/Fiddler抓包简介.png) + + + +##### Capture Traffic + +Fiddler想要抓到数据包,要确保Capture Traffic是开启,在File –> Capture Traffic。开启后再左下角会有显示,当然也可以直接点击左下角的图标来关闭/开启抓包功能。 + +![Fiddler-CaptureTraffic](images/Others/Fiddler-CaptureTraffic.png) + +Fiddler开始工作了,抓到的数据包就会显示在列表里面,下面总结了这些都是什么意思: + +![Fiddler-CaptureTraffic-Debugger](images/Others/Fiddler-CaptureTraffic-Debugger.png) + + + +##### Statistics请求的性能数据分析 + +随意点击一个请求,就可以看到Statistics关于HTTP请求的性能以及数据分析了。 + +![Fiddler-Statistics](images/Others/Fiddler-Statistics.png) + + + +##### Inspectors查看数据内容 + +Inspectors是用于查看会话的内容,上半部分是请求的内容,下半部分是响应的内容: + +![Fiddler-Inspectors](images/Others/Fiddler-Inspectors.png) + + + +##### AutoResponder允许拦截指定规则的请求 + +AutoResponder允许你拦截指定规则的求情,并返回本地资源或Fiddler资源,从而代替服务器响应。看下图5步,我将“baidu”这个关键字与我电脑“f:\Users\YukiO\Pictures\boy.jpeg”这张图片绑定了,点击Save保存后勾选Enable rules,再访问baidu,就会被劫持。这个玩意有很多匹配规则,如: + +1. 字符串匹配(默认):只要包含指定字符串(不区分大小写),全部认为是匹配 + +| 字符串匹配(baidu) | 是否匹配 | +| :--------------------- | :------- | +| http://www.baidu.com | 匹配 | +| http://pan.baidu.com | 匹配 | +| http://tieba.baidu.com | 匹配 | + +2. 正则表达式匹配:以“regex:”开头,使用正则表达式来匹配,这个是区分大小写的 + +| 字符串匹配(regex:.+.(jpg \| gif \| bmp ) $) | 是否匹配 | +| :-------------------------------------------- | :------- | +| http://bbs.fishc.com/Path1/query=foo.bmp&bar | 不匹配 | +| http://bbs.fishc.com/Path1/query=example.gif | 匹配 | +| http://bbs.fishc.com/Path1/query=example.bmp | 匹配 | +| http://bbs.fishc.com/Path1/query=example.Gif | 不匹配 | + + + +![Fiddler-AutoResponder-1](images/Others/Fiddler-AutoResponder-1.png) + +![Fiddler-AutoResponder-2](images/Others/Fiddler-AutoResponder-2.png) + + + +##### Composer自定义请求发送服务器 + +Composer允许自定义请求发送到服务器,可以手动创建一个新的请求,也可以在会话表中,拖拽一个现有的请求。Parsed模式下你只需要提供简单的URLS地址即可(如下图,也可以在RequestBody定制一些属性,如模拟浏览器User-Agent)。 + +![Fiddler-Composer](images/Others/Fiddler-Composer.png) + + + +##### Filters请求过滤规则 + +Fiters是过滤请求用的,左边的窗口不断的更新,当你想看你系统的请求的时候,你刷新一下浏览器,一大片不知道哪来请求,看着碍眼,它还一直刷新你的屏幕。这个时候通过过滤规则来过滤掉那些不想看到的请求。 + +![Fiddler-Filters](images/Others/Fiddler-Filters.png) + +勾选左上角的Use Filters开启过滤器,这里有两个最常用的过滤条件:Zone和Host + +- Zone:指定只显示内网(Intranet)或互联网(Internet)的内容 + + ![Fiddler-Filters-Zone](images/Others/Fiddler-Filters-Zone.png) + +- Host:指定显示某个域名下的会话 + + ![Fiddler-Filters-Host](images/Others/Fiddler-Filters-Host.png) + + 如果框框为黄色(如图),表示修改未生效,点击红圈里的文字即可。 + + + +#### Fiddler设置解密HTTPS的网络数据 + +Fiddler可以通过伪造CA证书来欺骗浏览器和服务器。Fiddler是个很会装逼的好东西,大概原理就是在浏览器面前Fiddler伪装成一个HTTPS服务器,而在真正的HTTPS服务器面前Fiddler又装成浏览器,从而实现解密HTTPS数据包的目的。 + +解密HTTPS需要手动开启,依次点击: + +1. Tools –> Fiddler Options –> HTTPS + +![Fiddler-HTTPS-1](images/Others/Fiddler-HTTPS-1.png) + +2. 勾选Decrypt HTTPS Traffic + +![Fiddler-HTTPS-2](images/Others/Fiddler-HTTPS-2.png) + +3. 点击OK + +![Fiddler-HTTPS-3](images/Others/Fiddler-HTTPS-3.png) + + + +#### Fiddler抓取IPhone/Android数据包 + +想要Fiddler抓取移动端设备的数据包,其实很简单,先来说说移动设备怎么去访问网络,看了下面这张图,就明白了。 + +![Fiddler抓取移动端-1](images/Others/Fiddler抓取移动端-1.png) + +可以看得出,移动端的数据包,都是要走wifi出去,所以我们可以把自己的电脑开启热点,将手机连上电脑,Fiddler开启代理后,让这些数据通过Fiddler,Fiddler就可以抓到这些包,然后发给路由器(如图): + +![Fiddler抓取移动端-2](images/Others/Fiddler抓取移动端-2.png) + +1. 打开Wifi热点,让手机连上(我这里用的360wifi,其实随意一个都行) + +![Fiddler抓取移动端-3](images/Others/Fiddler抓取移动端-3.png) + +2. 打开Fidder,点击菜单栏中的 [Tools] –> [Fiddler Options] + +![Fiddler抓取移动端-4](images/Others/Fiddler抓取移动端-4.png) + +3. 点击 [Connections] ,设置代理端口是8888, 勾选 Allow remote computers to connect, 点击OK + +![Fiddler抓取移动端-5](images/Others/Fiddler抓取移动端-5.png) + +4. 这时在 Fiddler 可以看到自己本机无线网卡的IP了(要是没有的话,重启Fiddler,或者可以在cmd中ipconfig找到自己的网卡IP) + +![Fiddler抓取移动端-6](images/Others/Fiddler抓取移动端-6.png) + +![Fiddler抓取移动端-7](images/Others/Fiddler抓取移动端-7.png) + +5. 在手机端连接PC的wifi,并且设置代理IP与端口(代理IP就是上图的IP,端口是Fiddler的代理端口8888) + +![Fiddler抓取移动端-8](images/Others/Fiddler抓取移动端-8.png) + +6. 访问网页输入代理IP和端口,下载Fiddler的证书,点击下图FiddlerRoot certificate + +![Fiddler抓取移动端-9](images/Others/Fiddler抓取移动端-9.png) + +【注意】:如果打开浏览器碰到类似下面的报错,请打开Fiddler的证书解密模式(Fiddler 设置解密HTTPS的网络数据) + +``` +No root certificate was found. Have you enabled HTTPS traffic decryption in Fiddler yet? +``` + +![Fiddler抓取移动端-10](images/Others/Fiddler抓取移动端-10.png)![Fiddler抓取移动端-11](images/Others/Fiddler抓取移动端-11.png) + +![Fiddler抓取移动端-12](images/Others/Fiddler抓取移动端-12.png)![Fiddler抓取移动端-13](images/Others/Fiddler抓取移动端-13.png) + +7. 安装完了证书,可以用手机访问应用,就可以看到截取到的数据包了。(下图选中是布卡漫画的数据包,下面还有QQ邮箱的) + +![Fiddler抓取移动端-14](images/Others/Fiddler抓取移动端-14.png) + + + +#### Fiddler内置命令与断点 + +Fiddler还有一个藏的很深的命令框,就是眼前,我用了几年的Fiddler都没有发现它,偶尔在别人的文章发现还有这个小功能,还蛮好用的,整理下记录在这里。Fiddler断点功能就是将请求截获下来,但是不发送,这个时候你可以干很多事情,比如说,把包改了,再发送给服务器君。还有balabala一大堆的事情可以做,就不举例子了。 + +![Fiddler内置命令与断点](images/Others/Fiddler内置命令与断点.png) + +| **命令** | **对应请求项** | **介绍** | **示例** | +| :------- | :------------- | :----------------------------------------------------------- | :------------- | +| ? | All | 问号后边跟一个字符串,可以匹配出包含这个字符串的请求 | ?google | +| > | Body | 大于号后面跟一个数字,可以匹配出请求大小,大于这个数字请求 | >1000 | +| < | Body | 小于号跟大于号相反,匹配出请求大小,小于这个数字的请求 | <100 | +| = | Result | 等于号后面跟数字,可以匹配HTTP返回码 | =200 | +| @ | Host | @后面跟Host,可以匹配域名 | @www.baidu.com | +| select | Content-Type | select后面跟响应类型,可以匹配到相关的类型 | select image | +| cls | All | 清空当前所有请求 | cls | +| dump | All | 将所有请求打包成saz压缩包,保存到“我的文档\Fiddler2\Captures”目录下 | dump | +| start | All | 开始监听请求 | start | +| stop | All | 停止监听请求 | stop | + + + +| **断点命令** | | | | +| :----------: | -------- | ------------------------------------------------------- | ------------------------------------ | +| bpafter | All | bpafter后边跟一个字符串,表示中断所有包含该字符串的请求 | bpafter baidu(输入bpafter解除断点) | +| bpu | All | 跟bpafter差不多,只不过这个是收到请求了,中断响应 | bpu baidu(输入bpu解除断点) | +| bps | Result | 后面跟状态吗,表示中断所有是这个状态码的请求 | bps 200(输入bps解除断点) | +| bpv / bpm | HTTP方法 | 只中断HTTP方法的命令,HTTP方法如POST、GET | bpv get(输入bpv解除断点) | +| g / go | All | 放行所有中断下来的请求 | g | + + + +**断点命令**:断点可以直接点击Fiddler下图的图标位置,就可以设置全部请求的断点,断点的命令可以精确设置需要截获那些请求。如下示例: + +![Fiddler-断点命令](images/Others/Fiddler-断点命令.png) + + + +### Wireshark + +### 科来网络分析系统 \ No newline at end of file diff --git a/src/Others/201.md b/src/Others/201.md new file mode 100644 index 0000000..210a45c --- /dev/null +++ b/src/Others/201.md @@ -0,0 +1 @@ +**JetBrains 破解许可服务器**:https://www.licensez.com \ No newline at end of file diff --git a/src/Others/202.md b/src/Others/202.md new file mode 100644 index 0000000..6351df9 --- /dev/null +++ b/src/Others/202.md @@ -0,0 +1,197 @@ +### 显示工具条 + +**效果图** +![显示工具条](images/Others/显示工具条.png) +**设置方法** + +- 标注1:View–>Toolbar +- 标注2:View–>Tool Buttons + + + +### 设置鼠标悬浮提示 + +**效果图** +![设置鼠标悬浮提示](images/Others/设置鼠标悬浮提示.png) + +**设置方法** +File–>settings–>Editor–>General–>勾选Show quick documentation… +![在这里插入图片描述](images/Others/20181030154227362.png) + + + +### 显示方法分隔符 + +**效果图** +![在这里插入图片描述](images/Others/20181030154728569.png) +**设置方法** + +File–>settings–>Editor–>Appearance–>勾选 + +![在这里插入图片描述](images/Others/2018103015481187.png) + + + +### 忽略大小写提示 + +**效果图** +备注:idea的默认设置是严格区分大小写提示的,例如输入string不会提示String,不方便编码 +![在这里插入图片描述](images/Others/20181030155133360.png) +**设置方法** +File–>settings–>Editor–>General -->Code Completion --> +![在这里插入图片描述](images/Others/20181030155413727.png) + + + +### 主题设置 + +**效果图** +备注:有黑白两种风格 +![在这里插入图片描述](images/Others/20181030155545483.png) +![在这里插入图片描述](images/Others/20181030155612301.png) +**设置方法** +File–>settings–>Appearance & Behavior–>Appearance–> +![在这里插入图片描述](images/Others/2018103015572874.png) + + + +### 护眼主题设置 + +**效果图** +![在这里插入图片描述](images/Others/20190110100508868.png) +**设置方法** + +如果想将编辑页面变换主题,可以去设置里面调节背景颜色 +![在这里插入图片描述](images/Others/20190110100622631.png) + +如果需要很好看的编码风格,这里有很多主题 +http://color-themes.com/?view=index&layout=Generic&order=popular&search=&page=1 +点击相应主题,往下滑点击按钮 +![在这里插入图片描述](images/Others/20190110100734530.png) +下载下来有很多Jar包 +![在这里插入图片描述](images/Others/2019011010115881.png) +![在这里插入图片描述](images/Others/2019011010123767.png) + +在上面的位置选择导入jar包,然后重启idea生效,重启之后去设置 + +![在这里插入图片描述](images/Others/20190110101907801.png) + + + +### 自动导入包 + +**效果图** +备注:默认情况是需要手动导入包的,比如我们需要导入Map类,那么需要手动导入,如果不需要使用了,删除了Map的实例,导入的包也需要手动删除,设置了这个功能这个就不需要手动了,自动帮你实现自动导入包和去包,不方便截图,效果请亲测~ +**设置方法** +File–>settings–>Editor–>general–>Auto Import–> + +![在这里插入图片描述](images/Others/2018103015593523.png) + + + +### 单行显示多个Tabs + +**效果图** +默认是显示单排的Tabs: +![在这里插入图片描述](images/Others/20181030160351154.png) +单行显示多个Tabs: + +![在这里插入图片描述](images/Others/20181030160604417.png) +**设置方法** +File–>settings–>Editor–>General -->Editor Tabs–>去掉√ +![在这里插入图片描述](images/Others/20181030160533499.png) + + + +### 设置字体 + +**效果图** +备注:默认安装启动Idea字体很小,看着不习惯,需要调整字体大小与字体(有需要可以调整) +**设置方法** +File–>settings–>Editor–>Font–> +![在这里插入图片描述](images/Others/20181030161017921.png) + + + +### 配置类文档注释信息和方法注释模版 + +**效果图** +备注:团队开发时方便追究责任与管理查看 +![在这里插入图片描述](images/Others/20181030161142910.png) +![在这里插入图片描述](images/Others/20181030161254216.png) +**设置方法** +https://blog.csdn.net/zeal9s/article/details/83514565 + + + +### 水平或者垂直显示代码 + +**效果图** +备注:Eclipse如果需要对比代码,只需要拖动Tabs即可,但是idea要设置 +![在这里插入图片描述](images/Others/20181030162041400.png) +**设置方法** +鼠标右击Tabs +![在这里插入图片描述](images/Others/20181030161922248.png) + + + +### 更换快捷键 + +**效果图** +备注:从Eclipse移植到idea编码,好多快捷键不一致,导致编写效率降低,现在我们来更换一下快捷键 +**设置方法** + +- 方法一: + +File–>Setting–> +![在这里插入图片描述](images/Others/20181030165223996.png) + +例如设置成Eclipse的,设置好了之后可以ctrl+d删除单行代码(idea是ctrl+y) + +- 方法二:设置模板 +- File–>Setting–> + ![在这里插入图片描述](images/Others/20181030165549295.png) +- 方法三: + +![在这里插入图片描述](images/Others/20181030165842703.png) +以ctrl+o重写方法为例 + +![在这里插入图片描述](images/Others/20181030170008544.png) + + + +### 注释去掉斜体 + +**效果图** +![在这里插入图片描述](images/Others/20181031135509461.png) +**设置方法** +File–>settings–>Editor–> +![在这里插入图片描述](images/Others/20181031135416445.png) + +![在这里插入图片描述](images/Others/20181031135540101.png) + + + +### 代码检测警告提示等级设置 + +![在这里插入图片描述](images/Others/20190316140152621.png) +强烈建议,不要给关掉,不要嫌弃麻烦,他的提示都是对你好,帮助你提高你的代码质量,很有帮助的。 + + + +### 项目目录相关–折叠空包 + +![在这里插入图片描述](images/Others/20190316140238852.png) + + + +### 窗口复位 + +![在这里插入图片描述](images/Others/20190316140505814.png) +这个就是当你把窗口忽然间搞得乱七八糟的时候,还可以挽回,就是直接restore一下,就好啦。 + + + +### 查看本地代码历史 + +![在这里插入图片描述](images/Others/20190316140617590.png) \ No newline at end of file diff --git a/src/Others/203.md b/src/Others/203.md new file mode 100644 index 0000000..e3051cf --- /dev/null +++ b/src/Others/203.md @@ -0,0 +1,195 @@ +### .ignore + +生成各种ignore文件,一键创建git ignore文件的模板,免得自己去写,如下图。 + +地址:https://plugins.jetbrains.com/plugin/7495--ignore + +![ignore](images/Others/ignore.gif) + + + +### Lombok + +支持lombok的各种注解,从此不用写getter setter这些 可以把注解还原为原本的java代码 非常方便。 + +地址:https://plugins.jetbrains.com/plugin/6317-lombok-plugin + +![Lombok](images/Others/Lombok.gif) + + + +### GsonFormat + +一键根据json文本生成java类 非常方便。 + +地址:https://plugins.jetbrains.com/plugin/7654-gsonformat + +![GsonFormat](images/Others/GsonFormat.gif) + + + +### GenerateAllSetter + +一键调用一个对象的所有set方法并且赋予默认值 在对象字段多的时候非常方便。 + +地址:https://plugins.jetbrains.com/plugin/9360-generateallsetter + +![GenerateAllSetter](images/Others/GenerateAllSetter.gif) + + + +### GenerateSerialVersionUID + +`Alt + Insert` 生成`serialVersionUID` + +![GenerateSerialVersionUID](images/Others/GenerateSerialVersionUID.gif) + + + +### MyBatisCodeHelper-Pro + +MybatisCodeHelperPro 是一款IDEA下全方位支持Mybatis的插件 大部分功能是免费的。 + +① 接口与xml 互相跳转 高清图标 更改图标 使用快捷键跳转 + +![MyBatisCodeHelper-Pro](images/Others/MyBatisCodeHelper-Pro.gif) + +② 一键添加param注解 + +![addParamAnnotation](images/Others/addParamAnnotation.gif) + + + +### Maven Helper + +一键查看maven依赖,查看冲突的依赖,一键进行exclude依赖,对于大型项目 非常方便。 + +地址:https://plugins.jetbrains.com/plugin/7179-maven-helper + +![Maven-Helper](images/Others/Maven-Helper.gif) + + + +### Rainbow Brackets + +代码作色工具(Rainbow Brackets)插件可以实现配对括号相同颜色,并且实现选中区域代码高亮的功能。 + +- 高亮效果快捷键 + - mac: command+鼠标右键单击 + - windows: ctrl+鼠标右键单击 + +- 选中部分外暗淡效果快捷键:alt+鼠标右键单击 + +地址:https://plugins.jetbrains.com/plugin/10080-rainbow-brackets + +![Rainbow-Brackets](images/Others/Rainbow-Brackets.gif) + +事实上,代码作色之后,可以非常方便我们阅读。类似的工具还有:Grep Console 来自定义设置控制台输出颜色等。 + + + +### HighlightBracketPair + +自动化高亮显示光标所在代码块对应的括号,可以定制颜色和形状。 + +![HighlightBracketPair](images/Others/HighlightBracketPair.gif) +![HighlightBracketPair-set](images/Others/HighlightBracketPair-set.jpg) + + + +### CodeGlance + +在编辑区的右侧显示的代码地图。 + +![CodeGlance](images/Others/CodeGlance.png) + + + +### Alibaba Java Coding Guidelines + +阿里巴巴出品的java代码规范插件(p3c)。可以扫描整个项目找到不规范的地方 并且大部分可以自动修复。Alibaba Java Code Guidelines 插件实现了开发手册中的的 53 条规则,大部分基于 PMD 实现,其中有 4 条规则基于 IDEA 实现,并且基于 IDEA Inspection 实现了实时检测功能。部分规则实现了 Quick Fix 功能。目前,插件检测有两种模式:实时检测、手动触发。 + +地址:https://plugins.jetbrains.com/plugin/10046-alibaba-java-coding-guidelines + + + +### Key promoter X + +Key Promoter X 是一个**快捷键提示插件**,如果鼠标操作是能够用快捷键替代,Key Promoter X 会提示可以用什么快捷键替代。详细使用文档。 + +地址:https://plugins.jetbrains.com/plugin/9792-key-promoter-x + +![key-promoter-x](images/Others/key-promoter-x.gif) + + +### Translation + +最好用的翻译插件,功能很强大,界面很漂亮。 + +地址:https://plugins.jetbrains.com/plugin/8579-translation + +![Translation](images/Others/Translation.gif) + + + +### SequenceDiagram + +时序图生成工具。有时我们需要梳理业务逻辑或者阅读源码。从中,我们需要了解整个调用链路,反向生成 UML 的时序图是强需求。其中,SequenceDiagram 插件是一个非常棒的插件。 + +地址:https://plugins.jetbrains.com/plugin/8286-sequencediagram + +![SequenceDiagram](images/Others/SequenceDiagram.gif) + + + +### CamelCase + +命名风格转换插件,可以在 kebab-case,SNAKE_CASE,PascalCase,camelCase,snake_case 和 空格风格之间切换。快捷键苹果为 **⇧+⌥+ U** ,windows 下为 **Shift + Alt +U**。 + +![CamelCase](images/Others/CamelCase.gif) + + + +### MybatisX + +**Mybatis-plus** 团队为 **Mybatis** 开发的插件,提供了 **Mapper** 接口和 **XML**之间的跳转和自动生成模版的功能。另外这个名字是我起的,嘿嘿! + +![MybatisX](images/Others/MybatisX.gif) + + + + + +### Git Commit Template + +老是有人吐槽你提交的 **Git** 不规范?你可以试试这个插件。它提供了很好的 **Git** 格式化模版,你可以按照实际情况格式化你的提交信息。 + +![Git-Commit-Template](images/Others/Git-Commit-Template.jpg) + + + +### Extra Icons + +最后是一个美化插件,为一些文件类型提供官方没有的图标。来看看效果吧。 + +![Extra-Icons](images/Others/Extra-Icons.jpg) + + + +### RestfulToolkit + +开发时经常会根据 URI 的部分信息来查找对应的Controller 中方法,RestfulToolkit提供了一套 RESTful 服务开发辅助工具集。 + +地址:https://plugins.jetbrains.com/plugin/10292-restfultoolkit + +![RestfulToolkit](images/Others/iuYryuy.jpg) + +### Grep Console + +### EasyCode + +### CheckStyle + +### Java Stream Debugger + +https://www.e-learn.cn/topic/3624009 \ No newline at end of file diff --git a/src/Others/204.md b/src/Others/204.md new file mode 100644 index 0000000..92121a0 --- /dev/null +++ b/src/Others/204.md @@ -0,0 +1,53 @@ +### FindBugs-IDEA + +检测代码中可能的bug及不规范的位置,检测的模式相比p3c更多,写完代码后检测下 避免低级bug,强烈建议用一下,一不小心就发现很多老代码的bug。 + +地址:https://plugins.jetbrains.com/plugin/3847-findbugs-idea + +![img](images/Others/1697faf5f3381462) + + + +### VisualVM Launcher + +运行java程序的时候启动visualvm,方便查看jvm的情况 比如堆内存大小的分配,某个对象占用了多大的内存,jvm调优必备工具。 + +地址:https://plugins.jetbrains.com/plugin/7115-visualvm-launcher + +![img](images/Others/1697faf61a88910f) + + + + + +### MyBatis Log Plugin + +Mybatis现在是java中操作数据库的首选,在开发的时候,我们都会把Mybatis的脚本直接输出在console中,但是默认的情况下,输出的脚本不是一个可以直接执行的。如果我们想直接执行,还需要在手动转化一下。MyBatis Log Plugin 这款插件是直接将Mybatis执行的sql脚本显示出来,无需处理,可以直接复制出来执行的,如图: + +![img](images/Others/v2-2e63a1d6ddf2782ab8a0cda4d3e41502_hd.jpg) + + + +### Activate-Power-Mode + +根据Atom的插件activate-power-mode(或Power mode II)的效果移植到IDEA上。 + +![8](images/Others/intellij-idea-zhuangbi-top-5-5.gif) + + + +### Background Image Plus + +可设置idea背景图片的插件,不但可以设置固体的图片,还可以设置一段时间后随机变化背景图片,以及设置图片的透明度等等。 + +![img](images/Others/772743-20181027200424736-854569575.png) + + + +### Material Theme UI + +这是一款主题插件,可以让你的ide的图标变漂亮,配色搭配的很到位,还可以切换不同的颜色,甚至可以自定义颜色。默认的配色就很漂亮了,如果需要修改配色,可以在工具栏中Tools->Material Theme然后修改配色等。 + +![tools](images/Others/material-theme-ui-tools.png) + +![](images/Others/oceanic.png) \ No newline at end of file diff --git a/src/Others/205.md b/src/Others/205.md new file mode 100644 index 0000000..2565176 --- /dev/null +++ b/src/Others/205.md @@ -0,0 +1,93 @@ +### 集成JIRA + +Jira是一个广泛使用的项目与事务跟踪工具,被广泛应用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪、项目跟踪和敏捷管理等工作领域。idea可以很好的跟它集成,参考下图: + +File -> Settings ->Task -> Servers 点击右侧上面的+号,选择JIRA,然后输入JIRA的Server地址,用户名、密码即可 + +![IDEA-JIRA-1](images/Others/IDEA-JIRA-1.png) + +然后打开Open Task界面 + +![IDEA-JIRA-2](images/Others/IDEA-JIRA-2.png) + +如果JIRA中有分配给你的Task,idea能自动列出来 + +![IDEA-JIRA-3](images/Others/IDEA-JIRA-3.png) + +代码修改后,向svn提交时,会自动与该任务关联 + +![IDEA-JIRA-4](images/Others/IDEA-JIRA-4.png) + +将每次提交的代码修改与JIRA上的TASK关联后,有什么好处呢?我们每天可能要写很多代码,修复若干bug,日子久了以后,谁也不记得当初为了修复某个bug做了哪些修改,只要你按上面的操作正确提交,idea都会帮你记着这些细节: + +![IDEA-JIRA-5](images/Others/IDEA-JIRA-5.png) + +如上图,选择最近提交的TASK列表,选择Switch to,idea就会自动打开该TASK关联的源代码,并定位到修改过的代码行。当然如果该TASK已经Close了,也可以选择Remove将其清空。 + + + +### UML类图插件 + +idea已经集成了该功能,只是默认没打开,仍然打开Settings界面,定位到Plugins,输入UML,参考下图: + +![img](images/Others/IDEA-UML-1.png) + + 确认UML 这个勾已经勾上了,然后点击Apply,重启idea,然后仍然找一个java类文件,右击Diagram + +![img](images/Others/IDEA-UML-2.png) + +然后,就自个儿爽去吧 + +![img](images/Others/IDEA-UML-3.png) + + + +### 集成SSH + +java项目经常会在linux上部署,每次要切换到SecureCRT这类终端工具未免太麻烦,idea也想到了这一点: + +![img](images/Others/IDEA-SSH-1.png) + +然后填入IP、用户名、密码啥的 + +![img](images/Others/IDEA-SSH-2.png) + +点击OK,就能连接上linux了 + +![img](images/Others/IDEA-SSH-3.png) + +注:如果有中文乱码问题,可以在Settings里调整编码为utf-8 + +![img](images/Others/IDEA-SSH-4.png) + + + +### 集成FTP + +![img](images/Others/IDEA-FTP-1.png) + +点击上图中的...,添加一个Remote Host + +![img](images/Others/IDEA-FTP-2.png) + +填写ftp的IP、用户名、密码,根路径啥的,然后点击Test FTP Connection,正常的话,应该能连接,如果连接不通,点击Advanced Options,参考下图调整下连接选项 + +![img](images/Others/IDEA-FTP-3.png) + +配置了FTP连接后,在提交代码时,可以选择提交完成后将代码自动上传到ftp服务器 + +![img](images/Others/IDEA-FTP-4.png) + + + +### Database管理工具 + +先看效果吧: + +![img](images/Others/IDEA-Database-1.png) + +有了这个,再也不羡慕vs.net的db管理功能了。配置也很简单,就是点击+号,增加一个Data Source即可 + +![img](images/Others/IDEA-Database-2.png) + +唯一要注意的是,intellij idea不带数据库驱动,所以在上图中,要手动指定db driver的jar包路径。 \ No newline at end of file diff --git a/src/Others/206.md b/src/Others/206.md new file mode 100644 index 0000000..6ea0b2b --- /dev/null +++ b/src/Others/206.md @@ -0,0 +1,157 @@ +### 弹框/显示 + +勾选Show debug window on breakpoint,则请求进入到断点后自动激活Debug窗口: + +![img](images/Others/856154-20170905111655647-1134637623.png) + +如果IDEA底部没有显示工具栏或状态栏,可以在View里打开,显示出工具栏会方便我们使用: + +  ![img](images/Others/856154-20170905112617351-1554043487.png) + + + +### 快捷键 + +在菜单栏Run里有调试对应的功能,同时可以查看对应的快捷键:  ![img](images/Others/856154-20170905124338444-556465721.png) + + 首先说第一组按钮,共8个按钮,从左到右依次如下: + +    ![img](images/Others/856154-20170905134837851-1615718043.png) + +- **Show Execution Point (Alt + F10)**:如果你的光标在其它行或其它页面,点击这个按钮可跳转到当前代码执行的行 +- **Step Over (F8)**:步过,一行一行地往下走,如果这一行上有方法不会进入方法 +- **Step Into (F7)**:步入,如果当前行有方法,可以进入方法内部,一般用于进入自定义方法内 +- **Force Step Into (Alt + Shift + F7)**:强制步入,能进入任何方法,查看底层源码的时候可以用这个进入官方类库的方法 +- **Step Out (Shift + F8)**:步出,从步入的方法内退出到方法调用处,此时方法已执行完毕,只是还没有完成赋值 +- **Drop Frame (默认无)**:回退断点,后面章节详细说明 +- **Run to Cursor (Alt + F9)**:运行到光标处,你可以将光标定位到你需要查看的那一行,然后使用这个功能,代码会运行至光标行,而不需要打断点 +- **Evaluate Expression (Alt + F8)**:计算表达式,后面章节详细说明 + +第二组按钮,共7个按钮,从上到下依次如下: + +     ![img](images/Others/856154-20170905134011101-1824595229.png) + +- **Rerun 'xxxx'**:重新运行程序,会关闭服务后重新启动程序 + +- **Update 'tech' application (Ctrl + F5)**:更新程序,一般在你的代码有改动后可执行这个功能 +- **Resume Program (F9)**:恢复程序,比如,你在第20行和25行有两个断点,当前运行至第20行,按F9,则运行到下一个断点(即第25行),再按F9,则运行完整个流程,因为后面已经没有断点了 +- **Pause Program**:暂停程序,启用Debug。目前没发现具体用法 +- **Stop 'xxx' (Ctrl + F2)**:连续按两下,关闭程序。有时候你会发现关闭服务再启动时,报端口被占用,这是因为没完全关闭服务的原因,你就需要查杀所有JVM进程了 +- **View Breakpoints (Ctrl + Shift + F8)**:查看所有断点,后面章节会涉及到 +- **Mute Breakpoints**:哑的断点,选择这个后,所有断点变为灰色,断点失效,按F9则可以直接运行完程序。再次点击,断点变为红色,有效 + + +### 变量查看 + +在IDEA中,参数所在行后面会显示当前变量的值:  ![img](images/Others/856154-20170905154209179-9123997.png) + +光标悬停到参数上,显示当前变量信息: + +  ![img](images/Others/856154-20170905154425772-770303651.png) + +![img](images/Others/856154-20170905154724866-160919363.png) + +在Variables里查看,这里显示当前方法里的所有变量: + +   ![img](images/Others/856154-20170905155339491-1166069157.png) + +在Watches里,点击New Watch,输入需要查看的变量。或者可以从Variables里拖到Watche里查看: + +  ![img](images/Others/856154-20170905160057038-750351531.png) + +如果你发现你没有Watches,可能在下图所在的地方: + +  ![img](images/Others/856154-20170905160433710-2004658473.png) + +![img](images/Others/856154-20170905160515538-1647769062.png) + + + +### 计算表达式 + +  ![img](images/Others/856154-20170905160826444-1625048711.png) + +![img](images/Others/856154-20170905161614694-93470669.png) + +设置变量,在计算表达式的框里,可以改变变量的值,这样有时候就能很方便我们去调试各种值的情况了不是: + +![img](images/Others/856154-20170905162404288-824548249.png) + + + +### 智能步入 + +一行代码里有好几个方法,怎么只选择某一个方法进入。之前提到过使用Step Into (Alt + F7) 或者 Force Step Into (Alt + Shift + F7)进入到方法内部,但这两个操作会根据方法调用顺序依次进入,这比较麻烦。 + +  那么智能步入就很方便了,智能步入,这个功能在Run里可以看到,Smart Step Into (Shift + F7): + +  ![img](images/Others/856154-20170905152523304-803289488.png) + +  按Shift + F7,会自动定位到当前断点行,并列出需要进入的方法,如图5.2,点击方法进入方法内部。 + + 如果只有一个方法,则直接进入,类似Force Step Into。 + +  ![img](images/Others/856154-20170905163730929-1374653206.png) [图5.2] + + + +### 断点条件设置 + +通过设置断点条件,在满足条件时,才停在断点处,否则直接运行: + +  ![img](images/Others/856154-20170905165253944-1162138475.png) [图6.1] + +点击View Breakpoints (Ctrl + Shift + F8),查看所有断点。Java Line Breakpoints 显示了所有的断点,在右边勾选Condition,设置断点的条件。 + +- 勾选Log message to console,则会将当前断点行输出到控制台 +- 勾选Evaluate and log,可以在执行这行代码是计算表达式的值,并将结果输出到控制台 + +![img](images/Others/856154-20170905170655163-1805982960.png) + +  ![img](images/Others/856154-20170905170947257-1667065155.png) + + + +### 异常断点 + +通过设置异常断点,在程序中出现需要拦截的异常时,会自动定位到异常行。点击+号添加Java Exception Breakpoints,添加异常断点。然后输入需要断点的异常类,如图6.7,之后可以在Java Exception Breakpoints里看到添加的异常断点。我这里添加了一个NullPointerException异常断点,出现空指针异常后,自动定位在空指针异常行: + +  ![img](images/Others/856154-20170905200131851-150143203.png) + +![img](images/Others/856154-20170905200305147-527881101.png)  ![img](images/Others/856154-20170905200726069-688175303.png) + + + +### 多线程调试 + +  一般情况下我们调试的时候是在一个线程中的,一步一步往下走。但有时候你会发现在Debug的时候,想发起另外一个请求都无法进行了?那是因为IDEA在Debug时默认阻塞级别是ALL,会阻塞其它线程,只有在当前调试线程走完时才会走其它线程。可以在View Breakpoints里选择Thread,如图下图,然后点击Make Default设置为默认选项: + +![img](images/Others/856154-20170905204329757-1196950664.png) + +  切换线程,在下图中Frames的下拉列表里,可以切换当前的线程,如下我这里有两个Debug的线程,切换另外一个则进入另一个Debug的线程:![img](images/Others/856154-20170905205012663-56609868.png) + + + +### 回退断点 + +在调试的时候,想要重新走一下流程而不用再次发起一个请求? + +所谓的断点回退,其实就是回退到上一个方法调用的开始处,在IDEA里测试无法一行一行地回退或回到到上一个断点处,而是回到上一个方法。回退的方式有两种: + +​ 方法一:是Drop Frame按钮,按调用的方法逐步回退,包括三方类库的其它方法(取消Show All Frames按钮会显示三方类库的方法,如图8.3)。 + +![img](images/Others/856154-20170905211428554-1617570377.png) + +  方法二:在调用栈方法上选择要回退的方法,右键选择Drop Frame(图8.4),回退到该方法的上一个方法调用处,此时再按F9(Resume Program),可以看到程序进入到该方法的断点处了。 + +  ![img](images/Others/856154-20170905212138101-113776159.png) + +但有一点需要注意,断点回退只能重新走一下流程,之前的某些参数/数据的状态已经改变了的是无法回退到之前的状态的,如对象、集合、更新了数据库数据等等。 + + + +### 中断Debug + +想要在Debug的时候,中断请求,不要再走剩余的流程了? + +  ![img](images/Others/856154-20170905213656241-1998475384.png) \ No newline at end of file diff --git a/src/Others/207.md b/src/Others/207.md new file mode 100644 index 0000000..fbf6f06 --- /dev/null +++ b/src/Others/207.md @@ -0,0 +1,51 @@ +### UID + +快捷键:`ALT` + `INS` + +### 折叠空包 + +![clipboard.png](images/Others/bV13Sa) + +![clipboard.png](images/Others/bV13RH) + + + +### 显示边沟图标 + +Editor→General→Gutter Icons + +### 设置自动import包 + +可选,对于不能import \*的要求的,建议不要用这个: + +[![img](images/Others/417876-20171119103804546-819180423.png)](https://images2017.cnblogs.com/blog/417876/201711/417876-20171119103804546-819180423.png) + +如果非要用这个自动导入却不想导入\*的,可以通过配置这个来解决: + +**![img](images/Others/417876-20171128105146972-1080966086.png)** + +调整import包导入的顺序,保持和Eclipse一致:![img](images/Others/417876-20171129081632175-614878351.png) + + + +### 右下角显示内存 + +[![img](images/Others/417876-20171119103943062-564729605.png)](https://images2017.cnblogs.com/blog/417876/201711/417876-20171119103943062-564729605.png) + +点击右下角可以回收内存。 + + + +### 自定义Javadoc注释 + +@date可能不是标准的Javadoc,但是在业界标准来说,这个已经成为Javadoc必备的注释,因为大多数人都用这个来标注日期。建议:注释不要太个性,比如自定义类说明,日期时间字段等等;尽量保持统一的代码风格,建议参考阿里巴巴Java开发手册: + +[![img](images/Others/417876-20171119150102656-1550889934.png)](https://images2017.cnblogs.com/blog/417876/201711/417876-20171119150102656-1550889934.png) + + + +### 鼠标放上去自动显示文档 + +![设置功能](images/Others/201705221495449669133450.jpg) + +![演示效果](images/Others/201705221495449833127277.png) \ No newline at end of file diff --git a/src/Others/208.md b/src/Others/208.md new file mode 100644 index 0000000..63b45a9 --- /dev/null +++ b/src/Others/208.md @@ -0,0 +1,216 @@ +Mac 键盘符号和修饰键说明 + +- `⌘` ——> `Command` +- `⇧` ——> `Shift` +- `⌥` ——> `Option` +- `⌃` ——> `Control` +- `↩︎` ——> `Return/Enter` +- `⌫` ——> `Delete` +- `⌦` ——> `向前删除键(Fn + Delete)` +- `↑` ——> `上箭头` +- `↓` ——> `下箭头` +- `←` ——> `左箭头` +- `→` ——> `右箭头` +- `⇞` ——> `Page Up(Fn + ↑)` +- `⇟` ——> `Page Down(Fn + ↓)` +- `⇥` ——> `右制表符(Tab键)` +- `⇤` ——> `左制表符(Shift + Tab)` +- `⎋` ——> `Escape(Esc)` +- `End` ——> `Fn + →` +- `Home` ——> `Fn + ←` + +### Editing(编辑) + +| 快捷键 | 作用 | +| ----------------------------------------------- | ------------------------------------------------------------ | +| `Control + Space` | 基本的代码补全(补全任何类、方法、变量) | +| `Control + Shift + Space` | 智能代码补全(过滤器方法列表和变量的预期类型) | +| `Command + Shift + Enter` | 自动结束代码,行末自动添加分号 | +| `Command + P` | 显示方法的参数信息 | +| `Control + J` | 快速查看文档 | +| `Shift + F1` | 查看外部文档(在某些代码上会触发打开浏览器显示相关文档) | +| `Command` + 鼠标放在代码上 | 显示代码简要信息 | +| `Command + F1` | 在错误或警告处显示具体描述信息 | +| `Command + N`, `Control + Enter`, `Control + N` | 生成代码(`getter`、`setter`、`hashCode`、`equals`、`toString`、构造函数等) | +| `Control + O` | 覆盖方法(重写父类方法) | +| `Control + I` | 实现方法(实现接口中的方法) | +| `Command + Option + T` | 包围代码(使用`if...else`、`try...catch`、`for`、`synchronized`等包围选中的代码) | +| `Command + /` | 注释 / 取消注释与行注释 | +| `Command + Option + /` | 注释 / 取消注释与块注释 | +| `Option` + 方向键上 | 连续选中代码块 | +| `Option` + 方向键下 | 减少当前选中的代码块 | +| `Control + Shift + Q` | 显示上下文信息 | +| `Option + Enter` | 显示意向动作和快速修复代码 | +| `Command + Option + L` | 格式化代码 | +| `Control + Option + O` | 优化 import | +| `Control + Option + I` | 自动缩进线 | +| `Tab / Shift + Tab` | 缩进代码 / 反缩进代码 | +| `Command + X` | 剪切当前行或选定的块到剪贴板 | +| `Command + C` | 复制当前行或选定的块到剪贴板 | +| `Command + V` | 从剪贴板粘贴 | +| `Command + Shift + V` | 从最近的缓冲区粘贴 | +| `Command + D` | 复制当前行或选定的块 | +| `Command + Delete` | 删除当前行或选定的块的行 | +| `Control + Shift + J` | 智能的将代码拼接成一行 | +| `Command + Enter` | 智能的拆分拼接的行 | +| `Shift + Enter` | 开始新的一行 | +| `Command + Shift + U` | 大小写切换 | +| `Command + Shift + ]` / `Command + Shift + [` | 选择直到代码块结束 / 开始 | +| `Option + Fn + Delete` | 删除到单词的末尾 | +| `Option + Delete` | 删除到单词的开头 | +| `Command` + 加号 / `Command` + 减号 | 展开 / 折叠代码块 | +| `Command + Shift` + 加号 | 展开所以代码块 | +| `Command + Shift` + 减号 | 折叠所有代码块 | +| `Command + W` | 关闭活动的编辑器选项卡 | + + + +### Search/Replace(查询/替换) + +| 快捷键 | 作用 | +| --------------------- | --------------------------------------------------------- | +| `Double Shift` | 查询任何东西 | +| `Command + F` | 文件内查找 | +| `Command + G` | 查找模式下,向下查找 | +| `Command + Shift + G` | 查找模式下,向上查找 | +| `Command + R` | 文件内替换 | +| `Command + Shift + F` | 全局查找(根据路径) | +| `Command + Shift + R` | 全局替换(根据路径) | +| `Command + Shift + S` | 查询结构(Ultimate Edition 版专用,需要在 Keymap 中设置) | +| `Command + Shift + M` | 替换结构(Ultimate Edition 版专用,需要在 Keymap 中设置) | + + + +### Usage Search(使用查询) + +| 快捷键 | 作用 | +| ------------------------------ | --------------------------------- | +| `Option + F7` / `Command + F7` | 在文件中查找用法 / 在类中查找用法 | +| `Command + Shift + F7` | 在文件中突出显示的用法 | +| `Command + Option + F7` | 显示用法 | + + + +### Compile and Run(编译和运行) + +| 快捷键 | 作用 | +| -------------------------------------------- | -------------------------- | +| `Command + F9` | 编译 Project | +| `Command + Shift + F9` | 编译选择的文件、包或模块 | +| `Control + Option + R` | 弹出 Run 的可选择菜单 | +| `Control + Option + D` | 弹出 Debug 的可选择菜单 | +| `Control + R` | 运行 | +| `Control + D` | 调试 | +| `Control + Shift + R`, `Control + Shift + D` | 从编辑器运行上下文环境配置 | + + + +### Debugging(调试) + +| 快捷键 | 作用 | +| ---------------------- | ------------------------------------------------------------ | +| `F8` | 进入下一步,如果当前行断点是一个方法,则不进入当前方法体内 | +| `F7` | 进入下一步,如果当前行断点是一个方法,则进入当前方法体内,如果该方法体还有方法,则不会进入该内嵌的方法中 | +| `Shift + F7` | 智能步入,断点所在行上有多个方法调用,会弹出进入哪个方法 | +| `Shift + F8` | 跳出 | +| `Option + F9` | 运行到光标处,如果光标前有其他断点会进入到该断点 | +| `Option + F8` | 计算表达式(可以更改变量值使其生效) | +| `Command + Option + R` | 恢复程序运行,如果该断点下面代码还有断点则停在下一个断点上 | +| `Command + F8` | 切换断点(若光标当前行有断点则取消断点,没有则加上断点) | +| `Command + Shift + F8` | 查看断点信息 | + + + +### Navigation(导航) + +| 快捷键 | 作用 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| `Command + O` | 查找类文件 | +| `Command + Shift + O` | 查找所有类型文件、打开文件、打开目录,打开目录需要在输入的内容前面或后面加一个反斜杠`/` | +| `Command + Option + O` | 前往指定的变量 / 方法 | +| `Control` + 方向键左 / `Control` + 方向键右 | 左右切换打开的编辑 tab 页 | +| `F12` | 返回到前一个工具窗口 | +| `Esc` | 从工具窗口进入代码文件窗口 | +| `Shift + Esc` | 隐藏当前或最后一个活动的窗口,且光标进入代码文件窗口 | +| `Command + Shift + F4` | 关闭活动 `run/messages/find/... tab` | +| `Command + L` | 在当前文件跳转到某一行的指定处 | +| `Command + E` | 显示最近打开的文件记录列表 | +| `Option` + 方向键左 / `Option` + 方向键右 | 光标跳转到当前单词 / 中文句的左 / 右侧开头位置 | +| `Command + Option` + 方向键左 / `Command + Option` + 方向键右 | 退回 / 前进到上一个操作的地方 | +| `Command + Shift + Delete` | 跳转到最后一个编辑的地方 | +| `Option + F1` | 显示当前文件选择目标弹出层,弹出层中有很多目标可以进行选择(如在代码编辑窗口可以选择显示该文件的 Finder) | +| `Command + B` / `Command` + 鼠标点击 | 进入光标所在的方法/变量的接口或是定义处 | +| `Command + Option + B` | 跳转到实现处,在某个调用的方法名上使用会跳到具体的实现处,可以跳过接口 | +| `Option + Space`, `Command + Y` | 快速打开光标所在方法、类的定义 | +| `Control + Shift + B` | 跳转到类型声明处 | +| `Command + U` | 前往当前光标所在方法的父类的方法 / 接口定义 | +| `Control` + 方向键下 / `Control` + 方向键上 | 当前光标跳转到当前文件的前一个 / 后一个方法名位置 | +| `Command + ]` / `Command + [` | 移动光标到当前所在代码的花括号开始 / 结束位置 | +| `Command + F12` | 弹出当前文件结构层,可以在弹出的层上直接输入进行筛选(可用于搜索类中的方法) | +| `Control + H` | 显示当前类的层次结构 | +| `Command + Shift + H` | 显示方法层次结构 | +| `Control + Option + H` | 显示调用层次结构 | +| `F2` / `Shift + F2` | 跳转到下一个 / 上一个突出错误或警告的位置 | +| `F4` / `Command` + 方向键下 | 编辑 / 查看代码源 | +| `Option + Home` | 显示到当前文件的导航条 | +| `F3` | 选中文件 / 文件夹 / 代码行,添加 / 取消书签 | +| `Option + F3` | 选中文件 / 文件夹/代码行,使用助记符添加 / 取消书签 | +| `Control + 0`…`Control + 9` | 定位到对应数值的书签位置 | +| `Command + F3` | 显示所有书签 | + + + +### Refactoring(重构) + +| 快捷键 | 作用 | +| ---------------------- | ---------------------------------- | +| `F5` | 复制文件到指定目录 | +| `F6` | 移动文件到指定目录 | +| `Command + Delete` | 在文件上为安全删除文件,弹出确认框 | +| `Shift + F6` | 重命名文件 | +| `Command + F6` | 更改签名 | +| `Command + Option + N` | 一致性 | +| `Command + Option + M` | 将选中的代码提取为方法 | +| `Command + Option + V` | 提取变量 | +| `Command + Option + F` | 提取字段 | +| `Command + Option + C` | 提取常量 | +| `Command + Option + P` | 提取参数 | + + + +### VCS / Local History(版本控制 / 本地历史记录) + +| 快捷键 | 作用 | +| -------------------- | -------------------------- | +| `Command + K` | 提交代码到版本控制器 | +| `Command + T` | 从版本控制器更新代码 | +| `Option + Shift + C` | 查看最近的变更记录 | +| `Control + C` | 快速弹出版本控制器操作面板 | + + + +### Live Templates(动态代码模板) + +| 快捷键 | 作用 | +| ---------------------- | ---------------------------------------------- | +| `Command + Option + J` | 弹出模板选择窗口,将选定的代码使用动态模板包住 | +| `Command + J` | 插入自定义动态代码模板 | + + + +### General(通用) + +| 快捷键 | 作用 | +| --------------------------- | ------------------------------------------------------------ | +| `Command + 1`…`Command + 9` | 打开相应编号的工具窗口 | +| `Command + S` | 保存所有 | +| `Command + Option + Y` | 同步、刷新 | +| `Control + Command + F` | 切换全屏模式 | +| `Command + Shift + F12` | 切换最大化编辑器 | +| `Option + Shift + F` | 添加到收藏夹 | +| `Option + Shift + I` | 检查当前文件与当前的配置文件 | +| Control + ` | 快速切换当前的 scheme(切换主题、代码样式等) | +| `Command + ,` | 打开 IDEA 系统设置 | +| `Command + ;` | 打开项目结构对话框 | +| `Shift + Command + A` | 查找动作(可设置相关选项) | +| `Control + Shift + Tab` | 编辑窗口标签和工具窗口之间切换(如果在切换的过程加按上 delete,则是关闭对应选中的窗口) | \ No newline at end of file diff --git a/src/Others/3.md b/src/Others/3.md new file mode 100644 index 0000000..b42a137 --- /dev/null +++ b/src/Others/3.md @@ -0,0 +1,17 @@ +### XShell/XFtp + +https://www.netsarang.com/zh/free-for-home-school + +![XShell](images/Others/XShell.png) + +### SecureCRT + +https://www.vandyke.com/cgi-bin/releases.php?product=securecrt + +![SecureCRT](images/Others/SecureCRT.jpg) + +### Terminal.icu + +https://www.terminal.icu/ + +![Terminal.icu](images/Others/Terminal.icu.png) \ No newline at end of file diff --git a/src/Others/301.md b/src/Others/301.md new file mode 100644 index 0000000..839b720 --- /dev/null +++ b/src/Others/301.md @@ -0,0 +1 @@ +提供快速原型设计工具。 \ No newline at end of file diff --git a/src/Others/302.md b/src/Others/302.md new file mode 100644 index 0000000..d1cedc9 --- /dev/null +++ b/src/Others/302.md @@ -0,0 +1,3 @@ +提供产品设计。 + +地址:https://lanhuapp \ No newline at end of file diff --git a/src/Others/303.md b/src/Others/303.md new file mode 100644 index 0000000..0762ca1 --- /dev/null +++ b/src/Others/303.md @@ -0,0 +1,3 @@ +地址:https://modao.cc/feature/flowchart + +提供原型、流程图、设计图、思维导图等功能。 \ No newline at end of file diff --git a/src/Others/4.md b/src/Others/4.md new file mode 100644 index 0000000..263e231 --- /dev/null +++ b/src/Others/4.md @@ -0,0 +1,7 @@ +### 谷歌访问助手 + +http://www.ggfwzs.com + +### Postman + +https://www.postman.com/downloads \ No newline at end of file diff --git a/src/Others/401.md b/src/Others/401.md new file mode 100644 index 0000000..8c28b47 --- /dev/null +++ b/src/Others/401.md @@ -0,0 +1,63 @@ +### 四象限法则 + +使用四象限法则来确定需要做的事情的优先级。 + +![时间管理-四象限法则](images/Others/时间管理-四象限法则.png) + +### 番茄工作法 + +![番茄工作法](images/Others/番茄工作法.jpeg) + +**番茄工作法优点** + +- 减轻对时间的焦虑 +- 提高工作效率、集中力、注意力,减少工作中断 +- 增强决策意识 +- 激励效果唤醒持久工作奖励 +- 巩固达成工作目标的决心 +- 完善工作任务预估流程,精确任务时间和质量 +- 优化工作、学习的流程,提高时间效率 +- 锻炼工作时间把控与高效时间管理能力 + + + +**番茄工作法原则** + +- 每一个番茄时间约为25分钟,每完成一个番茄时间休息5分钟 +- 在每一个番茄时间里,如遇突发事件被迫打断,该番茄时间作废 +- 非必需马山待办事项应安排到下一个番茄时间处理,并记录到敬业签 +- 每连续完成4个番茄时间后,建议休息时间增加到25分钟作为奖励 + + + +### PDCA循环管理 + +PDCA是最早由美国质量统计控制之父Shewhat(休哈特)提出的PDS(Plan Do See)演化而来,由美国质量管理专家戴明改进成为PDCA模式,所以又称为“戴明环”;它是全面质量管理所应遵循的科学程序。全面质量管理活动的全部过程,就是质量计划的制订和组织实现的过程,这个过程就是按照PDCA循环,不停顿地周而复始地运转的。 + +![pdca](images/Others/pdca.png) + +- **P——Plan(计划)** + 包括方针和目标的确定,以及活动规划的制定。 +- **D——Do(执行)** + 根据已知的信息,设计具体的方法、方案和计划布局;再根据设计和布局,进行具体运作,实现计划中的内容。 +- **C——Check(检查)** + 总结执行计划的结果,分清哪些对了,哪些错了,明确效果,找出问题。 +- **A——Action(处理)** + 对总结检查的结果进行处理,对成功的经验加以肯定,并予以标准化;对于失败的教训也要总结,引起重视。对于没有解决的问题,应提交给下一个PDCA循环中去解决。 + +每件事情,通常我们会先做计划(P),计划完了以后去实施(D),实施的过程中进行检查(C),检查执行结果是否达到了预期,分析影响的因素、出现问题的原因,并提出解决的措施,然后再把检查的结果进行改进、实施、改善(A)。 + + + +**适应范围** + +PDCA循环工作方法无论是在解决生产质量问题上还是在解决企业管理问题以及完善人生目标方面,都不愧为一个好的、有益的工作方法。   + + + +**现代观点** + +- **P(Planning)**:计划,包括三小部分:目标(goal)、实施计划(plan)、收支预算(budget) +- **D(design)**:设计方案和布局 +- **C(4C)**:4C管理,Check(检查)、Communicate(沟通)、Clean (清理)、Control(控制) +- **A(2A)**:Act(执行,对总结检查的结果进行处理)、Aim(按照目标要求行事,如改善、提高) \ No newline at end of file diff --git a/src/Others/402.md b/src/Others/402.md new file mode 100644 index 0000000..cafb8b9 --- /dev/null +++ b/src/Others/402.md @@ -0,0 +1,4 @@ +!> 你所查看的内容即将发布,敬请期待!有问题欢迎点击右上角Gitee仓库留言! + + +🚀点击左侧菜单栏查看其它文章吧! \ No newline at end of file diff --git a/src/Others/403.md b/src/Others/403.md new file mode 100644 index 0000000..9eec486 --- /dev/null +++ b/src/Others/403.md @@ -0,0 +1,6 @@ +### 离职退群方式 + +- 大群悄悄退,无伤大碍 +- 小群知会领导,正式退场 +- 关系好的同事群,发个红包再退群 +- 同事微信别删,都是日后资源 \ No newline at end of file diff --git a/src/Others/404.md b/src/Others/404.md new file mode 100644 index 0000000..13e417b --- /dev/null +++ b/src/Others/404.md @@ -0,0 +1,11 @@ +https://www.yinxiang.com/everhub/ + +### 多维度思考 + +![独立思考的三条法则](images/Others/独立思考的三条法则.jpg) + +![坚持健康思考的3条法则](images/Others/坚持健康思考的3条法则.jpg) + +![创造性思考的3条法则](images/Others/创造性思考的3条法则.jpg) + +![合作性思考的3条法则](images/Others/合作性思考的3条法则.jpg) \ No newline at end of file diff --git a/src/Others/405.md b/src/Others/405.md new file mode 100644 index 0000000..a6ad141 --- /dev/null +++ b/src/Others/405.md @@ -0,0 +1,65 @@ +### PPT演讲力 + +#### 定位PPT演讲主题 + +![定位PPT演讲主题](images/Others/定位PPT演讲主题.jpg) + + + +#### PPT演讲创新思维 + +![PPT演讲创新思维](images/Others/PPT演讲创新思维.jpg) + + + +#### PPT演讲的逻辑结构 + +![PPT演讲的逻辑结构](images/Others/PPT演讲的逻辑结构.jpg) + + + +#### 讲出好故事的HIT大法 + +![讲出好故事的HIT大发](images/Others/讲出好故事的HIT大发.jpg) + + + +#### 自我介绍公式MTV + +![自我介绍公式MTV](images/Others/自我介绍公式MTV.jpg) + + + +#### 打造个人品牌营销 + +![打造个人品牌营销](images/Others/打造个人品牌营销.jpg) + + + +#### 顶级演讲者的素养 + +![顶级演讲者的素养](images/Others/顶级演讲者的素养.jpg) + + + +#### 六步准备高光演讲 + +![六步准备高光演讲](images/Others/六步准备高光演讲.jpg) + + + +#### PPT演讲大树模型 + +![PPT演讲大树模型](images/Others/PPT演讲大树模型.jpeg) + + + +### 即兴演讲 + +![即兴交流的7种力量](images/Others/即兴交流的7种力量.jpg) + + + +### 精简发言 + +![精简发言的3个重点](images/Others/精简发言的3个重点.jpg) \ No newline at end of file diff --git a/src/Others/5.md b/src/Others/5.md new file mode 100644 index 0000000..87c6f93 --- /dev/null +++ b/src/Others/5.md @@ -0,0 +1,29 @@ +### WinMerge + +![WinMerge](images/Others/WinMerge.png) + +### Diffuse + +![Diffuse](images/Others/Diffuse.png) + +### Beyond Compare + +![BeyondCompare](images/Others/BeyondCompare.png) + +### Altova DiffDog + +![AltovaDiffDog](images/Others/AltovaDiffDog.png) + +### AptDiff + +![AptDiff](images/Others/AptDiff.png) + +### Code Compare + +![CodeCompare](images/Others/CodeCompare.png) + +### jq22 + +一款在线的文本比较工具,不想安装软件的直接用这个就好了!地址:http://www.jq22.com/textDifference + +![jq22](images/Others/jq22.png) \ No newline at end of file diff --git a/src/Others/6.md b/src/Others/6.md new file mode 100644 index 0000000..a5ed6f8 --- /dev/null +++ b/src/Others/6.md @@ -0,0 +1,25 @@ +### 图壳 + +免费好用稳定的图床网站。https://imgkr.com/ + +![图壳](images/Others/图壳.gif) + +### 小码短连接 + +简单易用的渠道短链接统计工具。https://xiaomark.com/ + +![小码短连接](images/Others/小码短连接.png) + +非常好用的长链接转短链接工具,能够让链接看起来更简洁。并且,转换为短链接之后,还能在后台监测访问数据,如访问次数、访问人数。 + +### removebg + +抠图神器。https://www.remove.bg/zh + +![removebg](images/Others/removebg.png) + +### 今日热榜 + +你关心的热点。今日热榜提供各站热榜聚合:微信、今日头条、百度、知乎、V2EX、微博、贴吧、豆瓣、天涯、虎扑、Github、抖音...。追踪全网热点、简单高效阅读。https://tophub.today + +![今日热榜](images/Others/今日热榜.png) \ No newline at end of file diff --git a/src/Others/README.md b/src/Others/README.md new file mode 100644 index 0000000..96e4347 --- /dev/null +++ b/src/Others/README.md @@ -0,0 +1,5 @@ +
Others
+ +Introduction:收纳其它相关的知识总结! + +## 🚀点击左侧菜单栏开始吧! \ No newline at end of file diff --git a/src/Others/_sidebar.md b/src/Others/_sidebar.md new file mode 100644 index 0000000..d62dab4 --- /dev/null +++ b/src/Others/_sidebar.md @@ -0,0 +1,26 @@ +* 🏁 常用软件 + * [✍ 画图工具](src/Others/1 "画图工具") + * [✍ 数据抓包](src/Others/2 "数据抓包") + * [✍ SSH](src/Others/3 "SSH") + * [✍ Chrome](src/Others/4 "Chrome") + * [✍ 代码对比](src/Others/5 "代码对比") + * [✍ 其它软件](src/Others/6 "其它软件") +* [🏁 开源工具](src/Others/101 "开源工具") +* [🏁 IDEA](src/Others/201 "IDEA") + * [✍ 常见设置](src/Others/202 "常见设置") + * [✍ 常用插件](src/Others/203 "常用插件") + * [✍ 功能插件](src/Others/204 "功能插件") + * [✍ 集成插件](src/Others/205 "集成插件") + * [✍ Debug](src/Others/206 "Debug") + * [✍ 常用设置](src/Others/207 "常用设置") + * [✍ 快捷键](src/Others/208 "快捷键") +* 🏁 Product + * [✍ Axure RP](src/Others/301 "Axure RP") + * [✍ 蓝湖](src/Others/302 "蓝湖") + * [✍ 墨刀](src/Others/303 "墨刀") +* 🏁 Product + * [✍ 时间管理](src/Others/401 "时间管理") + * [✍ 项目管理](src/Others/ComingSoon "项目管理") + * [✍ 团队管理](src/Others/403 "团队管理") + * [✍ 知识卡片](src/Others/404 "知识卡片") + * [✍ 演讲能力](src/Others/405 "演讲能力") \ No newline at end of file diff --git a/src/Others/images/Others/0BA8D167.gif b/src/Others/images/Others/0BA8D167.gif new file mode 100644 index 0000000..53da6ed Binary files /dev/null and b/src/Others/images/Others/0BA8D167.gif differ diff --git a/src/Others/images/Others/201705221495449669133450.jpg b/src/Others/images/Others/201705221495449669133450.jpg new file mode 100644 index 0000000..567d4b6 Binary files /dev/null and b/src/Others/images/Others/201705221495449669133450.jpg differ diff --git a/src/Others/images/Others/201705221495449833127277.png b/src/Others/images/Others/201705221495449833127277.png new file mode 100644 index 0000000..2bc05c4 Binary files /dev/null and b/src/Others/images/Others/201705221495449833127277.png differ diff --git a/src/Others/images/Others/20181030154227362.png b/src/Others/images/Others/20181030154227362.png new file mode 100644 index 0000000..f3eecf0 Binary files /dev/null and b/src/Others/images/Others/20181030154227362.png differ diff --git a/src/Others/images/Others/20181030154728569.png b/src/Others/images/Others/20181030154728569.png new file mode 100644 index 0000000..a7cf876 Binary files /dev/null and b/src/Others/images/Others/20181030154728569.png differ diff --git a/src/Others/images/Others/2018103015481187.png b/src/Others/images/Others/2018103015481187.png new file mode 100644 index 0000000..96bd7dd Binary files /dev/null and b/src/Others/images/Others/2018103015481187.png differ diff --git a/src/Others/images/Others/20181030155133360.png b/src/Others/images/Others/20181030155133360.png new file mode 100644 index 0000000..de48c6a Binary files /dev/null and b/src/Others/images/Others/20181030155133360.png differ diff --git a/src/Others/images/Others/20181030155413727.png b/src/Others/images/Others/20181030155413727.png new file mode 100644 index 0000000..b8c764b Binary files /dev/null and b/src/Others/images/Others/20181030155413727.png differ diff --git a/src/Others/images/Others/20181030155545483.png b/src/Others/images/Others/20181030155545483.png new file mode 100644 index 0000000..061d60c Binary files /dev/null and b/src/Others/images/Others/20181030155545483.png differ diff --git a/src/Others/images/Others/20181030155612301.png b/src/Others/images/Others/20181030155612301.png new file mode 100644 index 0000000..568bb99 Binary files /dev/null and b/src/Others/images/Others/20181030155612301.png differ diff --git a/src/Others/images/Others/2018103015572874.png b/src/Others/images/Others/2018103015572874.png new file mode 100644 index 0000000..f0e7101 Binary files /dev/null and b/src/Others/images/Others/2018103015572874.png differ diff --git a/src/Others/images/Others/2018103015593523.png b/src/Others/images/Others/2018103015593523.png new file mode 100644 index 0000000..1cc155b Binary files /dev/null and b/src/Others/images/Others/2018103015593523.png differ diff --git a/src/Others/images/Others/20181030160351154.png b/src/Others/images/Others/20181030160351154.png new file mode 100644 index 0000000..faf0349 Binary files /dev/null and b/src/Others/images/Others/20181030160351154.png differ diff --git a/src/Others/images/Others/20181030160533499.png b/src/Others/images/Others/20181030160533499.png new file mode 100644 index 0000000..b361fe8 Binary files /dev/null and b/src/Others/images/Others/20181030160533499.png differ diff --git a/src/Others/images/Others/20181030160604417.png b/src/Others/images/Others/20181030160604417.png new file mode 100644 index 0000000..bbac35e Binary files /dev/null and b/src/Others/images/Others/20181030160604417.png differ diff --git a/src/Others/images/Others/20181030161017921.png b/src/Others/images/Others/20181030161017921.png new file mode 100644 index 0000000..0ac9b40 Binary files /dev/null and b/src/Others/images/Others/20181030161017921.png differ diff --git a/src/Others/images/Others/20181030161142910.png b/src/Others/images/Others/20181030161142910.png new file mode 100644 index 0000000..216e013 Binary files /dev/null and b/src/Others/images/Others/20181030161142910.png differ diff --git a/src/Others/images/Others/20181030161254216.png b/src/Others/images/Others/20181030161254216.png new file mode 100644 index 0000000..7978134 Binary files /dev/null and b/src/Others/images/Others/20181030161254216.png differ diff --git a/src/Others/images/Others/20181030161922248.png b/src/Others/images/Others/20181030161922248.png new file mode 100644 index 0000000..ebe3a70 Binary files /dev/null and b/src/Others/images/Others/20181030161922248.png differ diff --git a/src/Others/images/Others/20181030162041400.png b/src/Others/images/Others/20181030162041400.png new file mode 100644 index 0000000..67ba17c Binary files /dev/null and b/src/Others/images/Others/20181030162041400.png differ diff --git a/src/Others/images/Others/20181030165223996.png b/src/Others/images/Others/20181030165223996.png new file mode 100644 index 0000000..e2bba81 Binary files /dev/null and b/src/Others/images/Others/20181030165223996.png differ diff --git a/src/Others/images/Others/20181030165549295.png b/src/Others/images/Others/20181030165549295.png new file mode 100644 index 0000000..4c5ab2d Binary files /dev/null and b/src/Others/images/Others/20181030165549295.png differ diff --git a/src/Others/images/Others/20181030165842703.png b/src/Others/images/Others/20181030165842703.png new file mode 100644 index 0000000..6bd00f4 Binary files /dev/null and b/src/Others/images/Others/20181030165842703.png differ diff --git a/src/Others/images/Others/20181030170008544.png b/src/Others/images/Others/20181030170008544.png new file mode 100644 index 0000000..9f3acaa Binary files /dev/null and b/src/Others/images/Others/20181030170008544.png differ diff --git a/src/Others/images/Others/20181031135416445.png b/src/Others/images/Others/20181031135416445.png new file mode 100644 index 0000000..0ec6bb7 Binary files /dev/null and b/src/Others/images/Others/20181031135416445.png differ diff --git a/src/Others/images/Others/20181031135509461.png b/src/Others/images/Others/20181031135509461.png new file mode 100644 index 0000000..5bce79b Binary files /dev/null and b/src/Others/images/Others/20181031135509461.png differ diff --git a/src/Others/images/Others/20181031135540101.png b/src/Others/images/Others/20181031135540101.png new file mode 100644 index 0000000..9119576 Binary files /dev/null and b/src/Others/images/Others/20181031135540101.png differ diff --git a/src/Others/images/Others/20190110100508868.png b/src/Others/images/Others/20190110100508868.png new file mode 100644 index 0000000..11648a8 Binary files /dev/null and b/src/Others/images/Others/20190110100508868.png differ diff --git a/src/Others/images/Others/20190110100622631.png b/src/Others/images/Others/20190110100622631.png new file mode 100644 index 0000000..43b34d6 Binary files /dev/null and b/src/Others/images/Others/20190110100622631.png differ diff --git a/src/Others/images/Others/20190110100734530.png b/src/Others/images/Others/20190110100734530.png new file mode 100644 index 0000000..467aff4 Binary files /dev/null and b/src/Others/images/Others/20190110100734530.png differ diff --git a/src/Others/images/Others/2019011010115881.png b/src/Others/images/Others/2019011010115881.png new file mode 100644 index 0000000..572deea Binary files /dev/null and b/src/Others/images/Others/2019011010115881.png differ diff --git a/src/Others/images/Others/2019011010123767.png b/src/Others/images/Others/2019011010123767.png new file mode 100644 index 0000000..4b3f60d Binary files /dev/null and b/src/Others/images/Others/2019011010123767.png differ diff --git a/src/Others/images/Others/20190110101907801.png b/src/Others/images/Others/20190110101907801.png new file mode 100644 index 0000000..89a089f Binary files /dev/null and b/src/Others/images/Others/20190110101907801.png differ diff --git a/src/Others/images/Others/20190316140152621.png b/src/Others/images/Others/20190316140152621.png new file mode 100644 index 0000000..07c1a80 Binary files /dev/null and b/src/Others/images/Others/20190316140152621.png differ diff --git a/src/Others/images/Others/20190316140238852.png b/src/Others/images/Others/20190316140238852.png new file mode 100644 index 0000000..bbbbd09 Binary files /dev/null and b/src/Others/images/Others/20190316140238852.png differ diff --git a/src/Others/images/Others/20190316140505814.png b/src/Others/images/Others/20190316140505814.png new file mode 100644 index 0000000..c2dc5f7 Binary files /dev/null and b/src/Others/images/Others/20190316140505814.png differ diff --git a/src/Others/images/Others/20190316140617590.png b/src/Others/images/Others/20190316140617590.png new file mode 100644 index 0000000..f2eaa04 Binary files /dev/null and b/src/Others/images/Others/20190316140617590.png differ diff --git a/src/Others/images/Others/417876-20171119103804546-819180423.png b/src/Others/images/Others/417876-20171119103804546-819180423.png new file mode 100644 index 0000000..c153c36 Binary files /dev/null and b/src/Others/images/Others/417876-20171119103804546-819180423.png differ diff --git a/src/Others/images/Others/417876-20171119103943062-564729605.png b/src/Others/images/Others/417876-20171119103943062-564729605.png new file mode 100644 index 0000000..444548b Binary files /dev/null and b/src/Others/images/Others/417876-20171119103943062-564729605.png differ diff --git a/src/Others/images/Others/417876-20171119150102656-1550889934.png b/src/Others/images/Others/417876-20171119150102656-1550889934.png new file mode 100644 index 0000000..c6da80b Binary files /dev/null and b/src/Others/images/Others/417876-20171119150102656-1550889934.png differ diff --git a/src/Others/images/Others/417876-20171128105146972-1080966086.png b/src/Others/images/Others/417876-20171128105146972-1080966086.png new file mode 100644 index 0000000..390ec0c Binary files /dev/null and b/src/Others/images/Others/417876-20171128105146972-1080966086.png differ diff --git a/src/Others/images/Others/417876-20171129081632175-614878351.png b/src/Others/images/Others/417876-20171129081632175-614878351.png new file mode 100644 index 0000000..5629346 Binary files /dev/null and b/src/Others/images/Others/417876-20171129081632175-614878351.png differ diff --git a/src/Others/images/Others/772743-20181027200424736-854569575.png b/src/Others/images/Others/772743-20181027200424736-854569575.png new file mode 100644 index 0000000..ee4d236 Binary files /dev/null and b/src/Others/images/Others/772743-20181027200424736-854569575.png differ diff --git a/src/Others/images/Others/856154-20170905111655647-1134637623.png b/src/Others/images/Others/856154-20170905111655647-1134637623.png new file mode 100644 index 0000000..3efbb6d Binary files /dev/null and b/src/Others/images/Others/856154-20170905111655647-1134637623.png differ diff --git a/src/Others/images/Others/856154-20170905112617351-1554043487.png b/src/Others/images/Others/856154-20170905112617351-1554043487.png new file mode 100644 index 0000000..e795842 Binary files /dev/null and b/src/Others/images/Others/856154-20170905112617351-1554043487.png differ diff --git a/src/Others/images/Others/856154-20170905124338444-556465721.png b/src/Others/images/Others/856154-20170905124338444-556465721.png new file mode 100644 index 0000000..0e39e8b Binary files /dev/null and b/src/Others/images/Others/856154-20170905124338444-556465721.png differ diff --git a/src/Others/images/Others/856154-20170905134011101-1824595229.png b/src/Others/images/Others/856154-20170905134011101-1824595229.png new file mode 100644 index 0000000..60e3d09 Binary files /dev/null and b/src/Others/images/Others/856154-20170905134011101-1824595229.png differ diff --git a/src/Others/images/Others/856154-20170905134837851-1615718043.png b/src/Others/images/Others/856154-20170905134837851-1615718043.png new file mode 100644 index 0000000..b12d940 Binary files /dev/null and b/src/Others/images/Others/856154-20170905134837851-1615718043.png differ diff --git a/src/Others/images/Others/856154-20170905152523304-803289488.png b/src/Others/images/Others/856154-20170905152523304-803289488.png new file mode 100644 index 0000000..0c5f1ef Binary files /dev/null and b/src/Others/images/Others/856154-20170905152523304-803289488.png differ diff --git a/src/Others/images/Others/856154-20170905154209179-9123997.png b/src/Others/images/Others/856154-20170905154209179-9123997.png new file mode 100644 index 0000000..6e157de Binary files /dev/null and b/src/Others/images/Others/856154-20170905154209179-9123997.png differ diff --git a/src/Others/images/Others/856154-20170905154425772-770303651.png b/src/Others/images/Others/856154-20170905154425772-770303651.png new file mode 100644 index 0000000..7f0c255 Binary files /dev/null and b/src/Others/images/Others/856154-20170905154425772-770303651.png differ diff --git a/src/Others/images/Others/856154-20170905154724866-160919363.png b/src/Others/images/Others/856154-20170905154724866-160919363.png new file mode 100644 index 0000000..94ca8f3 Binary files /dev/null and b/src/Others/images/Others/856154-20170905154724866-160919363.png differ diff --git a/src/Others/images/Others/856154-20170905155339491-1166069157.png b/src/Others/images/Others/856154-20170905155339491-1166069157.png new file mode 100644 index 0000000..59a2d6d Binary files /dev/null and b/src/Others/images/Others/856154-20170905155339491-1166069157.png differ diff --git a/src/Others/images/Others/856154-20170905160057038-750351531.png b/src/Others/images/Others/856154-20170905160057038-750351531.png new file mode 100644 index 0000000..22da02e Binary files /dev/null and b/src/Others/images/Others/856154-20170905160057038-750351531.png differ diff --git a/src/Others/images/Others/856154-20170905160433710-2004658473.png b/src/Others/images/Others/856154-20170905160433710-2004658473.png new file mode 100644 index 0000000..975dade Binary files /dev/null and b/src/Others/images/Others/856154-20170905160433710-2004658473.png differ diff --git a/src/Others/images/Others/856154-20170905160515538-1647769062.png b/src/Others/images/Others/856154-20170905160515538-1647769062.png new file mode 100644 index 0000000..45970a4 Binary files /dev/null and b/src/Others/images/Others/856154-20170905160515538-1647769062.png differ diff --git a/src/Others/images/Others/856154-20170905160826444-1625048711.png b/src/Others/images/Others/856154-20170905160826444-1625048711.png new file mode 100644 index 0000000..0eaffd1 Binary files /dev/null and b/src/Others/images/Others/856154-20170905160826444-1625048711.png differ diff --git a/src/Others/images/Others/856154-20170905161614694-93470669.png b/src/Others/images/Others/856154-20170905161614694-93470669.png new file mode 100644 index 0000000..7640ff0 Binary files /dev/null and b/src/Others/images/Others/856154-20170905161614694-93470669.png differ diff --git a/src/Others/images/Others/856154-20170905162404288-824548249.png b/src/Others/images/Others/856154-20170905162404288-824548249.png new file mode 100644 index 0000000..a1746b7 Binary files /dev/null and b/src/Others/images/Others/856154-20170905162404288-824548249.png differ diff --git a/src/Others/images/Others/856154-20170905163730929-1374653206.png b/src/Others/images/Others/856154-20170905163730929-1374653206.png new file mode 100644 index 0000000..cd02027 Binary files /dev/null and b/src/Others/images/Others/856154-20170905163730929-1374653206.png differ diff --git a/src/Others/images/Others/856154-20170905165253944-1162138475.png b/src/Others/images/Others/856154-20170905165253944-1162138475.png new file mode 100644 index 0000000..e51d6e3 Binary files /dev/null and b/src/Others/images/Others/856154-20170905165253944-1162138475.png differ diff --git a/src/Others/images/Others/856154-20170905170655163-1805982960.png b/src/Others/images/Others/856154-20170905170655163-1805982960.png new file mode 100644 index 0000000..68e422d Binary files /dev/null and b/src/Others/images/Others/856154-20170905170655163-1805982960.png differ diff --git a/src/Others/images/Others/856154-20170905170947257-1667065155.png b/src/Others/images/Others/856154-20170905170947257-1667065155.png new file mode 100644 index 0000000..e8cd5df Binary files /dev/null and b/src/Others/images/Others/856154-20170905170947257-1667065155.png differ diff --git a/src/Others/images/Others/856154-20170905200131851-150143203.png b/src/Others/images/Others/856154-20170905200131851-150143203.png new file mode 100644 index 0000000..06a7f31 Binary files /dev/null and b/src/Others/images/Others/856154-20170905200131851-150143203.png differ diff --git a/src/Others/images/Others/856154-20170905200305147-527881101.png b/src/Others/images/Others/856154-20170905200305147-527881101.png new file mode 100644 index 0000000..e9feae4 Binary files /dev/null and b/src/Others/images/Others/856154-20170905200305147-527881101.png differ diff --git a/src/Others/images/Others/856154-20170905200726069-688175303.png b/src/Others/images/Others/856154-20170905200726069-688175303.png new file mode 100644 index 0000000..91de736 Binary files /dev/null and b/src/Others/images/Others/856154-20170905200726069-688175303.png differ diff --git a/src/Others/images/Others/856154-20170905204329757-1196950664.png b/src/Others/images/Others/856154-20170905204329757-1196950664.png new file mode 100644 index 0000000..f726c48 Binary files /dev/null and b/src/Others/images/Others/856154-20170905204329757-1196950664.png differ diff --git a/src/Others/images/Others/856154-20170905205012663-56609868.png b/src/Others/images/Others/856154-20170905205012663-56609868.png new file mode 100644 index 0000000..812dedd Binary files /dev/null and b/src/Others/images/Others/856154-20170905205012663-56609868.png differ diff --git a/src/Others/images/Others/856154-20170905211428554-1617570377.png b/src/Others/images/Others/856154-20170905211428554-1617570377.png new file mode 100644 index 0000000..9fd93d0 Binary files /dev/null and b/src/Others/images/Others/856154-20170905211428554-1617570377.png differ diff --git a/src/Others/images/Others/856154-20170905212138101-113776159.png b/src/Others/images/Others/856154-20170905212138101-113776159.png new file mode 100644 index 0000000..9c09367 Binary files /dev/null and b/src/Others/images/Others/856154-20170905212138101-113776159.png differ diff --git a/src/Others/images/Others/856154-20170905213656241-1998475384.png b/src/Others/images/Others/856154-20170905213656241-1998475384.png new file mode 100644 index 0000000..635e7a3 Binary files /dev/null and b/src/Others/images/Others/856154-20170905213656241-1998475384.png differ diff --git a/src/Others/images/Others/AltovaDiffDog.png b/src/Others/images/Others/AltovaDiffDog.png new file mode 100644 index 0000000..ac4b6da Binary files /dev/null and b/src/Others/images/Others/AltovaDiffDog.png differ diff --git a/src/Others/images/Others/AptDiff.png b/src/Others/images/Others/AptDiff.png new file mode 100644 index 0000000..f44e866 Binary files /dev/null and b/src/Others/images/Others/AptDiff.png differ diff --git a/src/Others/images/Others/BeyondCompare.png b/src/Others/images/Others/BeyondCompare.png new file mode 100644 index 0000000..f0e2841 Binary files /dev/null and b/src/Others/images/Others/BeyondCompare.png differ diff --git a/src/Others/images/Others/CamelCase.gif b/src/Others/images/Others/CamelCase.gif new file mode 100644 index 0000000..a4d5c5c Binary files /dev/null and b/src/Others/images/Others/CamelCase.gif differ diff --git a/src/Others/images/Others/Carbon.png b/src/Others/images/Others/Carbon.png new file mode 100644 index 0000000..9bef86e Binary files /dev/null and b/src/Others/images/Others/Carbon.png differ diff --git a/src/Others/images/Others/CodeCompare.png b/src/Others/images/Others/CodeCompare.png new file mode 100644 index 0000000..f92d960 Binary files /dev/null and b/src/Others/images/Others/CodeCompare.png differ diff --git a/src/Others/images/Others/CodeGlance.png b/src/Others/images/Others/CodeGlance.png new file mode 100644 index 0000000..9ae1640 Binary files /dev/null and b/src/Others/images/Others/CodeGlance.png differ diff --git a/src/Others/images/Others/Diffuse.png b/src/Others/images/Others/Diffuse.png new file mode 100644 index 0000000..edb2756 Binary files /dev/null and b/src/Others/images/Others/Diffuse.png differ diff --git a/src/Others/images/Others/Excalidraw.png b/src/Others/images/Others/Excalidraw.png new file mode 100644 index 0000000..53636dc Binary files /dev/null and b/src/Others/images/Others/Excalidraw.png differ diff --git a/src/Others/images/Others/Extra-Icons.jpg b/src/Others/images/Others/Extra-Icons.jpg new file mode 100644 index 0000000..5815371 Binary files /dev/null and b/src/Others/images/Others/Extra-Icons.jpg differ diff --git a/src/Others/images/Others/Fiddler-AutoResponder-1.png b/src/Others/images/Others/Fiddler-AutoResponder-1.png new file mode 100644 index 0000000..39136f9 Binary files /dev/null and b/src/Others/images/Others/Fiddler-AutoResponder-1.png differ diff --git a/src/Others/images/Others/Fiddler-AutoResponder-2.png b/src/Others/images/Others/Fiddler-AutoResponder-2.png new file mode 100644 index 0000000..2cb51fc Binary files /dev/null and b/src/Others/images/Others/Fiddler-AutoResponder-2.png differ diff --git a/src/Others/images/Others/Fiddler-CaptureTraffic-Debugger.png b/src/Others/images/Others/Fiddler-CaptureTraffic-Debugger.png new file mode 100644 index 0000000..c20bcc3 Binary files /dev/null and b/src/Others/images/Others/Fiddler-CaptureTraffic-Debugger.png differ diff --git a/src/Others/images/Others/Fiddler-CaptureTraffic.png b/src/Others/images/Others/Fiddler-CaptureTraffic.png new file mode 100644 index 0000000..f50521f Binary files /dev/null and b/src/Others/images/Others/Fiddler-CaptureTraffic.png differ diff --git a/src/Others/images/Others/Fiddler-Composer.png b/src/Others/images/Others/Fiddler-Composer.png new file mode 100644 index 0000000..3aaa44d Binary files /dev/null and b/src/Others/images/Others/Fiddler-Composer.png differ diff --git a/src/Others/images/Others/Fiddler-Filters-Host.png b/src/Others/images/Others/Fiddler-Filters-Host.png new file mode 100644 index 0000000..41e3d52 Binary files /dev/null and b/src/Others/images/Others/Fiddler-Filters-Host.png differ diff --git a/src/Others/images/Others/Fiddler-Filters-Zone.png b/src/Others/images/Others/Fiddler-Filters-Zone.png new file mode 100644 index 0000000..1b736bf Binary files /dev/null and b/src/Others/images/Others/Fiddler-Filters-Zone.png differ diff --git a/src/Others/images/Others/Fiddler-Filters.png b/src/Others/images/Others/Fiddler-Filters.png new file mode 100644 index 0000000..0d0c2a6 Binary files /dev/null and b/src/Others/images/Others/Fiddler-Filters.png differ diff --git a/src/Others/images/Others/Fiddler-HTTPS-1.png b/src/Others/images/Others/Fiddler-HTTPS-1.png new file mode 100644 index 0000000..414db96 Binary files /dev/null and b/src/Others/images/Others/Fiddler-HTTPS-1.png differ diff --git a/src/Others/images/Others/Fiddler-HTTPS-2.png b/src/Others/images/Others/Fiddler-HTTPS-2.png new file mode 100644 index 0000000..b064615 Binary files /dev/null and b/src/Others/images/Others/Fiddler-HTTPS-2.png differ diff --git a/src/Others/images/Others/Fiddler-HTTPS-3.png b/src/Others/images/Others/Fiddler-HTTPS-3.png new file mode 100644 index 0000000..3801049 Binary files /dev/null and b/src/Others/images/Others/Fiddler-HTTPS-3.png differ diff --git a/src/Others/images/Others/Fiddler-Inspectors.png b/src/Others/images/Others/Fiddler-Inspectors.png new file mode 100644 index 0000000..09d25e1 Binary files /dev/null and b/src/Others/images/Others/Fiddler-Inspectors.png differ diff --git a/src/Others/images/Others/Fiddler-Statistics.png b/src/Others/images/Others/Fiddler-Statistics.png new file mode 100644 index 0000000..114d764 Binary files /dev/null and b/src/Others/images/Others/Fiddler-Statistics.png differ diff --git a/src/Others/images/Others/Fiddler-Timeline.png b/src/Others/images/Others/Fiddler-Timeline.png new file mode 100644 index 0000000..8b149a2 Binary files /dev/null and b/src/Others/images/Others/Fiddler-Timeline.png differ diff --git a/src/Others/images/Others/Fiddler-断点命令.png b/src/Others/images/Others/Fiddler-断点命令.png new file mode 100644 index 0000000..2e277ec Binary files /dev/null and b/src/Others/images/Others/Fiddler-断点命令.png differ diff --git a/src/Others/images/Others/Fiddler内置命令与断点.png b/src/Others/images/Others/Fiddler内置命令与断点.png new file mode 100644 index 0000000..411843e Binary files /dev/null and b/src/Others/images/Others/Fiddler内置命令与断点.png differ diff --git a/src/Others/images/Others/Fiddler抓包简介.png b/src/Others/images/Others/Fiddler抓包简介.png new file mode 100644 index 0000000..76869c8 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓包简介.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-1.png b/src/Others/images/Others/Fiddler抓取移动端-1.png new file mode 100644 index 0000000..0023602 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-1.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-10.png b/src/Others/images/Others/Fiddler抓取移动端-10.png new file mode 100644 index 0000000..5135190 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-10.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-11.png b/src/Others/images/Others/Fiddler抓取移动端-11.png new file mode 100644 index 0000000..afcec37 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-11.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-12.png b/src/Others/images/Others/Fiddler抓取移动端-12.png new file mode 100644 index 0000000..e45bfa8 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-12.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-13.png b/src/Others/images/Others/Fiddler抓取移动端-13.png new file mode 100644 index 0000000..41c978c Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-13.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-14.png b/src/Others/images/Others/Fiddler抓取移动端-14.png new file mode 100644 index 0000000..b032722 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-14.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-2.png b/src/Others/images/Others/Fiddler抓取移动端-2.png new file mode 100644 index 0000000..809b710 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-2.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-3.png b/src/Others/images/Others/Fiddler抓取移动端-3.png new file mode 100644 index 0000000..1a78b20 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-3.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-4.png b/src/Others/images/Others/Fiddler抓取移动端-4.png new file mode 100644 index 0000000..ca61cd1 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-4.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-5.png b/src/Others/images/Others/Fiddler抓取移动端-5.png new file mode 100644 index 0000000..bffae92 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-5.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-6.png b/src/Others/images/Others/Fiddler抓取移动端-6.png new file mode 100644 index 0000000..86a46f9 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-6.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-7.png b/src/Others/images/Others/Fiddler抓取移动端-7.png new file mode 100644 index 0000000..78582e4 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-7.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-8.png b/src/Others/images/Others/Fiddler抓取移动端-8.png new file mode 100644 index 0000000..1497524 Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-8.png differ diff --git a/src/Others/images/Others/Fiddler抓取移动端-9.png b/src/Others/images/Others/Fiddler抓取移动端-9.png new file mode 100644 index 0000000..2d21fcf Binary files /dev/null and b/src/Others/images/Others/Fiddler抓取移动端-9.png differ diff --git a/src/Others/images/Others/GenerateAllSetter.gif b/src/Others/images/Others/GenerateAllSetter.gif new file mode 100644 index 0000000..f01c5ac Binary files /dev/null and b/src/Others/images/Others/GenerateAllSetter.gif differ diff --git a/src/Others/images/Others/GenerateSerialVersionUID.gif b/src/Others/images/Others/GenerateSerialVersionUID.gif new file mode 100644 index 0000000..e03598f Binary files /dev/null and b/src/Others/images/Others/GenerateSerialVersionUID.gif differ diff --git a/src/Others/images/Others/Git-Commit-Template.jpg b/src/Others/images/Others/Git-Commit-Template.jpg new file mode 100644 index 0000000..82b1be6 Binary files /dev/null and b/src/Others/images/Others/Git-Commit-Template.jpg differ diff --git a/src/Others/images/Others/GsonFormat.gif b/src/Others/images/Others/GsonFormat.gif new file mode 100644 index 0000000..7f01979 Binary files /dev/null and b/src/Others/images/Others/GsonFormat.gif differ diff --git a/src/Others/images/Others/HighlightBracketPair-set.jpg b/src/Others/images/Others/HighlightBracketPair-set.jpg new file mode 100644 index 0000000..edb37a1 Binary files /dev/null and b/src/Others/images/Others/HighlightBracketPair-set.jpg differ diff --git a/src/Others/images/Others/HighlightBracketPair.gif b/src/Others/images/Others/HighlightBracketPair.gif new file mode 100644 index 0000000..ab7b055 Binary files /dev/null and b/src/Others/images/Others/HighlightBracketPair.gif differ diff --git a/src/Others/images/Others/IDEA-Database-1.png b/src/Others/images/Others/IDEA-Database-1.png new file mode 100644 index 0000000..315fe90 Binary files /dev/null and b/src/Others/images/Others/IDEA-Database-1.png differ diff --git a/src/Others/images/Others/IDEA-Database-2.png b/src/Others/images/Others/IDEA-Database-2.png new file mode 100644 index 0000000..8b8f0b2 Binary files /dev/null and b/src/Others/images/Others/IDEA-Database-2.png differ diff --git a/src/Others/images/Others/IDEA-FTP-1.png b/src/Others/images/Others/IDEA-FTP-1.png new file mode 100644 index 0000000..f0a4763 Binary files /dev/null and b/src/Others/images/Others/IDEA-FTP-1.png differ diff --git a/src/Others/images/Others/IDEA-FTP-2.png b/src/Others/images/Others/IDEA-FTP-2.png new file mode 100644 index 0000000..b8ae990 Binary files /dev/null and b/src/Others/images/Others/IDEA-FTP-2.png differ diff --git a/src/Others/images/Others/IDEA-FTP-3.png b/src/Others/images/Others/IDEA-FTP-3.png new file mode 100644 index 0000000..4740e91 Binary files /dev/null and b/src/Others/images/Others/IDEA-FTP-3.png differ diff --git a/src/Others/images/Others/IDEA-FTP-4.png b/src/Others/images/Others/IDEA-FTP-4.png new file mode 100644 index 0000000..4bd39e5 Binary files /dev/null and b/src/Others/images/Others/IDEA-FTP-4.png differ diff --git a/src/Others/images/Others/IDEA-JIRA-1.png b/src/Others/images/Others/IDEA-JIRA-1.png new file mode 100644 index 0000000..8bca6d3 Binary files /dev/null and b/src/Others/images/Others/IDEA-JIRA-1.png differ diff --git a/src/Others/images/Others/IDEA-JIRA-2.png b/src/Others/images/Others/IDEA-JIRA-2.png new file mode 100644 index 0000000..769320f Binary files /dev/null and b/src/Others/images/Others/IDEA-JIRA-2.png differ diff --git a/src/Others/images/Others/IDEA-JIRA-3.png b/src/Others/images/Others/IDEA-JIRA-3.png new file mode 100644 index 0000000..45b683b Binary files /dev/null and b/src/Others/images/Others/IDEA-JIRA-3.png differ diff --git a/src/Others/images/Others/IDEA-JIRA-4.png b/src/Others/images/Others/IDEA-JIRA-4.png new file mode 100644 index 0000000..94a2684 Binary files /dev/null and b/src/Others/images/Others/IDEA-JIRA-4.png differ diff --git a/src/Others/images/Others/IDEA-JIRA-5.png b/src/Others/images/Others/IDEA-JIRA-5.png new file mode 100644 index 0000000..6a6b3f7 Binary files /dev/null and b/src/Others/images/Others/IDEA-JIRA-5.png differ diff --git a/src/Others/images/Others/IDEA-SSH-1.png b/src/Others/images/Others/IDEA-SSH-1.png new file mode 100644 index 0000000..721cb13 Binary files /dev/null and b/src/Others/images/Others/IDEA-SSH-1.png differ diff --git a/src/Others/images/Others/IDEA-SSH-2.png b/src/Others/images/Others/IDEA-SSH-2.png new file mode 100644 index 0000000..e79f5f7 Binary files /dev/null and b/src/Others/images/Others/IDEA-SSH-2.png differ diff --git a/src/Others/images/Others/IDEA-SSH-3.png b/src/Others/images/Others/IDEA-SSH-3.png new file mode 100644 index 0000000..ee4d844 Binary files /dev/null and b/src/Others/images/Others/IDEA-SSH-3.png differ diff --git a/src/Others/images/Others/IDEA-SSH-4.png b/src/Others/images/Others/IDEA-SSH-4.png new file mode 100644 index 0000000..086f07b Binary files /dev/null and b/src/Others/images/Others/IDEA-SSH-4.png differ diff --git a/src/Others/images/Others/IDEA-UML-1.png b/src/Others/images/Others/IDEA-UML-1.png new file mode 100644 index 0000000..5b13fb5 Binary files /dev/null and b/src/Others/images/Others/IDEA-UML-1.png differ diff --git a/src/Others/images/Others/IDEA-UML-2.png b/src/Others/images/Others/IDEA-UML-2.png new file mode 100644 index 0000000..2cb702d Binary files /dev/null and b/src/Others/images/Others/IDEA-UML-2.png differ diff --git a/src/Others/images/Others/IDEA-UML-3.png b/src/Others/images/Others/IDEA-UML-3.png new file mode 100644 index 0000000..be7035b Binary files /dev/null and b/src/Others/images/Others/IDEA-UML-3.png differ diff --git a/src/Others/images/Others/Lombok.gif b/src/Others/images/Others/Lombok.gif new file mode 100644 index 0000000..c9b1e0b Binary files /dev/null and b/src/Others/images/Others/Lombok.gif differ diff --git a/src/Others/images/Others/Maven-Helper.gif b/src/Others/images/Others/Maven-Helper.gif new file mode 100644 index 0000000..cb95477 Binary files /dev/null and b/src/Others/images/Others/Maven-Helper.gif differ diff --git a/src/Others/images/Others/MyBatisCodeHelper-Pro.gif b/src/Others/images/Others/MyBatisCodeHelper-Pro.gif new file mode 100644 index 0000000..f65bef6 Binary files /dev/null and b/src/Others/images/Others/MyBatisCodeHelper-Pro.gif differ diff --git a/src/Others/images/Others/MybatisX.gif b/src/Others/images/Others/MybatisX.gif new file mode 100644 index 0000000..17a96e3 Binary files /dev/null and b/src/Others/images/Others/MybatisX.gif differ diff --git a/src/Others/images/Others/PPT演讲创新思维.jpg b/src/Others/images/Others/PPT演讲创新思维.jpg new file mode 100644 index 0000000..d935ed1 Binary files /dev/null and b/src/Others/images/Others/PPT演讲创新思维.jpg differ diff --git a/src/Others/images/Others/PPT演讲大树模型.jpeg b/src/Others/images/Others/PPT演讲大树模型.jpeg new file mode 100644 index 0000000..537038d Binary files /dev/null and b/src/Others/images/Others/PPT演讲大树模型.jpeg differ diff --git a/src/Others/images/Others/PPT演讲的逻辑结构.jpg b/src/Others/images/Others/PPT演讲的逻辑结构.jpg new file mode 100644 index 0000000..d03a1b4 Binary files /dev/null and b/src/Others/images/Others/PPT演讲的逻辑结构.jpg differ diff --git a/src/Others/images/Others/ProcessOn.png b/src/Others/images/Others/ProcessOn.png new file mode 100644 index 0000000..e05656d Binary files /dev/null and b/src/Others/images/Others/ProcessOn.png differ diff --git a/src/Others/images/Others/Rainbow-Brackets.gif b/src/Others/images/Others/Rainbow-Brackets.gif new file mode 100644 index 0000000..100d444 Binary files /dev/null and b/src/Others/images/Others/Rainbow-Brackets.gif differ diff --git a/src/Others/images/Others/SecureCRT.jpg b/src/Others/images/Others/SecureCRT.jpg new file mode 100644 index 0000000..b9f1d04 Binary files /dev/null and b/src/Others/images/Others/SecureCRT.jpg differ diff --git a/src/Others/images/Others/SequenceDiagram.gif b/src/Others/images/Others/SequenceDiagram.gif new file mode 100644 index 0000000..f0c2b67 Binary files /dev/null and b/src/Others/images/Others/SequenceDiagram.gif differ diff --git a/src/Others/images/Others/Terminal.icu.png b/src/Others/images/Others/Terminal.icu.png new file mode 100644 index 0000000..60b6bb9 Binary files /dev/null and b/src/Others/images/Others/Terminal.icu.png differ diff --git a/src/Others/images/Others/Translation.gif b/src/Others/images/Others/Translation.gif new file mode 100644 index 0000000..2f7fe5e Binary files /dev/null and b/src/Others/images/Others/Translation.gif differ diff --git a/src/Others/images/Others/WinMerge.png b/src/Others/images/Others/WinMerge.png new file mode 100644 index 0000000..d6fcd22 Binary files /dev/null and b/src/Others/images/Others/WinMerge.png differ diff --git a/src/Others/images/Others/XShell.png b/src/Others/images/Others/XShell.png new file mode 100644 index 0000000..9200ae0 Binary files /dev/null and b/src/Others/images/Others/XShell.png differ diff --git a/src/Others/images/Others/addParamAnnotation.gif b/src/Others/images/Others/addParamAnnotation.gif new file mode 100644 index 0000000..9abda27 Binary files /dev/null and b/src/Others/images/Others/addParamAnnotation.gif differ diff --git a/src/Others/images/Others/bV13RH b/src/Others/images/Others/bV13RH new file mode 100644 index 0000000..8d59285 Binary files /dev/null and b/src/Others/images/Others/bV13RH differ diff --git a/src/Others/images/Others/bV13Sa b/src/Others/images/Others/bV13Sa new file mode 100644 index 0000000..7e92b80 Binary files /dev/null and b/src/Others/images/Others/bV13Sa differ diff --git a/src/Others/images/Others/draw.io.jpeg b/src/Others/images/Others/draw.io.jpeg new file mode 100644 index 0000000..01abf94 Binary files /dev/null and b/src/Others/images/Others/draw.io.jpeg differ diff --git a/src/Others/images/Others/ignore.gif b/src/Others/images/Others/ignore.gif new file mode 100644 index 0000000..fa036ec Binary files /dev/null and b/src/Others/images/Others/ignore.gif differ diff --git a/src/Others/images/Others/intellij-idea-zhuangbi-top-5-5.gif b/src/Others/images/Others/intellij-idea-zhuangbi-top-5-5.gif new file mode 100644 index 0000000..9e6cd69 Binary files /dev/null and b/src/Others/images/Others/intellij-idea-zhuangbi-top-5-5.gif differ diff --git a/src/Others/images/Others/iuYryuy.jpg b/src/Others/images/Others/iuYryuy.jpg new file mode 100644 index 0000000..6be4ff2 Binary files /dev/null and b/src/Others/images/Others/iuYryuy.jpg differ diff --git a/src/Others/images/Others/jq22.png b/src/Others/images/Others/jq22.png new file mode 100644 index 0000000..2fccf1b Binary files /dev/null and b/src/Others/images/Others/jq22.png differ diff --git a/src/Others/images/Others/key-promoter-x.gif b/src/Others/images/Others/key-promoter-x.gif new file mode 100644 index 0000000..476794e Binary files /dev/null and b/src/Others/images/Others/key-promoter-x.gif differ diff --git a/src/Others/images/Others/material-theme-ui-tools.png b/src/Others/images/Others/material-theme-ui-tools.png new file mode 100644 index 0000000..64fed87 Binary files /dev/null and b/src/Others/images/Others/material-theme-ui-tools.png differ diff --git a/src/Others/images/Others/oceanic.png b/src/Others/images/Others/oceanic.png new file mode 100644 index 0000000..6f6d307 Binary files /dev/null and b/src/Others/images/Others/oceanic.png differ diff --git a/src/Others/images/Others/pdca.png b/src/Others/images/Others/pdca.png new file mode 100644 index 0000000..a4abd8f Binary files /dev/null and b/src/Others/images/Others/pdca.png differ diff --git a/src/Others/images/Others/removebg.png b/src/Others/images/Others/removebg.png new file mode 100644 index 0000000..1303445 Binary files /dev/null and b/src/Others/images/Others/removebg.png differ diff --git a/src/Others/images/Others/v2-2e63a1d6ddf2782ab8a0cda4d3e41502_hd.jpg b/src/Others/images/Others/v2-2e63a1d6ddf2782ab8a0cda4d3e41502_hd.jpg new file mode 100644 index 0000000..e0c9e0d Binary files /dev/null and b/src/Others/images/Others/v2-2e63a1d6ddf2782ab8a0cda4d3e41502_hd.jpg differ diff --git a/src/Others/images/Others/今日热榜.png b/src/Others/images/Others/今日热榜.png new file mode 100644 index 0000000..75d4368 Binary files /dev/null and b/src/Others/images/Others/今日热榜.png differ diff --git a/src/Others/images/Others/六步准备高光演讲.jpg b/src/Others/images/Others/六步准备高光演讲.jpg new file mode 100644 index 0000000..cabaf89 Binary files /dev/null and b/src/Others/images/Others/六步准备高光演讲.jpg differ diff --git a/src/Others/images/Others/创造性思考的3条法则.jpg b/src/Others/images/Others/创造性思考的3条法则.jpg new file mode 100644 index 0000000..a8ea2f5 Binary files /dev/null and b/src/Others/images/Others/创造性思考的3条法则.jpg differ diff --git a/src/Others/images/Others/即兴交流的7种力量.jpg b/src/Others/images/Others/即兴交流的7种力量.jpg new file mode 100644 index 0000000..77b523b Binary files /dev/null and b/src/Others/images/Others/即兴交流的7种力量.jpg differ diff --git a/src/Others/images/Others/合作性思考的3条法则.jpg b/src/Others/images/Others/合作性思考的3条法则.jpg new file mode 100644 index 0000000..f565d14 Binary files /dev/null and b/src/Others/images/Others/合作性思考的3条法则.jpg differ diff --git a/src/Others/images/Others/图壳.gif b/src/Others/images/Others/图壳.gif new file mode 100644 index 0000000..ec2d549 Binary files /dev/null and b/src/Others/images/Others/图壳.gif differ diff --git a/src/Others/images/Others/坚持健康思考的3条法则.jpg b/src/Others/images/Others/坚持健康思考的3条法则.jpg new file mode 100644 index 0000000..4cb87d1 Binary files /dev/null and b/src/Others/images/Others/坚持健康思考的3条法则.jpg differ diff --git a/src/Others/images/Others/定位PPT演讲主题.jpg b/src/Others/images/Others/定位PPT演讲主题.jpg new file mode 100644 index 0000000..b500e3b Binary files /dev/null and b/src/Others/images/Others/定位PPT演讲主题.jpg differ diff --git a/src/Others/images/Others/小码短连接.png b/src/Others/images/Others/小码短连接.png new file mode 100644 index 0000000..cabf66e Binary files /dev/null and b/src/Others/images/Others/小码短连接.png differ diff --git a/src/Others/images/Others/打造个人品牌营销.jpg b/src/Others/images/Others/打造个人品牌营销.jpg new file mode 100644 index 0000000..a4ad4db Binary files /dev/null and b/src/Others/images/Others/打造个人品牌营销.jpg differ diff --git a/src/Others/images/Others/时间管理-四象限法则.png b/src/Others/images/Others/时间管理-四象限法则.png new file mode 100644 index 0000000..b2dc452 Binary files /dev/null and b/src/Others/images/Others/时间管理-四象限法则.png differ diff --git a/src/Others/images/Others/显示工具条.png b/src/Others/images/Others/显示工具条.png new file mode 100644 index 0000000..64ec1ad Binary files /dev/null and b/src/Others/images/Others/显示工具条.png differ diff --git a/src/Others/images/Others/独立思考的三条法则.jpg b/src/Others/images/Others/独立思考的三条法则.jpg new file mode 100644 index 0000000..75e2e5f Binary files /dev/null and b/src/Others/images/Others/独立思考的三条法则.jpg differ diff --git a/src/Others/images/Others/番茄工作法.jpeg b/src/Others/images/Others/番茄工作法.jpeg new file mode 100644 index 0000000..8a72fdd Binary files /dev/null and b/src/Others/images/Others/番茄工作法.jpeg differ diff --git a/src/Others/images/Others/精简发言的3个重点.jpg b/src/Others/images/Others/精简发言的3个重点.jpg new file mode 100644 index 0000000..165ca18 Binary files /dev/null and b/src/Others/images/Others/精简发言的3个重点.jpg differ diff --git a/src/Others/images/Others/自我介绍公式MTV.jpg b/src/Others/images/Others/自我介绍公式MTV.jpg new file mode 100644 index 0000000..a6b6a73 Binary files /dev/null and b/src/Others/images/Others/自我介绍公式MTV.jpg differ diff --git a/src/Others/images/Others/讲出好故事的HIT大发.jpg b/src/Others/images/Others/讲出好故事的HIT大发.jpg new file mode 100644 index 0000000..6e98b0c Binary files /dev/null and b/src/Others/images/Others/讲出好故事的HIT大发.jpg differ diff --git a/src/Others/images/Others/设置鼠标悬浮提示.png b/src/Others/images/Others/设置鼠标悬浮提示.png new file mode 100644 index 0000000..4ec24ff Binary files /dev/null and b/src/Others/images/Others/设置鼠标悬浮提示.png differ diff --git a/src/Others/images/Others/顶级演讲者的素养.jpg b/src/Others/images/Others/顶级演讲者的素养.jpg new file mode 100644 index 0000000..667e95d Binary files /dev/null and b/src/Others/images/Others/顶级演讲者的素养.jpg differ