加载中…

加载中...

正文 字体大小:

网站建设众包需求书 【2】 系统架构

(2012-12-18 00:26:43)
标签:

网站

电商

jquery

mongodb

it

分类: 众包项目
前一篇,我们介绍了导购网站的页面及基本业务流程。基本业务有以下四项,

1. 系统管理员发帖。发帖包括从电脑本地硬盘中,上传图片,以及简短的文字叙述。
2. 普通用户看帖。用户看到的页面中,可能有多个帖子,每个帖子包括图片和文字描述。
3. 普通用户搜索。搜索结果页面中,也包括多个帖子,每个帖子也包括图片和文字描述。
4. 系统自动统计。系统管理员在什么时间,发过哪些帖子。哪位普通用户在什么时候,看过哪些帖子,收藏了哪些帖子,从什么帖子转接到哪家电商等等。

系统性能要求,

1. 每日上传图片不超过 500 张,每张图片不超过 5 MB。
2. 高峰时段每秒钟普通用户看帖的 PV 不超过 1000 次。
3. 系统刚上线时,业务逻辑可能会频繁修改,所以必须保持数据库 schema的柔性,不仅便于增加新的 tables,而且每个 table 的 column 数量和属性也会变化。
4. 系统刚上线时,尽可能少用服务器,以便降低成本。但是系统必须具有可扩展性,当存储的内容数据逐渐增多时,并且用户人数逐渐增加时,通过增加服务器数量,使整个系统的容量随之增大。系统扩容时,不需要修改数据库设计,不需要大幅度修改代码。

图一描绘了系统部署的规划。

网站建设众包需求书 <wbr>【2】 <wbr>系统架构

   图一. 系统部署图。

整个系统占用两台服务器,两台服务器都使用 Centos 操作系统。

前端服务器中,部署了 Nginx Web Engine。网页用 PHP 编写。

1. 使用 Nginx Web Engine,而不是 Tomcat 或者 Apache。原因是 Nginx 并发性好,并且容易使用。
2. 使用 PHP 的理由,是 PHP 插件丰富,便于开发,性能也不错。不使用 Struts+Spring 的原因,是因为后者更使用于业务流程复杂,但是对于并发性和性能要求不太高的企业应用。

PHP 通过 Thrift 通讯框架,与业务逻辑引擎,交换指令以及内容数据,内容数据不仅包括文本内容,也包括图片。

业务逻辑引擎,用 Java 实现。在初期的系统部署中,Java 业务逻辑引擎,与 Nginx Web Engine,还有 MemCached,部署在同一台服务器。在系统上线初期,业务流量压力不大的情况下,这样部署,目的是节省服务器的使用量。

今后如果业务流量逐渐增大以后,Java 业务逻辑引擎可以与 Web Engine 分开,独立运行于其它服务器上。做这个分离时,不需要修改代码,只需要修改 PHP Thrift 的设置即可。

但是用 Thrift 来沟通 PHP 与 Java,也有缺陷。主要顾虑是数据传输的性能。

另一种可能的设计是,在 PHP 中直接调用 Java,免去 Thrift 的中间环节。我们没有选用这种设计,原因有三。

1. 这种设计导致 Web Engine 与业务逻辑引擎,紧密耦合。不利于将来向分布式系统演化。
2. 在 PHP 中直接调用 Java时,隐藏着数据的序列化与反序列化,所以数据传输的性能,未必会比使用 Thrift 快很多。
3. Thrift 在处理多线程 NIO 数据传输时,手段丰富而且稳定性好。在 PHP 中直接调用 Java时,担心当流量较大,内存占用过高时,会出现数据丢失。

今后业务流量增大以后,MemCached 缓存,也可以与 Web Engine 分离,独立运行于其它服务器之上。PHP 调用 MemCached 的设置参数,不是写死在 PHP 中,而是由 PHP 向 Java 业务逻辑引擎咨询。

PHP 在读帖子时,先向 Java 业务逻辑引擎读取帖子的 MetaData,然后根据这些 MetaData数据,向 MemCached 读取内容数据。

也许有人问,为什么不把 MemCached 挂在 Java 业务引擎身后?换句话说,另外一种设计是,PHP -> Java  -> MemCached -> MongoDB/GridFS 。

我们之所以把 Java 业务引擎,与 MemCached 分离,主要目的在于分离指令流与数据流。

1. 在用户读帖子时,PHP 把请求转交给 Java 业务引擎,Java 业务引擎回应的是帖子的 MetaData,这个数据往来是指令流,数据量较少,但是来往次数可能较多。
2. PHP 收到帖子的 MetaData以后,根据MetaData,从 MemCached 中获取相关文字和图片内容。这一次是数据流,数据量较大,所以尽可能减少来往次数。

或许有人问,今后业务流量增加以后,不仅需要把 MemCached 与 Web Engine 分离,而且Web Engine 和 MemCached 分别运行在多台服务器上,怎么办?

先前我们提到,PHP 调用 MemCached 的设置参数,不是写死在 PHP 中,而是由 PHP 向 Java 业务引擎咨询。所以 Java 业务引擎,可以承担起调度的职责,实现系统的负载均衡。

后台服务器用于存储文本和图片内容,以及搜索。在系统的初期部署中,搜索引擎与数据库运行在同一台服务器。今后业务流量增大以后,两者可以分离,各自运行在不同的服务器上。

之所以使用 NoSQL 的 MongoDB,而不使用 MySQL 之类 RDBMS,是因为导购网站上线初期,业务逻辑尚不稳定。用 NoSQL 数据库,可以保持数据库设置保持柔性,便于修改。

但是选用 MongoDB 也会带来一些问题。

1. MongoDB 的稳定性不如 MySQL,但是鉴于导购网站本身并不涉及现金交易,所以对于稳定性的要求并不太高。
2. MongoDB 多个 Replica 之间的同步效率,业界有不少质疑。但是对于这个导购网站来说,暂时不需要 Replica。内容数据如果丢失,不会对业务有太大影响。
3. MongoDB 自带的 GridFS 文件系统,性能并不算太好。但是对于导购网站来说,每日上传图片不超过 500 张,每张图片不超过 5 MB,高峰时段每秒钟 PV 不超过 1000 次。GridFS 的性能应该足够了[1]。

MongoDB 虽然自带了搜索功能,但是导购网站对于搜索的要求较高,所以决定在 MongoDB 体外,用 Lucene 另行建设搜索引擎。

但是用 Lucene 另建搜索引擎的也有隐患。

1. Lucene 索引与 MongoDB 的数据,可能存在不及时同步的问题。不过,即便出现不同步的情况,后果是从 Lucene 中搜索出来的结果,在 MongoDB 中并不存在。这个问题,可以由业务流程引擎识别并处理。

2. 当数据文件越来越多时,Lucene 索引将越来越大。如果每次插入新的数据,便立刻更新 Lucene 索引,那么更新 Lucene 索引的速度,将越来越慢。解决办法是建立两套 Lucene 索引,一个是 Main Index,包含所有数据,另一个是 Rapid Index 只包含当日索引。用户搜索时,同时使用两套索引,然后合并搜索结果。每天夜间,把 Rapid Index 合并进 Main Index,接着清空 Rapid Index。


图二是发帖、看贴、和搜索,这三个主要业务的内部数据流程,方便读者进一步了解在这个系统架构下,数据的内部传输。

至于系统自动统计这项业务,由 Java 业务流程引擎控制。统计业务的内部数据流程,非常简单,这里就不详述了。

网站建设众包需求书 <wbr>【2】 <wbr>系统架构

  图二. 发帖、读贴、搜索三个业务的内部数据流程。



Reference

[1] Nginx + GridFS 的性能。
http://blog.zol.com.cn/2367/article_2366539.html

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有