系列文章目录
第一章 高性能服务器结构分析
第二章 实现简单的web请求与响应
第三章 实现非活跃用户检测与处理
第四章 实现服务器日志系统
第五章 使用redis实现MySQL缓存功能
第六章 高性能服务器之CDN
前言
1 高性能服务器设计目标:
高性能(High Performance)->大量的并发请求能及时的做出响应
高可用(High Availability) -> 保证服务器能7X24小时工作,如果出现故障也能自动转移到备用机工作
伸缩性(Scalability) ->指服务器具有良好的框架,分布式设计,业务分离并且能进行灵活的部署。
2 分布式主要有 负载均衡,分布式存储,分布式计算。
任何的网络系统都可以抽象为一个C/S结构,服务器又可以与其他服务器继续构成这种结构。
B/S结构本质上也是一种C/S结构,可以将浏览器看出HTTP客户端,向HTTP服务器(Web服务器)请求。
一个典型的服务器结构:
应用服务器处理大量的客户请求(epoll在大并发访问较为高效),数据库都有一个最大的并发请求值,当出现过多请求时候就会出现请求失败,所以我们应该在服务器和数据库中间加一个队列。
中间层可以与应用服务器部署一起也可以分开部署(伸缩性)
中间层DAL队列服务(在有大量请求的时候进行排队等候)
对于DAL与数据库的连接,我们还可以提前向数据库申请一些连接,放进连接池中,这样请求的时候不需要重新创建与数据库的连接,只需要从连接池中取就行。
对于上面的超出时限问题,假设服务器的规定的最高响应时间是5S,那么上面的就只有5000的并发量,为了提高并发量我们应该使用缓存技术,可以再增加一层缓存,客户端请求数据的时候,先向缓存中找,没有再取数据库中找,从而大大减轻数据库的压力,提高并发量。
但是使用缓存会存在缓存同步问题(缓存更新),怎么解决呢?
有两个解决手段:
1 缓存是有一定的时效的,在一定时间后会失效,如果缓存失效我们就需要重新去数据库里面查询,从而使得缓存和数据库数据存在同步,这种方法不是实时的,实时性比较差。
2 一旦数据库中的数据更新了,立即通知前端的缓存更新,实时性好。
此外如果缓存内容过多,会导致内存占用过高,可以将一些不活跃的缓存换出内存–》(缓存换页)
换出的方法有: FIFO LRU(最近最少使用) LFU(最不频繁使用)
实现缓存的方法常有nosql // redis memcached (分布式缓存)
关于缓存服务器部署的问题:
如果缓存服务器与应用服务器部署在一起,那么这个缓存是一个局部缓存(如果存在有多太应用服务器的情况下,不能相互访问,或者访问麻烦)。
如果缓存服务器部署在独立的主机上,并且使用分布式的缓存机制,全局缓存。
另外对于客户请求的数据库的访问类型来说(读,写),我们可以将数据库进行读写分离。同时可以对数据库进行负载均衡处理(主从负责机制进程实现)。
数据库压力进一步解决了,为了进一步解决应用服务器的压力,我们可以增加应用服务器,可以将不同业务进行分割,且分到不同的业务服务器。此外我们在应用服务器前一级加上任务服务器进行负载均衡处理。
//任务服务器能够监视每一个应用服务器的当前状态,查看服务器是CPU高,IO高,还是并发高,或者是内存换页高,查询到这些信息后,选取负责最低的进行分配任务。(应用服务器被动接收任务)
//应用服务器主动向任务服务器进行任务求取。//(最科学的负载均衡)
任务服务器可能出现故障,所以应该有一个备用任务服务器,进行备用。
综上,对于提升数据库的业务能力的方法:
1 使用中间队列+连接池
2 主要的业务逻辑挪到应用服务器,数据库只做辅助的业务处理
3 使用缓存
4 读写分离,数据分区(分库分表)等等。
应用服务器开发也要提升其性能,服务器性能的四大杀手:
1 数据拷贝 -》可以使用缓存(非分布式)来处理
2 环境切换 -》指线程的切换 ,该不该用多线程,单线程还是多线程好,线程也不一定是越多越好。
如果服务器是单核服务器(采用状态机编程,效率最佳),多核,使用多线程编程,也应该尽量避免线程切换
3 内存分配 -》使用内存池,减少向操作系统申请内存
4 锁竞争 -》尽可能使用锁竞争