﻿<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Gavin&#039;s Blog &#187; 网站架构</title>
	<atom:link href="http://laigw.name/tag/%e7%bd%91%e7%ab%99%e6%9e%b6%e6%9e%84/feed" rel="self" type="application/rss+xml" />
	<link>http://laigw.name</link>
	<description>Keep it simple, stupid. Simplicity is beauty.</description>
	<lastBuildDate>Sun, 29 Jan 2012 07:14:51 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>网站架构概述</title>
		<link>http://laigw.name/post/111.html</link>
		<comments>http://laigw.name/post/111.html#comments</comments>
		<pubDate>Sat, 15 Nov 2008 09:27:03 +0000</pubDate>
		<dc:creator>Gavin</dc:creator>
				<category><![CDATA[Web前端技术]]></category>
		<category><![CDATA[网站架构]]></category>

		<guid isPermaLink="false">http://www.laigw.name/?p=111</guid>
		<description><![CDATA[一：硬架构
1：机房的选择：
    在选择机房的时候，根据网站用户的地域分布，可以选择网通或电信机房，但更多时候，可能双线机房才是合适的。越大的城市，机房价格越贵，从成本的角 度看可以在一些中小城市托管服务器，比如说北京的公司可以考虑把服务器托管在天津，廊坊等地，不是特别远，但是价格会便宜很多。
2：带宽的大小：

    通常老板花钱请我们架构网站的时候，会给我们提出一些目标，诸如网站每天要能承受100万PV的访问量等等。这时我们要预算一下大概需要多大的带宽，计算带宽大小主要涉及两个指标（峰值流量和页面大小），我们不妨在计算前先做出必要的假设：
 第一：假设峰值流量是平均流量的5倍。
 第二：假设每次访问平均的页面大小是100K字节左右。
    如果100万PV的访问量在一天内平均分布的话，折合到每秒大约12次访问，如果按平均每次访问页面的大小是100K字节左右计算的话，这12次访 问总计大约就是1200K字节，字节的单位是Byte，而带宽的单位是bit，它们之间的关系是1Byte = 8bit，所以1200K Byte大致就相当于9600K bit，也就是9Mbps的样子，实际情况中，我们的网站必须能在峰值流量时保持正常访问，所以按照假设的峰值流量算，真实带宽的需求应该在45Mbps 左右。
    当然，这个结论是建立在前面提到的两点假设的基础上，如果你的实际情况和这两点假设有出入，那么结果也会有差别。
3：服务器的划分：
    先看我们都需要哪些服务器：图片服务器，页面服务器，数据库服务器，应用服务器，日志服务器等等。
对于访问量大点的网站而言，分离单独的图片服务器和页面服务器相当必要，我们可以用lighttpd来跑图片服务器，用apache来跑页面服务 器，当然也可以选择别的，甚至，我们可以扩展成很多台图片服务器和很多台页面服务器，并设置相关域名，如img.domain.com和 www.domain.com，页面里的图片路径都使用绝对路径，如&#60;img src=&#8221;http://img.domain.com/abc.gif&#8221; /&#62;，然后设置DNS轮循，达到最初级的负载均衡。当然，服务器多了就不可避免的涉及一个同步的问题，这个可以使用rsync软件来搞定。
    数据库服务器是重中之重，因为网站的瓶颈问题十有八九是出在数据库身上。现在一般的中小网站多使用MySQL数据库，不过它的集群功能似乎还没有达 到stable的阶段，所以这里不做评价。一般而言，使用MySQL数据库的时候，我们应该搞一个主从（一主多从）结构，主数据库服务器使用innodb 表结构，从数据服务器使用myisam表结构，充分发挥它们各自的优势，而且这样的主从结构分离了读写操作，降低了读操作的压力，甚至我们还可以设定一个 专门的从服务器做备份服务器，方便备份。不然如果你只有一台主服务器，在大数据量的情况下，mysqldump基本就没戏了，直接拷贝数据文件的话，还得 先停止数据库服务再拷贝，否则备份文件会出错。但对于很多网站而言，即使数据库服务仅停止了一秒也是不可接受的。如果你有了一台从数据库服务器，在备份数 据的时候，可以先停止服务（slave stop）再备份，再启动服务（slave start）后从服务器会自动从主服务器同步数据，一切都没有影响。但是主从结构也是有致命缺点的，那就是主从结构只是降低了读操作的压力，却不能降低写 操作的压力。为了适应更大的规模，可能只剩下最后这招了：横向/纵向分割数据库。所谓横向分割数据库，就是把不同的表保存到不同的数据库服务器上，比如说 用户表保存在A数据库服务器上，文章表保存在B数据库服务器上，当然这样的分割是有代价的，最基本的就是你没法进行LEFT JOIN之类的操作了。所谓纵向分割数据库，一般是指按照用户标识（user_id）等来划分数据存储的服务器，比如说：我们有5台数据库服务器，那么 “user_id % 5 + 1”等于1的就保存到1号服务器，等于2的就保存到2好服务器，以此类推，纵向分隔的原则有很多种，可以视情况选择。不过和横向分割数据库一样，纵向分割 数据库也是有代价的，最基本的就是我们在进行如COUNT, SUM等汇总操作的时候会麻烦很多。综上所述，数据库服务器的解决方案一般视情况往往是一个混合的方案，以其发挥各种方案的优势，有时候还需要借助 memcached之类的第三方软件，以便适应更大访问量的要求。
    如果有专门的应用服务器来跑PHP脚本是最合适不过的了，那样我们的页面服务器只保存静态页面就可以了，可以给应用服务器设置一些诸如 app.domain.com之类的域名来和页面服务器加以区别。对于应用服务器，我还是更倾向于使用prefork模式的apache，配上必要的 xcache之类的PHP缓存软件，加载模块要越少越好，除了mod_rewrite等必要的模块，不必要的东西统统舍弃，尽量减少httpd进程的内存 消耗，而那些图片服务器，页面服务器等静态内容就可以使用lighttpd或者tux来搞，充分发挥各种服务器的特点。
    如果条件允许，独立的日志服务器也是必要的，一般小网站的做法都是把页面服务器和日志服务器合二为一了，在凌晨访问量不大的时候cron运行前一天 的日志计算，不过如果你使用awstats之类的日志分析软件，对于百万级访问量而言，即使按天归档，也会消耗很多时间和服务器资源去计算，所以分离单独 的日志服务器还是有好处的，这样不会影响正式服务器的工作状态。
二：软架构
1：框架的选择：
    现在的PHP框架有很多选择，比如：CakePHP，Symfony，Zend Framework等等，至于应该使用哪一个并没有唯一的答案，要根据Team里团队成员对各个框架的了解程度而定。很多时候，即使没有使用框架，一样能 写出好的程序来，比如Flickr据说就是用Pear+Smarty这样的类库写出来的，所以，是否用框架，用什么框架，一般不是最重要的，重要的是我们 的编程思想里要有框架的意识。
2：逻辑的分层：
    网站规模到了一定的程度之后，代码里各种逻辑纠缠在一起，会给维护和扩展带来巨大的障碍，这时我们的解决方式其实很简单，那就是重构，将逻辑进行分层。通常，自上而下可以分为表现层，应用层，领域层，持久层。
    所谓表现层，并不仅仅就指模板，它的范围要更广一些，所有和表现相关的逻辑都应该被纳入表现层的范畴。比如说某处的字体要显示为红色，某处的开头要 空两格，这些都属于表现层。很多时候，我们容易犯的错误就是把本属于表现层的逻辑放到了其他层面去完成，这里说一个很常见的例子：我们在列表页显示文章标 题的时候，都会设定一个最大字数，一旦标题长度超过了这个限制，就截断，并在后面显示“..”，这就是最典型的表现层逻辑，但是实际情况，有很多程序员都 是在非表现层代码里完成数据的获取和截断，然后赋值给表现层模板，这样的代码最直接的缺点就是同样一段数据，在这个页面我可能想显示前10个字，再另一个 页面我可能想显示前15个字，而一旦我们在程序里固化了这个字数，也就丧失了可移植性。正确的做法是应该做一个视图助手之类的程序来专门处理此类逻辑，比 [...]]]></description>
		<wfw:commentRss>http://laigw.name/post/111.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

