做网站需要实名认证吗,兰州市城乡建设局网官网站,网站建设和管理工作,做pc端网站如何1、常用性能评价/测试指标
1.1、响应时间 提交请求和返回该请求的响应时间之间使用的时间#xff0c;一般比较关注平均响应时间。常用操作的响应时间列表#xff1a;
操作响应时间打开一个站点几秒数据库查询一条记录#xff08;有索引#xff09;十几毫秒机械磁盘一次寻…1、常用性能评价/测试指标
1.1、响应时间 提交请求和返回该请求的响应时间之间使用的时间一般比较关注平均响应时间。常用操作的响应时间列表
操作响应时间打开一个站点几秒数据库查询一条记录有索引十几毫秒机械磁盘一次寻址定位4毫秒从机械磁盘顺序读取1M数据2毫秒从SSD磁盘顺序读取1M数据0.3毫秒从远程分布式换成Redis读取一个数据0.5毫秒从内存读取1M数据十几微妙Java程序本地方法调用几微妙网络传输2Kb数据1微妙
1.2、并发数 同一时刻。对服务器有实际交互请求的请求数。和网站在线用户数的关联1000个同时在线用户数可以估计并发数在5%到15%之间也就是同时并发数在50~150之间。
1.3、吞吐量 对单位时间内完成的工作量(请求)的量度。
1.4、关系 系统吞吐量和系统并发数以及响应时间的关系可以理解为高速公路的通行状况
吞吐量是每天通过收费站的车辆数目可以换算成收费站收取的高速费并发数是高速公路上的正在行驶的车辆数目响应时间是车速 车辆很少时车速很快。但是收到的高速费也相应较少随着高速公路上车辆数目的增多车速略受影响但是收到的高速费增加很快并发少时响应就快同时也就是说吞吐量更低当并发增多时响应时间也会略受影响吞吐量也就逐步增多 随着车辆的继续增加车速变得越来越慢高速公路越来越堵收费不增反降如果车流量继续增加超过某个极限后任务偶然因素都会导致高速全部瘫痪车走不动当然后也收不着而高速公路成了停车场资源耗尽。随着并发继续增加响应时间会越来越慢服务器负载也就越高这时的吞吐量将不增反减如果并发数继续增加当超过某个极限后服务器可能会崩溃导致各服务无法运行
2、常用性能优化手段
2.1、避免过早优化 不应该把大量的时间耗费在小的性能改进上过早考虑优化是所有噩梦的根源。所以我们应该编写清晰直接易读和易理解的代码真正的优化应该留到以后等到性能分析表明优化措施有巨大的收益时再进行。
2.2、进行系统性能测试 所有的性能调优都有应该建立在性能测试的基础上直觉很重要但是要用数据说话可以推测但是要通过测试求证。
2.3、寻找系统瓶颈 性能测试后对整个请求经历的各个环节进行分析排查出现性能瓶颈的地方定位问题分析影响性能的的主要因素是什么内存、磁盘IO、网络、CPU还是代码问题架构设计不足或者确实是系统资源不足
3、前端优化常用手段
3.1、浏览器/APP
减少请求数合并CSSJs图片使用客户端缓存静态资源文件缓存在浏览器中有关的属性Cache-Control和Expires。如果文件发生了变化需要更新则通过改变文件名来解决。启用压缩减少网络传输量但会给浏览器和服务器带来性能的压力需要权衡使用。资源文件加载顺序css放在页面最上面js放在最下面减少Cookie传输cookie包含在每次的请求和响应中因此哪些数据写入cookie需要慎重考虑给用户一个提示有时候在前端给用户一个提示就能收到良好的效果。毕竟用户需要的是不要不理他。 3.2、CDN加速 CDN又称内容分发网络本质仍然是一个缓存而且是将数据缓存在用户最近的地方。无法自行实现CDN的时候可以考虑商用CDN服务。 3.3、反向代理缓存 将静态资源文件缓存在反向代理服务器上一般是Nginx。 3.4、web组件分离 将jscss和图片文件放在不同的域名下。可以提高浏览器在下载web组件的并发数。因为浏览器在下载同一个域名的的数据存在并发数限制。 4、应用服务性能优化
4.1、缓存 网站性能优化第一定律优先考虑使用缓存优化性能。缓存离用户越近越好
4.2、缓存的基本原理和本质 缓存是将数据存在访问速度较高的介质中。可以减少数据访问的时间同时避免重复计算。 4.3、合理使用缓存的准则
频繁修改的数据尽量不要缓存读写比2:1以上才有缓存的价值。缓存一定是热点数据。应用需要容忍一定时间的数据不一致。缓存可用性问题一般通过热备或者集群来解决。缓存预热新启动的缓存系统没有任何数据可以考虑将一些热点数据提前加载到缓存系统。 解决缓存击穿 布隆过滤器把不存在的数据也缓存起来 比如有请求总是访问 key 23 的数据但是这个key 23 的数据在系统中不存在可以考虑在缓存中构建一个( key23 value null)的数据。 4.4、分布式缓存与一致性哈希
1、分布式缓存
以集群的方式提供缓存服务有两种实现
需要更新同步的分布式缓存所有的服务器保存相同的缓存数据带来的问题就是缓存的数据量受限制其次数据要在所有的机器上同步代价很大。每台机器只缓存一部分数据然后通过一定的算法选择缓存服务器。常见的余数hash算法存在当有服务器上下线的时候大量缓存数据重建的问题。所以提出了一致性哈希算法。
2、一致性哈希
首先求出服务器节点的哈希值并将其配置到0232的圆continuum上。然后采用同样的方法求出存储数据的键的哈希值并映射到相同的圆上。然后从数据映射到的位置开始顺时针查找将数据保存到找到的第一个服务器上。如果超过232仍然找不到服务器就会保存到第一台服务器上。 一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据具有较好的容错性和可扩展性。 一致性哈希算法在服务节点太少时容易因为节点分部不均匀而造成数据倾斜问题此时必然造成大量数据集中到Node A上而只有极少量会定位到Node B上。为了解决这种数据倾斜问题一致性哈希算法引入了虚拟节点机制即对每一个服务节点计算多个哈希每个计算结果位置都放置一个此服务节点称为虚拟节点。具体做法可以在服务器ip或主机名的后面增加编号来实现。例如可以为每台服务器计算三个虚拟节点于是可以分别计算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值于是形成六个虚拟节点同时数据定位算法不变只是多了一步虚拟节点到实际节点的映射例如定位到“Node A#1”、“Node A#2”、“Node A#3”三个虚拟节点的数据均定位到Node A上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中通常将虚拟节点数设置为32甚至更大因此即使很少的服务节点也能做到相对均匀的数据分布。
5、同步 异步
5.1、同异步 阻塞和非阻塞 同步和异步关注的是结果消息的通信机制 同步:同步的意思就是调用方需要主动等待结果的返回
异步:异步的意思就是不需要主动等待结果的返回而是通过其他手段比如状态通知回调函数等。 阻塞和非阻塞主要关注的是等待结果返回调用方的状态 阻塞:是指结果返回之前当前线程被挂起不做任何事
非阻塞:是指结果在返回之前线程可以做一些其他事不会被挂起。 常见阻塞模型 同步阻塞同步阻塞基本也是编程中最常见的模型打个比方你去商店买衣服你去了之后发现衣服卖完了那你就在店里面一直等期间不做任何事(包括看手机)等着商家进货直到有货为止这个效率很低。jdk里的BIO就属于【同步阻塞】同步非阻塞同步非阻塞在编程中可以抽象为一个轮询模式你去了商店之后发现衣服卖完了这个时候不需要傻傻的等着你可以去其他地方比如奶茶店买杯水但是你还是需要时不时的去商店问老板新衣服到了吗。jdk里的NIO就属于【同步非阻塞】异步阻塞异步阻塞这个编程里面用的较少有点类似你写了个线程池,submit然后马上future.get()这样线程其实还是挂起的。有点像你去商店买衣服这个时候发现衣服没有了这个时候你就给老板留给电话说衣服到了就给我打电话然后你就守着这个电话一直等着他响什么事也不做。这样感觉的确有点傻所以这个模式用得比较少。异步非阻塞好比你去商店买衣服衣服没了你只需要给老板说这是我的电话衣服到了就打。然后你就随心所欲的去玩也不用操心衣服什么时候到衣服一到电话一响就可以去买衣服了。jdk里的AIO就属于异步
5.2、常见异步的手段
Servlet异步servlet3中才有支持的web容器在tomcat7和jetty8以后。多线程消息队列集群可以很好的将用户的请求分配到多个机器处理对总体性能有很大的提升
5.3、程序优化
选择合适的数据结构 Testpublic void buildTest() {ListObject list new LinkedList();int i 0;while (true) {i;if (i % 10000 0) {System.out.println(i i);}else {list.add(new Object());}}} 选择ArrayList和LinkedList对我们的程序性能影响很大为什么因为ArrayList内部是数组实现存在着不停的扩容和数据复制。
选择更优算法 举个例子最大子列和问题 给定一个整数序列a0, a1, a2, …… , an项可以为负数求其中最大的子序列和。如果所有整数都是负数那么最大子序列和为0例如a[1],a[2],a[3],a[4],a[5],a[6](-2,11,-4,13,-5,-2)时最大子段和为20子段为a[2],a[3],a[4]。
最坏的算法穷举法所需要的的计算时间是O(n^3).一般的算法分治法的计算时间复杂度为O(nlogn).最好的算法最大子段和的动态规划算法计算时间复杂度为O(n) n越大时间就相差越大比如10000个元素最坏的算法和最好的算法之间的差距绝非多线程或者集群化能轻松解决的。
编写更少代码 同样正确的程序小程序比大程序要快这点无关乎编程语言。
并发编程 充分利用CPU多核实现线程安全的类避免线程安全问题同步下减少锁的竞争资源的复用目的是减少开销很大的系统资源的创建和销毁比如数据库连接网络通信连接线程资源等等单例模式池化技术
6、JVM
6.1、与JIT编译器相关的优化 对JVM性能影响最大的是编译器。选择编译器是运行java程序首先要做的选择之一 6.2、热点编译概念 对于程序来说通常只有一部分代码被经常执行这些关键代码被称为应用的热点执行的越多就认为是越热。将这些代码编译为本地机器特定的二进制码可以有效提高应用性能。 6.3、选择编译器类型
-server更晚编译但是编译后的优化更多性能更高-client很早就开始编译-XX:TieredCompilation开启分层编译可以让jvm在启动时启用client编译随着代码变热后再转为server编译。 缺省编译器取决于机器位数、操作系统和CPU数目。32位的机器上一般默认都是client编译64位机器上一般都是server编译多核机器一般是server编译。 6.4、编译时机 图中的mix mode 一般指编译时机
-Xint 表示禁用JIT所有字节码都被解释执行这个模式的速度最慢的。-Xcomp 表示所有字节码都首先被编译成本地代码然后再执行。-Xmixed默认模式让JIT根据程序运行的情况有选择地将某些代码编译成本地代码。
6.5、代码缓存相关 在编译后会有一个代码缓存保存编译后的代码一旦这个缓存满了jvm将无法继续编译代码。当jvm提示 CodeCache is full就表示需要增加代码缓存大小。
–XX:ReservedCodeCacheSizeN //可以用来调整这个大小
6.6、编译阈值 代码是否进行编译取决于代码执行的频度是否到达编译阈值。计数器有两种分别是
方法调用计数器方法里的循环回边计数器 一个方法是否达到编译阈值取决于方法中的两种计数器之和。编译阈值调整的参数为
-XX:CompileThresholdN 方法调用计数器统计的并不是方法被调用的绝对次数而是一个相对的执行频率即一段时间之内方法被调用的次数。当超过一定的时间限度如果方法的调用次数仍然不足以让它提交给即时编译器编译那这个方法的调用计数器就会被减少一半这个过程称为方法调用计数器热度的衰减Counter Decay而这段时间就称为此方法统计的半衰周期Counter Half Life Time。进行热度衰减的动作是在虚拟机进行垃圾收集时顺便进行的可以使用虚拟机参数
-XX-UseCounterDecay
来关闭热度衰减让方法计数器统计方法调用的绝对次数这样只要系统运行时间足够长绝大部分方法都会被编译成本地代码。另外可以使用
-XXCounterHalfLifeTime
参数设置半衰周期的时间单位是秒。与方法计数器不同回边计数器没有计数热度衰减的过程因此这个计数器统计的就是该方法循环执行的绝对次数。
6.7、方法内联 内联默认开启-XX:-Inline可以关闭但是不要关闭一旦关闭对性能有巨大影响。方法是否内联取决于方法有多热和方法的大小很热的方法如果方法字节码小于325字节才会内联这个大小由参数-XX:MaxFreqInlinesSzieN 调整但是这个很热与热点编译不同没有任何参数可以调整热度。 方法小于35个字节码一定会内联这个大小可以通过参数-XX:MaxInlinesSzieN 调整。
7、GC调优
7.1、调优的原则和步骤
大多数的java应用不需要GC调优大部分需要GC调优的的不是参数问题是代码问题在实际使用中分析GC情况优化代码比优化GC参数要多得多GC调优是最后的手段 GC调优的最重要的三个选项 第一位选择合适的GC回收器第二位选择合适的堆大小第三位选择年轻代在堆中的比重 调优步骤 1、监控GC的状态 使用各种JVM工具查看当前日志分析当前JVM参数设置并且分析当前堆内存快照和gc日志根据实际的各区域内存划分和GC执行时间觉得是否进行优化
2、分析结果判断是否需要优化 如果各项参数设置合理系统没有超时日志出现GC频率不高GC耗时不高那么没有必要进行GC优化如果GC时间超过1-3秒或者频繁GC则必须优化
注意如果满足下面的指标则一般不需要进行GC
Minor GC执行时间不到50msMinor GC执行不频繁约10秒一次Full GC执行时间不到1sFull GC执行频率不算频繁不低于10分钟1次
3、调整GC类型和内存分配 如果内存分配过大或过小或者采用的GC收集器比较慢则应该优先调整这些参数并且先找1台或几台机器进行beta然后比较优化过的机器和没有优化的机器的性能对比并有针对性的做出最后选择
4、不断的分析和调整 通过不断的试验和试错分析并找到最合适的参数
5、全面应用参数 如果找到了最合适的参数则将这些参数应用到所有服务器并进行后续跟踪。
7.2、阅读GC日志
以参数 -Xms5m -Xmx5m -XX:PrintGCDetails -XX:UseSerialGC为例
[DefNew: 1855K-1855K(1856K), 0.0000148 secs][Tenured: 2815K-4095K(4096K), 0.0134819 secs] 4671K
DefNew指明了收集器类型而且说明了收集发生在新生代
1855K-1855K(1856K)表示回收前 新生代占用1855K回收后占用1855K新生代大小1856K
0.0000148 secs表明新生代回收耗时
Tenured表明收集发生在老年代
2815K-4095K(4096K)同上述新生代回收
0.0134819 secs同上述回收耗时
4671K指明堆的大小 将收集器参数调整为-XX:UseParNewGC日志将变为
[ParNew: 1856K-1856K(1856K), 0.0000107 secs][Tenured: 2890K-4095K(4096K), 0.0121148 secs]
收集器参数变为-XX: UseParallelGC或UseParallelOldGC日志变为
[PSYoungGen: 1024K-1022K(1536K)] [ParOldGen: 3783K-3782K(4096K)] 4807K-4804K(5632K)
7.3、GC相关的参数
调试跟踪与打印简单的GC信息参数-verbose:gc, -XX:PrintGC打印详细的GC信息-XX:PrintGCDetails, XX:PrintGCTimeStamps设置GC日志输出路径-Xlogger:log/gc.log定义滚动日志文件大小-XX:GCLogFileSize100M定义滚动日志文件的个数-XX:NumberOfGCLogFiles2 打印堆信息-XX:PrintHeapAtGC 应用场景获取Heap在每次垃圾回收前后的使用状况跟踪类的加载过程-XX:TraceClassLoading 应用场景在系统控制台信息中看到class加载的过程和具体的class信息可用以分析类的加载顺序以及是否可进行精简操作禁止调用GC-XX:DisableExplicitGC 应用场景-XX:DisableExplicitGC内存溢出快照记录-XX:-HeapDumpOnOutOfMemoryError 应用场景默认关闭建议开启在java.lang.OutOfMemoryError 异常出现时输出一个dump.core文件记录当时的堆内存快照。堆内存快照路径输出-XX:HeapDumpPath./java_pidpid.hprof 应用场景默认是java进程启动位置用来设置堆内存快照的存储文件路径
7.4、推荐策略 年轻代大小选择 响应时间优先的应用尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择).在此种情况下,年轻代收集发生的频率也是最小的.同时,减少到达年老代的对象.
吞吐量优先的应用尽可能的设置大,可能到达Gbit的程度.因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用.
避免设置过小当新生代设置过小时会导致
YGC次数更加频繁可能导致YGC对象直接进入旧生代,如果此时旧生代满了,会触发FGC. 老年代大小选择 响应时间优先的应用年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数.如果堆设置小了,可以会造成内存碎片,高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间.最优化的方案,一般需要参考以下数据获得
并发垃圾收集信息持久代并发收集次数传统GC信息花在年轻代和年老代回收上的时间比例
吞吐量优先的应用一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代.原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象