性能指标
网站性能,站在普通用户的角度,就是在浏览器上直观感受到的网站响应速度快还是慢。从开发和测试人员的角度,衡量性能的指标主要有响应时间、并发数、吞吐量等。
1.响应时间,就是应用执行一个操作的时间,从发出请求开始,到接收到最后响应数据所需要的时间。
2.并发数,即系统能够同时处理请求的数目;
3.吞吐量,即单位时间内系统处理的请求数量,对于网站可用TPS(每秒事务数)、HPS(每秒HTTP请求数)、QPS(每秒查询数)等;
网站性能优化的目的,就是改善用户体验的响应时间;提高并发数;提高系统吞吐量,最大限度的利用服务器资源;
Web前端性能优化
1.浏览器请求优化
1) 减少http请求
Http协议是无状态协议,每次http请求都需要建立通信链路、进行数据传输,而在服务器端,每个http都需要启动独立的线程去处理,这些通信和服务的开销都很昂贵,减少http请求的数目可有效提高访问性能。减少http请求的手段主要有合并CSS、合并JavaScript,合并图片(比如银行列表里使用同一张图片,借助于css偏移)。
2)启用压缩
在服务器端对文件进行压缩,可以减少通信传输的数据量。比如对JavaScript进行压缩。
3)CSS放在页面最上面,JavaScript放在页面最下面
浏览器会在下载完全部CSS后才对整个页面进行渲染,所以最好将CSS放到页面的最上面,让浏览器尽快下载CSS。浏览器在加载完JavaScript后立即执行,有可能阻塞整个页面,造成页面显示缓慢,所以JavaScript最好放在页面的最下面。
2.CDN加速
CDN部署在网络运行商的机房,因此用户请求路由的第一跳就达到了CDN服务器,当CDN中存在浏览器请求的资源时,从CDN直接返回给浏览器,最短路径返回响应,加快用户访问速度,减少数据中心负载压力;
3.反向代理
反向代理服务器可以通过配置缓存功能来加速web请求,当用户第一次访问静态内容的时候,静态内容就被缓存在反向代理服务器上,这样当其他用户访问该静态内容的时候,就可以直接从反向代理服务器上返回,加速web请求响应速度。反向代理服务器也有负载均衡的作用。
应用服务器性能优化
应用服务器就是处理网站业务的服务器,优化的手段主要有缓存、集群、异步等;
1.分布式缓存
缓存的本质是一个内存的hash表,数据缓存以一对key、value的形式存储在内存hash表中。计算KV对中key的hashcode对应的hash表索引,可以快速的访问hash表中的数据。Java语言中的hashcode方法包含在根对象Object中,其返回值是一个int,然后通过hashcode计算hash表的索引下标,使用该下标就可以直接访问hash表中存储的kv对。
缓存主要用来存储那些读写比很高,很少变化的数据。应用程序读数据时,会先到缓存中读取,如果读取不到,或者数据已失效,再访问数据库,并将数据写入缓存。
网站数据访问通常遵循二八原则,即80%的访问落在20%的数据上,将这20%的数据缓存起来,可以很好的改善系统性能。
以Memcahced为代表的互不通信的分布式缓存为例。
Memcached使用TCP协议通信。memcached对于内存管理,使用了一个简单的办法–固定内存分配。memcached将内存分为一组slab,每个slab里又包含一组chunk,同一个slab里的每个chunk的大小都是固定的,拥有相同大小chunk的slab被组织在一起,叫做slab_class。存储数据时根据数据的size大小,寻找一个大于size的最小chunk将数据写入,这种内存管理方式避免了内存碎片管理的问题,内存的分配和释放都是以chunk为单位的。当然这种方式也带来内存浪费的问题,数据只能存入一个比它大的chunk里,而一个chunk只能存一个数据,其他空间被浪费了。
2.异步操作
在不使用消息队列的情况下,用户的请求数据直接写入数据库,在高并发的情况下,会对数据库造成巨大的压力,同时也使得响应延迟加剧。在使用消息队列后,用户请求的数据发送给消息队列后立即返回,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。由于消息队列服务器处理速度远快于数据库,因此用户的响应延迟可以得到有效的改善。
需要注意的是,由于数据写入消息队列后立即返回,但接下来的消费者进程从消息队列中取出消息、做业务校验、或者写入数据库时可能发生错误,所以使用消息队列对业务处理后,需要适当修改业务流程进行配合,如订单提交后,订单数据写入消息队列,不能立即返回给用户订单提交成功,需要在消息队列的订单消费者进程中真正处理完该订单后,甚至商品出库后,再通过电子邮件或者SMS消息通知用户订单成功,以免交易纠纷。
3.使用集群
用负载均衡技术为一个应用构建一个由多台服务器组成的服务器集群,将并发访问请求分发到多台服务器上处理,避免单一服务器因负载压力过大而响应缓慢。
4.代码优化
1)多线程
解决线程安全的主要手段:
a. 将对象设计为无状态的对象。所谓无状态的对象,就是对象本身不存储状态信息,即对象没有成员变量,或者即便是有成员变量,成员变量也是无状态的对象。
b.使用局部对象
即在方法内部创建对象,这些对象会被每个进入该方法的线程创建,除非程序有意识的讲这些对象传递给其他线程,否则不会出现对象被多线程并发访问的情形;
c.并发访问资源时使用锁
2).资源复用
系统运行时,要尽量减少那些开销很大的系统资源的创建和销毁,比如数据库连接、网络通信连接、线程等,从编程的角度,资源复用主要有两种模式:单例和对象池(比如连接池、线程池)。
参考资料:《大型网站技术架构:核心原理与案例分析》 李智慧