高性能Web站点技巧原理

来源:互联网 发布:mac 打字反应很慢 编辑:程序博客网 时间:2024/05/17 07:43

大型网站关键技术介绍

1. pv值(page views),访问量大 

带来问题

a. 流量大 10000000*2m ->解决方案 买带宽 ,优化程序(处理图片)

b. 并发量,同时访问网站的人多.,解决方案

对程序的架构重新设计.->服务器集群  示意图:

1. 数据量大->10亿记录

解决方法是

a. 表的设计合理 

b. 分表技术(垂直分割,水平分割) c. 建立索引 d. 读写分离 e. mysql配置优化(调整最大并发量,定时对数据库碎片整理,备份 crontab) f.硬件升级) 

c. 页面静态化 

d. 缓存技术(memcached)


页面静态化

简单解释一下页面静态化:




看几个概念,然后写代码:

静态网址: 比如 http://localhost/abc.html  即,如果我们访问的页面是静态页面,我们把这个url称为静态网站.

特点: 1. 利用seo (search engine optimization) 搜索引擎优化2. 访问速度快 3. 防止sql注入

http://localhost/index.php?u=xx&p=/*11288 */

如果我们写程序 loginCheck.php

[php] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:SimSun;font-size:14px;"><?php  
  2.     $id=$_GET[‘id’];  
  3.     $pwd=$_GET[‘pwd’];  
  4.     $sql=”select  pwd  from users where id=$id”;  
  5.     $res=mysql_query($sql);  
  6.     if($pwd= = =从数据库中取出的密码){  
  7.         //说明该用户存在  
  8.   }else{  
  9.     //说明用户密码错误!  
  10.   }</span>  

动态网址 :比如 http://localhost/news.php?id=112 , 即,访问的是一个PHP页面,可以传入参数.称为动态网之.

特点: 1. 不利用SEO 2. 访问速度慢 3. 有被注入sql可能

 

伪静态网址 : 在实际开发中,我们希望达到这样目的,把下面的网址

http://localhost/ news.php?lang=cn&class=sprot&id=2

修改成如下网址

http://localhost/news-cn-sport-id2.html 

上面的网址,我们称为伪静态网址 :

特点: 1. 利用SEO 2. 防止注入  3. 他任然要访问数据库,速度没有变化

 

 页面静态化技术分类:

从方式看(1. 真静态 2.伪静态)

从范围看(1.全局静态2. 局部静态化[ajax+jquery])


 压力测试工具ab.exe


介绍一款测试压力的工具   该工具程序是apache自带的, 大家在工作中可以使用该工具来测试自己的网站并发量大小,和某个页面的访问时间

 基本用法,进入到cmd 控制台

ab.exe –n 访问的总次数 –c  有多少人访问(并发量) 访问的页面url

举例说明:

ab.exe –n 10000 –c 100 http://locahost/test.php

当我们把 –c 调整到1000时,发现apache瘫痪. 给大家说下如何调整apache的最大并发量.

MPM (多路处理模块, 即 apache采用怎样的方式来处理并发.), 主要有三种方式 

1. perfork 预处理进程方式

2. worker 工作模式

3. winnt  这个一般说是windows采用的.

原理示意图:

u 如何设置我们的apache的最大并发数 ,步骤如下:

(1) 在httpd.conf 文件中 修改

# Server-pool management (MPM specific)

Include conf/extra/httpd-mpm.conf

(2) 确定当前的apahce是什么MPM模式

进入到 apache/bin 

httpd.exe –l

说明: 看 mpm_xxx.c 如果xxx是 winnt 说明是winnt  ,另外还可能是 perfork 或者  worker

(1) 修改httpd-mpm.conf 文件.

<IfModule mpm_winnt_module>

    ThreadsPerChild      1000  

    MaxRequestsPerChild    0

</IfModule>

(2) 重启apahce ,测试

 

 

因为在linux下,一般说采用的MPM是 perfork模式,我们看看如何配置.

 

<IfModule mpm_prefork_module>

    StartServers          5

    MinSpareServers       5

    MaxSpareServers      10

    MaxClients          150   #并发量

  MaxRequestsPerChild   0  #一个进程对应的线程数,对 worker更用.

</IfModule>

 

给大家一个合理的建议配置. 对大部分网站,中型网站,配置:


<IfModule mpm_prefork_module>
              StartServers         5      #预先启动
              MinSpareServers      5
              MaxSpareServers      10  #最大空闲进程
              ServerLimit          1500   #用于修改apache编程参数
              MaxClients           1000   #最大并发数
              MaxRequestsPerChild  0

</IfModule>

 

如果你的网站pv值  百万 

ServerLimit          2500   #用于修改apache编程参数
MaxClients           2000   #最大并发数

 

 

最后有一个关于html和php的访问效率图 :


分享一下页面seo技巧:

如果一个图片希望被百度到

<img alt=’小狗’ src=’’/> 

在网站前台,我们建议 不要使用frame框架,不利用seo

如果我们给图片或者视频取名字,尽量简短.

 

 

页面静态化的技术实现有两种方式

1. 使用PHP自己的缓存机制

 先说明一下OB缓存的机制.

ob1.php 代码:说明的ob的各个用法->项目中

ob2.php 代码,说明了浏览器缓存存在.



说明: 在php5.2这个版本 在php.ini有一个配置 output_buffering  ,默认是关闭,如果是关闭,这刚才的代码就会警告.

 

☞ 如何打开ob缓存

① 配置php.ini 文件 output_buffering = 4096

② 直接在程序中  ob_start();

 

1. 使用模板替换技术实现(正则表达式)

使用ob缓存机制,完成一个简单的新闻管理系统-页面静态化(目标是实现全站静态化)


 

开发步骤:

(1) 做的页面:


(1)  简单的分析页面

 

(2) 创建数据表

 

create table news(

id int unsigned primary key auto_increment, /*新闻id,做成自增*/

title varchar(128) not null default ‘’, /*标题*/

content varchar(256) not null default ‘’, /*新闻内容*/

filename varchar(32) not null default ‘’ /*将来这个新闻对应静态页面*/

) engine=MyISAM charset utf8

 

测试数据:

insert into news (title,content) values('hello1','北京你好');

insert into news (title,content) values('hello2','四川你好');

 

 

(3) 走码

到此,我们已经实现了传统的查询任务, 

分析代码后,我们发现问题是,因为新闻内容相对稳定,所以没有必要每次都查询。优化的思路是: 当第一人查看某个新闻时,我们就生成一个对应的静态页面,当后面的人在查看,直接返回该静态页面即可.

代码实现: 

newsList.php 代码

showNews.php代码 


再想想,上面的代码缺点是什么?

cms(内容管理系统,新闻,软件发布, 文章管理) 内容就固定不变,我们不能接受.

解决方案:

1 我设一个超时,30s, 我们保证30内不去修改,超过30秒,就更新一把.

走码:

2 上面的解决方案有时间延时,所以如果我们希望静态化没有时间延时,就应该使用模板提换技术来搞定.

思路: 图.





代码实现:整理

newslist.php 



addnews.html页面



newsAction.php 页面



思考题:

① 请大家完成更新新闻的这个页面静态处理

② 如何把newsList.php 也做成一个静态页面.->思想

 

  任务是: 把新闻管理系统的首页面也静态化.

通用的CMS系统的示意图:


对我们的新闻管理系统首页静态化

 

思考: 我们能不能再添加新闻后,就直接静态化首页面, 如果你的确希望只要首页的内容有变化,就立即更新,最后的代理整理:

把所有的动态页面,放入到manage文件夹:

manage.html

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:SimSun;font-size:14px;"><html>  
  2. <head>  
  3. <meta http-equiv='content-type' content='text/html;charset=utf-8'/>  
  4. </head>  
  5. <h1>管理新闻</h1>  
  6. <hr/>  
  7. <a href='addNews.html'>添加新闻</a>|  
  8. <a href='newsList.php'>更新首页</a>|  
  9. <a href='xxx.php'>列出所有信息</a>  
  10. </html>  
  11.   
  12. addNews.html  
  13. <head>  
  14. <title>新闻标题</title>  
  15. <meta http-equiv="content-type" content="text/html;charset=utf-8" />  
  16. </head>  
  17.   
  18. <!--我们在添加新闻时,就同时生成一个对应的新闻页面(比如你设计好的一个新闻内容显示模板)-->  
  19.   
  20. <form action="newsAction.php" method="post">  
  21. <table>  
  22. <tr><td>新闻标题</td><td><input type="text" name="title"/></td></tr>  
  23. <tr><td>新闻内容</td><td><textarea cols="50" rows="10" name="content"></textarea></td></tr>  
  24. <tr><td><input type="submit" value="添加"/></td><td><input type="reset" value="重新填写"/></td></tr>  
  25. <!--隐藏区-->  
  26. <input type='hidden' name='oper' value='add'/>  
  27. </table>  
  28. </form>  
  29. </html></span>  

newsAction.php

[php] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:SimSun;font-size:14px;"><?php  
  2.   
  3.     //处理用户的添加/更新/删除...请求  
  4.     //先获取 oper值  
  5.     $oper=$_POST['oper'];  
  6.     if($oper==='add'){  
  7.         //接收用户的新闻的各个信息  
  8.         $title=$_POST['title'];  
  9.         $content=$_POST['content'];  
  10.         //把新闻添加到数据库  
  11.         //这里大家可以使用工具类完成.  
  12.         $con=mysql_connect("localhost","root","root");  
  13.         if(!$con){  
  14.             die("连接失败");  
  15.         }  
  16.         mysql_select_db("newssys",$con);  
  17.         $sql="insert into news values(null,'$title','$content','')";  
  18.         //echo $sql;  
  19.         if(mysql_query($sql,$con)){  
  20.             //生成静态文件.  
  21.             $id=mysql_insert_id();  
  22.             $html_filename='news-id'.$id.'.html';  
  23.             $html_fp=fopen("../".$html_filename,'w');  
  24.             //把模板文件读取.  
  25.             $fp=fopen('news.tpl','r');  
  26.             //循环读取  
  27.             //如果没有读到文件的最后,就一直读取  
  28.             while(!feof($fp)){  
  29.                 //一行行读.  
  30.                 $row=fgets($fp);  
  31.                 //把占位符替换掉->小函数 myreplace  
  32.                 //问题?  
  33.                 $row=str_replace('%title%',$title,$row);  
  34.                 $row=str_replace('%content%',$content,$row);  
  35.                 fwrite($html_fp,$row);  
  36.             }  
  37.             //关闭文件  
  38.             fclose($html_fp);  
  39.             fclose($fp);  
  40.             echo "恭喜你,添加成功<a href='manage.html'>管理新闻</a>";  
  41.             //怎样让首页面立即更新.  
  42.             include "newsList.php";  
  43.   
  44.         }else{  
  45.             die('添加失败');  
  46.         }  
  47.     }else if($oper==='update'){  
  48.       
  49.     }else if($oper==='delete'){  
  50.       
  51.     }</span>  

newsList.php

[php] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:SimSun;font-size:14px;"><?php  
  2.     //列出新闻列表  
  3.     //这里,我使用最简单的方法来操作,没有使用mvc模式  
  4.     //这里你们可以使用工具类完成. db.class.php  
  5.     $con=mysql_connect("localhost","root","root");  
  6.     if(!$con){  
  7.         die("连接失败");  
  8.     }  
  9.     mysql_select_db("newssys",$con);  
  10.     $sql="select * from news";  
  11.     $res=mysql_query($sql,$con);  
  12.         ob_start();  
  13.         echo "<head><meta http-equiv='content-type' content='text/html;charset=utf-8' /></head>";  
  14.         echo "<h1>新闻列表</h1>";  
  15.         echo "<table>";  
  16.         echo "<tr><td>id</td><td>标题</td><td>查看详情</td><td>修改新闻</td></tr>";  
  17.         //循环的取出新闻列表  
  18.         while($row=mysql_fetch_assoc($res)){  
  19.         echo '<tr><td>'.$row['id'].'</td><td>'.$row['title'].'</td><td><a href="news-id'.$row['id'].'.html">查看详情</a></td><td><a href="#">修改页面</a></td></tr>';  
  20.         }  
  21.         echo "</table>";  
  22.         $str_ob=ob_get_contents();  
  23.         file_put_contents('../index.html',$str_ob);  
  24.         //这里关闭资源.  
  25.         //清空ob  
  26.         ob_clean();  
  27.         echo "恭喜你,首页面更新成功<a href='../index.html'>点击查看最新新闻列表</a>";  
  28.   
  29.         mysql_free_result($res);  
  30.         mysql_close($con);  
  31. </span>  

完毕,大家可以进一步深入的完成修改和删除.

 真静态的优缺点分析

优点: 1. 利用SEO  2. 访问速度快. 3. 防止sql注入

缺点: 1. 因为真静态会生成大量的html文件,占用磁盘空间, 如果你把所有的静态页,都放在同一文件夹,寻找文件的速度随着文件的增多,速度变慢,因此可以考虑创建子文件夹来放.

 

在以下情况不建议使用真静态:

1.实时性要求高的网站或者页面.(股票、基金)

2.数据量大,同时查询一次后,以后很少查询(国家学历认证网,电信话费查询系统.)

3.不愿意被seo到的页面或者网站

 

 

 

 伪静态技术

在我们实际开发中,有需要,不希望使用真静态., 但是有希望利于SEO,可以考虑使用伪静态.

http://localhost/news.php?type=music&id=100   

我们希望这个地址可以用下面的访问url来替换

http://localhost/news-music-id100.html

 

 

上面的问题可以使用伪静态

 

1. 实现方式有 直接使用正则表达式来完成

2. 使用apache自带的rewrite机制来完成

 

 

看需求:

http://localhost/content.php/1,122,8912.html

 

我希望上面的地址

http://localhost/content.php?a=1&b=122&c=8912

 

实现思路: 

1. 我们可以使用str 函数,来进行分割处理->可行,但是不够灵活

2. 使用正则来处理

 

代码是:

[php] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:SimSun;font-size:14px;">$path_info=$_SERVER['PATH_INFO'];  
  2.     $reg='/(\d+),(\d+),(\d+)\.html$/i';  
  3.   
  4.     preg_match($reg,$path_info,$res);  
  5.   
  6.     echo "<pre>";  
  7.     print_r($res);  
  8.     echo "</pre>";</span>  

在实际开发中,我们实现伪静态,用的更多的还是rewrite 机制,但是他任然是以正则技术为基础的.

 

我们看看如何实现:

 

说明: 

比如 http://www.hsp.com/news.php?type=music&id=100  

希望上面的url 变成 

http://www.hsp.comt/news-music-id100.html 

 

 

原理图


步骤开始:

(1) 启用rewrite模块,在默认情况下,没有启用

修改httpd.conf文件

#启动rewrite模块

LoadModule rewrite_module modules/mod_rewrite.so

 

确认是否启动成功

<?php phpinfo();?>

(2) 配置我们的虚拟主机

httpd.conf 打开虚拟主机的配置文件

 

# Virtual hosts

Include conf/extra/httpd-vhosts.conf

 

修改 httpd-vhost.conf

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:SimSun;font-size:14px;"><VirtualHost *:80>  
  2.     DocumentRoot "C:/myenv/apache/htdocs/static2"  
  3.     #Directory配置节点,用于指定该目录下的文件或是图片.的访问权限  
  4.     #设置虚拟主机的错误页面,欢迎页面   
  5.     <Directory "C:/myenv/apache/htdocs/static2">  
  6.     </Directory>  
  7. </VirtualHost></span>  

(1) 在hosts文件中,配置ip和主机的对应关系

127.0.0.1 www.hsp.com

(2) 这时我们访问 http//www.hsp.com/news.php

我们可以访问到该页面.

☞ 一个重要的知识点:

在apache服务器中,如果某个文件夹,没有指定访问权限,则以上级目录的权限为准,如果他自己指定了访问权限,则以自己的为准.

请注意,在配置访问权限的时候,顺序很重要:

#Order allow,deny 表示先看allow ,在看deny,留下的就是可以访问

    Order deny,allow

    Deny from all

    allow from 127.0.0.1

 

(3) 关于<Directory> 节点配置必须掌握

比较完整的配置文件

第一种配置方式

<VirtualHost *:80>

    DocumentRoot "C:/myenv/apache/htdocs/static2"

    #Directory配置节点,用于指定该目录下的文件或是图片.的访问权限

    #设置虚拟主机的错误页面,欢迎页面 

    ServerName www.hsp.com

    <Directory "C:/myenv/apache/htdocs/static2">

#这里可以指定是否让人访问

#Allow from all

#是否列出文件目录结构

# 如果希望列出 indexes 不希望 none

#Options indexes

#如何配置网站的首页面

DirectoryIndex abc.html abc2.html

#如何配置404错误页面,引导用户引入新页面

errorDocument 404 /404.html

#配置我们的rewrite规则

RewriteEngine On

#rewrite的规则 如果 aaa.html 就跳转到news.php 

#$1 表示反向引用,第一个子表达式的内容

#说明如果在正则规范中直接引用子表达式的内容,则使用\n

#如果是在后面因为,则使用$n

RewriteRule news-([a-zA-Z]+)-id(\d+)\.html$  news.php?type=$1&id=$2

    </Directory>

</VirtualHost>

 

特别说明: 容易犯的错误,一定要记住启用rewrite模块.


思考: 上面我们配置都要去修改 httpd-vhost.文件,但管理员不给你这个权限,怎么办?

思路: 可以把配置,写到 .htaccess文件.

 

第二种配置方式: 即把一部分配置放在 http-vhost.conf 文件, 把rewrite 规则放在 .htaccess

<VirtualHost *:80>

    DocumentRoot "C:/myenv/apache/htdocs/static2"

    #Directory配置节点,用于指定该目录下的文件或是图片.的访问权限

    #设置虚拟主机的错误页面,欢迎页面 

    ServerName www.hsp.com

    <Directory "C:/myenv/apache/htdocs/static2">

#这里可以指定是否让人访问

#Allow from all

#是否列出文件目录结构

# 如果希望列出 indexes 不希望 none

#Options indexes

#如何配置网站的首页面

DirectoryIndex abc.html abc2.html

#如何配置404错误页面,引导用户引入新页面

errorDocument 404 /404.html

#如果你配置了allowoverride all 这表示到对应的目录的.htaccess去匹配规则

allowoverride all

    </Directory>

</VirtualHost>

 

在对应的文件下 .htaccess文件

<IfModule rewrite_module>

#如果rewrite 模块启用

#配置我们的rewrite规则

RewriteEngine On

#rewrite的规则 如果 aaa.html 就跳转到news.php 

#$1 表示反向引用,第一个子表达式的内容

#说明如果在正则规范中直接引用子表达式的内容,则使用\n

#如果是在后面因为,则使用$n

RewriteRule news-([a-zA-Z]+)-id(\d+)\.html$  news.php?type=$1&id=$2

#RewriteRule aaa.html  news.php

</IfModule>

 

请注意: 项目中的 .htaccess文件的配置也是继承管理

 

第三种配置方法:

http-vhost.conf

<VirtualHost *:80>

    DocumentRoot "C:/myenv/apache/htdocs/static2"

    #Directory配置节点,用于指定该目录下的文件或是图片.的访问权限

    #设置虚拟主机的错误页面,欢迎页面 

    ServerName www.hsp.com

    <Directory "C:/myenv/apache/htdocs/static2">

#如果你配置了allowoverride all 这表示到对应的目录的.htaccess去匹配规则

allowoverride all

    </Directory>

</VirtualHost>

 

.htacces文件 

 

#这里可以指定是否让人访问

#Allow from all

#是否列出文件目录结构

# 如果希望列出 indexes 不希望 none

#Options indexes

#如何配置网站的首页面

DirectoryIndex abc.html abc2.html

#如何配置404错误页面,引导用户引入新页面

errorDocument 404 /404.html

<IfModule rewrite_module>

#如果rewrite 模块启用

#配置我们的rewrite规则

RewriteEngine On

#rewrite的规则 如果 aaa.html 就跳转到news.php 

#$1 表示反向引用,第一个子表达式的内容

#说明如果在正则规范中直接引用子表达式的内容,则使用\n

#如果是在后面因为,则使用$n

RewriteRule news-([a-zA-Z]+)-id(\d+)\.html$  news.php?type=$1&id=$2

#RewriteRule aaa.html  news.php

</IfModule>


 伪静态的实际运用

1. 在一个项目中有两个文件夹,public 和 private ,public文件夹的图片可以被所有人访问.

private只能自己访问.请问如何实现.

 

第一个方法是. 在 public 和 private 下创建 .htaccess 文件,对于private 只让127.0.0.1访问 public 文件都可以访问

private 文件夹下的配置 .htaccess


Order deny, allow

deny from all

allow from 127.0.0.1

 

这个的缺点是,没有办法去控制,本apahce的另外一个虚拟主机请求., 另外不能精细化控制,于是我们就换了一个思路使用 http的 referer头信息搞定这个防盗链需求.

 

第二方法.在private 文件夹下 .htaccess

<ifModule rewrite_module>

RewriteEngine On

#你怎么知道,这个请求就是www.hsp.com发来的. referer

#如果你请求的是一个jpg图片, 就禁止

RewriteCond %{HTTP_REFERER} !www.hsp.com  

RewriteRule .*\.jpg -[F]

</ifModule>

 

☞ 说一下如果你的RewriteCond有多个条件

<ifModule rewrite_module>

RewriteEngine On

#你怎么知道,这个请求就是www.hsp.com发来的. referer

#如果你请求的是一个jpg图片, 就禁止

RewriteCond %{HTTP_REFERER} !www.hsp.com 

#RewriteCond %{ REQUEST_FILENAME} !-f

RewriteRule .*\.jpg -[F]

</ifModule>

1. 关于404的说明  就是对于ie浏览器而言,404页面的内容大小不能低于512b字节

2. 如果你在<Directory>节点配置了 Options Indexes , 同时你有启用了 rewriteEngine On你会看到403 的禁用提示., 原因是因为 我们的父级目录的Options 本身就配好 ,

Options Indexes FollowSymLinks  ,所以,我们要么就不配,要么就一样.

 伪静态实际运用案例2



在www.hsp.com 的主目录下,我们编写了 .htaccess文件,并增加规则


#增加规则

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. [img=http://img.bbs.csdn.net/upload/201403/07/1394181458_228087.png][/img]  
  2. [img=http://img.bbs.csdn.net/upload/201403/07/1394181464_304731.png][/img]  

 伪静态的实际运用3->引出rewriteCond的使用

思考: 可能有条件指令.

网上找到方案:

最后的配置在 .htaccess 

#如果请求的不是一个文件

RewriteCond %{REQUEST_FILENAME} !-f

#并且不是一个目录

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ccc.html index.php

 

伪静态的实际运用案例4:

在TP框架中使用rewrite简化url地址,目的是SEO, 步骤

1. 在httpd.conf 文件中启用rewrite模块

2. 在虚拟主机中配置 allowoverride all

3. 在tp的配置文件中 conf/config 文件把 URL_MODEL 配置2

4. 在tp框架的入口目录增加 .htaccess文件 写入规则



u 伪静态的特点


u 如何选用伪静态还是真静态,还是不静态?



高性能Web站点

概述一般而言,我们评估一个Web站点速度如何,通常先置身于用户的角度,访问该站点的一系列页面,体验等待时间。对于每个页面来说,等待时间从用户输入页面地址或点击跳转链接开始,一直持续到新的网页完整的展现出来。如何构建高性能Web站点,可以就一下几个方面进行着手。

1优化招数

服务器并发策略

1.这里的吞吐率特指Web服务器单位时间内处理的请求。
2.压力测试的前提:1>并发用户数 2>总请求数 3>请求资源描述
3.用户平均请求等待时间主要用户衡量服务器在一定并发用户数的情况下,对于单个用户的服务器质量;而服务器平均请求处理时间与前者相比,则用于衡量服务器的整体服务质量,它其实就是吞吐率的倒数。
4.对http header中标记为Connection: Keep-Alive的请求,开启web服务器的长连接支持。减少系统调用accept的次数,即减少建立连接的开销。
5.老调重弹,进程,内核级线程和用户级线程在不同情况下的优劣。IO模型,mmap(内村映射),直接IO,例如sendfile syscall以及异步IO等。多路IO复用(select, poll,epoll and kqueue etc)
6.服务器并发策略
1> 一个进程处理一个连接,非阻塞IO。稳定性强,但context switch的开销随http request递增而快速增长。
2> 一个内核级线程处理一个连接,非阻塞IO,多进程多线程混合方式。Context switch的问题依然存在。理论上可以支持更多的并发连接。
3>一个进程处理多个连接,非阻塞IO。(epoll, kqueue)lighttpd, nginx。支持并发性能强劲。 上述情况的适用范围不能一刀切,而且这里都是指单机并发,需根据实际情况(实际并发数)来选择。通常,在并发用户数较大的情况下,Web服务器使用什么样的并发策略,是影响最大并发数的关键。

动态内存缓存

在实际应用中,动态内容缓存可能是使用得最多的技术,但是并不见得所有的动态内容都适合使用网页缓存,缓存带来的性能提升恰恰与有些动态数据实时交互的需求形成矛盾,这就是一个权衡。
1. 缓存动态生成的html代码。
2. 把动态内容静态化,直接缓存整个html文件。这样就可以直接访问缓存。这时的更新策略:
1>在数据更新时重新生成静态化内容 2>定时重新生成静态化内容
3. 使用SSI(server side include)进行局部静态化。但web server的SSI功能会对静态文件的吞吐率有负面影响。

动态脚本加速

加快脚本语言的执行速度;缓存中间代码(opcode)以供复用。

浏览器缓存

减少http请求,充分利用浏览器的缓存。而webapp通过http协议(更具体位置就是http header)来与浏览器协商,那些东东浏览器可以使用其缓存即可。
1. Last-Modified/If-Modified-Since
2. ETag/If-None-Match
3.Expires + Cache-Control: max-age=<seconds>
1和2需要浏览器和webserver交互后,有服务器端通知浏览器是否使用浏览器缓存,而3则是在过期前直接使用浏览器缓存,这样就直接kill掉了http request。同时还需注意,在使用SSI的内容中,由于整个页面是服务器动态生成的,所以Last-Modified标记在不同的Web服务器中有不同的生成方法。

Web服务器缓存

这个第二点动态内存缓存有区别,前者更指缓存是否命中与否完全由应用程序决定,且缓存方式也有应用来决定;而后者更指有web服务器通过URL决定是否缓存命中,比如静态内容或者更新不太频繁的动态内容就比较时候由其缓存。

反向代理缓存

Web服务器隐藏在代理服务器之后。这种代理机制称为反向代理(Reverse proxy),同时,实现这种机制的服务器便成为反向代理服务器。隐藏在反向代理服务器之后的Web服务器,我们习惯称它为后端服务器(Back-end server),当然,反向代理服务器就被称为前端服务器(Front-end server)。
引入反向代理服务器的目的之一就是基于缓存的加速。我们可以将内容缓存在反向代理服务器上,所有缓存机制的实现仍然采用HTTP/1.1协议。
缓存命中率和后端吞吐率的理想技术模型
缓存丢失率=(活跃内容数/(实际吞吐率×平均缓存有效期))×100%
缓存命中率= 1-缓存丢失率 后端吞吐率= 活跃内容数/平均缓存有效期
缓存命中率= (1-(后端吞吐率/实际吞吐率))×100%
后端吞吐率 = (1 – 缓存命中率)×实际吞吐率
结论: 1. 活跃内容数和平均缓存有效期一定的情况下,缓存命中率与实际吞吐率成正比。
2. 实际吞吐率和平均缓存有效期一定的情况下,缓存命中率与活跃内容数成反比。
3. 活跃内容数和实际吞吐率一定的情况下,缓存命中率与平均缓存有效期成正比。
4. 活跃内容数一定的情况下,后端吞吐率与平均缓存有效期成反比。
5. 平均缓存有效期一定的情况下,后端吞吐率与活跃内容数成正比。
6. 缓存命中率的变化不一定会影响后端吞吐率。
7. 后端吞吐率的变化不一定会影响缓存命中率。
ESI – Edge Side Include类似与SSI,但不在webserver端组装内容,而是在http代理服务器上组装内容,包括反向代理。在处理只有局部更新动态内容时AJAX是更好的原则,它不依赖与底层webserver的实现,但ESI的优势在于再有多个后端服务器的情况下,变可以避免多个后端的重复组装,减少总工作量。

Web组件分离

从以下几个方面来看Web组件的差异:
1. 文件大小
2. 文件数量
3. 内容更新频率
4. 预计并发用户数
5. 是否需要脚本解释器
6. 是否涉及大量CPU计算
7. 是否访问数据库
8. 访问数据库的主要操作是读还是写
9. 是否包含RPC
对每种类型的Web组件采取不同的优化方式(一种或多种):
1. 是否使用epoll模型
2. 是否使用sendfile() syscall
3. 是否使用异步IO
4. 是否支持HTTP持久连接(http keep-alive)
5. 是否需要opcode缓存
6. 是否使用动态内容缓存以及有效期为多长
7. 是否使用Web服务器缓存以及有效期为多长
8. 是否使用浏览器缓存以及有效期为多长
9. 是否使用反向代理缓存以及有效期为多长
10. 是否使用负载均衡策略
按照Web组件的不同类型将其放在不同的二级域名/机器/不同类型的WebServer
同时,还需考虑到不同的浏览器对同一个域名下的访问有多大并发数限制,而使用多个域名。
IE6,7 2(http/1.1)
IE8 6(http/1.1)
Firefox2 2(http/1.1)
Firefox3 6(http/1.1)
发挥各自的潜力
对于动态内容:开启opcode缓存,使用足够快的CPU,足够大的内存,多进程以及与数据库保持高速连接
对于静态内容:支持epoll,非阻塞IO,异步IO,使用sendfile,单进程(对于IO密集型任务,多进程无法发挥优势),使用高速磁盘,使用RAID
对于image, css and script分配合理设置其过期时间(expires)

分布式缓存

使用分布式缓存避免应用服务器的内存缓存瓶颈,使其更易于扩展。当使用多台应用服务器时,分布式缓存易于内容共享。

数据库性能优化(泛泛而谈)

1.合理的执行计划,包括合理使用索引
2.使用慢查询分析工具,找出执行很慢的sql并优化之。
3.合理的数据库缓存,索引缓存,数据缓存等
4.更具实际需求选择合理的数据库引擎或数据库
5.反范式化设计,对查询带来优化,但增加写和更新的工作量。
6.放弃关系型数据库,针对实际情况,读写要求极高时 数据库扩展:读写分离,按业务实施合理的垂直分区,对热点表进行水平分区。

Web负载均衡

DNS负载均衡
需要DNS服务商提供该功能,且DNS记录存在缓存,无法及时修改,带来更新延迟。
反向代理负载均衡
HTTP重定向和DNS解析在请求的调度上体现在“转发”上,而其则体现在“转移”。
任何对于实际服务器的http请求都必须经过调度器;调度器必须等待实际服务器的http响应,并将它反馈给用户。
由于调度策略在自己手中,就可以使用诸如按照权重进行调度等策略。也可以对个应用服务器进行健康监控,对无效服务器不在把请求转移给它;还可以实现sticky sessions。
作为负载均衡调度器的反向代理服务器在扩展上的制约,反向代理服务器的处理能力制约了整个集群的处理能力,其次,容易出现单点故障
IP负载均衡
Netfilter+ IPVS
用iptables修改Netfilter规则,进行基于IP的tcp包转发,也即调度。 IPVS(IP Virtual Server)也成为LVS(Linux Virtual Server)。
两者结合的具体策略有 1. LVS + NAT
2. LVS + DR

2其他编辑

内容分发和同步 WebDAV rsync etc
分布式文件系统
分布式计算
十二 性能监控
工具列表:
1. MRTG 网卡流量报告,可以获取实际带宽(Max Speed),它便是从交换机接收端口获得的最大接收速度,同时也是该主机的最大数据发送速度。
2. apache ab 通过http进行压力测试
3. *nix中的strace, 追踪系统调用
4. 优秀的web server: apache, lighttpd, nginx
5. 反向代理:varnish
6. msyql工具: mysqlreport 数据库状态信息报表 mysql-proxy 数据库反向代理 spock-proxy 分区反向代理
7. Nmon OS实时监控
8. Cacti 系统监控
9. 监控宝 响应时间监控
10. 分布式缓存 memcached</seconds>
0 0