• Microchip推出具备代码集成功能的开源电力传输软件,助力实现USB系统差异化

    Microchip推出具备代码集成功能的开源电力传输软件,助力实现USB系统差异化

    支持电力传输(PD)功能的USB Type-C®和开源软件是引领下一波有线连接潮流的两种技术。借助Microchip Technology Inc.(美国微芯科技公司)推出的全新电力传输软件框架(PSF),设计人员现在可以在他们的USB-C®电力传输系统中修改并拥有IP。通过将他们的专有代码与Microchip的全功能PD协议栈相结合,设计人员可灵活地创建差异化产品,同时为其USB系统选择各种Microchip 智能集线器(SmartHub)、单片机(MCU)和独立PD决方案。 Microchip PSF解决方案提供一个用于电力传输的开源代码库和一个全面的编程环境,消除了对制造商的依赖,用户可以很方便地对MCU进行编程,并随着系统的升级及时修改PD代码。 利用这一引领行业变革的解决方案,客户可以缩短产品上市时间,减少总体物料清单(BOM),从而掌握自己产品的开发。 利用软件和硬件框架,开发人员还可以从Microchip新推出的控制器系列产品中进行选择,以拥有PD功能,包括新推出的UPD301B 和 UPD301C独立PD控制器。 PD架构的开放性使客户可以轻松地将USB-C / PD端口添加到各种嵌入式应用中,同时还允许客户将未使用的引脚或CPU存储器重新分配给其他系统功能,并支持多种Microchip SAM和PIC®单片机以及dsPIC®数字信号控制器(DSC)。通过添加UPD350 PD收发器或将PD集成到具有专有系统代码的复杂产品中,PSF解决方案为设计人员提供了在现有Microchip 单片机基础架构上运行PD的选项。 Microchip USB和网络业务部副总裁Charles Forni表示:“有了我们新的PD软件框架,所有支持USB-C的Microchip 单片机和独立控制器现在都可以共享相同的PD代码库。这些代码免费提供给客户,易于配置和修改,使我们的客户能够自行实施新功能和更新系统,而无需通过制造商定制代码。 Microchip的PSF产品改变了将USB-C PD集成到客户系统中的方式。” 开发工具 Microchip的MPLAB® X IDE开发环境支持PSF软件解决方案。 PSF评估板搭载SAMD20 单片机和UPD350 PD PHY,现已供货。 供货与定价 Microchip的开源电力传输软件框架(PSF)可在Microchip官网免费下载。UPD301C现已上市,10,000枚起订的单价为1.50美元。 如需了解更多信息,请联系Microchip销售代表、全球授权分销商或访问Microchip网站。

    Microchip Microchip USB 电力传输

  • 我写了一个脚本,可在“任意”服务器上执行命令!

    冰河之前维护着上千台服务器组成的服务器集群,如果每次需要在服务器上执行命令的时候,都要手动登录每台服务器进行操作的话,那也太麻烦了。你想想,如果在上千台服务器的集群中,每台服务器中只需要简单的执行一个相同的命令,那别说执行命令了,就是让你依次手动登录上千台服务器,那也够你受的了。估计依次登录上千台服务器,给你三天时间你可能都登不完,那怎么办呢?有没有什么好的方法来解决这个问题呢? 别急,我们今天就是来解决这个问题的。 说实话,我在维护上千台服务器集群的时候,并没有去依次手动登录每台服务器,为啥?没错,就是因为我懒啊!我懒的去登录,并且依次登录那么多台服务器,整个人都会崩溃的。 于是,我就想办法能不能写个脚本,让这个脚本接收我要执行的命令,然后将命令依次分发到集群上所有的服务器中执行,这不就解决问题了吗?说干就干。 不过,这里,有个需要注意的地方:那就是:需要提前配置好集群中每台服务器的主机名和IP地址的对应关系,能够互相使用主机名进行通信,并配置了SSH免密码登录。这一点不行担心,只要让运维在规划和分配服务器的时候,规划好就行了,无需后面再依次登录服务器处理。 为了方便小伙伴们理解,这里我们就假设集群中存在1024台服务器,每台服务器的主机名为binghe1~binghe1024。每台服务器可以通过主机名进行通信,接下来,我写了一个名称为distribute_command.sh的脚本,内容如下所示。 ./distribute_command.sh 在服务器上执行的完整命令 使用示例 在集群中的每台服务器的/home目录下创建hello.txt文,内容为hello world ./distribute_command.sh rm -rf /home/hello.txt 是不是很简单啊?所以说,有时候,不要盲目的去执行。很多时候,在做事情之前,要先思考下有没有更好的解决方案,有没有效率更加高效的解决方案。就比如这篇文章上说的,在上千台服务器上执行一条命令,如果依次手动登录每台服务器执行命令,估计花三天时间都搞不定;如果我们写了一个脚本的话,估计也就1分钟之内就搞定了。所以,效率和质量才是做事情需要追求的目标。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 服务器 集群 脚本

  • 金三银四,写个漂亮的技术简历

    金三银四跳槽季马上就要来了,最近招聘和求职市场明显火热了。 这几天有些朋友找我内推工作,我也使劲推了一波。不过我发现大家的简历还是需要修饰一下,虽然有些朋友已经工作多年了,但是简历里面依然看不出招聘团队最直接关心的问题。 这篇文章我来提一些简历中需要注意的地方。 必须要有的内容 1.姓名/性别/出生年月 姓名性别就不说了,必须让招聘公司知道吧。 出身年月有的人不愿意写,这样敏感的HR会猜测求职者年龄是否太大了,比如好多公司不愿意招聘35岁以上的程序员。既然大家都知道这回事,那不如写明白,这样不会浪费彼此的时间。 年龄大的程序员也不用太担心,肯定有机会的。我身边35岁以后去了阿里的人有的是啊。 2.工作城市 期望在哪个城市工作,写明白了有好处,会更加精准。 3.邮箱/电话/微信 邮箱电话必须有吧,不然HR怎么联系你呢? 微信写一个最好了,谁愿意在上班的时候总接到招聘公司打来的电话,然后匆匆跑到外面说话。 4.贴个照片 带点美颜,给求职公司一个好印象。 5.教育经历 要写的明明白白清清楚楚。其实很简单,就是下面这个格式: 2008/09-2011/04 泰山大学 本科 计算机科学与技术 有的同学中间断过层,比如毕业后又花了1年的时间复习考研没成,然后求职的,没事,加上一个标注,写清楚。 6.工作经历 也是要写清楚明白。推荐格式如下: 公司名称:xxx公司 工作时间:2016/05-今 工作岗位:高级研发工程师 工作内容:技术选型、系统设计、编码 工作产出:独自完成了某平台的xxx模块的设计和开发工作,累计提交代码5万行。 1.有的同学可能是工作几年后转的开发,怕简历被淘汰,但是背调阶段HR肯定会知道的。无需隐瞒。 2.实习经历也可以写上。 7.项目经历 这个是必须写的,面试官会根据项目来提问题,所以要写清楚,但是也要有点技巧,多写自己非常熟悉的地方。 下面是一个模板。 项目名称:大规模租赁平台建设项目描述:从0到1构建了租赁平台,该平台…项目时间:2014/06-今开发环境:idea+jdk8 +maven3+git使用框架:springboot+mybatis消息中间件:rabbitmq缓存:redis数据库:mysql+mongodb分布式中间件:seata部署环境:Nginx+k8s集群+docker/虚机混跑注册中心和网关:eureka + zuul个人参与工作:技术选型架构设计核心代码编写指导初中级工程师 有的项目太短,比如就两三个月,可以合并一下,不一定项目写越多越好 锦上添花 自我评价 可以写在教育经历前面,让面试官一眼看到,可以分开技术能力和业务能力来写。 比如: 技术方面: 擅长java/golang,对分布式有一定研究。 业务方面 熟悉信贷核心系统,熟悉征信相关业务。 开源社区 比如:docker社区commiter,这就很加分。建议写到教育经历前面。 博客地址 比如贴个公众号二维码,这也很加分。建议写到教育经历前面。 兴趣爱好 建议写到项目经验后面,这个可有可无,没有坏处,比如恰好一个团队有跑步文化,而自己热爱跑步,会是一个加分项。 最后 面试是一场持久战,简历就是自己的门面,对获得面试机会有很重要的作用。写一份简洁清晰的简历,至少不要让面试官反感。 有的同学可能故意隐瞒一些经历,想进入大厂。这个有人成功过,但是很难。其实也没有必要,公司那么多,找一个适合自己的平台最重要了。 当然,也不能太老实,比如我就想试试某些公司的面试,积累点面试经验,那简历你就自由发挥吧。 简历只是一个门面,硬核的专业技能和广泛的人脉才是王道。 最后的最后,运气也很重要,不过机会多数还是给有准备的人。加油。

    架构师社区 面试 简历 内推

  • 从2012到2021,从土木到程序员

    记得那是2012年的夏天 高考前我知道与清北无缘 高考完985也是相距甚远 打算选好专业再背水一战 但是迷茫的状态持续不断 好像我的挚爱就是金钱 于是到网吧百度了三天 发现土木工程毕业年入十万 于是就把土木放到志愿首选 就这样,我进了充满阳刚之气和尚班 就这样,我成了选错专业的最佳示范 因为自知出身贫贱 大一兼职从来不断 发传单送外卖还有饭店洗锅刷碗 更不要提深夜站岗到凌晨四点半 后来觉得这些工作谁都能干 迷茫的我常常夜里思绪万千 后来遇到学长问我做不做网站 他从互联网思维讲到o2o闭环 又从互联网营销讲到生态化反 我当场决定改变世界拯救人间 甚至入股我奖学金的两千块钱 虽然对网站的了解只有看书听歌 顺便品鉴日本电影贴吧分享经验 我们梦想纳斯达克敲钟上市圈钱 虽然团队现在只有我们两名成员 为了推广网站我们设计海报贴满校园 贴开贴去我发现这个活还是谁都能干 理想很丰满现实很骨感 团队在壮大预算在缩减 以及 海报太丑 功能太少 网站太慢 请外包费用太高我们付不起尾款 只缺少程序员的团队真的很可怜 为了早日能到纳斯达克敲钟圈钱 我思来想去决定自学设计和前端 为了早日上市我努力自学天天肝到两点 虽然啥都不会但是安慰自己有成长空间 没想到我的设计和审美能力天生缺陷 学了好久还是只能打几个字画几个圈 便放弃PS开始学习前端 从HTML CSS学到JS语言 从jq学到研究网上开源组件 做出来的效果终于还算入眼 可是兼容es6搞得我有点烦 而且我发现要做网站还得学会后端 前后端一把梭才配是野路子程序员 于是从网上搜了搜买了本PHP实战 是的我就是要学世界上最好的语言 什么数据结构什么算法靠边站 我要的就是三天开发一周上线 从变量声明学到for循环 从类的创建学到mvc概念 不懈努力做出了留言板 感叹增删改查其实不难 然而现在依然靠增删改查吃饭 转眼我已学了土木三年 唉我的本专业真的很惨 原本想的是毕业就年薪十万 谁知刚毕业的也就月入三千 而且这份工作你还爱干不干 每天工地一天奋斗一线 完事冲澡睡觉又到明天 别人工作只是无聊两点一线 我们还很危险处于生死之间 想了想还是写代码比较安全 最多也就是996和35岁红线 起码不会干着活突然被祭天 现在看来我还是想的太简单 想清楚我决定自己开发个网站 包括登陆注册文章发表与查看 前后端全部搞定毕竟我是全栈 做完之后放到GitHub开了个源 信心大增我可以闯闯美好明天 我决定到北京一试长短 找个实习工作应该不难 后来投遍简历我才发现 只有创业公司表示意愿 我不怪自己的简历入不了大厂筛选 我只想对他们说毕业土木我很抱歉 思虑万千还是来到前往北京的车站 去往北京火车挤得很满 坐着睡觉的我美梦不断 当火车开入北京那一刻 还记得正好是清晨六点 嘴边口水是梦想的垂涎 当阳光洒在我的帅脸上 我知道方向就在我前边 第一家面试的公司就坐落在西二旗周边 有点荒凉但却是中国互联网的半壁江山 只记得路上的风一直在侵扰我的发际线 我觉得在这工作能实现技术大牛的夙愿 面试来面试去,有一道题很常见 就是我为啥不干土木想做程序员 那一刻我不像程序员像一个演员 配合面试官演出的我对土木前景视而不见 都是因为爱好都是因为天赋都是因为有缘 人生挚爱怎能放弃即便转行也有美好明天 不知不觉在北京已经面了几天 从西二旗到望京到处兜兜转转 几家小公司实习offer纠结万千 根据办公环境技术水平综合来看 我毫不犹豫选择给钱最多的那个 并认为此行圆满 想到我选择土木原因也是变有钱 我只想说 我还是从前那个少年 真的没有一丝丝改变 实习了两个月说长不长说短不短 工作压力没有多大毕竟我是全栈 可是每当深夜矫情站在阳台吸烟 看着不远处的公司腾讯滴滴微软 真的好想入职大厂掀起新的一篇 实习结束回到学校是大学最后一年 我也得开始为自己的未来做个打算 土木就算了毕竟整个行业都很艰难 我又没有颜值找个老板女儿吃软饭 思来想去还是当个程序员比较简单 虽然我的简历想去中厂都过不了关 数据结构算法都没学过感觉要玩完 痛定思痛我买了本剑指offer开始看 发现这个不是屠龙之术确实可实战 从数组中找出不重复数字到单链表有没有环 越来越觉得PHP好像不是最好的语言 学来学去发现我不是全栈 只不过是会点前端和后端 代码优化缓存处理架构设计没有概念 只是简简单单把功能实现然后上个线 想到这我决定先把知识沉淀 只会皮毛功夫难入大厂法眼 有offer还得把内功修炼一番 于是大四逃课经常坐在图书馆 不是刷算法就是准备毕业答辩 期间还囊中羞涩实习了100天 不再详细表述因为都tm搬砖 终于到了大学毕业庆典 依然还没有offer的我竟然觉得比较悠闲 可能是因为土木专业毕业找工作的太惨 互联网实习多次也给我带来很多安全感 最起码毕业不会直接当中介销售卖保险 拿着学位证的我站在镜子前 那一刻觉得前尘往事成云烟 消散在彼此眼前 发了一条格外伤感的朋友圈 对社会说你好对朋友说再见 头也不回的离开校园 那一年 是2016年 背着行李来到北京开始一面二面 这次面试难度大了不是一点两点 会让我说说数据结构比如堆和栈 接着讲讲数据库索引的底层实现 最后和HR聊理论怎么结合和实践 面来面去最后成功入职中厂后端 春风得意的我像走到了人生之巅 我开始了每天挤地铁两点一线 虽然不是996但是也经常加班 生活最开心的事情是项目上线 心情轻松以及产品给买的甜点 最不开心的是技术方案还没定 老板说下周就是就是上线期限 接下来很忙很累而且压力空前 就这样迷迷糊糊的过了一年 开发功能也觉得越来越简单 每天接需求写代码提测上线 我有毛病竟然觉得没成就感 我说不行我得到大厂看一看 于是又开始了一轮刷题备战 这次投简历没有之前那么烦 估计是因为我有了一年经验 最起码大厂给机会让我一面 最后去了tmd一家入职后端 原本想的是进了大厂更值钱 技术氛围好使我每日开心颜 但是好多东西真就像驴粪蛋 依然增删改查只是表面光鲜 大厂也会996也会突然裁员 大厂没定方案就定上线期限 老板说不努力就是落后一员 我想了想这应该就是tm内卷 螺丝钉只有业务逻辑的实现 只能抽时间学习顺便在工作实践 每天的生活真像一个循环 一遍又一遍 每天还要和产品撕逼和运营撕逼负能量满满 也搞不懂都是打工的为啥相互为难 你的努力价值可能就是老板跑车引擎跑出来的一缕烟 我觉得我真得换个活法不然每晚失眠 好吧那段时间我确实很消极很悲观 人生很漫长我觉得不止只顾眼前 还是要拓宽视野路才能越走越宽 想清楚后工作很忙但是动力满满 工作完复习判断单链表有没有环 和三年前相比得到面试的机会更加简单 甚至还有猎头帮我找面试机会让我心安 这次面试有失败也有胜利凯旋 拿了几个offer纠结了好几晚 看薪水,看加班还看发展 不再像之前那样只考虑当下便已圆满 还得考虑未来尽量两全 算下来我已经在新公司呆了将近一年 同事都不错工作也有成就感 拿到好的offer凭实力也有运气使然 故事讲到这里其实还没有完 从外包到大厂,从土木到程序员 其实还有很多事情可以谈 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 程序员 后端 全栈

  • 提升电动汽车无线设备品质的测试解决方案

    提升电动汽车无线设备品质的测试解决方案

    随着5G通信与车联网发展,电动汽车逐渐升级为集自动驾驶、泊车与充电等为一体的智能电动汽车。当前电动汽车有线充电方式太过繁琐,无法满足智能电动汽车的自动充电的应用需要,这就给电动汽车无线发展提供了绝佳机遇。电动汽车无线充电相比有线充电具备得天独厚优势---超高的充电便利、无人值守后期维护成本低、占地小空间利用率高等,甚至能够解决当前电动汽车的续航焦虑。 电动汽车大功率无线充电设备常采用磁场共振式,与电动汽车通讯握手适配后,通过电磁场将能量传送至智能电动汽车接收到的能量设备,并对电池充电实现电动汽车能量补给,补给完成后自动断开充电。电动汽车无线充电设备功率通常为3~22kW,输入交流电压为180~270VAC,输出电压范围为200~ 900V DC。在研发、认证与生产等环节均需要可编程交流电源提供正常或异常的供电对电动汽车无线设备严格测试验证。 电动汽车无线充电设备对可编程交流电源的要求: 1. 输出宽范围电压与频率调节,并且精准的电压与频率输出; 2. 具备模拟电网波动功能(如List编程功能),可实现电压与频率同时变化; 3. 具备三相不平衡、谐波合成功能; 电动汽车无线充电设备的测试拓扑图 电动汽车无线充电设备的测试项目与设备 PSA6000系列高性能可编程交流电源是具有高精度、宽范围输出的电网模拟输出设备,输出功率2~21kVA,输出频率超过5000Hz,支持自校正输出以显著提升输出精度,集成丰富的前沿应用解决方案,为电子产品性能测试与品质验证提供多种类型的正常或异常供电工况,配备完善的保护功能(OVP/OCP/OPP/OTP 等),可轻松应对研发、认证、生产检验等阶段的复杂测试挑战,适用于消费电子、信息与通信技术、新能源与航空电子等领域。

    致远电子 无线充电 电动汽车 可编程交流电源

  • 直观讲解一下RPC调用和HTTP调用的区别

    作者:浮生忆梦 来源:blog.csdn.net/m0_38110132/article/details/81481454 很长时间以来都没有怎么好好搞清楚RPC(即Remote Procedure Call,远程过程调用)和HTTP调用的区别,不都是写一个服务然后在客户端调用么?这里请允许我迷之一笑~Naive! 本文简单地介绍一下两种形式的C/S架构,先说一下他们最本质的区别,就是RPC主要是基于TCP/IP协议的,而HTTP服务主要是基于HTTP协议的,我们都知道HTTP协议是在传输层协议TCP之上的,所以效率来看的话,RPC当然是要更胜一筹啦!下面来具体说一说RPC服务和HTTP服务。 OSI网络七层模型 在说RPC和HTTP的区别之前,我觉的有必要了解一下OSI的七层网络结构模型(虽然实际应用中基本上都是五层),它可以分为以下几层:(从上到下) 第一层:应用层。定义了用于在网络中进行通信和传输数据的接口; 第二层:表示层。定义不同的系统中数据的传输格式,编码和解码规范等; 第三层:会话层。管理用户的会话,控制用户间逻辑连接的建立和中断; 第四层:传输层。管理着网络中的端到端的数据传输; 第五层:网络层。定义网络设备间如何传输数据; 第六层:链路层。将上面的网络层的数据包封装成数据帧,便于物理层传输; 第七层:物理层。这一层主要就是传输这些二进制数据。 实际应用过程中,五层协议结构里面是没有表示层和会话层的。应该说它们和应用层合并了。我们应该将重点放在应用层和传输层这两个层面。因为HTTP是应用层协议,而TCP是传输层协议。好,知道了网络的分层模型以后我们可以更好地理解为什么RPC服务相比HTTP服务要Nice一些! RPC服务 从三个角度来介绍RPC服务:分别是RPC架构,同步异步调用以及流行的RPC框架。 RPC架构 先说说RPC服务的基本架构吧。允许我可耻地盗一幅图哈~我们可以很清楚地看到,一个完整的RPC架构里面包含了四个核心的组件,分别是Client ,Server,Client Stub以及Server Stub,这个Stub大家可以理解为存根。分别说说这几个组件: 客户端(Client),服务的调用方。 服务端(Server),真正的服务提供者。 客户端存根,存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。 服务端存根,接收客户端发送过来的消息,将消息解包,并调用本地的方法。 RPC主要是用在大型企业里面,因为大型企业里面系统繁多,业务线复杂,而且效率优势非常重要的一块,这个时候RPC的优势就比较明显了。实际的开发当中是这么做的,项目一般使用maven来管理。 比如我们有一个处理订单的系统服务,先声明它的所有的接口(这里就是具体指Java中的interface),然后将整个项目打包为一个jar包,服务端这边引入这个二方库,然后实现相应的功能,客户端这边也只需要引入这个二方库即可调用了。为什么这么做?主要是为了减少客户端这边的jar包大小,因为每一次打包发布的时候,jar包太多总是会影响效率。另外也是将客户端和服务端解耦,提高代码的可移植性。 同步调用与异步调用 什么是同步调用?什么是异步调用?同步调用就是客户端等待调用执行完成并返回结果。异步调用就是客户端不等待调用执行完成返回结果,不过依然可以通过回调函数等接收到返回结果的通知。如果客户端并不关心结果,则可以变成一个单向的调用。 这个过程有点类似于Java中的callable和runnable接口,我们进行异步执行的时候,如果需要知道执行的结果,就可以使用callable接口,并且可以通过Future类获取到异步执行的结果信息。如果不关心执行的结果,直接使用runnable接口就可以了,因为它不返回结果,当然啦,callable也是可以的,我们不去获取Future就可以了。 流行的RPC框架 目前流行的开源RPC框架还是比较多的。下面重点介绍三种: gRPC是Google最近公布的开源软件,基于最新的HTTP2.0协议,并支持常见的众多编程语言。我们知道HTTP2.0是基于二进制的HTTP协议升级版本,目前各大浏览器都在快马加鞭的加以支持。这个RPC框架是基于HTTP协议实现的,底层使用到了Netty框架的支持。 Thrift是Facebook的一个开源项目,主要是一个跨语言的服务开发框架。它有一个代码生成器来对它所定义的IDL定义文件自动生成服务代码框架。用户只要在其之前进行二次开发就行,对于底层的RPC通讯等都是透明的。不过这个对于用户来说的话需要学习特定领域语言这个特性,还是有一定成本的。 Dubbo是阿里集团开源的一个极为出名的RPC框架,在很多互联网公司和企业应用中广泛使用。协议和序列化框架都可以插拔是及其鲜明的特色。同样 的远程接口是基于Java Interface,并且依托于spring框架方便开发。可以方便的打包成单一文件,独立进程运行,和现在的微服务概念一致。 偷偷告诉你集团内部已经不怎么使用dubbo啦,现在用的比较多的叫HSF,又名“好舒服”。后面有可能会开源,大家拭目以待。 HTTP服务 其实在很久以前,我对于企业开发的模式一直定性为HTTP接口开发,也就是我们常说的RESTful风格的服务接口。的确,对于在接口不多、系统与系统交互较少的情况下,解决信息孤岛初期常使用的一种通信手段;优点就是简单、直接、开发方便。 利用现成的http协议进行传输。我们记得之前本科实习在公司做后台开发的时候,主要就是进行接口的开发,还要写一大份接口文档,严格地标明输入输出是什么?说清楚每一个接口的请求方法,以及请求参数需要注意的事项等。 接口可能返回一个JSON字符串或者是XML文档。然后客户端再去处理这个返回的信息,从而可以比较快速地进行开发。 但是对于大型企业来说,内部子系统较多、接口非常多的情况下,RPC框架的好处就显示出来了,首先就是长链接,不必每次通信都要像http一样去3次握手什么的,减少了网络开销;其次就是RPC框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作。 总结 RPC服务和HTTP服务还是存在很多的不同点的,一般来说,RPC服务主要是针对大型企业的,而HTTP服务主要是针对小企业的,因为RPC效率更高,而HTTP服务开发迭代会更快。 总之,选用什么样的框架不是按照市场上流行什么而决定的,而是要对整个项目进行完整地评估,从而在仔细比较两种开发框架对于整个项目的影响,最后再决定什么才是最适合这个项目的。一定不要为了使用RPC而每个项目都用RPC,而是要因地制宜,具体情况具体分析。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 RPC RPC调用 HTTP调用

  • 编码编成翔的十八般兵器

    今天愚人节,可以皮一下,可以开点玩笑,所以我决定这篇文章开启嘲讽模式。 程序员最怕读别人的代码,比这个更可怕的是什么? 从别人那里接手一个老项目 前任程序员或者是编码能力不行,或者是跳槽之前故意摆烂……于是,一个隐藏着一堆烂摊子的项目,扔给了后来接手的人。 本来以前是代码里夹翔,后来就是翔夹代码了。 这些翔有各种各样的风味,其中就有那么十八种味道最是冲人。 1. 块里堆上我满满的翔 Java 中有着无数的语句块,这些语句块可以嵌套。于是我们有很多优秀的产翔大师会在这些语句块中不断地嵌套,犹如无数层的俄罗斯套娃。 2. 把翔藏在注释里,有时候它会“惊艳”了世界 有些哥们儿很鸡贼的把一些代码藏在注释里,这些代码可以随时成为定时炸弹。 public class Base { public int field = 0; public int getField() { return field;   } } public class EmptyCatchBlockTest { public static void main(String[] args) { try { int a = 4, b = 0; int c = a/b;     } catch(ArithmeticException ae) { // ??? }   } } 对不起,兄弟,你留下这种薛定谔的处理是想让人帮你掀桌吗? 5. 只要我不考虑任何意外的情况,那么项目就一定会出意外 有些直性子的人,认为天下万物都可以直来直去,就好像直男只会让女生“多喝热水”一样。所以,他们写的代码非常直率,直接就不考虑意外情况。 public DateTime override Add(TimeSpan ts) { try { return base.Add(ts);   } catch (ArgumentOutOfRangeException nb) { // calculate how much the MaxValue is exceeded // regular program flow TimeSpan saldo = ts - (base.MaxValue - this); return DateTime.MinValue.Add(saldo)   } catch(Exception anyOther) { // 'real' exception handling. } } 我就想问问,如果以异常来控制流程,那么如何在这些异常中寻找真正的异常情况? 8. 为了我走之前不出意外,我要捕获所有的 NPE 有些哥们儿会把 NPE 捕获住,恩,不解决问题,但是把提出问题的人给解决了。

    架构师社区 编码 程序员

  • 精通Zookeeper系列开篇:进大厂不得不学的分布式协同利器!

    最近,有很多小伙伴让我更新一些Zookeeper的文章,正好也趁着清明假期把之前自己工作过程当中总结的Zookeeper知识点梳理了一番,打算写一个【精通Zookeeper系列】,希望能够帮助小伙伴们更好的理解和掌握Zookeeper。 今天是【精通Zookeeper系列】的开篇,我们先来简单的介绍下本篇文章的总体结构内容。 为何要学Zookeeper? 好了,我们直入主题吧,很多小伙伴可能都会问一个问题:为什么要学习Zookeeper呢? Zookeeper是一个开源的分布式协同服务系统,在业界的应用非常广泛,虽然最近几年有Consul、etcd、Nacos等分布式协同系统问世,但是Zookeeper依然是最主流的分布式协同服务系统。Zookeeper也是一个设计的非常成功的软件系统,从Zookeeper最初按照预想的需求场景进行设计实现到现在,Zookeeper的对外API,在基本上没有改变的前提下,在越来越广泛的领域得到应用,通过学习Zookeeper,小伙伴们可以熟悉Zookeeper中成功的设计和研发思路,提升自己的系统设计水平。另外,Zookeeper是使用Java语言开发的,通过学习Zookeeper,小伙伴们还可以积累使用Java研发系统级软件的实战经验。 另外,Zookeeper的应用场景十分广泛,例如:大数据领域中,Hadoop集群、Storm集群、Kafka集群、Spark集群、Flink集群、Flume集群等主流的大数据分析平台,在集群化的场景中,推荐使用Zookeeper作为集群环境中的分布式协同服务。在分布式和微服务领域中,Dubbo、SpringCloud、分布式锁、分布式序列号服务、RPC服务等框架和技术,也能够通过Zookeeper进行实现。 很多大厂在面试过程中,也要求深入掌握Zookeeper技术,所以,学好Zookeeper还是很有必要的。 Zookeeper很难吗? 说实话,大多数技术人员,都可以很快的上手Zookeeper,但是大部分都是局限于基于现有的Zookeeper协同服务示例做一些简单的修改和定制。如果要具备为自己的业务场景设计Zookeeper协同服务的能力,就需要深刻理解Zookeeper的内部工作原理,还要做大量的协同服务设计的积累和总结。理解Zookeeper的内部工作原理,需要学习大量的计算机理论知识,这些理论知识包括:分布式系统、数据库系统和操作系统。找到和学习这些知识点,需要耗费大量的时间。 在即将要连载的【精通Zookeeper系列】的文章中,会专门介绍学习Zookeeper需要学习的计算机理论知识,帮助小伙伴们迅速建立起对Zookeeper内部原理和机制的理解。 学习Zookeeper收获大不大? 在【精通Zookeeper系列】中,我们首先介绍Zookeeper的基础知识,然后就是高阶的原理和源代码剖析等内容。在介绍基础知识的时候,会结合代码多介绍些实战性的案例,也会介绍一些分布式系统的基本概念。高阶的内容主要介绍Zookeeper的内部原理和相关的源码实现。到时也会对Zookeeper和etcd进行简单的对比,以帮助小伙伴们更好的理解和掌握Zookeeper。 除了掌握Zookeeper本身的技术之外,冰河也要让你学到以下知识: 如何设计一个本地数据节点 分布式环境中节点之间如何通讯 如何从0到1设计一个RPC子系统 如何使用数据一致性协议保证数据的高可用 如何在数据一致性和系统性能之间做取舍 以上这些设计理念基本每个分布式系统都会涉及到,掌握这些分布式系统能够让你更好的理解分布式系统的架构设计,也可以将这些设计理念应用到自己设计和研发的系统当中。 进大厂Zookeeper要学到什么程度? 对于进大厂Zookeeper要学到什么程度?这个问题小伙伴们应该还是比较关心的,简单点说,进大厂,你只是会简单的使用Zookeeper还不行,你要理解Zookeeper的工作原理和底层源码机制。在之前的文章中,我就说过:大厂对于技术的要求高,不是他们故意刁难人。而是大厂的用户量级很大,业务体量很高,如果你不深刻理解原理和源码机制,一旦线上生产环境由于高并发、大流量等场景出现一些偶然的系统问题,你可能就会半天定位不到问题,甚至会一脸懵逼的看着问题反复出现。所以,要想进大厂,就要深刻理解Zookeeper的原理和源码机制。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 分布式 大厂 Zookeeper

  • 为什么李彦宏的这封信会刷屏朋友圈

    架构师社区 百度 李彦宏 上市

  • Java后端线上问题排查常用命令收藏

    本文来源:http://r6d.cn/b97q7 内存瓶颈 free free是查看内存使用情况,包括物理内存、交换内存(swap)和内核缓冲区内存。 free -h -s 3表示每隔三秒输出一次内存情况,命令如下 [1014154@cc69dd4c5-4tdb5 ~]$ free               total        used        free      shared  buff/cache   available Mem:      119623656    43052220    45611364     4313760    30960072    70574408 Swap:             0           0           0 [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(VirtualMeomoryStatistics,虚拟内存统计)是Linux中监控内存的常用工具,可对操作系统的虚拟内存、进程、CPU等的整体情况进行监视,推荐使用。 vmstat 5 3表示每隔5秒统计一次,一共统计三次。 [1014154@cc69dd4c5-4tdb5 ~]$ vmstat 5 3 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st  8  0      0 45453212 374768 30763728    0    0    14    99    1    1 11 10 78  0  1 10  0      0 45489232 374768 30763360    0    0     2  1275 95118 97908 13 11 75  0  1  6  0      0 45452908 374768 30765148    0    0     0  3996 89924 92073 12 10 78  0  1 procs r:表示运行和等待CPU时间片的进程数(就是说多少个进程真的分配到CPU),这个值如果长期大于系统CPU个数,说明CPU不足,需要增加CPU。b:表示在等待资源的进程数,比如正在等待I/O或者内存交换等。 memory swpd:表示切换到内存交换区的内存大小,即虚拟内存已使用的大小(单位KB),如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。free:表示当前空闲的物理内存。buff:表示缓冲大小,一般对块设备的读写才需要缓冲Cache:表示缓存大小,一般作为文件系统进行缓冲,频繁访问的文件都会被缓存,如果cache值非常大说明缓存文件比较多,如果此时io中的bi比较小,说明文件系统效率比较好。 swap si:表示数据由磁盘读入内存;通俗的讲就是每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。so:表示由内存写入磁盘,也就是由内存交换区进入内存的数据大小。 !! 注意:一般情况下si、so的值都为0,如果si、so的值长期不为0,则说明系统内存不足,需要增加系统内存 io bi:表示由块设备读入数据的总量,即读磁盘,单位kb/sbo:表示写到块设备数据的总量,即写磁盘,单位kb/s !! 注意:如果bi+bo的值过大,且wa值较大,则表示系统磁盘IO瓶颈。 system in:表示某一时间间隔内观测到的每秒设备终端数。cs:表示每秒产生的上下文切换次数,这个值要越小越好,太大了,要考虑调低线程或者进程的数目。例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。 !! 注意:这两个值越大,则由内核消耗的CPU就越多。 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等待的原因可能是磁盘大量随机读写造成的,也可能是磁盘或者监控器的贷款瓶颈(主要是块操作)造成的。 sar sar和free类似sar -r 3每隔三秒输出一次内存信息: [root@localhost ~]# sar -r 3 Linux 3.10.0-1062.el7.x86_64 (localhost.localdomain)    2020年04月28日  _x86_64_        (2 CPU) 15时40分10秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty 15时40分13秒    106800   1314960     92.49      2144    573248   4110864    116.82    563664    498888        36 15时40分16秒    106816   1314944     92.49      2144    573248   4110864    116.82    563668    498888        36 15时40分19秒    106816   1314944     92.49      2144    573248   4110864    116.82    563668    498888        36 CPU瓶颈 查看机器cpu核数 CPU总核数 = 物理CPU个数 * 每颗物理CPU的核数  总逻辑CPU数 = 物理CPU个数 * 每颗物理CPU的核数 * 超线程数 查看CPU信息(型号) [1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c      32  Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz 查看物理CPU个数 [1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l 16 查看每个物理CPU中core的个数(即核数) [1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo| grep "cpu cores"| uniq cpu cores       : 2 查看逻辑CPU的个数 [1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo| grep "processor"| wc -l 32 top 在Linux内核的操作系统中,进程是根据虚拟运行时间(由进程优先级、nice值加上实际占用的CPU时间进行动态计算得出)进行动态调度的。在执行进程时,需要从用户态转换到内核态,用户空间不能直接操作内核空间的函数。通常要利用系统调用来完成进程调度,而用户空间到内核空间的转换通常是通过软中断来完成的。例如要进行磁盘操作,用户态需要通过系统调用内核的磁盘操作指令,所以CPU消耗的时间被切分成用户态CPU消耗、系统(内核) CPU 消耗,以及磁盘操作 CPU 消耗。执行进程时,需要经过一系列的操作,进程首先在用户态执行,在执行过程中会进行进程优先级的调整(nice),通过系统调用到内核,再通过内核调用,硬中断、软中断,让硬件执行任务。执行完成之后,再从内核态返回给系统调用,最后系统调用将结果返回给用户态的进程。 top可以查看CPU总体消耗,包括分项消耗,如User,System,Idle,nice等。Shift + H显示java线程;Shift + M按照内存使用排序;Shift + P按照CPU使用时间(使用率)排序;Shift + T按照CPU累积使用时间排序;多核CPU,进入top视图1,可以看到各各CPU的负载情况。 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     55 ymmapp    20   0   17432   1808   1232 S   0.0  0.0   0:00.00 bash     56 ymmapp    20   0   17556   2156   1460 S   0.0  0.0   0:00.03 control.sh     57 ymmapp    20   0   11880    740    576 S   0.0  0.0   0:00.00 tee    115 ymmapp    20   0   17556   2112   1464 S   0.0  0.0   0:00.02 control_new_war    133 root      20   0  106032   4240   3160 S   0.0  0.0   0:00.03 sshd    134 ymmapp    20   0   17080   6872   3180 S   0.0  0.0   0:01.82 ops-updater    147 ymmapp    20   0   17956   2636   1544 S   0.0  0.0   0:00.07 control.sh   6538 ymmapp    20   0  115656  10532   3408 S   0.0  0.0   0:00.46 beidou-agent   6785 ymmapp    20   0 2572996  22512   2788 S   0.0  0.0   0:03.44 gatherinfo4dock  29241 root      20   0  142148   5712   4340 S   0.0  0.0   0:00.04 sshd  29243 1014154   20   0  142148   2296    924 S   0.0  0.0   0:00.00 sshd  29244 1014154   20   0   15208   2020   1640 S   0.0  0.0   0:00.00 bash  32641 1014154   20   0   57364   2020   1480 R   0.0  0.0   0:00.00 top 第一行:15:24:11 up 8 days, 7:52, 1 user, load average: 5.73, 6.85, 7.33:15:24:11 系统时间,up 8 days 运行时间,1 user 当前登录用户数,load average 负载均衡情况,分别表示1分钟,5分钟,15分钟负载情况。 第二行:Tasks: 17 total, 1 running, 16 sleeping, 0 stopped, 0 zombie:总进程数17,运行数1,休眠 16,停止0,僵尸进程0。 第三行:%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%。 第四和第五行表示内存和swap区域的使用情况。 第七行表示: PID: 进程id USER:进程所有者 PR:进程优先级 NI:nice值。负值表示高优先级,正值表示低优先级 VIRT:虚拟内存,进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES RES:常驻内存,进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA SHR:共享内存,共享内存大小,单位kb S:进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程 %CPU:上次更新到现在的CPU时间占用百分比 %MEM:进程使用的物理内存百分比 TIME+:进程使用的CPU时间总计,单位1/100秒 COMMAND:进程名称(命令名/命令行) 计算在cpu load里面的uninterruptedsleep的任务数量 top -b -n 1 | awk '{if (NR<=7)print;else if($8=="D"){print;count++}}END{print "Total status D:"count}' [root@localhost ~]# top -b -n 1 | awk '{if (NR<=7)print;else if($8=="D"){print;count++}}END{print "Total status D:"count}' top - 15:35:05 up 1 day, 26 min,  3 users,  load average: 0.00, 0.01, 0.05 Tasks: 225 total,   1 running, 224 sleeping,   0 stopped,   0 zombie %Cpu(s):  2.5 us, 10.0 sy,  0.0 ni, 87.5 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st KiB Mem :  1421760 total,   104516 free,   777344 used,   539900 buff/cache KiB Swap:  2097148 total,  2071152 free,    25996 used.   456028 avail Mem    PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND Total status D: sar 通过sar -u 3可以查看CUP总体消耗占比: [root@localhost ~]# sar -u 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; 定位线上最耗CPU的线程 准备工作 启动一个程序。arthas-demo是一个简单的程序,每隔一秒生成一个随机数,再执行质因数分解,并打印出分解结果。 curl -O https://alibaba.github.io/arthas/arthas-demo.jar java -jar arthas-demo.jar [root@localhost ~]# curl -O https://alibaba.github.io/arthas/arthas-demo.jar % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                  Dload  Upload   Total   Spent    Left  Speed 100  3743  100  3743    0     0   3022      0  0:00:01  0:00:01 --:--:--  3023 [root@localhost ~]# java -jar arthas-demo.jar 1813=7*7*37 illegalArgumentCount:  1, number is: -180005, need >= 2 illegalArgumentCount:  2, number is: -111175, need >= 2 18505=5*3701 166691=7*23813 105787=11*59*163 60148=2*2*11*1367 196983=3*3*43*509 illegalArgumentCount:  3, number is: -173479, need >= 2 illegalArgumentCount:  4, number is: -112840, need >= 2 39502=2*19751 .... 通过top命令找到最耗时的进程 [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 #pid cu命令,查看某个进程中的线程CPU消耗排序: [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' 98345命令做进制转换: [root@localhost ~]# printf '%x\n' 98345 18029 查看线程堆栈信息 使用jstack获取堆栈信息jstack 98344 | grep -A 10 18029: [root@localhost ~]# jstack 98344 | grep -A 10 18029 "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) grep -C 5 foo file 显示file文件里匹配foo字串那行以及上下5行 grep -B 5 foo file 显示foo及前5行 grep -A 5 foo file 显示foo及后5行 网络瓶颈 定位丢包,错包情况 watch more /proc/net/dev用于定位丢包,错包情况,以便看网络瓶颈,重点关注drop(包被丢弃)和网络包传送的总量,不要超过网络上限: [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可以查看路由经过的地址,常用来统计网络在各个路由区段的耗时,如: [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可以查看网络错误: [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来计算重传率tcpetr=RetransSegs/OutSegs。 [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 重传率=292/223186≈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发送数据报; 磁盘瓶颈 查磁盘空间 查看磁盘剩余空间 查看磁盘剩余空间使用df -hl命令: [root@localhost ~]# df -hl 文件系统                       容量  已用  可用 已用% 挂载点 devtmpfs                       678M     0  678M    0% /dev tmpfs                          695M     0  695M    0% /dev/shm tmpfs                          695M   28M  667M    4% /run tmpfs                          695M     0  695M    0% /sys/fs/cgroup /dev/mapper/centos_aubin-root   27G  5.6G   22G   21% / /dev/sda1                     1014M  211M  804M   21% /boot 查看磁盘已使用空间 du -sh命令是查看磁盘已使用空间的情况,这里的“已使用的磁盘空间”意思是指定的文件下的整个文件层次结构所使用的空间,在没给定参数的情况下,du报告当前目录所使用的磁盘空间。其实就是显示文件或目录所占用的磁盘空间的情况: [root@localhost ~]# du -sh 64K -h:输出文件系统分区使用的情况,例如:10KB,10MB,10GB等。 -s:显示文件或整个目录的大小,默认单位是KB。 !! du的详细信息可以通过man du查看。 查看磁盘读写情况 查看磁盘总体读写情况 通iostat查看磁盘总体的读写情况: [root@localhost ~]# iostat Linux 3.10.0-1062.el7.x86_64 (localhost.localdomain)    2020年05月02日  _x86_64_        (2 CPU) avg-cpu:  %user   %nice %system %iowait  %steal   %idle            0.17    0.00    0.20    0.46    0.00   99.17 Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn sda               1.56        30.45        39.61    4659620    6060644 scd0              0.00         0.02         0.00       3102          0 dm-0              1.96        30.01        38.42    4591998    5878155 dm-1              0.09         0.09         0.30      13840      45328 tps:该设备每秒的传输次数。 kB_read/s:每秒从设备(drive expressed)读取的数据量; kB_wrtn/s:每秒向设备(drive expressed)写入的数据量; kB_read:读取的总数据量; kB_wrtn:写入的总数量数据量; 查看磁盘详细读写情况 通过iostat -x 1 3可以看到磁盘详细读写情况,没隔一秒输出一次一共输出3次,当看到I/O等待时间所占CPU时间的比重很高的时候,首先要检查的就是机器是否正在大量使用交换空间,同时关注iowait占比cpu的消耗是否很大,如果大说明磁盘存在大的瓶颈,同时关注await,表示磁盘的响应时间以便小于5ms: [root@localhost ~]# iostat -x 1 3 Linux 3.10.0-1062.el7.x86_64 (localhost.localdomain)    2020年05月02日  _x86_64_        (2 CPU) avg-cpu:  %user   %nice %system %iowait  %steal   %idle            0.17    0.00    0.20    0.46    0.00   99.16 Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util sda               0.01     0.49    0.63    0.95    30.59    39.78    89.58     0.34  214.23   49.16  323.48   8.55   1.34 scd0              0.00     0.00    0.00    0.00     0.02     0.00    98.48     0.00    1.21    1.21    0.00   0.95   0.00 dm-0              0.00     0.00    0.62    1.35    30.15    38.59    69.70     0.91  460.67   49.12  648.54   6.66   1.31 dm-1              0.00     0.00    0.02    0.07     0.09     0.30     8.52     0.04  442.74   95.43  521.17   6.91   0.06 avg-cpu表示总体cpu使用情况统计信息,对于多核cpu,这里为所有cpu的平均值: %user:CPU处在用户模式下的时间百分比。 %nice:CPU处在带NICE值的用户模式下的时间百分比。 %system:CPU处在系统模式下的时间百分比。 %iowait:CPU等待输入输出完成时间的百分比, 如果%iowait的值过高,表示硬盘存在I/O瓶颈。 %steal:管理程序维护另一个虚拟处理器时,虚拟CPU的无意识等待时间百分比。 %idle:CPU空闲时间百分比, 如果%idle值高,表示CPU较空闲;如果%idle值高但系统响应慢时,可能是CPU等待分配内存,应加大内存容量;如果%idle值持续低于10,表明CPU处理能力相对较低,系统中最需要解决的资源是CPU。。 Device表示设备信息: rrqm/s:每秒对该设备的读请求被合并次数,文件系统会对读取同块(block)的请求进行合并 wrqm/s:每秒对该设备的写请求被合并次数 r/s:每秒完成的读次数 w/s:每秒完成的写次数 rkB/s:每秒读数据量(kB为单位) wkB/s:每秒写数据量(kB为单位) avgrq-sz:平均每次IO操作的数据量(扇区数为单位) avgqu-sz:平均等待处理的IO请求队列长度 await:平均每次IO请求等待时间(包括等待时间和处理时间,毫秒为单位) svctm:平均每次IO请求的处理时间(毫秒为单位) %util:一秒中有百分之多少的时间用于 I/O如果%util接近100%,说明产生的I/O请求太多,I/O系统已经满负荷。idle小于70% IO压力就较大了,一般读取速度有较多的wait。 !! iostat -xmd 1 3:新增m选项可以在输出是使用M为单位。 查看最耗IO的进程 一般先通过iostat查看是否存在io瓶颈,再使用iotop命令来定位那个进程最耗费IO: [root@localhost ~]# iotop Total DISK READ :       0.00 B/s | Total DISK WRITE :       0.00 B/s Actual DISK READ:       0.00 B/s | Actual DISK WRITE:       0.00 B/s    TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND 123931 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.02 % [kworker/1:30]  94208 be/4 xiaolyuh    0.00 B/s    0.00 B/s  0.00 %  0.00 % nautilus-desktop --force [gmain]      1 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % systemd --system --deserialize 62      2 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kthreadd]  94211 be/4 xiaolyuh    0.00 B/s    0.00 B/s  0.00 %  0.00 % gvfsd-trash --spawner :1.4 /org/gtk/gvfs/exec_spaw/0      4 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kworker/0:0H]      6 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [ksoftirqd/0]      7 rt/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [migration/0]      8 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [rcu_bh]      9 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [rcu_sched]     10 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [lru-add-drain] ... 通过iotop -p pid可以查看单个进程的IO情况: [root@localhost ~]# iotop -p 124146 Total DISK READ :       0.00 B/s | Total DISK WRITE :       0.00 B/s Actual DISK READ:       0.00 B/s | Actual DISK WRITE:       0.00 B/s    TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND 124146 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % java -jar arthas-demo.jar 应用瓶颈 查看某个进程的PID 如查看java的进程的pid,ps -ef | grep java: [root@localhost ~]# ps -ef | grep java root     124146   1984  0 09:13 pts/0    00:00:06 java -jar arthas-demo.jar root     125210  98378  0 10:07 pts/1    00:00:00 grep --color=auto java 查看特定进程的数量 如查看java进程的数量,ps -ef | grep java| wc -l: [root@localhost ~]# ps -ef | grep java| wc -l 2 查看线程是否存在死锁 查看线程是否存在死锁,jstack -l pid: [root@localhost ~]# jstack -l 124146 2020-05-02 10:13:38 Full thread dump OpenJDK 64-Bit Server VM (25.252-b09 mixed mode): "C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f27f013c000 nid=0x1e4f9 waiting on condition [0x0000000000000000]    java.lang.Thread.State: RUNNABLE    Locked ownable synchronizers:         - None "C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f27f012d000 nid=0x1e4f8 waiting on condition [0x0000000000000000]    java.lang.Thread.State: RUNNABLE    Locked ownable synchronizers:         - None "main" #1 prio=5 os_prio=0 tid=0x00007f27f004b800 nid=0x1e4f3 waiting on condition [0x00007f27f7274000]    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)    Locked ownable synchronizers:         - None ... 查看某个进程的线程数 ps -efL | grep [PID] | wc -l,如: [root@localhost ~]# ps -efL | grep 124146 | wc -l 12 查看具体有哪些线程用ps -Lp [pid] cu: [root@localhost ~]# ps -Lp 124146 cu USER        PID    LWP %CPU NLWP %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND root     124146 124146  0.0   11  2.5 2489116 35724 pts/0   Sl+  09:13   0:00 java root     124146 124147  0.0   11  2.5 2489116 35724 pts/0   Sl+  09:13   0:01 java root     124146 124148  0.0   11  2.5 2489116 35724 pts/0   Sl+  09:13   0:00 VM Thread root     124146 124149  0.0   11  2.5 2489116 35724 pts/0   Sl+  09:13   0:00 Reference Handl root     124146 124150  0.0   11  2.5 2489116 35724 pts/0   Sl+  09:13   0:00 Finalizer root     124146 124151  0.0   11  2.5 2489116 35724 pts/0   Sl+  09:13   0:00 Signal Dispatch root     124146 124152  0.0   11  2.5 2489116 35724 pts/0   Sl+  09:13   0:00 C2 CompilerThre root     124146 124153  0.0   11  2.5 2489116 35724 pts/0   Sl+  09:13   0:00 C1 CompilerThre root     124146 124154  0.0   11  2.5 2489116 35724 pts/0   Sl+  09:13   0:00 Service Thread root     124146 124155  0.1   11  2.5 2489116 35724 pts/0   Sl+  09:13   0:05 VM Periodic Tas root     124146 125362  0.0   11  2.5 2489116 35724 pts/0   Sl+  10:13   0:00 Attach Listener 统计所有的log文件中,包含Error字符的行 find / -type f -name "*.log" | xargs grep "ERROR",这个在排查问题过程中比较有用: [root@localhost ~]# find / -type f -name "*.log" | xargs grep "ERROR" /var/log/tuned/tuned.log:2020-03-13 18:05:59,145 ERROR    tuned.utils.commands: Writing to file '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' error: '[Errno 19] No such device' /var/log/tuned/tuned.log:2020-03-13 18:05:59,145 ERROR    tuned.utils.commands: Writing to file '/sys/devices/system/cpu/cpu1/cpufreq/scaling_governor' error: '[Errno 19] No such device' /var/log/tuned/tuned.log:2020-04-28 14:55:34,857 ERROR    tuned.utils.commands: Writing to file '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' error: '[Errno 19] No such device' /var/log/tuned/tuned.log:2020-04-28 14:55:34,859 ERROR    tuned.utils.commands: Writing to file '/sys/devices/system/cpu/cpu1/cpufreq/scaling_governor' error: '[Errno 19] No such device' /var/log/tuned/tuned.log:2020-04-28 15:23:19,037 ERROR    tuned.utils.commands: Writing to file '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' error: '[Errno 19] No such device' ... 应用启动时指定JVM参数 java -jar -Xms128m -Xmx1024m -Xss512k -XX:PermSize=128m -XX:MaxPermSize=64m -XX:NewSize=64m -XX:MaxNewSize=256m arthas-demo.jar,如: [root@localhost ~]# java -jar -Xms128m -Xmx1024m -Xss512k -XX:PermSize=128m -XX:MaxPermSize=64m -XX:NewSize=64m -XX:MaxNewSize=256m  arthas-demo.jar OpenJDK 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0 OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=64m; support was removed in 8.0 157518=2*3*3*3*2917 illegalArgumentCount:  1, number is: -187733, need >= 2 illegalArgumentCount:  2, number is: -102156, need >= 2 173379=3*57793 总结 在使用linux命令时,如果想看帮助可以使用--help或者man查看帮助信息: [root@localhost ~]# grep --help 用法: grep [选项]... PATTERN [FILE]... 在每个 FILE 或是标准输入中查找 PATTERN。 默认的 PATTERN 是一个基本正则表达式(缩写为 BRE)。 例如: grep -i 'hello world' menu.h main.c ... [root@localhost ~]# man grep GREP(1)                                                        General Commands Manual                                                        GREP(1) NAME        grep, egrep, fgrep - 打印匹配给定模式的行 总览 SYNOPSIS        grep [options] PATTERN [FILE...]        grep [options] [-e PATTERN | -f FILE] [FILE...] 描述 DESCRIPTION        Grep    搜索以    FILE    命名的文件输入   (或者是标准输入,如果没有指定文件名,或者给出的文件名是   -   的话),寻找含有与给定的模式   PATTERN ... 类别 监控命令 描述 备注 内存瓶颈 free 查看内存使用 vmstat 3(间隔时间) 100(监控次数) 查看swap in/out详细定位是否存在性能瓶颈 推荐使用 sar -r 3 和free命令类似,查看内存的使用情况,但是不包含swap的情况 cpu瓶颈 top -H 按照cpu消耗高低进行排序 ps -Lp 进程号 cu 查看某个进程的cpu消耗排序 cat /proc/cpuinfo |grep 'processor'|wc -l 查看cpu核数 top 查看cpu总体消耗,包括分项消耗如user,system,idle,nice等消耗 top 然后shift+h:显示java线程,然后shift+M:按照内存使用进行排序;shift+P:按照cpu时间排序;shift+T:按照cpu累计使用时间排序多核cpu,按“1”进入top视图 专项性能排查,多核CPU主要看CUP各个内核的负载情况 sar -u 3(间隔时间) 查看cpu总体消耗占比 sar -q 查看cpu load top -b -n 1 | awk '{if (NR<=7)print;else if($8=="D"){print;count++}}END{print "Total status D:"count}' 计算在cpu load里面的uninterruptedsleep的任务数量 uninterruptedsleep的任务会被计入cpu load,如磁盘堵塞 网络瓶颈 cat /var/log/messages 查看内核日志,查看是否丢包 watch more /proc/net/dev 用于定位丢包,错包情况,以便看网络瓶颈 重点关注drop(包被丢弃)和网络包传送的总量,不要超过网络上限 sar -n SOCK 查看网络流量 netstat -na|grep ESTABLISHED|wc -l 查看tcp连接成功状态的数量 此命令特别消耗cpu,不适合进行长时间监控数据收集 netstat -na|awk'{print $6}'|sort |uniq -c |sort -nr 看tcp各个状态数量 netstat -i 查看网络错误 ss state ESTABLISHED| wc -l 更高效地统计tcp连接状态为ESTABLISHED的数量 cat /proc/net/snmp 查看和分析240秒内网络包量,流量,错包,丢包 用于计算重传率tcpetr=RetransSegs/OutSegs ping $ip 测试网络性能 traceroute $ip 查看路由经过的地址 常用于定位网络在各个路由区段的耗时 dig $域名 查看域名解析地址 dmesg 查看系统内核日志 磁盘瓶颈 iostat -x -k -d 1 详细列出磁盘的读写情况 当看到I/O等待时间所占CPU时间的比重很高的时候,首先要检查的就是机器是否正在大量使用交换空间,同时关注iowait占比cpu的消耗是否很大,如果大说明磁盘存在大的瓶颈,同时关注await,表示磁盘的响应时间以便小于5ms iostat -x 查看系统各个磁盘的读写性能 重点关注await和iowait的cpu占比 iotop 查看哪个进程在大量读取IO 一般先通过iostat查看是否存在io瓶颈,再定位哪个进程在大量读取IO df -hl 查看磁盘剩余空间 du -sh 查看磁盘使用了多少空间 应用瓶颈 ps -ef grep java 查看某个进程的id号 ps -ef | grep httpd| wc -l 查看特定进程的数量 cat ***.log | grep ***Exception| wc -l 统计日志文件中包含特定异常数量 jstack -l pid 用于查看线程是否存在死锁 awk'{print $8}' 2017-05-22-access_log|egrep '301|302'| wc -l 统计log中301、302状态码的行数,$8表示第八列是状态码,可以根据实际情况更改 常用于应用故障定位 grep 'wholesaleProductDetailNew' cookie_log | awk '{if($10=="200")}'print}' awk 'print $12' | more 打印包含特定数据的12列数据 grep "2017:05:22" cookielog | awk '($12>0.3){print 8}' | sort > 目录地址 对apache或者nginx访问log进行响应时间排序,$12表示cookie log中的12列表示响应时间 用于排查是否是由于是某些访问超长造成整体的RT变长 grep -v 'HTTP/1.1" 200' 取出非200响应码的URL pgm -A -f $应用集群名称 "grep "'301' log文件地址 | wc -l" 查看整个集群的log中301状态码的数量 ps -efL | grep [PID] | wc -l 查看某个进程创建的线程数 find / -type f -name "*.log" | xargs grep "ERROR" 统计所有的log文件中,包含Error字符的行 这个在排查问题过程中比较有用 jstat -gc [pid] 查看gc情况 jstat -gcnew [pid] 查看young区的内存使用情况,包括MTT(最大交互次数就被交换到old区),TT是目前已经交换的次数 jstat -gcold 查看old区的内存使用情况 jmap -J-d64 -dump:format=b,file=dump.bin PID dump出内存快照 -J-d64防止jmap导致虚拟机crash(jdk6有bug) -XX:+HeapDumpOnOutOfMemeryError 在java启动时加入,当出现内存溢出时,存储内存快照 jmap -histo [pid] 按照对象内存大小排序 注意会导致full gc gcore [pid] 导出完成的内存快照 通常和jmap -permstat /opt/**/java gcore.bin一起使用,将core dump转换成heap dump -XX:HeapDumpPath=/home/logs -Xloggc:/home/log/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps 在Java启动参数中加入,打印gc日志 -server -Xms4000m -Xmx4000m -Xmn1500m -Xss256k -XX:PermSize=340m -XX:MaxPermSize=340m -XX:+UseConcMarkSweepGC 调整JVM堆大小 xss是栈大小 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 内存 Java Java后端

  • Redis 高负载排查记录

    来源:https://www.sevenyuan.cn/ 周一早上刚上班,突然大量用户反馈进入网页很慢,登录服务器一看,Redis调用时间严重超时,这样高速的缓存反而变成了短板,由于数据一直没有返回,导致了请求响应变慢。 网页监控 通过阿里的 Grafana 监控,服务器的 CPU 负载、内存、网络输入输出都挺正常的,所以肯定是 Redis 出现了问题。 我们应用使用的是单节点的 32M 16GB 的阿里云 Redis,登录网页监控看性能监控,发现 CPU 使用情况飙升到100%!!! QPS 虽然从 1000 多升到 6000,但是远远低于极限值,连接数量从 0 升到 3000,也是远远低于极限值(可能用户刚上班,开始有请求,然后响应延迟,导致命令队列数量过多,打开很多连接)。 临时方案:先租用一台新的 Redis 服务器,更换应用服务器的 Redis 配置,重启应用,避免影响更多用户。 然后我们继续跟踪 Redis 的具体情况。 服务器命令监控 登录 Redis-cli,通过 info 命令查看服务器状态和命令统计,祥哥总结了两点异常点: 查询 redis 慢指令 slowlog,排行前十的指令均为keys *,并且耗时严重,在当前业务流量下执行keys*,一定会阻塞业务,导致查询慢,cpu 高的。值得注意的是应用层面没有开放keys *接口,不排查有后台人为或后台程序触发该指令。 查看 redis 指令执行情况,排除exec,flushall等指令,业务使用指令中,耗时严重的有 setnx 有7.5千万次调用平均耗时 6s,setex 有8.4千万次调用平均耗时7.33s,del 有2.6亿次调用平均耗时69s,hmset 有1亿次调用平均耗时 64s,hmget 有6.8千万次调用平均耗时 9s,hgetall 有14亿次调用平均耗时 205s,keys 有2千万次调用平均耗时 3740s。 通常而言,这些指令耗时与 value 大小呈正比,所以可以排查这些指令相关的数据近期有没有较大增长。或者近期有没有业务改造,会频繁使用上述指令,也会造成 cpu 高。 通过 info commandstats 可以查看 Redis 命令统计信息,其中命令格式是

    架构师社区 Redis 高负载

  • 颠覆认知——Redis会遇到的15个「坑」,你踩过几个?

    阅读本文大约需要 20 分钟。 这篇文章,我想和你聊一聊在使用 Redis 时,可能会踩到的「坑」。 明明一个 key 设置了过期时间,怎么变成不过期了? 执行 RANDOMKEY 随机拿出一个 key,竟然也会阻塞 Redis? 从库内存为什么比主库用得还多? ... 这篇文章,我就来和你盘点一下,使用 Redis 时可能会踩到「坑」,以及如何去规避。 常见命令有哪些坑? 主从库同步有哪些坑? 这篇文章干货很多,希望你可以耐心读完。 常见命令有哪些坑? 1) 过期时间意外丢失? SET 除了可以设置 key-value 之外,还可以设置 key 的过期时间,就像下面这样: 127.0.0.1:6379> SET testkey val1 EX 60 OK 127.0.0.1:6379> TTL testkey (integer) 59 看到了么?testkey 变成永远不过期了! 导致这个问题的原因在于:SET 命令如果不设置过期时间,那么 Redis 会自动「擦除」这个 key 的过期时间。 这时你的 Redis 中就会存在大量不过期的 key,消耗过多的内存资源。 2) DEL 竟然也会阻塞 Redis? O(1)?其实不一定。 Redis 官方文档在介绍 DEL 命令时,是这样描述的: key 是 List/Hash/Set/ZSet 类型,DEL 时间复杂度是 O(M),M 为元素数量 为什么会这样? 而这么长的操作耗时,势必会阻塞整个 Redis 实例,影响 Redis 的性能。 查询元素数量:执行 LLEN/HLEN/SCARD/ZCARD 命令 分批删除:执行 LRANGE/HSCAN/SSCAN/ZSCAN + LPOP/RPOP/HDEL/SREM/ZREM 删除 啊?前面不是提到,Redis 官方文档的描述,删除 String 类型的 key,时间复杂度是 O(1) 么?这不会导致 Redis 阻塞吧? 你思考一下,如果这个 key 占用的内存非常大呢? 这是因为,Redis 释放这么大的内存给操作系统,也是需要时间的,所以操作耗时也会变长。 此时,你可能会想:Redis 4.0 不是推出了 lazy-free 机制么?打开这个机制,释放内存的操作会放到后台线程中执行,那是不是就不会阻塞主线程了? 真的会是这样吗? 这是为什么? 其实,关于 lazy-free 的知识点也很多,由于篇幅原因,所以我打算后面专门写一篇文章来讲,欢迎持续关注~ 如果你想随机查看 Redis 中的一个 key,通常会使用 RANDOMKEY 这个命令。 既然是随机,那这个执行速度肯定非常快吧? 要解释清楚这个问题,就要结合 Redis 的过期策略来讲。 而 RANDOMKEY 在随机拿出一个 key 后,首先会先检查这个 key 是否已过期。 但清理完了还不能结束,Redis 还要找出一个「不过期」的 key,返回给客户端。 整个流程就是这样的: 如果 key 已过期,删除它,继续随机取 key 但这里就有一个问题了:如果此时 Redis 中,有大量 key 已经过期,但还未来得及被清理掉,那这个循环就会持续很久才能结束,而且,这个耗时都花费在了清理过期 key + 寻找不过期 key 上。 以上流程,其实是在 master 上执行的。 为什么? 那 slave 什么时候删除过期 key 呢? 还是同样的场景:Redis 中存在大量已过期,但还未被清理的 key,那在 slave 上执行 RANDOMKEY 时,就会发生以下问题: key 已过期,但 slave 不会删除它,而是继续随机寻找不过期的 key 也就是说,在 slave 上执行 RANDOMKEY,有可能会造成整个 Redis 实例卡死! 这其实是 Redis 的一个 Bug,这个 Bug 一直持续到 5.0 才被修复。 这个方案就是增加上了一个最大重试次数,这样一来,就避免了陷入死循环。 所以,你在使用 RANDOMKEY 时,如果发现 Redis 发生了「抖动」,很有可能是因为这个原因导致的! 在使用 Redis 的 String 类型时,除了直接写入一个字符串之外,还可以把它当做 bitmap 来用。 其中,操作的每一个 bit 位叫做 offset。 如果这个 key 不存在,或者 key 的内存使用很小,此时你要操作的 offset 非常大,那么 Redis 就需要分配「更大的内存空间」,这个操作耗时就会变长,影响性能。 这种类型的 key,也是典型的 bigkey,除了分配内存影响性能之外,在删除它时,耗时同样也会变长。 这个坑你肯定听说过很多次了。 但是,如果你的 Redis QPS 很高,这将会导致这个输出缓冲区内存持续增长,占用 Redis 大量的内存资源,如果恰好你的机器的内存资源不足,那 Redis 实例就会面临被 OOM 的风险。 以上这些问题场景,都是我们在使用常见命令时发生的,而且,很可能都是「无意」就会触发的。 Redis 的数据持久化,分为 RDB 和 AOF 两种方式。 在数据持久化方面发生问题,主要也集中在这两大块,我们依次来看。 如果你的 Redis 采用如下模式部署,就会发生数据丢失的问题: master 没有开启数据持久化功能 如果此时 master 宕机,就会导致下面的问题: 但 master 没有开启任何数据持久化,启动后是一个「空」实例 看到了么?在这个场景下,master / slave 的数据就全部丢失了。 所以,你一定要避免这种情况发生,我给你的建议是: master 宕机后,让哨兵发起切换,把 slave 提升为 master 你在配置数据持久化时,要避免这个问题的发生。 当 Redis 开启 AOF 时,需要配置 AOF 的刷盘策略。 这种方案的工作模式为,Redis 的后台线程每间隔 1 秒,就把 AOF page cache 的数据,刷到磁盘(fsync)上。 但真的不会影响主线程吗? 其实存在这样一种场景:Redis 后台线程在执行 AOF page cache 刷盘(fysnc)时,如果此时磁盘 IO 负载过高,那么调用 fsync 就会被阻塞住。 如何判断呢? 主线程会根据这个时间来判断,距离上一次刷盘已经过去多久了。整个流程是这样的: fsync 已完成,主线程直接写 AOF page cache 如果距离上次 fysnc 成功在 2 秒内,那么主线程会直接返回,不写 AOF page cache 由于磁盘 IO 负载过高,此时,后台线程 fynsc 会发生阻塞,那主线程在写 AOF page cache 时,也会发生阻塞等待(操作同一个 fd,fsync 和 write 是互斥的,一方必须等另一方成功才可以继续执行,否则阻塞等待) 其实,产生这个问题的重点在于,磁盘 IO 负载过高导致 fynsc 阻塞,进而导致主线程写 AOF page cache 也发生阻塞。 3) AOF everysec 真的只会丢失 1 秒数据? 如上所述,这里我们需要重点关注上面的步骤 4。 这就意味着,后台线程在执行 fsync 刷盘时,主线程最多等待 2 秒不会写 AOF page cache。 我们继续分析,Redis 主线程为什么要等待 2 秒不写 AOF page cache 呢? 也就是说,Redis 主线程其实根本不用关心后台线程是否刷盘成功,只要无脑写 AOF page cache 即可。 所以,Redis 作者在主线程写 AOF page cache 之前,先检查一下距离上一次 fsync 成功的时间,如果大于 1 秒没有成功,那么主线程此时就能知道,fsync 可能阻塞了。 降低主线程阻塞的风险(如果无脑写 AOF page cache,主线程则会立即阻塞住) 但代价就是,如果此时发生宕机,AOF 丢失的就是 2 秒的数据,而不是 1 秒。 无论如何,这里你只需要知道的是,即使 AOF 配置为每秒刷盘,在发生上述极端情况时,AOF 丢失的数据其实是 2 秒。 最后,我们来看一下,当 Redis 在执行 RDB 快照和 AOF rewrite 时,会发生的问题。 创建子进程,会调用操作系统的 fork 函数。 但此时的主进程依旧是可以接收写请求的,而进来的写请求,会采用 Copy On Write(写时复制)的方式操作内存数据。 写时复制你也可以理解成,谁需要发生写操作,谁就先拷贝,再修改。 如果你的业务特点是「写多读少」,而且 OPS 非常高,那在 RDB 和 AOF rewrite 期间,就会产生大量的内存拷贝工作。 因为写请求很多,这会导致 Redis 父进程会申请非常多的内存。在这期间,修改 key 的范围越广,新内存的申请就越多。 这就是你会从 DBA 同学那里听到的,要给 Redis 机器预留内存的原因。 以上这些,就是「数据持久化」会遇到的坑,你踩到过几个? Redis 为了保证高可用,提供了主从复制的方式,这样就可以保证 Redis 有多个「副本」,当主库宕机后,我们依旧有从库可以使用。 1) 主从复制会丢数据吗? 这就意味着,如果 master 突然宕机,可能存在有部分数据还未同步到 slave 的情况发生。 如果你把 Redis 当做纯缓存来使用,那对业务来说没有什么影响。 但是,对于把 Redis 当做数据库,或是当做分布式锁来使用的业务,有可能因为异步复制的问题,导致数据丢失 / 锁丢失。 2) 同样命令查询一个 key,主从库却返回不同的结果? slave 正常返回 key 的值 你认为是哪一种?可以思考一下。 嗯?为什么会不一定? 其实,返回什么结果,这要取决于以下 3 个因素: 具体执行的命令 先来看 Redis 版本。 也就是说,即使这个 key 已过期,在 slave 上依旧可以查询到这个 key。 // Redis 2.8 版本 在 slave 上执行 127.0.0.1:6479> TTL testkey (integer) -2    // 已过期 127.0.0.1:6479> GET testkey "testval"       // 还能查询到! 发现了吗?在 master 和 slave 上查询同一个 key,结果竟然不一样? 为什么会发生这种情况? 这个 Bug 在 3.2 版本进行了修复,但是,它修复得「不够彻底」。 这就要结合前面提到的,第 2 个影响因素「具体执行的命令」来解释了。 也就是说,一个 key 已过期,在 slave 直接查询它的数据,例如执行 GET/LRANGE/HGETALL/SMEMBERS/ZRANGE 这类命令时,slave 会返回 NULL。 原因在于,EXISTS 与查询数据的命令,使用的不是同一个方法。 直到 Redis 4.0.11 这个版本,Redis 才真正把这个遗漏的 Bug 完全修复。 这里我们先小结一下,slave 查询过期 key,经历了 3 个阶段: 3.2 - 4.0.11 版本,查询数据返回 NULL,但 EXISTS 依旧返回 true 这里要特别鸣谢《Redis开发与运维》的作者,付磊。 虽然已在微信中亲自答谢,但在这里再次表达对他的谢意~ 假设我们已规避了上面提到的版本 Bug,例如,我们使用 Redis 5.0 版本,在 slave 查询一个 key,还会和 master 结果不同吗? 这就与 master / slave 的机器时钟有关了。 如果 slave 的机器时钟比 master 走得「快」,那就会导致,即使这个 key 还未过期,但以 slave 上视角来看,这个 key 其实已经过期了,那客户端在 slave 上查询时,就会返回 NULL。 如果你也遇到了类似的情况,就可以通过上述步骤进行排查,确认是否踩到了这个坑。 这个问题是上一个问题的延伸。 此时,从 slave 角度来看,Redis 中的数据存在「大量过期」。 它成为 master 后,就会开始大量清理过期 key,此时就会导致以下结果: Redis 中数据大量过期,引发缓存雪崩 所以,如果你是 DBA 运维,一定要保证主从库的机器时钟一致性,避免发生这些问题。 还有一种场景,会导致 master / slave 的数据存在大量不一致。 Redis 的 maxmemory 可以控制整个实例的内存使用上限,超过这个上限,并且配置了淘汰策略,那么实例就开始淘汰数据。 例如,master 配置的 maxmemory 为 5G,而 slave 的 maxmemory 为 3G,当 Redis 中的数据超过 3G 时,slave 就会「提前」开始淘汰数据,此时主从库数据发生不一致。 调大 maxmemory 时,先调整 slave,再调整 master 以此方式操作,就避免了 slave 提前超过 maxmemory 的问题。 其根本原因在于,slave 超过 maxmemory 后,会「自行」淘汰数据。 没错。 Redis 5.0 增加了一个配置项:replica-ignore-maxmemory,默认 yes。 这样一来,slave 永远会向 master 看齐,只会老老实实地复制 master 发送过来的数据,不会自己再搞「小动作」。 如果你使用的恰好是 5.0 版本,就不用担心这个问题了。 是的,你没看错。 当你在使用 Redis 时,符合以下场景,就会触发 slave 内存泄露: slave 配置项为 read-only=no(从库可写) 这时的 slave 就会发生内存泄露:slave 中的 key,即使到了过期时间,也不会自动清理。 最麻烦的是,你使用命令查询这些 key,却还查不到任何结果! 这其实也是 Redis 的一个 Bug,Redis 4.0 才修复了这个问题。 然后 slave 会定时扫描这些 key,如果到达过期时间,则清理之。 你需要确认你的 Redis 版本,如果是 4.0 以下版本,一定要避免踩这个坑。 6) 为什么主从全量同步一直失败? slave 向 master 发起全量同步请求,master 生成 RDB 后发给 slave,slave 加载 RDB。 此时你会发现,slave 加载 RDB 还未完成,master 和 slave 的连接却断开了,数据同步也失败了。 同样地,slave 在加载 RDB 时,master / slave 同步又失败了,以此往复。 其实,这就是 Redis 的「复制风暴」问题。 就像刚才描述的:主从全量同步失败,又重新开始同步,之后又同步失败,以此往复,恶性循环,持续浪费机器资源。 如果你的 Redis 有以下特点,就有可能发生这种问题: 复制缓冲区(slave client-output-buffer-limit)配置过小 主从在全量同步数据时,master 接收到的写请求,会先写到主从「复制缓冲区」中,这个缓冲区的「上限」是配置决定的。 为了避免内存持续增长,此时的 master 会「强制」断开 slave 的连接,这时全量同步就会失败。 如何解决这个问题呢?我给你以下几点建议: 复制缓冲区配置的尽量大一些,给 slave 加载 RDB 留足时间,降低全量同步失败的概率 好了,总结一下,这篇文章我们主要讲了 Redis 在「命令使用」、「数据持久化」、「主从同步」3 个方面可能存在的「坑」。 这篇文章信息量还是比较大的,如果你现在的思维已经有些「凌乱」了,别急,我也给你准备好了思维导图,方便你更好地理解和记忆。 最后,我想和你聊一聊在开发过程中,关于踩坑的经验和心得。 那在踩坑这个阶段,如何少踩坑?或者踩坑后如何高效率地排查问题呢? 1) 多看官方文档 + 配置文件的注释 2) 不放过疑问细节,多思考为什么? 3) 敢于提出质疑,源码不会骗人 通过源码寻找问题的真相,这种方式要好过你看一百篇网上互相抄袭的文章(抄来抄去很有可能都是错的)。 任何优秀的软件,都是一步步迭代出来的。在迭代过程中,存在 Bug 很正常,我们需要抱着正确的心态去看待它。

    架构师社区 Redis OOM RANDOMKEY

  • 大厂为什么都很重视 API 网关?聊聊 API 网关的作用

    -     API 网关的用处     - 在这篇文章中将我们一起来探讨当前的API网关的作用。 API网关我的分析中会用到以下三种场景。 Open API 企业需要将自身数据、能力等作为开发平台向外开放,通常会以rest的方式向外提供,最好的例子就是淘宝开放平台、腾讯公司的QQ开发平台、微信开放平台。 Open API开放平台必然涉及到客户应用的接入、API权限的管理、调用次数管理等,必然会有一个统一的入口进行管理,这正是API网关可以发挥作用的时候。 微服务网关 微服务的概念最早在2012年提出,在Martin Fowler的大力推广下,微服务在2014年后得到了大力发展。在微服务架构中,有一个组件可以说是必不可少的,那就是微服务网关,微服务网关处理了负载均衡,缓存,路由,访问控制,服务代理,监控,日志等。API网关在微服务架构中正是以微服务网关的身份存在。 API服务管理平台 上述的微服务架构对企业来说有可能实施上是困难的,企业有很多遗留系统,要全部抽取为微服务器改动太大,对企业来说成本太高。但是由于不同系统间存在大量的API服务互相调用,因此需要对系统间服务调用进行管理,清晰地看到各系统调用关系,对系统间调用进行监控等。 API网关可以解决这些问题,我们可以认为如果没有大规模的实施微服务架构,那么对企业来说微服务网关就是企业的API服务管理平台。 -     API 网关在企业整体架构中的地位     - 一个企业随着信息系统复杂度的提高,必然出现外部合作伙伴应用、企业自身的公网应用、企业内网应用等,在架构上应该将这三种应用区别开,三种应用的安排级别、访问方式也不一样。 因此在我的设计中将这三种应用分别用不同的网关进行API管理,分别是:API网关(OpenAPI合伙伙伴应用)、API网关(内部应用)、API网关(内部公网应用)。 -     企业如何应用 API 网关     - 1、对于OpenAPI使用的API网关来说,一般合作伙伴要以应用的形式接入到OpenAPI平台,合作伙伴需要到 OpenAPI平台申请应用。 因此在OpenAPI网关之外,需要有一个面向合作伙伴的使用的平台用于合作伙伴,这就要求OpenAPI网关需要提供API给这个用户平台进行访问。 当然如果是在简单的场景下,可能并不需要提供一个面向合作伙伴的门户,只需要由公司的运营人员直接添加合作伙伴应用id/密钥等,这种情况下也就不需要合作伙伴门户子系统。 2、对于内网的API网关,在起到的作用上来说可以认为是 微服务网关 ,也可以认为是内网的API服务治理平台。当企业将所有的应用使用微服务的架构管理起来,那么API网关就起到了微服务网关的作用。 而当企业只是将系统与系统之间的调用使用rest api的方式进行访问时使用API网关对调用进行管理,那么API网关起到的就是API服务治理的作用。 3、对于公司内部公网应用(如APP、公司的网站),如果管理上比较细致,在架构上是可能由独立的API网关来处理这部分内部公网应用,如果想比较简单的处理,也可以是使用面向合作伙伴的API网关。 如果使用独立的API网关,有以下的好处: 面向合作伙伴和面向公司主体业务的优先级不一样,不同的API网关可以做到业务影响的隔离。 内部API使用的管理流程和面向合作伙伴的管理流程可能不一样。 内部的API在功能扩展等方面的需求一般会大于OpenAPI对于功能的要求。 基于以上的分析,如果公司有能力,那么还是建议分开使用合作伙伴OPEN API网关和内部公网应用网关。 -     API 网关有哪些竞争方案     - 1、对于Open API平台的API网关,我分析只能选择API网关作为解决方案,业界没有发现比较好的可以用来作为Open API平台的入口的其他方案。 2、对于作为微服务网关的API网关,业界的选择可以选择的解决方案比较多,也取决于微服务器的实现方案,有一些微服务架构的实现方案是不需要微服务网关的。 Service Mesh ,这是新兴的基于无API网关的架构,通过在客户端上的代理完成屏蔽网络层的访问,这样达到对应用层最小的改动,当前Service Mesh的产品还正在开发中,并没有非常成熟可直接应用的产品。发展最迅速的产品是Istio。建议大家密切关注相关产品的研发、业务使用进展。 基于dubbo架构,在这个架构中通常是不需要网关的,是由客户端直接访问服务提供方,由注册中心向客户端返回服务方的地址。 -     API 网关解决方案     - 私有云开源解决方案如下: Kong kong是基于Nginx+Lua进行二次开发的方案, https://konghq.com/ Netflix Zuul,zuul是spring cloud的一个推荐组件,https://github.com/Netflix/zuul orange,这个开源程序是国人开发的, http://orange.sumory.com/ 公有云解决方案: Amazon API Gateway,https://aws.amazon.com/cn/api-gateway/ 阿里云API网关,https://www.aliyun.com/product/apigateway/ 腾讯云API网关, https://cloud.tencent.com/product/apigateway 自开发解决方案: 基于Nginx+Lua+ OpenResty的方案,可以看到Kong,orange都是基于这个方案。 基于Netty、非阻塞IO模型。通过网上搜索可以看到国内的宜人贷等一些公司是基于这种方案,是一种成熟的方案。 基于Node.js的方案。这种方案是应用了Node.js天生的非阻塞的特性。 基于java Servlet的方案。zuul基于的就是这种方案,这种方案的效率不高,这也是zuul总是被诟病的原因。 -     企业怎么选择 API 网关     - 如果是要选择一款已有的API网关,那么需要从以下几个方面去考虑。 1、性能与可用性 如果一旦采用了API网关,那么API网关就会作为企业应用核心,因此性能和可用性是必须要求的。 从性能上来说,需要让网关增加的时间消耗越短越好,个人觉得需要10ms以下。系统需要采用非阻塞的IO,如epoll,NIO等。网关和各种依赖的交互也需要是非阻塞的,这样才能保证整体系统的高可用性,如:Node.js的响应式编程和基于java体现的RxJava和Future。 网关必须支持集群部署,任务一台服务器的crash都应该不影响整体系统的可用性。 多套网关应该支持同一管理平台和同一监控中心。如:一个企业的OpenAPI网关和内部应用的多个系统群的不同的微服务网关可以在同一监控中心进行监控。 2、可扩展性、可维护性 一款产品总有不能满足生产需求的地方,因此需求思考产品在如何进行二次开发和维护,是否方便公司团队接手维护产品。 3、需求匹配度 需要评估各API网关在需求上是否能满足,如:如果是OpenAPI平台需要使用API网关,那么需要看API网关在合作伙伴应用接入、合作伙伴门户集成、访问次数限额等OpenAPI核心需求上去思考产品是否能满足要求。如果是微服务网关,那么要从微服务的运维、监控、管理等方面去思考产品是否足够强大。 4、是否开源?公司是否有自开发的能力? 现有的开源产品如kong,zuul,orange都有基础的API网关的核心功能,这些开源产品大多离很好的使用有一定的距离,如:没有提供管理功能的UI界面、监控功能弱小,不支持OpenAPI平台,没有公司运营与运维的功能等。 当然开源产品能获取源代码,如果公司有比较强的研发能力,能hold住这些开源产品,经过二次开发kong、zuul应该还是适应一些公司,不过需求注意以下一些点: kong是基于ngnix+lua的,从公司的角度比较难于找到能去维护这种架构产品的人。需求评估当前公司是否有这个能力去维护这个产品。 zuul因为架构的原因在高并发的情况下性能不高,同时需要去基于研究整合开源的适配zuul的监控和管理系统。 orange由于没有被大量使用,同时是国内个人在开源,在可持续性和社区资源上不够丰富,出了问题后可能不容易找到人问。 另外kong提供企业版本的API网关,当然也是基于ngnix+lua的,企业版本可以购买他们的技术支持、培训等服务、以及拥有界面的管理、监控等功能。 5、公有云还是私有云 现在的亚马逊、阿里、腾讯云都在提供基础公有云的API网关,当然这些网关的基础功能肯定是没有问题,但是二次开发,扩展功能、监控功能可能就不能满足部分用户的定制需求了。另外很多企业因为自身信息安全的原因,不能使用外网公有网的API网关服务,这样就只有选择私有云的方案了。 在需求上如果基于公有云的API网关只能做到由内部人员为外网人员申请应用,无法做到定制的合作伙伴门户,这也不适合于部分企业的需求。 如果作为微服务网关,大多数情况下是希望网关服务器和服务提供方服务器是要在内网的,在这里情况下也只有私有云的API网关才能满足需求。 综合上面的分析,基础公有云的API网关只有满足一部分简单客户的需求,对于很多企业来说私有云的API网关才是正确的选择。 作者:coolfiry 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 网关 API

  • 因为一次 Kafka 宕机,终于搞透了 Kafka 高可用原理!

    -     Kafka 宕机引发的高可用思考     - 问题要从一次Kafka的宕机开始说起。 笔者所在的是一家金融科技公司,但公司内部并没有采用在金融支付领域更为流行的 RabbitMQ ,而是采用了设计之初就为日志处理而生的 Kafka ,所以我一直很好奇Kafka的高可用实现和保障。从Kafka部署后,系统内部使用的Kafka一直运行稳定,没有出现不可用的情况。 但最近系统测试人员常反馈偶有Kafka消费者收不到消息的情况,登陆管理界面发现三个节点中有一个节点宕机挂掉了。但是按照高可用的理念,三个节点还有两个节点可用怎么就引起了整个集群的消费者都接收不到消息呢? 要解决这个问题,就要从Kafka的高可用实现开始讲起。 -     Kafka 的多副本冗余设计     - 不管是传统的基于关系型数据库设计的系统,还是分布式的如 zookeeper 、 redis 、 Kafka 、 HDFS等等,实现高可用的办法通常是采用冗余设计,通过冗余来解决节点宕机不可用问题。 首先简单了解Kafka的几个概念: 物理模型 Broker (节点):Kafka服务节点,简单来说一个 Broker 就是一台Kafka服务器,一个物理节点。 Topic (主题):在Kafka中消息以主题为单位进行归类,每个主题都有一个 Topic Name ,生产者根据Topic Name将消息发送到特定的Topic,消费者则同样根据Topic Name从对应的Topic进行消费。 Partition (分区):Topic (主题)是消息归类的一个单位,但每一个主题还能再细分为一个或多个 Partition (分区),一个分区只能属于一个主题。主题和分区都是逻辑上的概念,举个例子,消息1和消息2都发送到主题1,它们可能进入同一个分区也可能进入不同的分区(所以同一个主题下的不同分区包含的消息是不同的),之后便会发送到分区对应的Broker节点上。 Offset (偏移量):分区可以看作是一个只进不出的队列(Kafka只保证一个分区内的消息是有序的),消息会往这个队列的尾部追加,每个消息进入分区后都会有一个偏移量,标识该消息在该分区中的位置,消费者要消费该消息就是通过偏移量来识别。 其实,根据上述的几个概念,是不是也多少猜到了Kafka的多副本冗余设计实现了?别急,咱继续往下看。 在Kafka 0.8版本以前,是没有多副本冗余机制的,一旦一个节点挂掉,那么这个节点上的所有 Partition的数据就无法再被消费。这就等于发送到Topic的有一部分数据丢失了。 在0.8版本后引入副本记者则很好地解决宕机后数据丢失的问题。副本是以 Topic 中每个 Partition的数据为单位,每个Partition的数据会同步到其他物理节点上,形成多个副本。 每个 Partition 的副本都包括一个 Leader 副本和多个 Follower副本,Leader由所有的副本共同选举得出,其他副本则都为Follower副本。在生产者写或者消费者读的时候,都只会与Leader打交道,在写入数据后Follower就会来拉取数据进行数据同步。 就这么简单?是的,基于上面这张多副本架构图就实现了Kafka的高可用。当某个 Broker 挂掉了,甭担心,这个 Broker 上的 Partition 在其他 Broker 节点上还有副本。你说如果挂掉的是 Leader 怎么办?那就在 Follower中在选举出一个 Leader 即可,生产者和消费者又可以和新的 Leader 愉快地玩耍了,这就是高可用。 你可能还有疑问,那要多少个副本才算够用?Follower和Leader之间没有完全同步怎么办?一个节点宕机后Leader的选举规则是什么? 直接抛结论: 多少个副本才算够用? 副本肯定越多越能保证Kafka的高可用,但越多的副本意味着网络、磁盘资源的消耗更多,性能会有所下降,通常来说副本数为3即可保证高可用,极端情况下将 replication-factor 参数调大即可。 Follower和Lead之间没有完全同步怎么办? Follower和Leader之间并不是完全同步,但也不是完全异步,而是采用一种 ISR机制( In-Sync Replica)。每个Leader会动态维护一个ISR列表,该列表里存储的是和Leader基本同步的Follower。如果有Follower由于网络、GC等原因而没有向Leader发起拉取数据请求,此时Follower相对于Leader是不同步的,则会被踢出ISR列表。所以说,ISR列表中的Follower都是跟得上Leader的副本。 一个节点宕机后Leader的选举规则是什么? 分布式相关的选举规则有很多,像Zookeeper的 Zab 、 Raft 、 Viewstamped Replication 、微软的 PacificA 等。而Kafka的Leader选举思路很简单,基于我们上述提到的 ISR列表,当宕机后会从所有副本中顺序查找,如果查找到的副本在ISR列表中,则当选为Leader。另外还要保证前任Leader已经是退位状态了,否则会出现脑裂情况(有两个Leader)。怎么保证?Kafka通过设置了一个controller来保证只有一个Leader。 -     Ack 参数决定了可靠程度     - 另外,这里补充一个面试考Kafka高可用必备知识点:request.required.asks 参数。 Asks这个参数是生产者客户端的重要配置,发送消息的时候就可设置这个参数。该参数有三个值可配置:0、1、All 。 第一种是设为0 意思是生产者把消息发送出去之后,之后这消息是死是活咱就不管了,有那么点发后即忘的意思,说出去的话就不负责了。不负责自然这消息就有可能丢失,那就把可用性也丢失了。 第二种是设为1 意思是生产者把消息发送出去之后,这消息只要顺利传达给了Leader,其他Follower有没有同步就无所谓了。存在一种情况,Leader刚收到了消息,Follower还没来得及同步Broker就宕机了,但生产者已经认为消息发送成功了,那么此时消息就丢失了。 设为1是Kafka的默认配置 可见Kafka的默认配置也不是那么高可用,而是对高可用和高吞吐量做了权衡折中。 第三种是设为All(或者-1) 意思是生产者把消息发送出去之后,不仅Leader要接收到,ISR列表中的Follower也要同步到,生产者才会任务消息发送成功。 进一步思考, Asks=All 就不会出现丢失消息的情况吗?答案是否。当ISR列表只剩Leader的情况下, Asks=All 相当于 Asks=1 ,这种情况下如果节点宕机了,还能保证数据不丢失吗?因此只有在 Asks=All并且有ISR中有两个副本的情况下才能保证数据不丢失。 -     解决问题     - 绕了一大圈,了解了Kafka的高可用机制,终于回到我们一开始的问题本身, Kafka 的一个节点宕机后为什么不可用? 我在开发测试环境配置的 Broker 节点数是3, Topic 是副本数为3, Partition 数为6, Asks参数为1。 当三个节点中某个节点宕机后,集群首先会怎么做?没错,正如我们上面所说的,集群发现有Partition的Leader失效了,这个时候就要从ISR列表中重新选举Leader。如果ISR列表为空是不是就不可用了?并不会,而是从Partition存活的副本中选择一个作为Leader,不过这就有潜在的数据丢失的隐患了。 所以,只要将Topic副本个数设置为和Broker个数一样,Kafka的多副本冗余设计是可以保证高可用的,不会出现一宕机就不可用的情况(不过需要注意的是Kafka有一个保护策略,当一半以上的节点不可用时Kafka就会停止)。那仔细一想,Kafka上是不是有副本个数为1的Topic? 问题出在了 __consumer_offset 上, __consumer_offset 是一个Kafka自动创建的 Topic,用来存储消费者消费的 offset (偏移量)信息,默认 Partition数为50。而就是这个Topic,它的默认副本数为1。如果所有的 Partition 都存在于同一台机器上,那就是很明显的单点故障了!当将存储 __consumer_offset 的Partition的Broker给Kill后,会发现所有的消费者都停止消费了。 这个问题怎么解决? 第一点 ,需要将 __consumer_offset 删除,注意这个Topic时Kafka内置的Topic,无法用命令删除,我是通过将 logs 删了来实现删除。 第二点 ,需要通过设置 offsets.topic.replication.factor 为3来将 __consumer_offset 的副本数改为3。通过将 __consumer_offset 也做副本冗余后来解决某个节点宕机后消费者的消费问题。 最后,关于为什么 __consumer_offset的Partition会出现只存储在一个Broker上而不是分布在各个Broker上感到困惑。 作者:JanusWoo 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 宕机 Kafka RabbitMQ

  • 架构设计的真谛:系统与子系统、模块与组件、框架与架构

    -     前言     - 在软件研发这个领域,程序员的终极目标都是想成为一名合格的架构师。然而梦想很美好,但现实却很曲折。 在实际工作中,程序员会分很多种,有的擅长编码实现,有的擅长底层原理,有的擅长逻辑实现等等,在各自的领域都表现不俗、担当核心,然而,面临更高层架构设计时,很多优秀的程序员却折戟沙场,未能完成华丽转身。 架构的真谛是什么呢?架构真的如此难把控吗?难道真的只有天资聪慧、天赋异能的程序员才能驾驭架构吗? 不要气馁,平常心,其实人人都是架构师,可能你做的任一一件事已无形中用到了架构。 本篇文章将带您慢慢走进架构,揭秘架构的真谛。正如,架构不是神秘物,吸取真谛即了然。 -     架构的背景     - 如果想要深入理解某一事物的本质,最好的方式就是去追寻这个事物出现的历史背景和推动因素。所以我们先来梳理一下软件开发的进化史,探索一下软件架构出现的历史背景。 1、机器语言 最早的软件开发使用的是“机器语言”,其直接使用二进制码0和1来表示机器可以识别的指令和数据。 比如:为了完成“将寄存器 BX 的内容送到 AX 中”,机器语言如下: 1000100111011000 面对上面的1&0的字符串,不用多说,程序员心里肯定会万马奔腾吧,更别说输入错误要去定位问题,求程序员的心里阴影面积? 归纳一下,机器语言的主要问题是三难: 太难写、太难读、太难改! 2、汇编语言 为了解决机器语言编写、阅读、修改复杂的问题,汇编语言应运而生。汇编语言又叫“符号语言”,用助记符代替机器指令的操作码,用地址符号(Symbol)或标号(Label),代替指令或操作数的地址。 比如:为了完成“将寄存器 BX 的内容送到 AX 中”,汇编语言如下: mov ax,bx 相比机器语言来说,汇编语言就清晰得多了。汇编语言虽然解决了机器语言读写复杂的问题,但本质上还是面向机器的,因为写汇编语言需要我们精确了解计算机底层的知识。 面向机器的语言,带来的问题就是: 汇编语言需要针对不同 CPU 的汇编指令和结构,代码编写多份。 3、高级语言 为了解决汇编语言的问题,前辈们又设计出了一个“高级语言”。为什么会叫“高级语言”呢?原因在于这些语言让程序员不需要关注机器底层的低级结构和指令,只需要关注具体的问题和业务即可。 比如:以4+6=?这个加法为例,如果用Lisp语言,只需要简单一行代码: (+ 4 6) 除此以外,通过编译程序的处理,高级语言可以被编译为适合不同CPU指令的机器语言。程序员只要写一次程序,就可以在不同的机器上编译运行,无须根据不同的机器指令重写整个程序。 4、两次软件危机 第一次软件危机与结构化程序设计 高级语言的出现,解放了程序员,但好景不长,随着软件的规模和复杂度的大大增加,软件质量低下,质量把控难度高,项目无法如期完成,严重超支等现象。例如,1963 年美国的 水手一号火箭发射失败事故,就是因为一行 FORTRAN 代码错误导致的。 所以,为了解决上面的问题,针对性的提出了解决方法“软件工程”,虽然“软件工程”提出之后也曾被视为软件领域的银弹,但后来事实证明,软件工程同样无法根除软件危机,只能在一定程度上缓解软件危机。 差不多同一时间,“结构化程序设计” 作为另外一种解决软件危机的方案被提了出来。结构化程序设计的主要特点是抛弃 goto 语句,采取“自顶向下、逐步细化、模块化”的指导思想。 结构化程序设计本质上还是一种面向过程的设计思想,但通过“自顶向下、逐步细化、模块化”的方法,将软件的复杂度控制在一定范围内,从而从整体上降低了软件开发的复杂度。 第二次软件危机与面向对象 结构化编程的风靡在一定程度上缓解了软件危机,然而随着硬件的快速发展,业务需求越来越复杂,以及编程应用领域越来越广泛,第二次软件危机很快就到来了。 第二次软件危机的根本原因还是 在于软件生产力远远跟不上硬件和业务的发展。 第一次软件危机的根源在于 软件的“逻辑”变得非常复杂; 第二次软件危机主要体现在 软件的“扩展”变的非常复杂。 结构化程序设计虽然能够缓解软件逻辑的复杂性,但是对于业务变化带来的软件扩展却无能为力。软件领域迫切希望找到新的银弹来解决软件危机,在这种背景下,面向对象的思想开始流行起来。 虽然面向对象开始也被当做解决软件危机的银弹,在一定程度上解决了软件“扩展”带来的复杂性。但事实证明,和软件工程、结构化程度设计一样,面向对象也不是银弹,而只是一种新的软件方法而已。 5、软件架构的产生 与之前的各种新方法或者新理念不同的是,“软件架构”出现的背景并不是整个行业都面临类似相同的问题,“软件架构”也不是为了解决新的软件危机而产生的,这是怎么回事呢? 随着软件系统规模的增加,计算相关的算法和数据结构不再构成主要的设计问题。当系统由许多部分组成时,整个系统的组织,也就是所说的“软件架构”,产生了一系列新的设计问题。比如: 系统规模庞大,内部耦合严重,开发效率低; 系统耦合严重,牵一发动全身,后续修改和扩展困难; 系统逻辑复杂,容易出问题,出问题后很难排查和修复; “软件架构”的出现有其历史必然性。第一次软件危机引出了“结构化编程”,创造了“模块”概念;第二次软件危机引出了“面向对象编程”,创造了“对象”概念;直到“软件架构”的产生,创造了“组件”概念。 “模块”、“对象”和“组件”本质上都是对达到一定规模的软件进行拆分,差别只是在于随着软件的复杂度不断增加,拆分的粒度越来越粗,拆分的层次越来越高。 -     架构指什么     - 对于技术人员来说,“架构”是一个再常见不过的词了。当提起“架构”这个词时,如果去深究一下:“架构”到底指什么?大部分人也许并不一定能够准确地回答。1000个人心中可能有1001种架构的含义。 那么如何才能准确的理解架构呢?理解架构首先理解三个有关系而又相似的概念,包括:系统与子系统、模块与组件、框架与架构。 1、系统与子系统 关于“系统”的定义,我们先来看维基百科的定义: 系统泛指由一群 有关联 的个体组成,根据某种 规则运作,能完成 个别元件不能单独完成的工作的群体。它的意思是“总体”、“整体”或“联盟”。 来提炼下里面的关键信息: 关联:系统是由一群有关联的个体组成的,没有关联的个体堆在一起不能成为一个系统,例如:把一个发动机和一台PC放在一起不能称之为一个系统,把发动机、底盘、轮胎、车架组合起来才能成为一台汽车。 规则:系统内的个体需要按照指定的规则运作,而不是单个个体各自为政。规则规定了系统内个体分工和协作的方式。例如:汽车发动机负责产生动力,然后通过变速器和传动轴,将动力输出到轮胎上,从而驱动汽车前进。 能力:系统能力和个体能力有本质的差别,系统能力也不是个体能力之和,而是产生了新的能力。例如:汽车能够载重前进,而发动机、变速器、传动轴、车轮本身都不具备这样的能力。 再来看下子系统的定义: 子系统也是由一群有关联的个体所组成的系统,多半会是更大系统中的一部分。 其实子系统和系统的定义是一样的,只是观察的角度有差异,一个系统可能是另外一个更大系统的子系统。 按照这个定义,系统和子系统比较容易理解。以微信为例来做一个分析: 微信本身是一个系统,包含聊天、登录、支付、朋友圈等子系统; 朋友圈这个系统又包括动态、评论、点赞等子系统; 评论这个系统可能又包括防刷子系统、审核子系统、发布子系统、存储子系统等; 评论审核子系统不再包含业务意义上的子系统,而是包括各个模块或者组件,这些模块或者组件本身也是另外一个维度上的系统,例如:MySQL、Redis等存储系统,但不是业务子系统。 2、模块与组件 从逻辑的角度来拆分系统,得到的单元就是“模块”;从物理的角度来拆分系统,得到的单元就是“组件”。划分模块的主要目的是职责分离;划分组件的主要目的是单元复用。其实,“组件”的英文“component”也可以翻译成中文的“零件”一词,“零件”更容易理解一些,“零件”是一个物理的概念,并且具备“独立且可替换”的特点。 3、框架与架构 单纯从定义的角度来看,框架关注的是“规范”,架构关注的是“结构”。框架的英文是“Framework”,架构的英文是“Architecture”。 我们经常会说,比如:“工程采用的是MVC架构”、“工程使用的是SSH框架”等。所以,第一句话是站在结构的层面来说明,第二句话是站在规范的层面来说明。 同时,如果是以不同的角度来说明结构,会得出不同的架构描述,比如: 从业务逻辑的角度分解,“学生管理系统”的架构: “学生管理系统”的架构 4、重新定义架构 软件架构指软件系统的顶层结构。 首先,“系统是一群关联个体组成”,这些“个体”可以是“子系统”、“模块”、“组件”等;架构需要明确系统包含哪些“个体”。 其次,系统中的个体需要“根据某种规则”运作,架构需要明确个体运作和协作的规则。 -     总结     - 架构其实就是为了应对软件系统复杂度而提出的解决方案。架构关键思维即为判断与取舍。 正如,在一个有约束的盒子里去求解或接近最合适的解。这个约束的盒子可能会包含团队经验、成本、资源、时间、业务阶段等因素掺杂在一起的综合体,针对这个综合体,分析出系统架构的复杂度,进行合适的判断与取舍,从而设计出恰当的架构用在合适的软件系统中。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 架构 框架 软件研发

首页  上一页  1 2 3 4 5 6 7 8 9 10 下一页 尾页
发布文章