当前位置: 首页 > news >正文

有了域名后怎么做网站湖州网站开发公司

有了域名后怎么做网站,湖州网站开发公司,网站制作简介,石家庄做公司网站作者#xff1a;vivo 互联网服务器团队 - Liu Zhen、Ye Wenhao 服务器内存问题是影响应用程序性能和稳定性的重要因素之一#xff0c;需要及时排查和优化。本文介绍了某核心服务内存问题排查与解决过程。首先在JVM与大对象优化上进行了有效的实践#xff0c;其次在故障转移与… 作者vivo 互联网服务器团队 - Liu Zhen、Ye Wenhao 服务器内存问题是影响应用程序性能和稳定性的重要因素之一需要及时排查和优化。本文介绍了某核心服务内存问题排查与解决过程。首先在JVM与大对象优化上进行了有效的实践其次在故障转移与大对象监控上提出了可靠的落地方案。最后总结了内存优化需要考虑的其他问题。 一、问题描述 音乐业务中core服务主要提供歌曲、歌手等元数据与用户资产查询。随着元数据与用户资产查询量的增长一些JVM内存问题也逐渐显露例如GC频繁、耗时长在高峰期RPC调用超时等问题导致业务核心功能受损。 图1 业务异常数量变化 二、分析与解决 通过对日志机器CPU、内存等监控数据分析发现 YGC平均每分钟次数12次峰值为24次平均每次的耗时在327毫秒。FGC平均每10分钟0.08次峰值1次平均耗时30秒。可以看到GC问题较为突出。 在问题期间机器的CPU并没有明显的变化但是堆内存出现较大异常。图2黄色圆圈处内存使用急速上升FGC变的频繁释放的内存越来越少。 图2 老年代内存使用异常 因此我们认为业务功能异常是机器的内存问题导致的需要对服务的内存做一次专项优化。 步骤1 JVM优化 以下是默认的JVM参数 -Xms4096M -Xmx4096M -Xmn1024M -XX:MetaspaceSize256M -Djava.security.egdfile:/dev/./urandom -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/data/{runuser}/logs/other 如果不指定垃圾收集器那么JDK 8默认采用的是Parallel Scavenge新生代 Parallel Old老年代这种组合在多核CPU上充分利用多线程并行的优势提高垃圾回收的效率和吞吐量。但是由于采用多线程并行方式会造成一定的停顿时间不适合对响应时间要求较高的应用程序。然而core这类的服务特点是对象数量多生命周期短。在系统特点上吞吐量较低要求时延低。因此默认的JVM参数并不适合core服务。 根据业务的特点和多次对照实验选择了如下参数进行JVM优化4核8G的机器。该参数将young区设为原来的1.5倍减少了进入老年代的对象数量。将垃圾回收器换成ParNewCMS可以减少YGC的次数降低停顿时间。此外还开启了CMSScavengeBeforeRemark在CMS的重新标记阶段进行一次YGC以减少重新标记的时间。 -Xms4096M -Xmx4096M -Xmn1536M -XX:MetaspaceSize256M -XX:UseConcMarkSweepGC -XX:CMSScavengeBeforeRemark -Djava.security.egdfile:/dev/./urandom -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/data/{runuser}/logs/other 图3 JVM优化前后的堆内存对比 优化后效果如图3堆内存的使用明显降低但是Dubbo超时仍然存在。 我们推断在业务高峰期该节点出现了大对象晋升到了老年代导致内存使用迅速上升并且大对象没有被及时回收。那如何找到这个大对象及其产生的原因呢为了降低问题排查期间业务的损失提出了临时的故障转移策略尽量降低异常数量。 步骤2 故障转移策略 在api服务调用core服务出现异常时将出现异常的机器ip上报给监控平台。然后利用监控平台的统计与告警能力配置相应的告警规则与回调函数。当异常触发告警通过配置的回调函数将告警ip传递给api服务此时api服务可以将core服务下的该ip对应的机器视为“故障”进而通过自定义的故障转移策略实现Dubbo的AbstractLoadBalance抽象类并且配置在项目自动将该ip从提供者集群中剔除从而达到不去调用问题机器。图 4 是整个措施的流程。在该措施上线前每当有机器内存告警时将会人工重启该机器。 图4 故障转移策略 步骤3 大对象优化 大对象占用了较多的内存导致内存空间无法被有效利用甚至造成OOMOut Of Memory异常。在优化过程中先是查看了异常期间的线程信息然后对堆内存进行了分析最终确定了大对象身份以及产生的接口。 1 Dump Stack 查看线程 从监控平台上Dump Stack文件发现一定数量的如下线程调用。 Thread 5612: (state IN_JAVA)- org.apache.dubbo.remoting.exchange.codec.ExchangeCodec.encodeResponse(org.apache.dubbo.remoting.Channel, org.apache.dubbo.remoting.buffer.ChannelBuffer, org.apache.dubbo.remoting.exchange.Response) bci11, line282 (Compiled frame; information may be imprecise)- org.apache.dubbo.remoting.exchange.codec.ExchangeCodec.encode(org.apache.dubbo.remoting.Channel, org.apache.dubbo.remoting.buffer.ChannelBuffer, java.lang.Object) bci34, line73 (Compiled frame)- org.apache.dubbo.rpc.protocol.dubbo.DubboCountCodec.encode(org.apache.dubbo.remoting.Channel, org.apache.dubbo.remoting.buffer.ChannelBuffer, java.lang.Object) bci7, line40 (Compiled frame)- org.apache.dubbo.remoting.transport.netty4.NettyCodecAdapter$InternalEncoder.encode(io.netty.channel.ChannelHandlerContext, java.lang.Object, io.netty.buffer.ByteBuf) bci51, line69 (Compiled frame)- io.netty.handler.codec.MessageToByteEncoder.write(io.netty.channel.ChannelHandlerContext, java.lang.Object, io.netty.channel.ChannelPromise) bci33, line107 (Compiled frame)- io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(java.lang.Object, io.netty.channel.ChannelPromise) bci10, line717 (Compiled frame)- io.netty.channel.AbstractChannelHandlerContext.invokeWrite(java.lang.Object, io.netty.channel.ChannelPromise) bci10, line709 (Compiled frame) ...state IN_JAVA 表示Java虚拟机正在执行Java程序。从线程调用信息可以看到Dubbo正在调用Netty将输出写入到缓冲区。此时的响应可能是一个大对象因而在对响应进行编码、写缓冲区时需要耗费较长的时间导致抓取到的此类线程较多。另外耗时长也即是大对象存活时间长导致full gc 释放的内存越来越小空闲的堆内存变小这又会加剧full gc 次数。 这一系列的连锁反应与图2相吻合那么接下来的任务就是找到这个大对象。 2Dump Heap 查看内存 对core服务的堆内存进行了多次查看其中比较有代表性的一次快照的大对象列表如下 图5 core服务的堆内存快照 整个Netty的taskQueue有258MB。并且从图中绿色方框处可以发现单个的Response竟达到了9M红色方框处显示了调用方的服务名以及URI。 进一步排查发现该接口会通过core服务查询大量信息至此基本排查清楚了大对象的身份以及产生原因。 3优化结果 在对接口进行优化后整个core服务也出现了非常明显的改进。YGC全天总次数降低了76.5%高峰期累计耗时降低了75.5%。FGC三天才会发生一次并且高峰期累计耗时降低了90.1%。 图6 大对象优化后的core服务GC情况 尽管优化后因内部异常导致获取核心业务失败的异常请求数显著减少但是依然存在。为了找到最后这一点异常产生的原因我们打算对core服务内存中的对象大小进行监控。 图7 系统内部异常导致核心业务失败的异常请求数 步骤4 无侵入式内存对象监控 Debug Dubbo 源码的过程中发现在网络层Dubbo通过encodeResponse方法对响应进行编码并写入缓冲区通过checkPayload方法去检查响应的大小当超过payload时会抛出ExceedPayloadLimitException异常。在外层对异常进行了捕获重置buffer位置而且如果是ExceedPayloadLimitException异常重新发送一个空响应这里需要注意空响应没有原始的响应结果信息源码如下。 //org.apache.dubbo.remoting.exchange.codec.ExchangeCodec#encodeResponse protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response res) throws IOException {//...省略部分代码try {//1、检查响应大小是否超过 payload如果超过则抛出ExceedPayloadLimitException异常checkPayload(channel, len);} catch (Throwable t) {//2、重置bufferbuffer.writerIndex(savedWriteIndex);//3、捕获异常后生成一个新的空响应Response r new Response(res.getId(), res.getVersion());r.setStatus(Response.BAD_RESPONSE);//4、ExceedPayloadLimitException异常将生成的空响应重新发送一遍if (t instanceof ExceedPayloadLimitException) {r.setErrorMessage(t.getMessage());channel.send(r);return;}} }//org.apache.dubbo.remoting.transport.AbstractCodec#checkPayload protected static void checkPayload(Channel channel, long size) throws IOException {int payload getPayload(channel);boolean overPayload isOverPayload(payload, size);if (overPayload) {ExceedPayloadLimitException e new ExceedPayloadLimitException(Data length too large: size , max payload: payload , channel: channel);logger.error(e);throw e;} } 受此启发自定义了编解码类实现org.apache.dubbo.remoting.Codec2接口并且配置在项目去监控超出阈值的对象并打印请求的详细信息方便排查问题。在具体实现中如果特意去计算每个对象的大小那么势必是对服务性能造成影响。经过分析采取了和checkPayload一样的方式根据编码前后buffer的writerIndex位置去判断有没有超过设定的阈值。代码如下。 /*** 自定义dubbo编码类**/ public class MusicDubboCountCodec implements Codec2 {/*** 异常响应池缓存超过payload大小的responseId*/private static CacheLong, String EXCEED_PAYLOAD_LIMIT_CACHE Caffeine.newBuilder()// 缓存总条数.maximumSize(100)// 过期时间.expireAfterWrite(300, TimeUnit.SECONDS)// 将value设置为软引用在OOM前直接淘汰.softValues().build();Overridepublic void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException {//1、记录数据编码前的buffer位置int writeBefore null buffer ? 0 : buffer.writerIndex();//2、调用原始的编码方法dubboCountCodec.encode(channel, buffer, message);//3、检查记录超过payload的信息checkOverPayload(message);//4、计算对象长度int writeAfter null buffer ? 0 : buffer.writerIndex(); int length writeAfter - writeBefore;//5、超过告警阈值进行日志打印处理warningLengthTooLong(length, message);}//校验response是否超过payload超过了缓存idprivate void checkOverPayload(Object message){if(!(message instanceof Response)){return;}Response response (Response) message;//3.1、新的发送过程通过状态码BAD_RESPONSE与错误信息识别出空响应并记录响应idif(Response.BAD_RESPONSE response.getStatus() StrUtil.contains(response.getErrorMessage(), OVER_PAYLOAD_ERROR_MESSAGE)){ EXCEED_PAYLOAD_LIMIT_CACHE.put(response.getId(), response.getErrorMessage());return;}//3.2、原先的发送过程通过异常池识别出超过payload的响应打印有用的信息if(Response.OK response.getStatus() EXCEED_PAYLOAD_LIMIT_CACHE.getIfPresent(response.getId()) ! null){ String responseMessage getResponseMessage(response);log.warn(dubbo序列化对象大小超过payload,errorMsg is {},response is {}, EXCEED_PAYLOAD_LIMIT_CACHE.getIfPresent(response.getId()),responseMessage);}}} 在上文中提到当捕获到超过payload的异常时会重新生成空响应导致失去了原始的响应结果此时再去打印日志是无法获取到调用方法和入参的但是encodeResponse方法步骤4中重新发送这个Response给了我们机会去获取到想要的信息因为重新发送意味着会再去走一遍自定义的编码类。 假设有一个超出payload的请求执行到自定编码类encode方法的步骤2Dubbo源码中的编码方法在这里会调用encodeResponse方法重置buffer发送新的空响应。 1当这个新的空响应再次进入自定义encode方法执行 checkOverPayload方法的步骤3.1时就会记录异常响应的id到本地缓存。由于在encodeResponse中buffer被重置无法计算对象的大小所以步骤4、5不会起到实际作用就此结束新的发送过程。 2原先的发送过程回到步骤2 继续执行到了步骤3.2 时发现本地缓存的异常池中有当前的响应id这时就可以打印调用信息了。 综上对于大小在告警阈值和payload之间的对象由于响应信息成功写入了buffer可以直接进行大小判断并且打印响应中的关键信息对于超过payload的对象在重新发送中记录异常响应id到本地在原始发送过程中访问异常id池识别是否是异常响应进行关键信息打印。 在监控措施上线后通过日志很快速的发现了一部分产生大对象的接口当前也正在根据接口特点做针对性优化。 三、总结 在对服务JVM内存进行调优时要充分利用日志、监控工具、堆栈信息等分析与定位问题。尽量降低问题排查期间的业务损失引入对象监控手段也不能影响现有业务。除此之外还可以在定时任务、代码重构、缓存等方面进行优化。优化服务内存不仅仅是JVM调参而是一个全方面的持续过程。
http://www.zqtcl.cn/news/603849/

相关文章:

  • 做招聘求职网站wordpress启用插件出错
  • 珠海网站运营网站个人备案流程
  • 网站开发用什么图片格式最好网络营销名词解释是什么
  • 做柜子网站老电脑做网站服务器
  • 域名购买网站网店装修是什么
  • wordpress 网站备份为什么企业要建设自己的企业文化
  • 想做一个部门的网站怎么做潍坊网站建设价
  • 网站建设公司的公司哪家好什么行业必须做网站
  • 电子商务网站前台设计wordpress 上传文件大小
  • 深圳市住房和城乡建设局网站非常好的资讯网站设计
  • 长春作网站建设的公司国家建设环保局网站
  • 网站开发的有哪些好的软件wordpress菜单栏的函数调用
  • 家庭清洁东莞网站建设技术支持建筑模板厂投资多少钱
  • 郑州企业建站详情网站开发和网页开发有什么区别
  • 山西古建筑网站个人网站可以做自媒体吗
  • 腾讯云服务器可以做网站wordpress中文正式版
  • 做相亲网站赚钱吗vultr部署wordpress
  • 网站被挂马原因做网站较好的框架
  • 网站开发毕业设计参考文献自考大型网站开发工具
  • p2p网站建设方案策划书黄山旅游攻略冬季
  • 最世网络建设网站可以吗小说网站制作开源
  • 广州网站建设知名 乐云践新网页界面制作
  • 沈阳网站哪家公司做的好招标信息发布
  • 兰州企业网站h5页面用什么软件
  • 东莞自助建站软件ppt怎么做 pc下载网站
  • 兴化网站建设价格怎样用自己的电脑,做网站
  • 东莞网站建设企慕网站名称 注册
  • 佛山网站建设服务商百度推广客户端手机版下载
  • 做网站找个人还是找公司wordpress jiathis
  • 淘宝客推广网站建设百度云wordpress转服务器