Fork me on GitHub

网站性能优化

前端优化

减少http请求数

  • 图片地图。客户单图片地图可以使用map标签来实现。如果正在导航或者其他超链接中使用多个图片,将他们转换为图片地图是加速页面的最简单的方式。
  • CSS Sprites。将多幅图片合并成单独的图片。使用CSS的background-position属性,可以将HTML元素放置到背景图片期望的位置上。
  • 内联图片。使用data:URL模式可以在Web页面中包含图片但无需额外的HTTP请求。
  • 合并脚本和样式表。理想情况下,一个页面应该使用不多于一个脚本和样式表。

使用CDN存储前端资源

CDN用于发布静态内容,如图片、脚本、样式和Flash。

可使用http://17ce.com这个网站网站使用CDN后在各地的响应速度。

添加Expires头

充分利用浏览器缓存

多域名访问前端资源

使用单独的静态资源域名。

资源数据的压缩

压缩代码大小、图片大小,开启服务器gzip压缩

优化首屏展示速度

延迟加载、异步加载

扩展阅读:

php优化

使用opcode缓存

opcode缓存简介

当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode)。Opcode cache的目地是避免重复编译,减少CPU和内存开销。如果动态内容的性能瓶颈不在于CPU和内存,而在于I/O操作,比如数据库查询带来的磁盘I/O开销,那么opcode cache的性能提升是非常有限的。

使用opcode缓存

opcode-cache

从图中可以看出,使用了opcode缓存后,php代码的生命周期少了词典扫描和表达式(将PHP代码转换为语言片段[Tokens])、解析文件(将Tokens转换成简单而有意义的表达式)、创建要执行的计算机代码(称为Opcode)几步。

opecode缓存-Zend OPcache安装使用

PHP>=5.5.0,php内置了OPcache,PHP小于5.5.0的话,要通过PCEL安装。

OPcache配置

1
2
3
4
5
6
7
8
9
10
11
12
#检查脚本时间戳是否有更新的周期,以秒为单位。 设置为0会导致针对每个请求,OPcache都会检查脚本更新。
opcache.revalidate_freq=60
#如果启用,那么 OPcache 会每隔 opcache.revalidate_freq 设定的秒数 检查脚本是否更新。 如果禁用此选项,你必须使用 opcache_reset() 或者 opcache_invalidate() 函数来手动重置 OPcache,也可以 通过重启 Web 服务器来使文件系统更改生效
opcache.validate_timestamps=1
#OPcache 哈希表中可存储的脚本文件数量上限。 真实的取值是在质数集合 { 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 } 中找到的第一个大于等于设置值的质数。 设置值取值范围最小值是 200,最大值在 PHP 5.5.6 之前是 100000,PHP 5.5.6 及之后是 1000000
opcache.max_accelerated_files=1000
#OPcache 的共享内存大小,以兆字节为单位。
opcache.memory_consumption=512
# 用来存储预留字符串的内存大小,以兆字节为单位。 PHP 5.3.0 之前的版本会忽略此配置指令。
opcache.interned_strings_buffer=16
#如果启用,则会使用快速停止续发事件。 所谓快速停止续发事件是指依赖 Zend 引擎的内存管理模块 一次释放全部请求变量的内存,而不是依次释放每一个已分配的内存块。
opcache.fast_shutdown=1

PHP 7

PHP 7相对比PHP 5.*,性能有了质的飞跃。PHP7相对于php5.6有2~3倍的性能提升。目前PHP的最新版本是PHP 7.2.5,相对于PHP 7.1也有部分性能提升。

性能评测文章参考:

PHP的性能演进(从PHP5.0到PHP7.1的性能全评测
PHP7.2、PHP7.1 性能对比

SWOOLE

Swoole是一款常驻内存的 PHP C扩展,Swoole提供了协程、Http Server、Tcp Server、UDP Server、
Websocket Server、定时器等功能

php性能分析 xhui + tideways实践

tiways是一个测试php性能的php扩展,php版本要求是大于等于7.0。如果php版本小于7.0,可以使用xhprof扩展。
xhgui用来展示测试数据,xhgui将数据保存到MongoDB。

安装tideways

在ubuntu环境下:

1
2
3
4
echo 'deb http://s3-eu-west-1.amazonaws.com/qafoo-profiler/packages debian main' > /etc/apt/sources.list.d/tideways.list
wget -qO - https://s3-eu-west-1.amazonaws.com/qafoo-profiler/packages/EEB5E8F4.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install tideways-php tideways-daemon

重启php-fpm,查看是否安装成功:

1
sudo service php7.1-fpm restart

安装MongoDB

1
2
3
sudo apt-get install mongodb
sudo apt-get install php-mongodb
sudo /etc/init.d/mongodb start

安装xhgui

1
2
3
git clone https://github.com/laynefyc/xhgui-branch.git
cd xhgui-branch
composer install

配置xhgui

添加config/config.php,添加支持扩展为tideways

1
2
3
return [
'extension' => 'tideways',
];

MongoDB加索引

1
2
3
4
5
6
7
$ mongo
> use xhprof
> db.results.ensureIndex( { 'meta.SERVER.REQUEST_TIME' : -1 } )
> db.results.ensureIndex( { 'profile.main().wt' : -1 } )
> db.results.ensureIndex( { 'profile.main().mu' : -1 } )
> db.results.ensureIndex( { 'profile.main().cpu' : -1 } )
> db.results.ensureIndex( { 'meta.url' : 1 } )

配置nginx

1.要监控的应用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

#加上下面的这两句
fastcgi_param TIDEWAYS_SAMPLERATE "25";
fastcgi_param PHP_VALUE "auto_prepend_file=/home/vagrant/Code/xhgui/external/header.php";

fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
}
2.分析平台应用
1
2
3
4
5
6
7
8
9
10
#表示省略了一些nginx配置
server {
listen 80;
listen 443 ssl http2;
server_name xhgui.app;
root "/home/vagrant/Code/xhgui/webroot";
.
.
.
}

性能分析平台搭建效果

xhgui

相关链接 :

Mysql优化

表的设计优化

  • 添加主键索引

innodb需要有一个主键,主键不要有业务用途。

  • 表的字段类型选择

    • 能选短整形,就不要选长整型

    • 能选char就避免varchar

    • 使用varchar类型的时候,长度够用就行

    • 大字段考虑分开存储

    • 字段适当冗余

索引的优化

  • 索引不要建太多

    在修改数据时,每个索引都要进行更新,降低写速度。

  • 使用覆盖索引

  • explain分析sql语句的执行计划

示例:

1
2
3
4
5
6
> explain select * from typecho_contents where cid=40;
+----+-------------+------------------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | typecho_contents | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
+----+-------------+------------------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

重要列:

type - 连接使用的类型

链接类型从最佳到最坏:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

解释:

system:表仅有一行(=系统表)。这是const联接类型的一个特例。
const:表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!
eq_ref:对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。
ref:对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。
ref_or_null:该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。
index_merge:该联接类型表示使用了索引合并优化方法。
unique_subquery:该类型替换了下面形式的IN子查询的ref: value IN (SELECT primary_key FROM single_table WHERE some_expr) unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。
index_subquery:该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引: value IN (SELECT key_column FROM single_table WHERE some_expr)
range:只检索给定范围的行,使用一个索引来选择行。
index:该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。

一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题。

key: Mysql实际使用的索引

Extra:

  • Using filesort: Mysql需要额外的步骤排序,表示语句需要优化
  • Using temporary: 使用到临时表来存储查询结果,表示语句需要优化

SQL查询优化

通过慢查询日志获取存在性能问题的SQL

慢查询日志分析工具

相关配置参数

1
2
3
4
5
6
7
8

slow_query_log # 启动停止记录慢查日志,慢查询日志默认是没有开启的可以在配置文件中开启(on)

slow_query_log_file # 指定慢查日志的存储路径及文件,日志存储和数据存储应该分开存储

long_query_time # 指定记录慢查询日志SQL执行时间的阀值默认值为10秒通常,对于一个繁忙的系统来说,改为0.001秒(1毫秒)比较合适

log_queries_not_using_indexes # 是否记录未使用索引的SQL

工具:pt-query-digest

1
pt-query-digest --explain h=127.0.0.1,u=root,p=123456  slow-mysql.log

pt-query-digest是用于分析mysql慢查询的一个工具,它可以分析binlog、General log、slowlog。可以把分析结果输出到文件中,也可以对SHOW PROCESSLIST或者通过tcpdump抓取的MySQL协议数据进行分析。分析过程是先对查询语句的条件进行参数化,然后对参数化以后的查询进行分组统计,统计出各查询的执行时间、次数、占比等,可以借助分析结果找出问题。

pt-query-digest工具的安装

因为pt-query-digest是包含在percona-tookit工具集中的,所以只要安装percona-tookit即可。percona-tookie链接:https://www.percona.com/doc/percona-toolkit/3.0/installation.html

pt-query-digest工具的使用参考

https://www.cnblogs.com/luyucheng/p/6265873.html

实时获取存在性能问题的SQL

直接通过表查询
1
2
3
4

SELECT id,user,host,DB,command,time,state,info
FROM information_schema.processlist
WHERE TIME>=1

查询当前服务器执行超过1s的SQL,可以通过脚本周期性的来执行这条SQL,就能查出有问题的SQL。

通过pt-query-digst来分析
1
pt-query-digest --processlist h=host1

特定SQL的查询优化

优化not in和<>查询

子查询改写为关联查询

1
2
3
4
5

select id,name
from a
where id
not in (select id from b)

改写后:

1
2
3
4
5

select id,name
from a
left join b on a.id=b.id
where b.id is null
------本文结束感谢阅读------
欣赏此文?求鼓励,求支持!