Friday, April 28, 2006

How much money can you make with a web site?

There are two reasons why you would spend the time that it takes to create a web site:
  1. You enjoy it. For example, you might enjoy bicycling as a hobby and you enjoy writing about it to spread the word.

  2. You have read How to make a million dollars and you are thinking about starting a web site as a business -- specifically to generate revenue.
When I started HowStuffWorks, it began strictly as a hobby. I worked on HowStuffWorks because I enjoyed it. Eventually the site had so many visitors that it had to become a business. So, sometimes, you end up moving from #1 to #2 whether you like it or not.

In Lesson #2 - the different types of web sites, you learned that there are different kinds of web sites and they generate revenue in different ways. For example:
  • Retail web sites generate revenue from sales

  • Content web sites generate revenue from advertising

  • Dating and porn web sites generate revenue from subscriptions

  • Transactional web sites like Ebay generate revenue from each transaction.

  • And so on...
Let's start by looking at content web sites that make their money off of advertising revenue. How much money can a simple content web site make?

Right now, if you look in the right sidebar of WebKEW, there is a single sidebar ad being provided by Google. This is called a Google AdSense ad, and these ads are incredibly easy to set up and use. How much money can a single sidebar ad like that generate?

I have a friend with a small web site that uses AdSense. On his site he has placed a Google sidebar ad like this. Google provides statistics for his site on a daily basis. Looking at his site's performance between April 1, 2005 and April 21, 2005, here is what we find:
  • On average, his site displays 3,100 sidebar ads per day. We know, by looking at the log file statistics on his site, that he receives about 1,000 unique visitors a day. So each visitor looks at about 3.1 pages each, and that means roughly 3,100 ad impressions per day are displayed on his web site.

  • On average, those 3,100 ad impressions per day generate 60 clicks. With Google AdSense, you get paid only when someone clicks.

  • On average, each one of those clicks generates 15 cents.

  • So, on average, his site is making $9.00 per day.
Another common way to talk about the revenue of his site would be to say that, "He is getting a $2.90 average CPM." CPM translates into "Cost Per Thousand", when the M is the roman numeral for thousand. That means that, for every 1,000 ad impressions he displays, he is receiving $2.90 on average. Between April 1 and April 21 he displayed a total of almost 67,000 ad impressions. So:
    67,000 / 1000 x $2.90 = $194
In a typical month, he normally receives about $270 from Google.

Your mileage will vary depending on the type of visitors that your site attracts, but those results are fairly typical. A Google AdSense ad tends to generate between $2 and $3 CPM on average. Here are some scenarios:
  • If your site has 1,000 visitors a day and they read 3 pages per visit, you get 3,000 page impressions a day and make about $270 per month.

  • If your site has 1,000 visitors a day and they read 5 pages per visit, you get 5,000 page impressions a day and make about $435 per month.

  • If your site has 10,000 visitors a day and they read 5 pages per visit, you get 50,000 page impressions a day and make about $4,350 per month.

  • If your site has 100,000 visitors a day and they read 5 pages per visit, you get 500,000 page impressions a day and make about $43,500 per month.

  • And so on
Typically a site will put several ads on a page. For example, there might be a banner ad at the top, a sidebar ad along the side and another ad at the bottom. You cannot simply multiply by three to calculate the revenue -- banner ads tend not to perform as well as sidebar ads, ads at the bottom of the page tend to perform not as well as ads at the top, multiple ads on a page tend to dilute the click rate of other ads on the page, and so on. But let's imagine that you put three Google AdSense ads on your pages and you get a total of $5 CPM as a result.

If you can build a site like About.com with an Alexa Rank of 100 or so, you can see that there is a lot of money to be made. 15 million visitors come per month. They read 5 pages each. You make $375,000 per month just off of those 3 ads. You are making 2.5 cents every time someone comes to visit. By adding other features to your pages, like Google search boxes, small affiliate ads, pop-under ads, etc., you can push the revenue-per-visitor number up towards 5 cents per visitor on a large site.

Here is a funny side note that is interesting. Wikipedia.org is a very large web site. It has about 8 million pages and an Alexa Rank of about 100, meaning that it gets about 10 million visitors a month. Right now, Wikipedia has zero ads on the site. If they were to put ads on their pages, and if the average visitor reads 5 pages, it would mean that Wikipedia could be making somewhere between $250,000 and $500,000 per month, or $3 to $6 million per year. Pretty amazing.

What about a retail site? In this case, calculating revenue ahead of time can be trickier because revenue per visit can be all over the map. But here is a way to think about it. Let's say that you put up your retail site and attract some visitors. You find that, for every thousand visitors who come to the site, two of them on average make a purchase. You also find that, on average, you make $5 profit from a purchase. So you are making $10 per 1,000 visitors. In other words, the amount of money you make tends to be not that different from the money made on a content web site. You might make between $1 and $20 per one thousand visitors. It depends on what you sell, how much profit you make on each sale, etc. Of course, there can be niches where far more than two people per thousand make a purchase. I know of sites where the number is more like 10 or 20. If you can create such a site, then you are in very good shape.

Monday, April 24, 2006

利用 ASP.NET 的内置功能抵御 Web 攻击

ASP.NET 开发人员应当始终坚持的做法

如果您正在阅读本文,可能就不需要再向您灌输 Web 应用程序中的安全性愈来愈重要这一事实了。您需要的可能是一些有关如何在 ASP.NET 应用程序中实现安全性的实际建议。坏消息是,没有任何开发平台 — 包括 ASP.NET在内 — 能够保证一旦采用了该平台,您就能够编写百分百安全的代码。谁要是这么说,一准在撒谎。好消息是,就 ASP.NET 来说,ASP.NET,特别是版本 1.1 和即将发行的版本 2.0,集成了一些便于使用的内置防御屏障。

光是应用所有这些功能并不足以保护 Web 应用程序,使其免受任何可能和可预见的攻击。但是,如果与其他防御技巧和安全策略相结合,内置的 ASP.NET 功能将可以构成一个强大的工具包,有助于确保应用程序在安全的环境中运行。

Web 安全性是各种因素的总和,是一种范围远超单个应用程序的策略的结果,这种策略涉及数据库管理、网路配置,以及社会工程和 phishing。

本文的目的在于说明 ASP.NET 开发人员为了将安全标准保持到合理的高度,所应始终坚持的做法。这也就是安全性最主要的内容:保持警惕,永不完全放松,让坏人越来越难以发起黑客攻击。

下面我们来看看 ASP.NET 提供了哪些可以简化这项工作的功能。

威胁的来源

在表 1 中,我汇总了最常见的 Web 攻击类型,以及应用程序中可能导致这些攻击得手的缺陷。

攻击 攻击的可能发起人

跨站点脚本 (XSS)

回显到页的不可信用户输入

SQL 注入

串连用户输入以形成 SQL 命令

会话劫持

会话 ID 猜测和失窃的会话 ID Cookie

一次单击

通过脚本发送的未被察觉的 HTTP 张贴

隐藏域篡改

未检查(且受信)的隐藏域被填充以敏感数据

表 1. 常见的 Web 攻击

列表中显现出来的关键性事实有哪些?在我看来,起码有以下三点:

无论您何时将何种用户输入插入浏览器的标记中,您都潜在地将自己暴露在了代码注入攻击(任何 SQL 注入和 XSS 变种)之下。

必须以安全的方式实现数据库访问,就是说,应当为数据库使用尽可能少的权限,并通过角色来划分各个用户的职责。

永远都不通过网络发送敏感数据(更别说是明文了),并且必须以安全的方式将敏感数据存储在服务器上。

有意思的是,上面的三点分别针对的是 Web 安全性的三个不同方面,而这三个方面结合起来,才是唯一的一种生成防攻击、防篡改应用程序的合理方式。Web 安全性的各个层面可以总结如下:

编码实践:数据验证、类型和缓冲区长度检查,防篡改措施

数据访问策略:使用决策来保护可能最弱的帐户,使用存储过程或者至少是参数化的命令。

有效的存储和管理:不将关键性数据发送到客户端,使用哈希代码来检测操作,对用户进行身份验证并保护标识,应用严格的密码策略

如您所看到的,只有可以通过开发人员、架构师和管理员的共同努力,才可以产生安全的应用程序。请不要假定您能够以其他方式达到同样目的。

编写 ASP.NET 应用程序时,您并不是独自面对黑客大军:唯一的武器是通过自己的大脑、技能和手指键入的代码行。ASP.NET 1.1 和更高版本都会施加援手,它们具有一些特定的功能,可以自动提高防御以上列出的某些威胁的屏障。下面我们对它们进行详细的检视。

ViewStateUserKey

从 ASP.NET 1.1 开始引入,ViewStateUserKeyPage 类的一个字符串属性,只有很少数开发人员真正熟悉该属性。为什么呢?让我们看看文档中是怎么说的。

在与当前页相关联的视图状态变量中将一个标识符分配给单个用户

除了有些累赘,这个句子的意思相当清楚;但是,您能老老实实地告诉我,它说明了该属性原本的用途吗?要理解 ViewStateUserKey 的角色,您需要继续往下读,直到 Remarks 部分。

该属性有助于防止一次单击攻击,因为它提供了附加的输入以创建防止视图状态被篡改的哈希值。换句话说,ViewStateUserKey 使得黑客使用客户端视图状态的内容来准备针对站点的恶意张贴困难了许多。可以为该属性分配任何非空的字符串,但最好是会话 ID 或用户的 ID。为了更好地理解这个属性的重要性,下面我们简短介绍一下一次单击攻击的基本知识。

一次单击攻击包括将恶意的 HTTP 表单张贴到已知的、易受攻击的 Web 站点。之所以称为“一次单击”,是因为它通常是以受害者不经意的单击通过电子邮件发送的或者在拥挤的论坛中浏览时发现的诱惑性链接而开始的。通过点击该链 接,用户无意中触发了一个远程进程,最终导致将恶意的

提交到一个站点。大家都坦白些吧:您真能告诉我,您从未因为好奇而单击过 Click here to win $1,000,000 这样的链接吗?显然,并没有什么糟糕的事情发生在您身上。让我们假定的确是这样的;您能说 Web 社区中的所有其他人都幸免于难了吗?谁知道呢。

要想成功,一次单击攻击需要特定的背景条件:

攻击者必须充分了解该有漏洞的站点。这是可能的,因为攻击者可以“勤奋地”研究该文件,或者他/她是一位愤怒的内部人员(例如,被解雇而又不诚实的雇员)。因此,这种攻击的后果可能是极其严重的。

站点必须是使用 Cookie(如果是持续性 Cookie,效果更好)来实现单次登录,而攻击者曾经收到过有效的身份验证 cookie。

该站点的某些用户进行了敏感的事务。

攻击者必须能够访问目标页。

前已提及,攻击包括将恶意的 HTTP 表单提交到等待表单的页。可以推知,该页将使用张贴来的数据执行某些敏感操作。可想而知,攻击者清楚地了解如何使用各个域,并可以想出一些虚假的值来达到 他的目的。这通常是目标特定的攻击,而且由于它所建立的三角关系,很难追本溯源 — 即黑客诱使受害者单击该黑客站点上的一个链接,而这又会导致恶意代码被张贴到第三个站点。(请参阅图 1。)


图 1. 一次单击攻击

为什么是不抱怀疑的受害者?这是因为,这种情况下,服务器日志中所显示的发出恶意请求的 IP 地址,是该受害者的 IP 地址。如前所述,这种工具并不像“经典”的 XSS 一样常见(和易于发起);但是,它的性质决定了它的后果可能是灾难性。如何应对它?下面,我们审视一下这种攻击在 ASP.NET 环境下的工作机理。

除非操作编码在 Page_Load 事件中,否则 ASP.NET 页根本不可能在回发事件之外执行敏感代码。要使回发事件发生,视图状态域是必需的。请牢记,ASP.NET 会检查请求的回发状态,并根据是否存在 _VIEWSTATE 输入域,相应地设置 IsPostBack。因此,无论谁要向 ASP.NET 页发送虚假请求,都必须提供一个有效的视图状态域。

一次单击攻击要想得手,黑客必须能够访问该页。此时,有远见的黑客会在本地保存该页。这样,他/她就可以访问 _VIEWSTATE 域并使用该域,用旧的视图状态和其他域中的恶意值创建请求。问题是,这能行吗?

为什么不能?如果攻击者可以提供有效的身份验证 cookie,黑客就可以进入,请求将被照常处理。服务器上根本不会检查视图状态内容(当 EnableViewStataMac 为 off 时),或者只会检查是否被篡改过。默认情况下,试图状态中没有机制可以将该内容与特定的用户关联起来。攻击者可以轻松地重用所获取的视图状态,冒充另一个用户合法地访问该页,以生成虚假请求。这正是 ViewStateUserKey 介入的地方。

如果选择准确,该属性可以将用户特定的信息添加到视图状态。处理请求时,ASP.NET 会从视图状态中提取秘钥,并将其与正在运行的页的 ViewStateUserKey 进行比较。如果两者匹配,请求将被认为是合法的;否则将引发异常。对于该属性,什么值是有效的?

为所有用户将 ViewStateUserKey 设置为常量字符串,相当于将它保留为空。您必须将它设置为对各个用户都不同的值 — 用户 ID,会话 ID 更好些。由于一些技术和社会原因,会话 ID 更为合适,因为会话 ID 不可预测,会超时失效,并且对于每个用户都是不同的。

以下是一些在您的所有页中都必不可少的代码:

void Page_Init (object sender, EventArgs e) {
ViewStateUserKey = Session.SessionID;
:
}

为了避免重复编写这些代码,您可以将它们固定在从 Page 派生的类的 OnInit 虚拟方法中。(请注意,您必须在 Page.Init 事件中设置此属性。)

protected override OnInit(EventArgs e) {
base.OnInit(e);
ViewStateUserKey = Session.SessionID;
}

总体说来,使用基 page 类始终都不失为一件好事,我在 Build Your ASP.NET Pages on a Richer Bedrock 一文中已经进行了说明。如果您要了解更多有关一次单击攻击者的伎俩的信息,可以在 aspnetpro.com 找到一篇非常好的文章。

Cookie 和身份验证

Cookie 之所以存在,是因为它们可以帮助开发人员达到一定目的。Cookie 充当了浏览器与服务器之间的一种持续性链接。特别是对于使用单次登录的应用程序来说,失窃的 cookie 正是使得攻击成为可能的罪魁祸首。这对于一次单击攻击来说一点没错。

要使用 Cookie,无需以编程方式显式创建和读取它们。如果您使用会话状态且实现表单身份验证,您会隐式地使用 Cookie。当然,ASP.NET 支持无 cookie 的会话状态,而且,ASP.NET 2.0 还引入了无 cookie 的表单身份验证。因此,理论上您可以在没有 Cookie 的情况下使用这些功能。我并不是说您不再必须这么做了,但事实上这正是疗法比疾病更糟的情形之一。无 Cookie 的会话,实际上将会话 ID 嵌入了 URL 中,这样谁都可以看到。

与使用 Cookie 有关的潜在问题有哪些?Cookie 可能被盗(即被复制到黑客的计算机)和投毒(即被填充以恶意数据)。这些操作通常是即将发起的攻击的前奏。如果被盗,Cookie 会“授权”外部用户以您的名义连接到应用程序(并使用受保护的页),这可能使黑客轻松地规避授权,并能够执行角色和安全设置所允许受害者执行的任何操作。 因此,身份验证 Cookie 通常被赋予相对较短的生存期,即 30 分钟。(请注意,即使浏览器的会话完成所需的时间更长,cookie 仍会过期。)发生失窃时,黑客有 30 分钟的时限来尝试攻击。

可以将这个时限加长,以免用户不得不过于频繁地登录;但请注意,这么做会将您自己置于危险境地。任何情况下,都应避免使用 ASP.NET 持续性 Cookie。它将导致 cookie 具有几乎永久的生存期,最长可达 50 年!下面的代码片段演示了如何轻松修改 cookie 的过期日期。

void OnLogin(object sender, EventArgs e) {
// Check credentials
if (ValidateUser(user, pswd)) {
// Set the cookie's expiration date
HttpCookie cookie;
cookie = FormsAuthentication.GetAuthCookie(user, isPersistent);
if (isPersistent)
cookie.Expires = DateTime.Now.AddDays(10);

// Add the cookie to the response
Response.Cookies.Add(cookie);

// Redirect
string targetUrl;
targetUrl = FormsAuthentication.GetRedirectUrl(user, isPersistent);
Response.Redirect(targetUrl);
}
}

您可以在自己的登录表单中使用这些代码来微调身份验证 Cookie 的生存期。

会话劫持

Cookie 还被用于检索特定用户的会话状态。会话的 ID 被存储到 cookie 中,该 cookie 与请求一起来回传送,存储在浏览器的计算机上。同样,如果失窃,会话 cookie 将可被用来使黑客进入系统并访问别人的会话状态。不用说,只要指定的会话处于活动状态(通常不超 20 分钟),这就有可能发生。通过冒充的会话状态发起的攻击称为会话劫持。有关会话劫持的详细信息,请阅读 Theft On The Web: Prevent Session Hijacking

这种攻击有多危险?很难讲。这要取决于 Web 站点的功能,更为重要的是,该站点的页是如何设计的。例如,假定您能够获得别人的会话 cookie,并将它附加到对站点上某个页的请求中。您加载该页并逐步研究它的普通用户界面。除了该页使用另一个用户的会话状态工作外,您无法将任何代码 注入该页,也无法修改该页中的任何内容。这本身并不太坏,但是如果该会话中的信息是敏感和关键性的,就有可能直接导致黑客成功实现利用。黑客无法渗透到会 话存储的内容中,但他可以使用其中存储的信息,就像自己是合法进入的一样。例如,假定有这样一个电子商务应用程序,它的用户在浏览站点时将物品添加到购物 车中。

方案 1。 购物车的内容存储在会话状态中。但是,在结帐时,用户被要求通过安全的 SSL 连接确认和输入付款详细信息。这种情况下,通过接入其他用户的会话状态,黑客仅可以了解到一些有关受害者的购物喜好的细节。在这种环境下劫持实际上并不会 导致任何损害。受威胁的只是保密性。

方案 2。应 用程序为每位注册用户处理一份档案,并将档案保存在会话状态中。糟糕的是,档案中(可能)包括信用卡信息。为什么要将用户档案详细信息存储到会话中?可能 应用程序的其中一个目标是,从根本上避免使用户不得不重复键入自己的信用卡和银行信息。因此,在结算时,应用程序会将用户定位到一个具有预先填充的域的 页。而有失谨慎的是,这些域的其中一个是从会话状态中获取的信用卡号。现在您可以猜到故事的结局了吗?

应用程序的页的设计,是防止会话劫持攻击的关键所在。当然,还有两点没有理清。第一点是,如何防止 cookie 盗窃?第二点是,ASP.NET 可以如何检测和阻止劫持?

ASP.NET 会话 cookie 极其简单,仅限于包含会话 ID 字符串本身。ASP.NET 运行库从 cookie 中提取会话 ID,并将其与活动的会话进行比较。如果 ID 有效,ASP.NET 将连接到对应的会话并继续。这种行为极大地方便了已经偷到或者可以猜出有效的会话 ID 的黑客。

XSS 和中间人 (man-in-the-middle) 攻击以及对客户端 PC 的强力访问,都是获取有效 cookie 的方法。为了防止盗窃,您应当实现安全最佳实践来防止 XSS 及其各变种得手。

而为了防止会话 ID 猜测,您应当干脆避免太高估计自己的技能。猜测会话 ID 意味着您知道如何预测有效的会话 ID 字符串。对于 ASP.NET 所使用的算法(15 个随机数字,映射为启用 URL 的字符),随机猜测到有效 ID 的概率接近于零。我想不到任何理由来用自己的会话 ID 生成器替换默认的会话 ID 生成器。许多情况下,这么做只会为攻击者提供方便。

会话劫持更为糟糕的后果是一旦 cookie 被盗或者被猜出,ASP.NET 并没有什么办法来检测欺诈性的 cookie 使用。同样,原因是 ASP.NET 将自己限制为检查 ID 的有效性,以及 cookie 的来源地。

我在 Wintellect 的朋友 Jeff Prosise 为 MSDN Magazine 写了一篇很好的关于会话劫持的文章。他的结论并不令人安慰:几乎不可能建立能够完全抵御依靠偷来的会话 ID Cookie 所发起的攻击的防御工事。但是他开发的代码为进一步提升安全标准提供了非常明智的建议。Jeff 创建了一个 HTTP 模块,该模块为会话 ID Cookie 监视传入的请求和传出的响应。该模块将一条哈希代码附加到会话 ID 之后,使攻击者重用 cookie 更为困难。您可以在此处阅读详情。

EnableViewStateMac

视图状态用于在对同一个页的两个连续请求之间保持控件的状态。默认情况下,视图状态是 Base64 编码的,并使用一个哈希值签名,以防止篡改。除非更改默认的页设置,否则不可能篡改视图状态。如果攻击者修改了视图状态,甚至使用正确的算法重新生成了视 图状态,ASP.NET 都会捕获这些尝试并引发异常。视图状态被篡改并不一定有害,虽然它修改了服务器控件的状态 — 但可能成为造成严重感染的工具。因此, 移除默认情况下进行的计算机身份验证代码 (MAC) 交叉检查就异常重要。请参阅图 2。


图 2. 启用 EnableViewStateMac 时,使视图状态本身难以篡改的因素

启用了 MAC 检查时(默认情况),将对序列化的视图状态附加一个哈希值,该值是使用某些服务器端值和视图状态用户秘钥(如果有)生成的。回发视图状态时,将使用新的服 务器端值重新计算该哈希值,并将其与存储的值进行比较。如果两者匹配,则允许请求;否则将引发异常。即使假设黑客具有破解和重新生成视图状态的能力,他/ 她仍需要知道服务器存储的值才可以得出有效的哈希。具体说来,该黑客需要知道 machine.config 的 <machineKey> 项中引用的计算机秘钥。

默认情况下, 项是自动生成的,以物理方式存储在 Windows Local Security Authority (LSA) 中。仅在 Web 场(此时视图状态的计算机秘钥必须在所有的计算机上都相同)的情形下,您才应当在 machine.config 文件中将其指定为明文。

视图状态 MAC 检查是通过一个名为 EnableViewStateMac@Page 指令属性控制的。如前所述,默认情况下,它被设置为 true。请永远不要禁用它;否则将会使视图状态篡改一次单击攻击成为可能,并具有很高的成功概率。

ValidateRequest

跨站点脚本 (XSS) 对于很多经验丰富的 Web 开发人员来说是老朋友了,它在 1999 年左右就已经出现了。简单地说,XSS 利用代码中的漏洞来将黑客的可执行代码引入另一个用户的浏览器会话中。如果被执行,注入的代码可以执行多种不同的操作 — 获取 Cookie 并将一个副本上载到黑客控制的 Web 站点,监视用户的 Web 会话并转发数据,修改被黑的页的行为和外观以使其提供错误的信息,甚至使自己变为持续性的,这样用户下一次返回该页时,欺诈代码会再次运行。请在 TechNet 文章 Cross-site Scripting Overview 中详细阅读有关 XSS 攻击的基础知识。

代码中的哪些漏洞导致 XSS 攻击成为可能?

XSS 利用的是动态生成 HTML 页、但并不验证回显到页的输入的 Web 应用程序。这里的输入 是指查询字符串、Cookie 和表单域的内容。如果这些内容在未经适当性能检查的情况下出现在网络上,就存在黑客对其进行操作以在客户端浏览器中执行恶意脚本的风险。(前面提到的一次 单击攻击其实是 XSS 的一种新近变种。)典型的 XSS 攻击会导致不抱怀疑的用户点击一条诱惑性链接,而该链接中嵌入了转义的脚本代码。欺诈代码将被发送到一个存在漏洞且会毫不怀疑地输出它的页。以下是可能发 生的情况的一个示例:

">Click to claim your prize

用户单击一个看上去明显安全的链接,最终导致将一些脚本代码传递到存在漏洞的页,这些代码首先获取用户计算机上的所有 Cookie,然后将它们发送到黑客的 Web 站点。

请务必注意,XSS 不是一个特定于供应商的问题,因此并不一定会利用 Internet Explorer 中的漏洞。它影响目前市场上的所有 Web 服务器和浏览器。更应注意的是,没有哪一个修补程序能够修复这一问题。您完全可以保护自己的页免受 XSS 攻击,方法是应用特定的措施和合理的编码实践。此外,请注意,攻击者并不需要用户单击链接就可以发起攻击。

要防御 XSS,您必须从根本上确定哪些输入是有效的,然后拒绝所有其他输入。您可以在一本书中读到抵御 XSS 攻击的详细检查表,该书在 Microsoft 属于必读范围 — Writing Secure Code,作者是 Michael Howard 和 David LeBlanc。特别地,我建议您仔细阅读第 13 章。

阻止阴险的 XSS 攻击的主要方法是向您的输入(任何类型的输入数据)添加一个设计合理、有效的验证层。例如,某些情况下即使是原本无害的颜色(RGB 三色)也会将不受控制的脚本直接带入页中。

在 ASP.NET 1.1 中,@Page 指令上的 ValidateRequest 属性被打开后,将检查以确定用户没有在查询字符串、Cookie 或表单域中发送有潜在危险性的 HTML 标记。如果检测到这种情况,将引发异常并中止该请求。该属性默认情况下是打开的;您无需进行任何操作就可以得到保护。如果您想允许 HTML 标记通过,必须主动禁用该属性。


ValidateRequest不是 万能的药方,无法替代有效的验证层。请阅读此处以获取大量有关该功能的基础原理的宝贵信息。它基本上通过应用一个正则表达式来捕获一些可能有害的序列。

注 ValidateRequest 功能原本是有缺陷的,因此您需要应用一个修补程序它才能按预期工作。这样的重要信息常常不为人们所注意。奇怪的是,我发现我的其中一台计算机仍受该缺陷的影响。试试看!

没有任何关闭 ValidateRequest 的理由。您可以禁用它,但必须有非常好的理由;其中一条这样的理由可能是用户需要能够将某些 HTML 张贴到站点,以便得到更好的格式设置选项。这种情况下,您应当限制所允许的 HTML 标记(



)的数目,并编写一个正则表达式,以确保不会允许或接受任何其他内容。

以下是一些有助于防止 ASP.NET 遭受 XSS 攻击的其他提示:

使用 HttpUtility.HtmlEncode 将危险的符号转换为它们的 HTML 表示形式。

使用双引号而不是单引号,这是因为 HTML 编码仅转义双引号。

强制一个代码页以限制可以使用的字符数。

总之,使用但是不要完全信任 ValidateRequest 属性,不要太过懒惰。花些时间,从根本上理解 XSS 这样的安全威胁,并规划以一个关键点为中心的防御策略:所有的用户输入都是危险的。

数据库角度

SQL 注入是另一种广为人知的攻击类型,它利用的是使用未筛选的用户输入来形成数据库命令的应用程序。如果应用程序兴高采烈地使用用户键入表单域中的内容来创建 SQL 命令字符串,就会将您暴露在这一风险下:恶意用户只需访问该页并输入欺诈参数,就可以修改查询的性质。您可以在此处了解更多有关 SQL 注入的信息。

要阻止 SQL 注入攻击,有许多方法。以下介绍最常见的技巧。

确保用户输入属于适当的类型,并遵循预期的模式(邮政编码、身份证号,电子邮件等)。如果预期来自文本框的数字,请在用户输入无法转换为数字的内容时阻止该请求。

使用参数化的查询,使用存储过程更好。

使用 SQL Server 权限来限制各个用户可以对数据库执行的操作。例如,您可能需要禁用 xp_cmdshell 或者将该操作的权限仅限于管理员。

如果使用存储过程,可以显著降低发生这种攻击的可能性。实际上,有了存储过程,您就无需动态地撰写 SQL 字符串。此外,SQL Server 中将验证所有参数是否具有指定的类型。虽然光是这些并不是百分百安全的技巧,但是加上验证的话,将足以提高安全性。

更为重要的是,应确保只有经过授权的用户才能够执行可能具有严重后果的操作,如删除表。这要求认真仔细地设计应用程序的中间层。好的技巧(不光是为了安全性)应把焦点集中在角色上。应当将用户分组为各种角色,并为各个角色定义一个包含一组最少的权限的帐户。

几周前,Wintellect Web 站点受到一种很复杂的 SQL 注入的攻击。那位黑客试图创建并启动一个 FTP 脚本来下载一个可能是恶意的可执行程序。幸运的是,这次攻击失败了。或者,其实是强用户验证,使用存储过程和使用 SQL Server 权限,导致了攻击未能成功?

总而言之,您应当遵循这些指南,以避免被注入有害的 SQL 代码:

使用尽可能少的权限运行,永远不以“sa”身份执行代码。

将访问限制给内置的存储过程。

首选使用 SQL 参数化查询。

不通过字符串串连来生成语句,不回显数据库错误。

隐藏域

在传统的 ASP 中,隐藏域是唯一一种在请求之间保持数据的方法。您需要在下一个请求中检索的任何数据都被打包到隐藏的 域中,并执行回程。如果有人在客户端上修改了该域中存储的值,会怎样?只要文本是明文的,服务器端环境就无法测知这一情况。ASP.NET 中,页和各个控件的 ViewState 属性有两个用途。一方面,ViewState 是跨请求保持状态的方法;另一方面,ViewState 使您能够在受保护的、不易篡改的隐藏域中存储自定义值。

如图 2 所示,视图状态被附加了一个哈希值,对于每条请求,都会检查该值,以检测是否发生了篡改。除少数几种情况外,没有任何理由要在 ASP.NET 中使用隐藏域。视图状态能够以安全得多的方式实现相同的功能。前面开门见山地讲到过,在明文的隐藏域中存储敏感的值(如价格或信用卡详细信息),相当于对 黑客张开大门;视图状态甚至能够使这种不好的做法比以前更为安全,因为视图状态具有数据保护机制。但是,请牢记,视图状态可以防止篡改,但是并不能保证保 密性,除非使用加密 — 存储在视图状态中的信用卡详细信息无论如何都有风险。

在 ASP.NET 中,哪些情况下使用隐藏域是可接受的?当您生成需要将数据发送回服务器的自定义控件时。例如,假定您要创建一个支持重派列顺序的新 DataGrid 控件。您需要在回发中将新的顺序发送回服务器。如果不将这些信息存储到隐藏域中,又可以存储到哪里?

如果隐藏域为读/写域,即预期客户端会写入它,没什么办法能够完全制止黑客攻击。您可以尝试哈希或者加密该文本,但这并不能让您合理地确信不会遭受黑客攻击。此时,最好的防御就是让隐藏域包含惰性和无害的信息。

此外,应当注意 ASP.NET 公开了一个鲜为人知的类,可用于编码和哈希任何序列化的对象.该类为 LosFormatterViewState 实现用于创建回程到客户端的编码文本正是同一个类。

private string EncodeText(string text) {
StringWriter writer = new StringWriter();
LosFormatter formatter = new LosFormatter();
formatter.Serialize(writer, text);
return writer.ToString();
}

前面的代码片段演示了如何使用 LosFormatter 来创建类似视图状态的内容,对其编码并进行哈希。

电子邮件和垃圾邮件

在本文结尾,请让我指出,最常见的攻击中至少有两种(经典的 XSS 和一次单击)通常是通过诱使不抱怀疑的受害者单击诱惑性和欺骗性的链接来发起的。很多时候我们都可以在自己的收件箱中发现这样的链接,虽然有反垃圾邮件过 滤器。几美元就可以买到大量电子邮件地址。用来生成这种列表的其中一种主要的技巧就是扫描 Web 站点上的公共页,查找并获取所有看上去像电子邮件的内容。

如果页上显示了电子邮件地址,很可能或早或晚这个地址都会被自动 Web 程序捕获。真的吗?当然,这要看该电子邮件是如何显示的。如果硬编码它,您输定了。如果采用其他表示形式(如 dino-at-microsoft-dot-com),是否能够骗过自动 Web 程序不太清楚,但能让所有阅读您的页并想建立合法联系的人光火,倒是一定的。

总体说来,您应当确定一种方法,将电子邮件动态地生成为 mailto 链接。Marco Bellinaso 编写的一个免费组件恰好可以完成这项工作。您可以从 DotNet2TheMax Web 站点获得该组件的全部源代码。

小结

有人怀疑 Web 可能是所有运行时环境中敌意最盛的吗?根源在于谁都可以访问 Web 站点,并尝试向它传递好的或坏的数据。但是,创建不接受用户输入的 Web 应用程序,又有什么意义呢?

我们还是直面现实吧:无论您的防火墙如何强大,无论您如何频繁地应用可用的修补程序,只要您运行的 Web 应用程序先天包含缺陷,攻击者迟早都可以通过主通道,也就是端口 80,直接进入您的系统的最核心部分。

ASP.NET 应用程序与其他 Web 应用程序相较,既不更易受攻击,也不更安全。安全性和漏洞同样根植于编码实践、实际经验和团队合作。如果网络不安全,那么任何应用程序都不安全;类似地, 无论网络如何安全,管理如何精良,如果应用程序存在缺陷,攻击者总是能够得手。

ASP.NET 的好处是提供了一些好的工具,只需少量工作,就可以将安全标准提升到可以接受的级别。当然,这并不是 足够高的级别。不应纯粹以来 ASP.NET 的内置解决方案,同样也不应忽视它们。尽可能多地了解常见的攻击。

本文提供了内置功能的带注释的列表,以及一些有关攻击与防御的背景知识。用来检测传出的攻击的技巧是另一回事,可能需要一篇专门的文章来进行介绍。

Sunday, April 23, 2006

《BBS、论坛、社区、SNS》

这是最近所谓的WEB2.0时代中一个方向的关键词,也是几个现在非常时髦的词,闲杂人等都在谈论,从各种角度在谈着、写着、议着。比如靶子里的麦田与断桥的争论、比如前一阶段奇虎在三亚的人等的议论。

在我感觉均有摸象的感觉,在我看来都摸成四不象了,按新浪论坛里常用的说法是:不知所云。

为什么别人能摸象,我就不能摸,于是今天摸一摸,只是极力希望能摸出一个象,或者摸出一个鲸出来,再不济也是个“自摸”,理理自己的思路,是否能理别人的思路,那就看“缘分”了。

#1 1、我们的目的

这四个词在我看来是有顺序的,我的顺序是以用户规模、主题数量以及服务层次来排序的。其实这四个东西均是互联网多对多交互系统。

为了描述方便,我还是以单一论坛为代表。

作为一个论坛的经营者,一定要搞清楚操盘一个论坛的目的,那目的是什么,我咋知道你的目的是什么,只是告诉你要想好目的。

而论坛是什么,他就是你实现你目的的一个工具,工具的表现、规格与使用方式一定要切合你的目的。

现在有很多说法让人觉得舍本逐末:

A.论坛的关键是功能;

B.论坛的关键是文化;

C.论坛的关键是服务;

D.论坛的关键是内容;

其实说得都没错,但思考的层面有问题。在我看来自身目的、发展阶段、竞争环境不同的论坛,关键点都是不同的。拿板儿砖与新浪IT业界论坛去争论单一的关键点,那不叫效率低,那叫有毛病。


#2 2、经营的思路

我一直说,在目的明确的情况下,经营一个论坛就是经营一个社会,板儿砖上过去有一系列的讨论,而且不是表现层的讨论,更多的是社会学层面的讨论。(注:对于论坛类的讨论,一定不能从哲学角度切入,否则自乱)。我想列举一些供大家参考:

2.1.六度关系设论

2.2.150人规模论

2.3.自组织论

2.4.规则有效论

2.5.知识有序

2.6.输血机制

2.7.传播论

2.8.资本转化论

2.9.三板斧论

这些东西虽叫“论”,但对于我们的论坛乃至SNS的操盘都具有很强的指导意义。

但同时也要说明的是,这些理论是以简单至深入,同时又相互包含的。

另外社会学在变化,关于这些“论”也只是一部分,也会发生变化,但作为我们现在的论坛操作者,可以先别去想是否完整或今后的变化,关键是得有这样的东西作为我们行动的参考。

在这里再度提醒,在你了解这些“论”的同时,不能忘了根本:你的目的!请有机的在操盘中组合你的思路。


#3 2.1 六度关系设论

六度关系是个设论,很多人谈及,我这里就不多说,对于这个论点我们绝不该看成做论坛、社区以及SNS的所有理论,他只是“茫茫苍海一小粟”。

我们做论坛的人,应该把握的是:创造一种机制、环境(不一定是功能),利用用户过去的人脉关系,扩大论坛的访问量。


#4 2.2 150人规模论

150人规模论的核心是:一个人所能直接承受以及处理的社会关系在150个,过多就会造成冗堵。

而在论坛的操作时,这个理论给我们的一个旁注是:一个好论坛,即高效率交互、高凝聚度的达到,与人数不成正比,而是在一定用户数下,过多或过少都将不理想。

很多论坛操盘手总在思考:我一定要把用户数做高,越高越好。其实这是一个极大的误区。

在我看来一个论坛有50个经常发文的用户,效率是最高的,特别对于将论坛作为工具的操作者。


#5 2.3 自组织论

自组织理论很深,深到很多人都听着晕。

我们来基于论坛简化一下:

A.一个论坛在前期经营时,应以发展用户数量为主;

B.在经营到一定规模后,应力促其中的一些主题或用户分化;

C.分化方向是对你目标有利的方向


#6 2.4 规则有效论

社会学的一个特点是有效而没有真理,而对于论坛来说规则的建立应考虑:

A.追求规则的公平性,不要追求结果的公平性;

B.根据自己的不同发展阶段70%用户的共同特点,建立或调整游戏规则。

避免:

A.结果的大公平=大锅饭

B.规则不变或乱变

#7 2.5 知识有序论

论坛的一个大弱点,就是知识的无序化,这一点有时阻碍了论坛的长久发展,造成了集体智慧的流失。

在这方面WIKI以及TAG的作法与理念是值得很好参考的。


#8 2.6 输血机制

任何团体、社区的成员都会有其它因素影响到他在该社区的参与度,论坛也一样,婚丧嫁娶都会影响成员对你的论坛的参与度。

因此提前建立输血机制,保证论坛的活跃人群在一个动态的数量上,这一点非常重要。


#9 2.7 加强传播论

其实网络论坛最早经常的根本就是在经营传播:

A.发展传播匹配度高的节点(文化主题相似);

B.促进重要的传播节点的产生(论坛名人产生);

C.提高某信息的传播次数;

D.提高某信息的传播速度;

E.建立一个有序的传播线路

F.提高某信息的传播质量

这样的传播一方面促进论坛内部流畅、也是促进论坛对外影响力的产生。

#10 2.8 资本转化论

资本转化论下如:

A.人(用户)在社会中生存中都有资本做为生存条件,包括:

· 文化资本 (个人能力、水平、技能)

· 社会资本 (个人外部人脉资源的掌控)

· 符号资本 (个人在某个范围内的名气)

· 经济资本 (个人在金钱方面的能力)

B.以上四个资本是一定可以相互转化的,一个人可以通过良好的转化,达到另外一个个人资本水平。

基于网络论坛或社区或SNS扩展的一个思路是:

如果某一个论坛、社区、SNS能帮助用户建立这么一个良好的转化环境,那么这个论坛、社区、SNS一定是有价值的,所带来的收益也可观的。

我们的论坛操作者,别想着自己如何如何,先想想我们如何帮助用户吧。


#11 2.9 三板斧论

三板斧论是板儿砖砖家Z13综合以前聊天,鬼混提出来的,这三招的确是非常重要的,特别是对于那些SNS操作者来说:

第一招:偏好聚合

通过某一个特性聚合用户,比如体育、音乐、文学、游戏、地域、身份等等,这个特性可以是无限的,但请从一个特性出发;

第二招:事件诱导

事件:节点之间由于偏好而产生的一系列事件--自组织的而非网站经营者的策划。(Z13语)

诱导:经营者提供的事件完成功能+临界点到来时候的“处理机制

通过某个服务、某个活动、某个热点,来促进用户的互动行为,而且诱导方向一定是基于你的目的的;

第三招:资本转化

前面所述

有的人会说,我也是这么想的,这么做的,那恭喜你,但你有没有这样成形地去操作?不一定了吧?

可以说三板斧论是非常可操作性的,详细可以请教板儿砖上的Z13。


#12 3 实现的手段

每一个论坛乃至SNS都会有自己的特点,在实现中不一定有通吃套路。

但在手段设计中最大的几个忌讳:

A.总是先想到功能,总想用功能来完成目标,其实功能是很难形成长久竞争力;

B.没有应用社会学中已有的思路。请不要过高估计自己的能力,站在别人肩上办事,并不会把你的身份降低,反而会更牛;

C.单一应用某一个理论,没去想用户行为与心理、社会行业与心理是多元的;

D.不充分积累或使用现实资源,光在七平方米的机房办不成事儿,特别是现在的中国市场环境

关于实现的手段这一段,不好意思,我就不多写了


#13 4 最后的闲话

很多人在谈及论坛时,都在说自己的经验,但中国有哪个论坛值得说我牛B到哪哪哪?

A.我们的观众更需要的是一些如何从零开始的经验,而不仅是在已经有非常规模的论坛;

B.论坛或社区的文化、精神、魂甚至麦田所说的图腾是非常重要的,但请放在经营思路后去想,或者说当经营思路有了后,自然会有这样的文化、精神、魂!

C.论坛的经营中,时间成本非常大,以上的文字只是希望操作者能提高论坛经营的效率,别指望着一下子把论坛建立的多牛,哪怕你非常有钱。

D.没有一个长盛不衰的论坛,但可以有一个生根发芽的论坛,这是规律,请不要过于自恋于自己现有的论坛;

Friday, April 21, 2006

从LiveJournal后台发展看大规模网站性能优化方法

一、LiveJournal发展历程

LiveJournal是99年始于校园中的项目,几个人出于爱好做了这样一个应用,以实现以下功能:
  • 博客,论坛
  • 社会性网络,找到朋友
  • 聚合,把朋友的文章聚合在一起
LiveJournal采用了大量的开源软件,甚至它本身也是一个开源软件。

在上线后,LiveJournal实现了非常快速的增长:

  • 2004年4月份:280万注册用户。
  • 2005年4月份:680万注册用户。
  • 2005年8月份:790万注册用户。
  • 达到了每秒钟上千次的页面请求及处理。
  • 使用了大量MySQL服务器。
  • 使用了大量通用组件。

二、LiveJournal架构现状概况

livejournal_backend.png

三、从LiveJournal发展中学习

LiveJournal从1台服务器发展到100台服务器,这其中经历了无数的伤痛,但同时也摸索出了解决这些问题的方法,通过对LiveJournal的学习,可以让我们避免LJ曾经犯过的错误,并且从一开始就对系统进行良好的设计,以避免后期的痛苦。

下面我们一步一步看LJ发展的脚步。

1、一台服务器

一台别人捐助的服务器,LJ最初就跑在上面,就像Google开始时候用的破服务器一样,值得我们尊敬。这个阶段,LJ的人以惊人的速度熟悉的 Unix的操作管理,服务器性能出现过问题,不过还好,可以通过一些小修小改应付过去。在这个阶段里LJ把CGI升级到了FastCGI。

最终问题出现了,网站越来越慢,已经无法通过优过化来解决的地步,需要更多的服务器,这时LJ开始提供付费服务,可能是想通过这些钱来购买新的服务器,以解决当时的困境。
毫无疑问,当时LJ存在巨大的单点问题,所有的东西都在那台服务器的铁皮盒子里装着。

LJ-backend-7.png

2、两台服务器

用付费服务赚来的钱LJ买了两台服务器:一台叫做Kenny的Dell 6U机器用于提供Web服务,一台叫做Cartman的Dell 6U服务器用于提供数据库服务。

LJ-backend-8.png

LJ有了更大的磁盘,更多的计算资源。但同时网络结构还是非常简单,每台机器两块网卡,Cartman通过内网为Kenny提供MySQL数据库服务。

暂时解决了负载的问题,新的问题又出现了:

  • 原来的一个单点变成了两个单点。
  • 没有冷备份或热备份。
  • 网站速度慢的问题又开始出现了,没办法,增长太快了。
  • Web服务器上CPU达到上限,需要更多的Web服务器。

3、四台服务器

又买了两台,Kyle和Stan,这次都是1U的,都用于提供Web服务。目前LJ一共有3台Web服务器和一台数据库服务器。这时需要在3台Web服务器上进行负载均横。

LJ-backend-9.png

LJ把Kenny用于外部的网关,使用mod_backhand进行负载均横。

然后问题又出现了:

  • 单点故障。数据库和用于做网关的Web服务器都是单点,一旦任何一台机器出现问题将导致所有服务不可用。虽然用于做网关的Web服务器可以通过保持心跳同步迅速切换,但还是无法解决数据库的单点,LJ当时也没做这个。
  • 网站又变慢了,这次是因为IO和数据库的问题,问题是怎么往应用里面添加数据库呢?

4、五台服务器

又买了一台数据库服务器。在两台数据库服务器上使用了数据库同步(Mysql支持的Master-Slave模式),写操作全部针对主数据库(通过Binlog,主服务器上的写操作可以迅速同步到从服务器上),读操作在两个数据库上同时进行(也算是负载均横的一种吧)。

LJ-backend-10.png

实现同步时要注意几个事项:

  • 读操作数据库选择算法处理,要选一个当前负载轻一点的数据库。
  • 在从数据库服务器上只能进行读操作
  • 准备好应对同步过程中的延迟,处理不好可能会导致数据库同步的中断。只需要对写操作进行判断即可,读操作不存在同步问题。

5、更多服务器

有钱了,当然要多买些服务器。部署后快了没多久,又开始慢了。这次有更多的Web服务器,更多的数据库服务器,存在 IO与CPU争用。于是采用了BIG-IP作为负载均衡解决方案。

LJ-backend-11.png

6、现在我们在哪里:

LJ-backend-1.png

现在服务器基本上够了,但性能还是有问题,原因出在架构上。

数据库的架构是最大的问题。由于增加的数据库都是以Slave模式添加到应用内,这样唯一的好处就是将读操作分布到了多台机器,但这样带来的后果就是写操作被大量分发,每台机器都要执行,服务器越多,浪费就越大,随着写操作的增加,用于服务读操作的资源越来越少。

LJ-backend-2.png

由一台分布到两台

LJ-backend-3.png

最终效果

现在我们发现,我们并不需要把这些数据在如此多的服务器上都保留一份。服务器上已经做了RAID,数据库也进行了备份,这么多的备份完全是对资源的浪费,属于冗余极端过度。那为什么不把数据分布存储呢?

问题发现了,开始考虑如何解决。现在要做的就是把不同用户的数据分布到不同的服务器上进行存储,以实现数据的分布式存储,让每台机器只为相对固定的用户服务,以实现平行的架构和良好的可扩展性。

为了实现用户分组,我们需要为每一个用户分配一个组标记,用于标记此用户的数据存放在哪一组数据库服务器中。每组数据库由一个master及几个 slave组成,并且slave的数量在2-3台,以实现系统资源的最合理分配,既保证数据读操作分布,又避免数据过度冗余以及同步操作对系统资源的过度 消耗。

LJ-backend-4.png

由一台(一组)中心服务器提供用户分组控制。所有用户的分组信息都存储在这台机器上,所有针对用户的操作需要先查询这台机器得到用户的组号,然后再到相应的数据库组中获取数据。

这样的用户架构与目前LJ的架构已经很相像了。

在具体的实现时需要注意几个问题:

  • 在数据库组内不要使用自增ID,以便于以后在数据库组之间迁移用户,以实现更合理的I/O,磁盘空间及负载分布。
  • 将userid,postid存储在全局服务器上,可以使用自增,数据库组中的相应值必须以全局服务器上的值为准。全局服务器上使用事务型数据库InnoDB。
  • 在数据库组之间迁移用户时要万分小心,当迁移时用户不能有写操作。

7、现在我们在哪里

LJ-backend-5.png

问题:

  • 一个全局主服务器,挂掉的话所有用户注册及写操作就挂掉。
  • 每个数据库组一个主服务器,挂掉的话这组用户的写操作就挂掉。
  • 数据库组从服务器挂掉的话会导致其它服务器负载过大。

对于Master-Slave模式的单点问题,LJ采取了Master-Master模式来解决。所谓Master-Master实际上是人工实现的,并不是由MySQL直接提供的,实际上也就是两台机器同时是Master,也同时是Slave,互相同步。

Master-Master实现时需要注意:

  • 一个Master出错后恢复同步,最好由服务器自动完成。
  • 数字分配,由于同时在两台机器上写,有些ID可能会冲突。

解决方案:

  • 奇偶数分配ID,一台机器上写奇数,一台机器上写偶数
  • 通过全局服务器进行分配(LJ采用的做法)。

Master-Master模式还有一种用法,这种方法与前一种相比,仍然保持两台机器的同步,但只有一台机器提供服务(读和写),在每天晚上的时候进行轮换,或者出现问题的时候进行切换。

8、现在我们在哪里

LJ-backend-6.png

现在插播一条广告,MyISAM VS InnoDB。

使用InnoDB:

  • 支持事务
  • 需要做更多的配置,不过值得,可以更安全的存储数据,以及得到更快的速度。

使用MyISAM:

  • 记录日志(LJ用它来记网络访问日志)
  • 存储只读静态数据,足够快。
  • 并发性很差,无法同时读写数据(添加数据可以)
  • MySQL非正常关闭或死机时会导致索引错误,需要使用myisamchk修复,而且当访问量大时出现非常频繁。

9、缓存

去年我写过一篇文章介绍memcached,它就是由LJ的团队开发的一款缓存工具,以key-value的方式将数据存储到分布的内存中。LJ缓存的数据:

  • 12台独立服务器(不是捐赠的)
  • 28个实例
  • 30GB总容量
  • 90-93%的命中率(用过squid的人可能知道,squid内存加磁盘的命中率大概在70-80%)

如何建立缓存策略?

想缓存所有的东西?那是不可能的,我们只需要缓存已经或者可能导致系统瓶颈的地方,最大程度的提交系统运行效率。通过对MySQL的日志的分析我们可以找到缓存的对象。

缓存的缺点?

  • 没有完美的事物,缓存也有缺点:
  • 增大开发量,需要针对缓存处理编写特殊的代码。
  • 管理难度增加,需要更多人参与系统维护。
  • 当然大内存也需要钱。

10、Web访问负载均衡

在数据包级别使用BIG-IP,但BIG-IP并不知道我们内部的处理机制,无法判断由哪台服务器对这些请求进行处理。反向代理并不能很好的起到作用,不是已经够快了,就是达不到我们想要的效果。

所以,LJ又开发了Perlbal。特点:

  • 快,小,可管理的http web 服务器/代理
  • 可以在内部进行转发
  • 使用Perl开发
  • 单线程,异步,基于事件,使用epoll , kqueue
  • 支持Console管理与http远程管理,支持动态配置加载
  • 多种模式:web服务器,反向代理,插件
  • 支持插件:GIF/PNG互换?

11、MogileFS

LJ使用开源的MogileFS作为分布式文件存储系统。MogileFS使用非常简单,它的主要设计思想是:

  • 文件属于类(类是最小的复制单位)
  • 跟踪文件存储位置
  • 在不同主机上存储
  • 使用MySQL集群统一存储分布信息
  • 大容易廉价磁盘

到目前为止就这么多了,更多文档可以在http://www.danga.com/words/找到。Danga.comLiveJournal.com的 同学们拿这个文档参加了两次MySQL Con,两次OS Con,以及众多的其它会议,无私的把他们的经验分享出来,值得我们学习。在web2.0时代快速开发得到大家越来越多的重视,但良好的设计仍是每一个应 用的基础,希望web2.0们在成长为Top500网站的路上,不要因为架构阻碍了网站的发展。

参考资料:http://www.danga.com/words/2005_oscon/oscon-2005.pdf

感谢向静推荐了这篇文档给我。

Sunday, April 16, 2006

海内外中文网站以及港台日韩美印人气网站排名

现在全球互联网上的网站总数已经超过了四千万家(其中中国大陆的网站总数是将近七十万家), 针对如此众多的网站,有一家比较权威的网络流量访问统计机构,叫ALEXA排名网站。 最近因为查看自己开的BLOG网站的排名,也顺便发现了其他很多有意思的排名。。。

首先,在全球四千多万家网站中,只有前一百万名的网站,才会有具体排名和数据统计,下面这些网站后的数字就是其最近(当前星期?)被访问次数的全球排名:

(一)先说说几个主要海外中文网站:

文学城 235
留园网 382
MITBBS 1276
倍可亲 2122
万维网 2141
多维网 2505

。。。

海归网 6223
世界军事论坛 6660

。。。

CND 12658
POPYARD 13775
YIFAN 14869
MUZI 27518

。。。

0gan.net 852690 Smile 不好意思,网站开了还不到三个月,排名全球八十五万名,不过好歹进了前一百万。。。:-) 。。。。

几点说明:

1) 文学城还是海外中文网站里的老大。如果将来他们要是能够在国内也能被看到,其前途是不可限量的。不过,一方面他们遭受了被禁的苦痛,另一方面,他们却出於纯商业的考虑,对於一些我这样的网友的个人BLOG网站,居然都采取封锁的做法,比如,只因为我去偶尔贴了一下我自己拍的几个音乐MTV录像,现在我的个人BLOG网站名 www.0gan.net 在文学城就成了过滤词了,只要帖子里面出现,就发不出去。。

2) 前几年曾经很热门的一些网站,比如木子网,一凡网,还有CND华夏文摘,最近在一些新的网站的冲击下,都不行了。。。逆水行舟,不进则退,就是这个道理。。。


(二)再说说世界头十名被访问的网站

这个排行是根据最近三个月统计而每日更新的,以下是2006年4月16日的:

1) YAHOO

2) GOOGLE

3) MSN

4) 百度

5) YAHOO日本

6) 新浪

7) EBAY

8.) MYSPACE

9) 腾讯网 (QQ)

10) (微软)PASSPORT NET


(三)国内访问量头十几名的网站

1) 百度

2) 新浪

3) 腾讯网 (QQ)

4) 搜狐

5) 网易

6) 雅虎中国

7) GOOGLE

8.) MSN

9) 淘宝网

10) TOM。COM

11) 阿里巴巴

12) 搜狗 (SOGOU)


(四)香港的头十几名被访问的网站

1) YAHOO

2) XANGA 欧美网上BLOG网站

3) MSN

4) 香港赛马会 HKJC。COM

5) 新闻组啦 (newsgroup.la)

6) UWANTS.COM

7) 香港讨论区 (discuss.com.hk)

8.) 壹苹果网络(ATNEXT.COM 香港壹周刊下属网站?)

9) 新浪香港 (SINA.COM.HK)

10) SEX141.COM

11) GOOGLE

12) GOOGLE香港

13) 雅虎中国

几点说明:

大家看,香港就是一典型的殖民地文化下的特点: 前几名完全与西方接轨,剩下的就是赛马,然后居然第十名是一纯色情资讯网站。哈哈。真倔! 您要指望这个地方出个把三星现代那样的企业,不是做梦吗。



(五) 台湾头十名被访问网站

1) YAHOO

2) 无名小站 (WRETCH。CC)

3) 电脑报 (PCHOME。COM。TW)

4) MSN

5) HINET 台湾入门网站 (HINET。NET)

6) GOOGLE台湾

7) 优仕网 (YOUTHWANT。COM。TW)

8.) 番薯藤 (YAM。COM)

9) MSN台湾

10) 雅虎台湾

几点说明:

台湾的文化说什么要比香港的殖民地文化强多了。 过去听的所有香港歌星的歌曲,包括什么张学友,谭永麟,大多是抄袭日本人的,张国荣是GAY,谭校长两个老婆一起出殡,周星驰的无厘头,这样的东西要是有人还推崇,实在是没办法了。

再看看台湾过去的老牌歌星和艺人,感觉就好太多了:罗大佑,李宗盛,等等,至少歌是自己写的,而不是简单抄日本人的。


(六)日本头十名被访问网站

1) YAHOO日本

2) GOOGLE

3) MIXI (日文介绍:SOCIAL NETWORK SITE 好像是交友网站)

4) 乐天市场 ( RAKUTEN。CO。JP)

5) LIVEDOOR 就是最近新闻里面大名鼎鼎的 活力门 公司网站

6) GOO辞书 (GOO。NE。JP 三省堂书店)

7) MSN 日本

8.) FC2 (fc2.com 好像是WEB HOSTING的网站)

9) AMAZON 日本

10) INFOSEEK 日本

几点说明:

和香港比较一下,日本的头十名网站里面居然有二个是网上书籍销售相关网站。 都说网络时代大家就可以不看书了,不知是否正确。。。


(七) 韩国头十名被访问网站

1) NAVER。COM (完全不知是什么东西,没有一个英文,汉字,都是韩文,好像是综合门户网站的感觉)

2) NATE。COM (完全不知是什么东西,没有一个英文,汉字,都是韩文,好像是综合门户网站的感觉,是SK电信公司办的)

3) DAUM。NET (WALL CALL 还是: 完全不知是什么东西,没有一个英文,汉字,都是韩文,好像是综合门户网站的感觉)

4) YAHOO 终於,终於 有个和世界接轨的网站。。。

5) NETMARBLE。NET 还是不知是干什么的网站

6) INTERNET AUCTION (AUCTION。CO。KR) 从名字判断,是网上拍卖行

7) GMARKET。CO。KR 从名字判断,是网上购物网站

8.) SAYCLOB。COM 从网站域名判断,是网上交友网站

9) HANGAME。COM 从网站域名判断,是网上游戏网站

10) EMPAS。COM 好像是综艺音乐资讯网站

几点说明:

韩国人的强烈民族性从这个头十名网站,一眼就看出来了,什么MSN GOOGLE,玩去,根本没人尿。。。



(八) 美国的头十名被访问网站

1) YAHOO

2) GOOGLE

3) MSN

4) MYSPACE

5) EBAY

6) AMAZON

7) CRAIGSLIST

8.) GO.COM

9) PASSPORT。NET

10) CNN

说明:

CRAIGSLIST 如果上市,会很成功。。。



还有:

(九) 印度头十名被访问网站:

1) YAHOO

2) GOOGLE

3) GOOGLE 印度

4) REDIFF。COM 这是一个海外印度人背景的综合门户网站,NASDAQ上市公司。

5) MSN

6) ORKUT。COM 网上交友网站,是印度的吗?还是在西方的印度人开的?

7) INDIATIMES 印度时报报纸网站,新闻。

8.) MAUKRI。COM 印度最大的找工作网站

9) (微软)PASSPORT。NET

10) RAPIDSHARE。DE 这是一个德国的网上文件SHARING网站,看来印度的硬件还是差。。。

美国,西方有很多印度人,我问过几个美国的印度人他们平常上什么样的印度网站,下面是几个主要答案: (网站后数字是其排行)

1) samachar.com 4391

2) rediff.com 111

3) sulekha.com 3334

其中,REDIFF因为有大量印度国内用户访问,可以说不能算真正只有海外印度人访问的网站,所以,可以和文学城这样网站比的印度网站的排名都是三千以外,这说明什么呢?

这说明:

1) 印度人没有自己很深的民族国家概念

2) 海外印度人估计上CNN,MSN的比上以上印度人ONLY网站的多,结果就是他们和欧美人打起交道来,比老中厉害。