本博客并不是所有原创,实际上是一个知识的概括和汇总,里面我引用了不少网上、书上的内容。也给出了相关的连接。javascript
本文涉及的知识点比较多,你们能够根据关键字去搜索相关的内容和购买相应的书籍进行系统的学习。不对的地方你们予以批评指正。php
有人给我留言说,亿级 PV 就别写文章了,随便用几个开源软件就能搞定了,只要不犯什么大错。我不觉得然,若是你利用了相同的思想,使用了更高性能的基础服务,也许就能支持更多的流量并发,节约更多的服务器,优化的思路才是重点。css
本内容的视频分享见个人直播html
咱们先看一张简单的 web 架构图前端
从上到下从用户的浏览器到最后的数据库,那么咱们说先前端的优化。java
雅虎军规:http://www.cnblogs.com/paul-3...node
把多个JS、CSS在可能的状况下写进一个文件,页面里直接写入图片也是很差的作法,应该写进CSS里,小图拼合后利用 background 来定位。mysql
expires
,cache-control
,last-modified
,etag
http://blog.csdn.net/eroswang...
防止缓存,好比资源更新了,原来的作法是?v=xxxx 如今前端的打包工做能够能会生成 /v1.2.0/xxx.jslinux
接地气利用 cdn 存储前端资源nginx
分为下面三个部分来
fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 256k;
gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.0; gzip_comp_level 2; gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/json; gzip_vary on; gzip_proxied expired no-cache no-store private auth; gzip_disable "MSIE [1-6]\.";
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; }
http://mailman.nginx.org/pipe...
time wait bucket table overflow
tcp_tw_recycle 快速回收可能致使丢包的问题 https://mengkang.net/1144.html
除了上面的网络协议配置也是在系统基础以外,为了配合nginx本身里面的设定须要作以下修改
更多详细的优化配置说明:http://os.51cto.com/art/20140...
注意有不少函数和扩展被废弃,好比mysql相关的,有风险,作好测试再切换。
php 5.5 以后好像就内置了吧,须要在php.ini里添加以下配置
opcache.revalidate_freq=60 opcache.validate_timestamps=1 opcache.max_accelerated_files=1000 opcache.memory_consumption=512 opcache.interned_strings_buffer=16 opcache.fast_shutdown=1
这个选项用于设置缓存的过时时间(单位是秒),当这个时间达到后,opcache会检查你的代码是否改变,若是改变了PHP会从新编译它,生成新的opcode,而且更新缓存。
当这个选项被启用(设置为1),PHP会在opcache.revalidate_freq设置的时间到达后检测文件的时间戳(timestamp)。
这个选项用于控制内存中最多能够缓存多少个PHP文件。
你能够经过调用opcachegetstatus()来获取opcache使用的内存的总量
字符串opcache的复用,单位为MB
开启快速中止续发事件,依赖于Zend引擎的内存管理模块
Hugepage 的做用:间接提升虚拟地址和内存地址转换过程当中查表的TLB缓存命中率
opcache.huge_code_pages=1
鸟哥博客详细介绍:http://www.laruence.com/2015/...
以thinkphp为例,它会把框架基础组件(必须用到的组件)合并压缩到一个文件中,不只减小了文件目录查找,文件打开的系统调用。
经过strace
php-fpm子进程,能够清楚系统调用的过程,在我上面例子中有打开一个文件有12次系统调用(只是举例,我这里相对路径设置的缘由致使多了两次文件查找)。若是有10个文件,那就是120次,优化的效果可能不是那么明显,可是这是一种思路。
顺便说下 set_include_path
能不用就不要用,上面的demo的截图里面找不到目录就是证实。
模板把它们自定义的语法,最后转换成php语法,这样方便解析。而不是每次都解析一遍。
个人截图一直上传不成功,正好社区有这样的博客,推荐下 https://segmentfault.com/a/11...
好比原来有一个model,叫问答,如今须要开发一个有奖问答,须要支持话题打赏,里面多了不少功能。这个时候应该利用面向对象的继承的特性。而不是作下面的开发
<?php class AskModel { public function detail($id){ $info = 从数据库查询到该问题的信息; // 逻辑1 // 逻辑2 } }
<?php class AskModel { public function detail($id){ $info = 从数据库查询到该问题的信息; // 逻辑1 if($info['type'] == 2){ //... }else{ } // 逻辑2 if($info['type'] == 2){ //... }else{ } } }
这样逻辑多了,子类型多了,逻辑判断就很是重复,程序运行起来低效多是一方面,更多的是不可维护性。
业务和架构不分家,架构是创建在对业务的理解之上的。再放下上次直播的PPT (sf故障没法传图,等会补吧)
举例:
这些都是异步的思想。能分步走就分步走,能不能请求的就不请求。
专题页面,好比秒杀页面,为了应对更大的流量、并发。并且更新起来也比较方便。
好比刚刚上面说的专题页面,还有必要走整个框架的一套流程吗?进来引用一大堆的文件,初始化一大堆的东西?是否是特别低效呢?因此须要业务解耦,专题页面若是真要框架(能够首次访问以后生成静态页面)也应该是足够轻量级的。不能与传统业务混为一谈。
说业务优化,真的不得不提架构方面的东西,业务解耦以后,就有了分布式和soa,由于这在上次分享中已经都说过了,就很少说了。
只说下 soa 自定义 socket 传输协议。
最重要的就是在自定义头里面强调body_len
,注意设置为紧凑型,才能保证跨平台性 具体说明:https://mengkang.net/586.html
数据索引相关的文章网上不少了,不足的地方你们补充。
如今大多数状况都会使用innodb类型了。具体缘由是 mysql 专家给的意见。
我本身对 mysql 的优化不了解,每个细分领域都是一片汪洋,每一个人的时间精力是有限的,因此你们也不用什么都非要深刻去研究,每每是一些计算机基础更为重要。
参考这份ppt https://static.mengkang.net/u...
举例:
以前项目里有些索引是article_id
+ tag_id
联合作的主键,那么这种状况下,就是业务了属性了。主键也不是顺序递增,每插入新的数据都有可能致使很大的索引变更(了解下数据库b+索引的原理)
大多数状况下,索引扫描要比全表扫描更快,性能更好。但也不是绝对的,好比须要查找的数据占了整个数据表的很大比例,反而使用索引更慢了。
联合索引“最左前缀”,查询优化器还会帮你调整条件表达式的顺序,以匹配组合索引的要求。
CREATE TABLE `test` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `a` int(10) unsigned NOT NULL, `b` int(10) unsigned NOT NULL, `c` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `index_abc` (`a`,`b`,`c`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
能使用到索引
explain select * from test where a=1; explain select * from test where a=1 and b=2; explain select * from test where a=1 and b=2 and c=3; explain select * from test where a=1 and b in (2,3) and c=3; explain select * from test where a=1 and b=2 order by c desc;
不能使用索引
explain select * from test where a=1 and b in (2,3) order by c desc; explain select * from test where b=2;
索引更详细讲解 https://mengkang.net/1302.html
explain 搜到一篇不错的: http://blog.csdn.net/woshiqjs...
很重要的参数type
,key
,extra
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
值 | 说明 |
---|---|
const | 经过索引直接找到一个匹配行,通常主键索引的时候 |
ref | 没有主键索引或者惟一索引的条件索引,查询结果多行,在联合查询中很常见 |
index | 利用到了索引,有可能有其它排序,where 或者 group by 等 |
all | 全表扫描,没有使用到索引 |
若是有Using filesort
或者Using temporary
的话,就必需要优化了
my.ini 配置里增长
long_query_time=2 log-slow-queries=/data/var/mysql_slow.log
redis 丰富的数据类型,很是适合配合mysql 作一些关系型的查询。好比一个很是复杂的查询列表能够将其插入zset 作排序列表,而后具体的信息,经过zset里面的纸去mysql 里面去查询。
static
变量存储,好比朋友圈信息流,在一次性获取20条信息的时候,有可能,点赞的人里面20条里面有30我的是重复的,他们点赞你的a图片也点赞了你的b图片,因此这时,若是能使用static数组来存放这些用户的基本信息就高效了些。
请求结束了,下拉更新朋友圈,里面又出现了上面的一样的好友,还得从新请求一次。因此本地常驻内存的缓存就更高效了。
在A服务器上已经查询过了,在下拉更新的时候被分配到B服务器上了,难道一样的数据再查一次再存到B服务器的本地缓存里面吗,弄一个分布式缓存吧,这样防止了重复查询。可是多了网络请求这一步。
不少时候是三者共存的。
案例分析
用户积分更新
为了取数据方便把多个数据源混合缓存了,这种状况,相比你们可能都见过,这是灾难性的设计。
{ id:x, title:x, gift:{ id:x, name:x, img:x, } }
若是须要更新礼物的图片,那么全部用到过这个礼物的话题的缓存都要更新。
因为比较基础基础好的老司机就能够忽略了,新人同窗能够看下 https://mengkang.net/356.html
图片id=>uid
的关系数据,用了21g,后来改成水平分割,图片id 1000 取模,而后将分片的数据存在一个hashse 里面,这样最后的内容减小了5g,四分之一基本上。每一段使用一个Hash结构存储,因为Hash结构会在单个Hash元素在不足必定数量时进行压缩存储,因此能够大量节约内存。这一点在String结构里是不存在的。而这个必定数量是由配置文件中的hash-zipmap-max-entries参数来控制的。
下面的内容,只能是让你们有一个大概的认识,了解一个优化的方向,具体的内容须要系统学习不少不少的知识。
多进程有利于 CPU 计算和 I/O 操做的重叠利用。一个进程消耗的绝大部分时间都是在磁盘I/O和网络I/O中。
若是是单进程时cpu大量的时间都在等待I/O,因此咱们须要使用多进程。
为了让全部的进程轮流使用系统资源,进程调度器在必要的时候挂起正在运行的进程,同时恢复之前挂起的某个进程。这个就是咱们常说的“上下文切换”。
关于上下文我以前写一个简单笔记 https://mengkang.net/729.html
无限制增长进程数,则会增多 cpu 在各个进程间切换的次数。
若是咱们但愿服务器支持较大的并发数,那么久要尽可能减小上下文切换的次数,好比在nginx服务上nginx的子进程数不要超过cpu的核数。
咱们能够在压测的时候经过vmstat
,nmon
来监控系统上下文切换的次数。
# top top - 09:40:40 up 565 days, 5:47, 2 users, load average: 0.03, 0.03, 0.00 Tasks: 121 total, 2 running, 119 sleeping, 0 stopped, 0 zombie Cpu(s): 8.6%us, 0.3%sy, 0.0%ni, 90.7%id, 0.2%wa, 0.0%hi, 0.2%si, 0.0%st
通常状况下IOwait表明I/O操做的时间占(I/O操做的时间 + I/O和CPU时间)的比例。
可是也时候也不许,好比nginx来做为web服务器,当咱们开启不少nginx子进程,IOwait会很高,当再减小进程数到cpu核数附近时,IOwait会减小,监控网络流量会发现也增长。
只要是提供socket
服务,就能够利用多路复用 I/O 模型。
须要补充的知识 https://mengkang.net/726.html
strace 很是方便统计系统调用
# strace -c -p 23374 Process 23374 attached - interrupt to quit ^CProcess 23374 detached % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 30.68 0.000166 0 648 poll 12.01 0.000065 0 228 munmap 11.65 0.000063 0 228 mmap 10.54 0.000057 0 660 recvfrom 10.35 0.000056 0 708 fstat 7.76 0.000042 0 252 open 6.10 0.000033 1 36 write 5.73 0.000031 0 72 24 access 5.18 0.000028 0 72 read 0.00 0.000000 0 276 close 0.00 0.000000 0 13 13 stat 0.00 0.000000 0 269 240 lstat 0.00 0.000000 0 12 rt_sigaction 0.00 0.000000 0 12 rt_sigprocmask 0.00 0.000000 0 12 pwrite 0.00 0.000000 0 48 setitimer 0.00 0.000000 0 12 socket 0.00 0.000000 0 12 connect 0.00 0.000000 0 12 accept 0.00 0.000000 0 168 sendto 0.00 0.000000 0 12 shutdown 0.00 0.000000 0 48 fcntl 0.00 0.000000 0 12 flock 0.00 0.000000 0 156 getcwd 0.00 0.000000 0 24 chdir 0.00 0.000000 0 24 times 0.00 0.000000 0 12 getuid ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000541 4038 277 total
经过strace
查看“系统调用时间”和“调用次数”来定位问题 https://huoding.com/2013/10/0...
要想理解web服务器优化的原理,最好的办法是了解它的前因后果,实践就是最好的方式,我分为如下几个步骤:
上面是个人学习笔记,图片资源丢失了,你们能够根据相关关键词去搜搜相关的文章和书籍,更推荐你们去看书。