本文是线上问题处理案例系列之一,旨在通过真实案例向读者介绍发现问题、定位问题、解决问题的方法。本文讲述了从垃圾回收耗时过长的表象,逐步定位到数据库连接池保活问题的全过程,并对其中用到的一些知识点进行了总结。
大促期间,某接口超时次数增多,经排查直接原因是GC耗时过长,查看监控FullGC达500ms以上,接口超时时间与FullGC发生时间吻合。
图1 FullGC耗时监控
1、 GC耗时过长,说明内存中垃圾对象很多。
2、 首先怀疑是否有内存泄漏,观察FullGC后堆内存回收情况,尚属正常,暂时排除内存泄漏原因。
图2 发生FullGC后堆内存回收监控
3、 推断FullGC耗时过长是否因为老年代有大量死亡对象,遂导出FullGC前后堆内存dump,通过比对“保留大小”,发现FullGC后大量数据库相关对象被回收。
图3 堆内存对象分析
4、 数据库连接正常应该不会频繁创建和断开,进入老年代后,正常不应该被回收,通过堆dump内容OQL分析每个数据库连接数量,发现很多库连接数都大于“maxActive”数量,可以肯定有很多失效连接。
5、 初步判断直接原因是很多失效数据库连接进入老年代,导致FullGC耗时过长。
6、 怀疑连接池验证周期过长,导致数据库因空闲过长关闭连接,将连接池参数“
timeBetweenEvictionRunsMillis”由1分钟调整到10秒,问题依旧。
7、 阅读DBCP源码,发现是通过
org.apache.commons.pool.impl.GenericObjectPool.Evictor定时任务,按照timeBetweenEvictionRunsMillis配置的周期定时驱逐失效连接,驱逐条件:若连接空闲时间大于“minEvictableIdleTimeMillis”,则会驱逐连接,等待垃圾回收。若开启“testWhileIdle”则会执行“validationQuery”。进一步阅读代码,发现执行“validationQuery”后,连接空闲时间并不会重新计算,导致连接在业务低谷时很容易被淘汰,而数据库连接会关联大量对象,创建、回收成本昂贵,并且影响GC。
8、 反向思考,为何只有在大促期间才发生问题?
图4 平时和大促时回收频率对比
可以看到平时由于业务量小,GC不频繁,过期连接没有达到进入老年代阈值,在年轻代被回收。而大促时业务量大,GC频繁,连接在进入老年代以后才过期,导致老年代FullGC时间过长。
9、 至此,基本可以肯定问题原因是数据库连接池不具备“保活”能力,导致连接不断淘汰和新建,在业务高峰时段,连接进入老年代然后失效,造成FullGC耗时过长,最终导致接口超时次数增多。
方案1:改为G1回收器,对老年代回收是分块进行,可以防止长时间停顿。另外默认MaxTenuringThreshold值是15,可以防止失效连接过早进入老年代;
方案2:
minEvictableIdleTimeMillis设置为0,使数据库连接不会自动失效,进入老年代以后一直存活,避免在老年代失效回收;
数据库连接池并不具备通常理解的“保活”能力,数据库连接在业务不活跃的应用中,会不断淘汰和重连,而连接会通过虚引用方式(
com.mysql.jdbc.NonRegisteringDriver$ConnectionPhantomReference)携带大量对象,如果连接存活时间内YGC次数达到寿命阈值,则会进入老年代,老年代是使用“标记-清除”算法,回收成本更高,进而造成FullGC耗时过长。
1、 Druid连接池同样存在不能“保活”问题,较新版本提供“KeepAlive”选项(未验证);
2、 Druid连接池配置的“validationQuery”语句通常并不会被执行,MySqlValidConnectionChecker在检查连接有效性时,会判断驱动是否实现pingInternal方法,如果实现则会通过此方法验证有效性。MySQL的JDBC驱动实现了该方法,因此“validationQuery”配置的语句通常不会执行;
图5 连接有效性校验代码
3、 DBCP和Druid连接池默认都是FILO,如果业务不繁忙,会导致只有最前边的连接被使用-归还-使用,后边连接基本都在无谓的驱逐、重建连接;
4、 虚引用对GC的影响:这些引用只有经过两次GC才能被回收掉,如果进入老年代,则必须经过两次FullGC才能释放内存。本例中由于不断有新的虚引用对象在老年代失效,导致FullGC后,内存水位仍然偏高,会加剧GC压力。新版本JVM已对此做了优化,一次GC可以回收掉;
5、 类似的影响还有finalize方法;
6、 CMS回收器默认MaxTenuringThreshold为6,而ParallelGC和G1均默认15;
本文对数据库连接失效引起的GC问题进行了详细分析,希望读者通过本文对数据库连接“保活”机制、GC问题基本分析方法有所收益,后续该系列文章会继续推出其他案例分享。
作者:京东零售 王利辉
内容来源:京东云开发者社区
Updatefailed @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @WARNING:REMOTEHOSTIDENTIFICATIONHASCHANGED!@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ITISPOSSIBLETHATSOMEONEISDOINGSOMETHINGNASTY! Someonecouldbeeavesdroppingonyourightnow(man-in-the-middleattack)! Itisalsopossiblethatahostkeyhasjustbeenchanged. ThefingerprintfortheRSAkeysentbytheremotehostis SHA256:LN13BX1ApST5JIibTwZ5IUQOpPFr8DcJnAxYEYWNdrk. Pleasecontactyoursystemadministrator. Addcorrecthostkeyin/c/
Flutter颜值大师基于Flutter+百度人工智能开发出的一款测颜值的App。最重要的一点:一颗满怀学习热情的心项目核心知识点1.渲染头部区域// 头部 AppBar 区域 appBar: AppBar( title: Text( "人脸识别", // 设置标题文字样式 style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), // 设置标题居中显示 centerTitle: true, )复制2.渲染多个浮动按钮正常情况下,一个页面中,通过floatingActionButton选项,默认只能渲染一个浮动按钮。如果需要渲染多个浮动按钮,可以通过ButtonBar控件来实现,代码示例如下:floatingActionButton: ButtonBar( // alignment 属性用来指定子元素如何在横轴上进行排列 // MainAxisAlignment.spaceAround 表示分散对齐 alignment: MainAxisAlignm
如今越来越多的网站需要用户登录才能访问更多的内容和进行更多的操作,使得要想采集这些网站的数据,自动化登录是一个必不可少的操作。最初的登录页面只需要输入用户名和密码即可登录。到后来为了防止机器人恶意登录,开始在登录页面上添加数字验证码、英文数字验证码、数学算数验证码。再之后,各种变态的验证码开始出现,比如滑块、拼图、勾选物品等验证码。但是在深度学习的介入下,绕过这些验证码也不是难事。再到后来,越来越多的网站开始在登录的时候需要进行手机短信验证码验证了。处理短信验证码的逻辑如何自动处理短信验证码呢?我们将这个问题解剖一下,其实主要涉及一个最关键的问题:如何获取到短信验证码?自动处理短信验证码的流程有3个部分:在发送短信验证码环节,我们可以直接使用Selenium之类的工具对短信发送按钮进行模拟点击。在输入短信验证码环节,我们同样可以直接使用Selenium之类的自动化测试工具对页面表单进行填充。一个卡壳的点在于如何获取到发送的短信验证码,毕竟验证码与网页不在同一个载体之上,解决了这个问题,就解决了短信验证码的问题。如何获取到短信验证码 如何解决这个问题?我们其实可以设计一个「中间件」或者是
自然语言是指人类相互交流的语言,而自然语言处理是将数据以可理解的形式进行预处理,使计算机能够理解的一种方法。简单地说,自然语言处理(NLP)是帮助计算机用自己的语言与人类交流的过程。自然语言处理是最广泛的研究领域之一。许多大公司在这个领域投资很大。NLP为公司提供了机会,让他们能够根据消费者的情绪和文本很好地了解他们。NLP的一些最佳用例是检测假电子邮件、对假新闻进行分类、情感分析、预测你的下一个单词、自动更正、聊天机器人、个人助理等等。解决任何NLP任务前要知道的7个术语标记:它是将整个文本分割成小标记的过程。占卜是根据句子和单词两个基础来完成的。text="Hellothere,howareyoudoingtoday?Theweatherisgreattoday.pythonisawsome" ##sentecetokenize(Separatedbysentence) ['Hellothere,howareyoudoingtoday?','Theweatherisgreattoday.','pythonisa
作者:HelloGitHub-追梦人物[1]文中所涉及的示例代码,已同步更新到HelloGitHub-Team仓库[2]我们完成了对blog应用和comment应用这两个核心app的测试。现在我们想知道的是究竟测试效果怎么样呢?测试充分吗?测试全面吗?还有没有没有测到的地方呢? 单凭肉眼观察难以回答上面的问题,接下来我们就借助Coverage.py,从代码覆盖率的角度来检测一下我们的测试效果究竟如何。Coverage.py(以下简称Coverage)是Python测试界最为流行的一个库之一,用来统计测试覆盖率。测试覆盖率可以从一个角度衡量代码的质量,覆盖率越高,说明测试越充分,代码出现bug的几率也就越小。当然需要注意的是,测试覆盖率仅仅只是衡量代码质量的一个角度,即使是100%的覆盖率也不能说代码就是完美的,没有bug的。安装Coverage要使用Coverage,首先当然是安装它:$pipenvinstallcoverage--dev 复制因为只在开发时才用得到,所以使用Pipenv安装时加--dev选项将其标记为开发时的依赖库。简单配置CoverageCoverage支持很多配置
前几天微信公开课十年之约,相信不少童鞋都看了直播,在一个半小时的演讲中,张小龙把绝大部分时间花在了讲解视频号和直播上,因为在他看来,视频化表达将会成为下一个十年内容领域的主题,同时也透露了新版本8.0的功能。目前只有ios更新了8.0版本,安卓应该也会更新,但是已经有内测版本了,想要提前体验的童鞋可以底部公众号后台回复【内测】即可获取哦。作为安卓党的我也是下载了体验版体验了一番,那我们来看看8.0有啥炸裂的功能吧:1、开场启动动画,还是一如既往的文艺,这也契合公开课上所说的:微信十年,如果非要用两个词来描述微信,我想,一个是连接,一个是简单。没错就是简单在这里插入图片描述2、表情,最受瞩目的应该就是微信默认表情,全都动起来了,最好玩的就是【烟花】【庆祝】【炸弹】动态效果非常炫酷,来感受一下在这里插入图片描述3、状态,还记得QQ的状态显示吧,8.0.0微信也上线了类似的功能,可以选择自己喜欢的状态,包括还可以看到有多少朋友跟你在同一状态。在这里插入图片描述4、优化了浮窗样式,新版浮窗的展现方式和位置变了,浮窗固定在微信主界面左上角【…】,要打开浮窗,只能回到微信主界面,点击【…】,打开浮
5.8多态 上面我们了解了向上转型,即一个对象变量可以引用本类及子类的对象实例,这种现象称为多态(polymorphism)。多态究竟有什么用呢?我们先学习一个知识点。5.8.1方法重写 前面我们学习类与对象的时候,学习过方法重载(overload),方法重载指的是在同一个类,存在多个方法名相同,但是方法签名不同的现象。 方法重写是啥呢?我们先看一个问题。Gun类有单发的方法:publicvoidshoot(){ System.out.println("单发"); }复制对于狙击枪AWM来说,射击的子弹是7.62mm子弹,不想只输出“单发”两个字,而是想输出“发射7.62mm子弹”。那么怎么办呢?可以在AWM类中重新写定义一个一模一样的方法,然后重写方法体:publicvoidshoot(){ System.out.println("发射7.62mm子弹"); }复制这种在子类中重新定义一个和超类相同方法签名的操作,称为方法重写(override)。这里需要注意一个问题,就是构造方法是不能被重写的,因为构造方法不能被继承
冒泡排序:比较两个相邻的项,如果第一个大于第二个则交换他们的位置,元素项向上移动至正确的顺序,就好像气泡往上冒一样冒泡demo:functionbubbleSort(arr){ letlen=arr.length; for(leti=0;i<len;i++){ for(letj=0;j<len-1-i;j++){ if(arr[j]>arr[j+1]){//相邻元素两两对比 [arr[j+1],arr[j]]=[arr[j],arr[j+1]]; } } } returnarr; }复制快速排序:1)首先,在数组中选择一个中间项作为主元2)创建两个指针,左边的指向数组第一个项,右边的指向最后一个项,移动左指针,直到找到一个比主元大的项,接着,移动右边的指针,直到找到一个比主元小的项,然后交换它们。重复这个过程,直到左侧的指针超过了右侧的指针。这个使比主元小的都在左侧,比主元大的都在右侧。这一步叫划分操作3)接着,算法对划分后的小数组(较主元小的值组成的的小数组,以及较主元大的值组成的小数组)重复之前的两个步骤,直到排序完成快速排序demo:functionquickS
nginx在应用程序中的作用解决跨域请求过滤配置gzip负载均衡静态资源服务器 #正向代理与反向代理代理在服务器和客户端之间假设的一层服务器将接收客户端的请求并将它转发给服务器,然后将服务端的响应转发给客户端:::tip正向代理是一个位于客户端和原始服务器(originserver)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。为我们服务的,即为客户端服务的,客户端可以根据正向代理访问到它本身无法访问到的服务器资源。对我们是透明的,对服务端是非透明的,即服务端并不知道自己收到的是来自代理的访问还是来自真实客户端的访问。 ::::::tip反向代理是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。为服务端服务的,反向代理可以帮助服务器接收来自客户端的请求,帮助服务器做请求转发,负载均衡等。对服务端是透明的,对我们是非透明的,即我们并不知道自己
Go基本类型布尔型:bool 长度:1字节取值范围:true,false注意事项:不可以用数字代表true或false整型:int/uint 根据运行平台可能为32或64位8位整型:int8/uint8 长度:1字节取值范围:-128~127/0~255字节型:byte(uint8别名)16位整型:int16/uint16 长度:2字节取值范围:-32768~32767/0~6553532位整型:int32(rune)/uint32 长度:4字节取值范围:-2^32/2~2^32/2-1/0~2^32-164位整型:int64/uint64 长度:8字节取值范围:-2^64/2~2^64/2-1/0~2^64-1浮点型:float32/float64 长度:4/8字节小数位:精确到7/15小数位复数:complex64/complex128 长度:8/16字节足够保存指针的32位或64位整数型:uintptr其它值类型: array、struct、string引用类型: slice、map、chan接口类型:inteface函数类型:func类型零值零值并不等于空值,而是当变量被声明为
WordPress网站建设中,固定链接设置是必不可少的,好的固定链接更美观、易用、利于用户分享和搜索引擎收录,需要注意的是,要使设置的固定链接生效的前提是你的网站环境支持伪静态。常用的参数有 日期和名称型/%year%/%monthnum%/%day%/%postname%/月份和名称型/%year%/%monthnum%/%postname%/数字型/archives/%post_id%文章名/%postname%/ID+html型/%post_id%.html很多站长在玩WordPress的时候,可能会碰到一个问题,就是想把WordPress伪静态,在后台设置好固定链接之后,就会出现文章页面或者所有的页面都出现404错误。下面就提供各种web环境下的WordPress伪静态规则设置教程。Apache伪静态规则 Apache是Linux主机下常见的环境,现在一般的Linux虚拟主机都采用这种环境。新建一个htaccess.txt文件,添加下面的代码:<IfModulemod_rewrite.c> RewriteEngineOn RewriteBase/ RewriteRu
ROS1云课→04功能包消息类似各类编程语言中的变量和常量等,ROS1中消息分为:主题消息服务消息行动消息主题消息ROS1使用了一种简化的消息类型描述语言来描述ROS节点发布的数据值。通过这样的描述语言,ROS1能够使用多种编程语言生成不同类型消息的源代码。ROS提供了很多预定义消息类型。如果创建了一种新的消息类型,那么就要把消息的类型定义放到功能包的msg/文件夹下。在该文件夹中,有用于定义各种消息的文件。这些文件都以.msg为扩展名。消息类型必须具有两个主要部分:字段(fields)和常量(constants)。字段定义了要在消息中传输的数据类型,例如int32、float32、string或之前创建的新类型,如叫做type1和type2的新类型。常量用于定义字段的名称。一个msg文件的示例如下:int32idfloat32velstringname颜色案例(rgb):在下表中找到很多ROS消息所使用的标准数据类型:Primitivetype基本类型Serialization序列化C++C++PythonPythonbool(1)unsigned8-bitintuint8_t(2)
注意:该破解补丁未经过广泛测试 前提概要 1、该补丁,仅涉及以下产品,所有版权归Xamarin所有,仅供学习练手: ①Xamarin.iOS8.10.2.37Xamarin.iOS8.10.3.2(我去,搞好了才发现官网竟然悄悄又更新了,为了支持Xcode6.4和IOS8.4) ②Xamarin.Android5.1.4.16 ③Xamarin.Mac2.0.2.35 ④XamarinStudio5.9.4.5 ReleaseNotes Xamarin.iOS8.10.3.2 原版下载链接:monotouch-8.10.3.2.pkg ,度盘备份 ReleaseNotes:简略、详细 Xamarin.Android5.1.4.16 原版下载链接:mono-android-5.1.4-16.pkg ,度盘备份 ReleaseNotes:简略、详细 Xamarin.Mac2.0.2.35 原版下载链接:xamarin.mac-2.0.2.35.pkg ,度盘备份 ReleaseNotes:简略、详细 破解说明 1、提升本地权限到最高
在本文中,将给大家介绍如何使用autoconf和automake两个工具来帮助我们自动地生成符合自由软件惯例的Makefile,这样就可以象常见的GNU程序一样,只要使用“./configure”,“make”,“makeinstall”就可以把程序安装到Linux系统中去了。这将特别适合想做开放源代码软件的程序开发人员,又或如果你只是自己写些小的Toy程序,那么这个文章对你也会有很大的帮助。 编译一个简单的源文件main.c,需要自动生成一个makefile,以下是步骤: 第一步: ---------- 在/root/project/main目录下创建一个文件main.c,其内容如下: ------------------------------------------------ #include<stdio.h> intmain(intargc,char**argv) { printf("Hello,AutoMakefile!\n"); return0; } ------------------------------------------------ 此时状态如下
生命周期函数 相当于是一种特殊事件,当vm实例在整个运行的过程中,会在不同的时期去执行特定的函数,这样的函数就是vue的生命周期函数 beforeCreatecreatedbeforeMountmounteddestory/x这些钩子都只执行一次 beforeUpdateupdated第一次构建不会调用,以后每次data被更新了就会调用 beforeDestroydestroyed销毁的方式有两种:用户关闭和代码 this.$destroy()//销毁vm实例 newVue({ el:"#app", data:{ msg:"hello", url:"66666", count:0 }, methods:{ des(){ this.$destroy() }, change1(){ this.count++ this.url="https://img1.baidu.com/it/u=1966616150,2146512490&
1基本概念 1.1Callable与Future Runnable封装一个异步运行的任务,可以把它想象成为一个没有参数和返回值的异步方法。Callable与Runnable类似,但是有返回值。Callable接口是一个参数化的类型,只有一个方法call。 publicinterfaceCallable<V>{ Vcall()throwsException; } 复制 类型参数是返回值的类型。例如, Callable<Integer>表示一个最终返回Integer对象的异步计算。 复制 Future保存异步计算的结果。可以启动一个计算,将Future对象交给某个线程,然后忘掉它。Future对象的所有者在结果计算好之后就可以获得它。 Future接口具有下面的方法: publicinterfaceFuture<V>{ booleancancel(booleanmayInterruptIfRunning); booleanisCancelled(); booleanisDone(); Vget()throwsInterruptedExcepti
前言 (1)下载RedisGitHub地址: https://github.com/redis/redis/tags (2)将下载后的Redis安装包通过Xftp上传到Linux(home目录下) (3)查看Redis是否已上传成功 输入:cd/home--进入到home目录下 输入:ls-s--查看home目录下的文件列表复制 (4)将下载好的Redis移动到opt目录下 输入:mvredis-6.0.0.tar.gz/opt--移动到opt目录下复制 (5)解压Redis tar-zxvfredis-6.0.0.tar.gz复制 (6)解压完成 输入:ls-l--查看解压情况复制 (7)进入解压后的文件,查看解压目录 输入:cdredis-6.0.0 输入:ls-l复制 (8)基本的运行环境安装 输入:yuminstallgcc-c++复制 (9)安装完毕 (10)输入命令查看gcc版本 输入:gcc-v复制 (11)安装make用于环境变量配置 输入:make--安装make复制 (12)此处出现报错,错误原因是gcc版本太低,安装Re
编程标准(CodingStandard) FreeRTOS源代码遵守MISRA(MotorIndustrySoftwareReliabilityAssociation)规范。 与MISRA标准有出入的地方如下: •两个API函数具有两个出口点。之所以这样是为了效率。 •使用标准C数据类型,而不是用typedef将其名称重定义。 •当建立一个任务时,代码会直接处理堆栈的栈顶和栈底地址。由于不同的平台的总线宽度不同,这就需要代码中对指针变量进行算术运算。因此,对指针变量的算术运算是不可避免的。 •trace宏定义,默认情况下被定义为空,因此不会产生任何代码。 命名约定(NamingConventions) RTOS内核与Demo程序源代码使用下面的约定: 变量char类型的变量以c为前缀short类型的变量以s为前缀long类型的变量以l为前缀float类型的变量以f为前缀double类型的变量以d为前缀枚举变量以e为前缀其他类型(如结构体)以x为前缀指针有一个额外的前缀p,例如