USDT第三方支付

菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

原题目:常见线上故障的最优解法,运维老司机也未必都懂

许多人在面试时,会被问到这样的问题:遇到过什么系统故障?怎么解决的?下面是笔者凭据自己15年互联网研发履历总结的多个线上故障真实案例。

本文图不多,但内容很干!明白为主,学以致用!

故障一:JVM频仍FULL GC快速排查

在分享此案例前,先聊聊哪些场景会导致频仍Full GC:

  1. 死循环。
  2. 大工具。

尤其是大工具,80%以上的情形就是他。

那么大工具从哪里来的呢?

  1. 数据库(包罗MySQL和MongoDB等NoSQL数据库),效果集太大。
  2. 第三方接口传输的大工具。
  3. 新闻行列,新闻太大。

凭据多年一线互联网履历,绝大部门情形是数据库大效果集导致。

好,现在我们最先先容这次线上故障:

在没有任何公布的情形下,POP服务(接入第三方商家的服务)突然最先疯狂Full GC,考察堆内存监控没内存泄露,回滚到前一版本,问题仍然存在,尴尬了!!!

根据通例做法,一样平常先用jmap导出堆内存快照(jmap -dump:format=b,file=文件名 [pid]),然后用mat等工具剖析出什么工具占用了大量空间,再查看相关引用找到问题代码。这种方式定位问题周期会对照长,若是是要害服务,长时间不能定位解决问题,影响太大。

下面来看看我们的做法:

先根据通例做法剖析堆内存快照,与此同时另外的同学去查看数据库服务器网络IO监控,若是数据库服务器网络IO有显著上升,而且时间点吻合,基本可以确定是数据库大效果集导致了Full GC,赶快找DBA快速定位大SQL(对DBA来说很简朴,分分钟搞定,若是DBA不知道怎么定位,那他要被开除了,哈哈),定位到SQL后再定位代码就异常简朴了。

根据这种设施,我们很快定位了问题。原来是一个接口必传的参数没传进来,也没加校验,导致SQL语句where后面少了两个条件,一次查几万条纪录出来,真坑啊!这种方式是不是要快许多,哈哈,5分钟搞定。

那时的DAO层是基于Mybatis实现的,出问题的SQL语句如下:

<select id="selectOrders" resultType="com.***.Order" >

select * from user where 1=1

<if test=" orderID != null ">

and order_id = #{orderID}

</if >

<if test="userID !=null">

and user_id=#{userID}

</if >

<if test="startTime !=null">

and create_time >= #{createTime}

</if >

<if test="endTime !=null">

and create_time <= #{userID}

</if >

</select>

上面SQL语句意思是凭据orderID查一个订单,或者凭据userID查一个用户所有的订单,两个参数至少要传一个。然则两个参数都没传,只传了startTime和endTime。以是一次Select就查出了几万条纪录。

以是我们在使用Mybatis的时刻一定要慎用if test,一不小心就会带来灾难。厥后我们将上面的SQL拆成了两个:

凭据订单ID查询订单:

<select id="selectOrderByID" resultType="com.***.Order" >

select * from user where

order_id = #{orderID}

</select>

凭据userID查询订单:

<select id="selectOrdersByUserID" resultType="com.***.Order" >

select * from user where

user_id=#{userID}

<if test="startTime !=null">

and create_time >= #{createTime}

</if >

<if test="endTime !=null">

and create_time <= #{userID}

</if >

</select>

故障二:内存泄露

先容案例前,先领会一下内存泄露和内存溢出的区别。

内存溢出:程序没有足够的内存使用时,就会发生内存溢出。内存溢出后程序基本上就无法正常运行了。

内存泄露:当程序不能实时释放内存,导致占用内存逐渐增添,就是内存泄露。内存泄露一样平常不会导致程序无法运行。不外连续的内存泄露,累积到内存上限时,就会发生内存溢出。在Java中,若是发生内存泄露,会导致GC接纳不彻底,每次GC后,堆内存使用率逐渐增高。

下图是JVM发生内存泄露的监控图,我们可以看到每次GC后堆内存使用率都比以前提高了:

图片泉源于网络

那时内存泄露的场景是,用内陆缓存(公司基础架构组自己研发的框架)存放了商品数据,商品数目不算太多,几十万的样子。若是只存热门商品,内存占用不会太大,然则若是存放全量商品,内存就不够了。

初期我们给每个缓存纪录都加了7天的过时时间,这样就可以保证缓存中绝大部门都是热门商品。不外厥后内陆缓存框架经由一次重构,过时时间被去掉了。没有了过时时间,日积月累内陆缓存越来越大,许多冷数据也被加载到了缓存。

直到有一天接到告警短信,提醒堆内存过高。赶快通过jmap(jmap -dump:format=b,file=文件名 [pid] )下载了堆内存快照,然后用eclipse的mat工具剖析快照,发现了内陆缓存中有大量的商品纪录。定位问题后赶快让架构组加上了过时时间,然后逐个节点重启了服务。

亏了我们加了服务器内存和JVM堆内存监控,实时发现了内存泄露的问题。否则随着泄露问题日积月累,若是哪天真的OOM就惨了。

以是手艺团队除了做好CPU,内存等运维监控,JVM监控也异常重要。

故障三:幂等问题

许多年前,笔者在一家大型电商公司做Java程序员,那时开发了积分服务。那时的营业逻辑是,用户订单完结后,订单系统发送新闻到新闻行列,积分服务接到新闻后给用户积分,在用户现有的积分上加上新发生的积分。

由于网络等缘故原由会有新闻重复发送的情形,这样也就导致了新闻的重复消费。那时笔者照样个初入职场的小菜鸟,并没有考虑到这种情形。以是上线后偶然会泛起重复积分的情形,也就是一个订单完结后会给用户加两次或多次积分。

厥后我们加了一个积分纪录表,每次消费新闻给用户增添积分前,先凭据订单号查一遍积分纪录表,若是没有积分纪录才给用户增添积分。这也就是所谓的“幂等性”,即多次重复操作不影响最终的效果。

现实开发中许多需要重试或重复消费的场景都要实现幂等,以保证效果的正确性。例如,为了制止重复支付,支付接口也要实现幂等。

故障四:缓存雪崩

我们经常会遇到需要初始化缓存的情形。好比,我们曾经履历过用户系统重构,用户系统表结构发生了转变,缓存信息也要变。重构完成后上线前,需要初始化缓存,将用户信息批量存入Reids。

每条用户信息缓存纪录过时时间是1天,纪录过时后再从数据库查询最新的数据并拉取到Redis中。灰度上线时一切正常,以是很快就全量公布了。整个上线历程异常顺遂,码农们也很开心。

不外,第二天,灾难发生了!到某一个时间点,种种报警络绎不绝。用户系统响应突然变得异常慢,甚至一度没有任何响应。查看监控,用户服务CPU突然飙高(IO wait很高),MySQL接见量激增,MySQL服务器压力也随之暴增,Reids缓存命中率也跌到了极点。

依赖于我们壮大的监控系统(运维监控,数据库监控,APM全链路性能监控),很快定位了问题。缘故原由就是Reids中大量用户纪录集中失效,获取用户信息的请求在Redis中查不到用户纪录,导致大量的请求穿透到数据库,瞬间给数据库带来伟大压力。同时用户服务和相关联的其他服务也都受到了影响。

这种缓存集中失效,导致大量请求同时穿透到数据库的情形,就是所谓的“缓存雪崩”。若是没到缓存失效时间点,性能测试也测不出问题。以是一定要引起人人注重。

以是,需要初始化缓存数据时,一定要保证每个缓存纪录过时时间的离散性。例如,我们给这些用户信息设置过时时间,可以接纳一个较大的固定值加上一个较小的随机值。好比过时时间可以是:24小时 + 0到3600秒的随机值。

故障五:磁盘IO导致线程壅闭

问题发生在2017年下半年,有一段时间地理网格服务时不常的会响应变慢,每次连续几秒钟到几十秒钟就自动恢复。

若是响应变慢是连续的还好办,直接用jstack抓线程客栈,基本可以很快定位问题。要害连续时间只有最多几十秒钟,而且是偶发的,一天只发生一两次,有时几天才发生一次,发生时间点也不确定,人盯着然后用jstack手工抓线程客栈显然不现实。

好吧,既然手工的设施不现实,咱们就来自动的,写一个shell剧本自动准时执行jstack,5秒执行一次jstack,每次执行效果放到差别日志文件中,只保留20000个日志文件。

Shell剧本如下:

#!/bin/bash

num=0

log="/tmp/jstack_thread_log/thread_info"

cd /tmp

if [ ! -d "jstack_thread_log" ]; then

mkdir jstack_thread_log

fi

while ((num <= 10000));

do

ID=`ps -ef | grep java | grep gaea | grep -v "grep" | awk '{print $2}'`

if [ -n "$ID" ]; then

jstack $ID >> ${log}

,

Usdt第三方支付接口

菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

,

fi

num=$(( $num + 1 ))

mod=$(( $num%100 ))

if [ $mod -eq 0 ]; then

back=$log$num

mv $log $back

fi

sleep 5

done

下一次响应变慢的时刻,我们找到对应时间点的jstack日志文件,发现内里有许多线程壅闭在logback输出日志的历程,厥后我们精简了log,而且把log输出改成异步,问题解决了,这个剧本果真好用!建议人人保留,以后遇到类似问题时,可以拿来用!

故障六:数据库死锁问题

在剖析案例之前,我们先领会一下MySQL InnoDB。在MySQL InnoDB引擎中主键是接纳聚簇索引的形式,即在B树的叶子节点中既存储了索引值也存储了数据纪录,即数据纪录和主键索引是存在一起的。

而通俗索引的叶子节点存储的只是主键索引的值,一次查询找到通俗索引的叶子节点后,还要凭据叶子节点中的主键索引去找到聚簇索引叶子节点并拿到其中的详细数据纪录,这个历程也叫“回表”。

故障发生的场景是关于我们商城的订单系统。有一个准时义务,每一小时跑一次,每次把所有一小时前未支付订单作废掉。而客服后台也可以批量作废订单。

订单表t_order结构大至如下:

id

订单id,主键

status

订单状态

created_time

订单建立时间

id是表的主键,created_time字段上是通俗索引。

聚簇索引(主键id)。

id(索引)

status

created_time

1

UNPAID

2020-01-01 07:30:00

2

UNPAID

2020-01-01 08:33:00

3

UNPAID

2020-01-01 09:30:00

4

UNPAID

2020-01-01 09:39:00

5

UNPAID

2020-01-01 09:50:00

通俗索引(created_time字段)。

created_time(索引)

id(主键)

2020-01-01 09:50:00

5

2020-01-01 09:39:00

4

2020-01-01 09:30:00

3

2020-01-01 08:33:00

2

2020-01-01 07:30:00

1

准时义务每一小时跑一次,每次把所有一小时前两小时内的未支付订单作废掉,好比上午11点会作废8点到10点的未支付订单。SQL语句如下:

update t_order set status = 'CANCELLED' where created_time > '2020-01-01 08:00:00' and created_time < '2020-01-01 10:00:00' and status = 'UNPAID'

客服批量作废订单SQL如下:

update t_order set status = 'CANCELLED' where id in (2, 3, 5) and status = 'UNPAID'

上面的两条语句同时执行就可能发生死锁。我们来剖析一下缘故原由。

第一条准时义务的SQL,会先找到created_time通俗索引并加锁,然后再在找到主键索引并加锁。

第一步,created_time通俗索引加锁。

第二步,主键索引加锁。

第二条客服批量作废订单SQL,直接走主键索引,直接在主键索引上加锁。

我们可以看到,准时义务SQL对主键加锁顺序是5,4,3,2。客服批量作废订单SQL对主键加锁顺序是2,3,5。当第一个SQL对3加锁后,正准备对2加锁时,发现2已经被第二个SQL加锁了,以是第一个SQL要守候2的锁释放。

而此时第二个SQL准备对3加锁,却发现3已经被第一个SQL加锁了,就要守候3的锁释放。两个SQL相互守候对方的锁,也就发生了“死锁”。

解决设施就是从SQL语句上保证加锁顺序一致。或者把客服批量作废订单SQL改成每次SQL操作只能作废一个订单,然后在程序里多次循环执行SQL,若是批量操作的订单数目不多,这种笨设施也是可行的。

故障七:域名挟制

先看看DNS剖析是怎么回事,当我们接见www.baidu.com时,首先会凭据www.baidu.com到DNS域名剖析服务器去查询百度服务器对应的IP地址,然后再通过http协议接见该IP地址对应的网站。

而DNS挟制是互联网攻击的一种方式,通过攻击域名剖析服务器(DNS)或者伪造域名剖析服务器,把目的网站域名剖析到其他的IP。从而导致请求无法接见目的网站或者跳转到其他网站。如下图:

下面这张图是我们曾经履历过的DNS挟制的案例:

看图中的红框部门,原本上方的图片应该是商品图片,然则却显示成了广告图片。是不是图片配错了?不是,是域名(DNS)被挟制了。

原本应该显示存储在CDN上的商品图片,然则被挟制之后却显示了其他网站的广告链接图片。由于那时的CDN图片链接接纳了不平安的http协议,以是很容易被挟制。厥后改成了https,问题就解决了。

固然域名挟制有许多方式,https也不能规避所有问题。以是,除了一些平安防护措施,许多公司都有自己的备用域名,一旦发生域名挟制可以随时切换到备用域名。

故障八:带宽资源耗尽

带宽资源耗尽导致系统无法接见的情形,虽然不多见,然则也应该引起人人的注重。来看看,之前遇到的一起事故。

场景是这样的。社交电商每个分享出去的商品图片都有一个唯一的二维码,用来区分商品和分享者。以是二维码要用程序天生,最初我们在服务端用Java天生二维码。

前期由于系统接见量不大,系统一直没什么问题。然则有一天运营突然搞了一次优惠力度空前的大促,系统瞬时接见量翻了几十倍。问题也就随之而来了,网络带宽直接被打满,由于带宽资源被耗尽,导致许多页面请求响应很慢甚至没任何响应。

缘故原由就是二维码天生数目瞬间也翻了几十倍,每个二维码都是一张图片,对带宽带来了伟大压力。

怎么解决呢?若是服务端处置不了,就考虑一下客户端。把天生二维码放到客户端APP处置,充分利用用户终端手机,现在Andriod,IOS或者React都有相关天生二维码的SDK。

这样不只解决了带宽问题,而且也释放了服务端天生二维码时消耗的CPU资源(天生二维码历程需要一定的盘算量,CPU消耗对照显著)。

外网带宽异常昂贵,我们照样要省着点用啊!

本文分享的案例都是笔者的亲身履历,希望对列位读者有所辅助。

作者丨二马念书

泉源丨民众号:二马念书(ID:ermadushu)

Allbet Gaming声明:该文看法仅代表作者自己,与www.allbetgame.us无关。转载请注明:usdt充值(www.caibao.it):常见线上故障的最优解法,运维老司机也未必都懂
发布评论

分享到:

usdt回收(www.caibao.it):杨清珑确定接秘书长 蔡其昌视他为偶像
2 条回复
  1. UG环球
    UG环球
    (2021-02-10 00:08:45) 1#

    来看看他季后赛的数据。11场竞赛,场均出战19.1分钟,场均获得3.6分2.5篮板1.4助攻0.9抢断,命中率48.4%不算低,但三分命中率只有31.6%,场均只能投中0.5个三分球,威胁异常有限。而3.6分的得分也是伊戈达拉季后赛生涯的新低,要知道,他在2004-05赛季就最先加入季后赛。而在最近4场竞赛里,他场均进场15分钟,但一共才获得9分,其中2场一分未得。没废话,我喜欢

    1. 以太坊彩票网
      以太坊彩票网
      (2021-04-09 14:32:55)     

      www.allbet8.us欢迎进入欧博平台网站(Allbet Gaming),Allbet Gaming开放欧博平台网址、欧博注册、欧博APP下载、欧博客户端下载、欧博真人游戏(百家乐)等业务。一定持续创作啊

发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。