前面写过一些电商网站相关的文章,这几天有时间,就把之前写得网站架构相关的文章,总结整理一下。把以前的一些内容就连贯起来,这样也能系统的知道,一个最小的电商平台是怎么一步步搭建起来的。
本文大纲:
-
小型电商网站的架构
-
日志与监控系统的解决方案
-
构建数据库的主从架构
-
基于共享存储的图片服务器架构
-
移动M站建设
-
系统容量预估
- 缓存系统
刚从传统软件行业进入到电商企业时,觉得电商网站没有什么技术含量,也没有什么门槛,都是一些现有的东西堆积木似的堆出来罢了。然而,真正进入到这个行业之后,才发现并非如此。有人说过,好的架构,是演化出来的,电商网站的架构也是如此。现在好的电商网站,看似很复杂,很牛逼,其实也是从很小的架构,也是从没什么技术含量开始的。所以,架构的演化过程,就是在技术团队不断追求极致的过程。
今天就来总结小型电商网站的架构演进。一套电商系统最初期的架构,往往会采用一个比较典型的LAMP架构,前端加上Apache/PHP,后端是MySQL。这个算是比较流行的。不过,目前还有一套.net的技术架构,可能大家很少提到。很不幸,我就是在一个.net平台为基础的电商公司。所以,今天也是要总结.net 平台的电商架构。
1.技术架构
一般初期的电商网站,基本就几个业务子系统:网站前台、商家前台、系统管理后台、App、M站等。业务量也不是很大。所以,MVC + 缓存 + 数据库基本就搞定了。
单就开发效率而言,.net MVC 的技术架构不会比LAMP开发速度慢。所以,一些企业,为了快速推出自己的电商平台,也会采用.net 架构。
2.基础架构
上图为基础架构层面。这是一个很简单的基础架构。
前端网站和M站,考虑到访问量和系统的可用性,基本会采用分布式部署。通过代理服务器进行请求分发。
其它的业务子系统,像商家前台和管理系统,基本上都是单机或是主从部署。
各个DB ,Redis 服务和文件和图片服务,搜索引擎Solr服务等,采用主从部署。
3.详细架构
整个系统架构里面,还有一个比较重要的组成部分,那就是监控系统。例如:流量监控、硬件监控、系统性能监控等, 还有就是对某个页面进行监控,设置页面的其中一块进行监控等。它是提高整个平台可用性的一个重要手段。多平台、多个维度的监控,能够确保系统的可用性。一旦出现异常,特别在硬件或者性能方面出现异常,监控系统也能立刻发出警告,这样也好防范于未然。
总而言之,一个好的系统架构应该从扩展性、安全性、性能和可靠性来考虑。罗马不是一天建成的,架构适合就行,可以先行之而后优。通过渐进演化的过程,逐步让系统越来越完善。
二、日志与监控系统的解决方案监控系统主要用于服务器集群的资源和性能监控,以及应用异常、性能监控、日志管理等多维度的性能监控分析。一个完善的监控系统和日志系统对于一个系统的重要性不必多说。总之,只有实时了解各系统的状态,才能保证各系统的稳定。
如上图所示,监控平台监控的范围很广,从服务器性能及资源,到应用系统的监控。每个公司都有特定的平台统一监控的需求及解决方案,但监控平台的任务和作用基本是一致的。
1.日志
日志是监视程序运行的一种重要的方式,主要有两个目的:1.bug的及时发现和定位;2.显示程序运行状态。
正确详细的日志记录能够快速的定位问题。同样,通过查看日志,可以看出程序正在做什么,是不是按预期的设计在执行,所以记录下程序的运行状态是必要的。这里将日志分为两种:1.异常日志;2.运行日志。
我们主要是使用log4net,将各个系统的日志,持久化记录到数据库或者文件中,以方便后续的系统异常监控和性能分析。如何集成log4net,这里不多说。
日志记录的几个原则:
-
日志级别一定要区分清楚,哪些属于error、warning、info等。
-
记录错误的位置。如果是分层系统,一定要在某个层统一处理,例如我们的MVC架构,都是在各个Action中Catch异常并处理,而业务层和数据库层这些地方的异常,都是Catch到异常后,往上一层抛。
- 日志信息清晰准确有意义,日志尽量详细点,以方便处理。应该记录相关系统、模块、时间、操作人、堆栈信息等。方便后续处理。
2.监控
监控系统是一个复杂的系统平台,目前有很多的开源产品和平台。不过我们平台小,监控任务和需求少,所以基本都是自己开发。主要有这五个方面:1.系统资源;2.服务器;3.服务;4.应用异常;5.应用性能。
具体的架构图如下:
1)系统资源监控
监控各种网络参数和各服务器相关资源(CPU、内存、磁盘读写、网络、访问请求等),保证服务器系统的安全运营,并提供异常通知机制以让系统管理员快速定位/解决存在的各种问题。目前比较流行的应该是Zabbix。
2)服务器监控
服务器的监控,主要是监控各个服务器、网络节点、网关等网络设备的请求响应是否正常。通过定时服务,定时去Ping各个网络节点设备,以确认各网络设备是否正常。如果哪个网络设备出现异常,则发出消息提醒。
3)服务监控
服务监控,指的是各个Web服务、图片服务、搜索引擎服务、缓存服务等平台系统的各项服务是否正常运行。可以通过定时服务,每隔一段时间,就去请求相关的服务,以确保平台的各项服务正常运行。
4)应用异常监控
目前我们平台所有系统的异常记录,都记录在数据库中。通过定时服务,统计分析一段时间之内的异常记录。如果发现有相关重要的模块的系统异常,比如支付、下单模块频繁发生异常,则立即通知相关人员处理,确保服务正常运行。
5)应用性能监控
在API接口和各应用的相关位置进行拦截和记录下程序性能(SQL性能,或是 程序执行效率)。相关重要模块提供性能预警,提前发现问题。 同时统计相关监控信息并显示给开发的人员,以方便后续的性能分析。
三、构建数据库的主从架构发展到大型成熟的公司之后,主从架构可能就有点落伍了,取而代之的是更加复杂的数据库集群。但作为一个小型电商公司,数据库的主从架构应该是最基础的。任何大型的系统架构,都是不断演进的。主从架构便是数据库架构中最基础的架构。所以研究完主从架构,也就能看懂更加复杂的架构了。
首先为什么要读写分离?
对于一个小型网站,可能单台数据库服务器就能满足需求。但在一些大型的网站或者应用中,单台的数据库服务器可能难以支撑大的访问压力,升级服务器性能成本又太高,所以必须要横向扩展。还有就是,单库的话,读、写都是操作一个数据库。数据多了之后,对数据库的读、写性能就会有很大影响。同时对于数据安全性和系统的稳定性也是挑战。
数据库的读写分离的好处?
-
将读操作和写操作分离到不同的数据库上,避免主服务器出现性能瓶颈;
-
主服务器进行写操作时,不影响查询应用服务器的查询性能,降低阻塞,提高并发;
-
数据拥有多个容灾副本,提高数据安全性,同时当主服务器故障时,可立即切换到其他服务器,提高系统可用性。
读写分离的基本原理就是让主数据库处理事务性增、改、删操作(Insert、Update、Delete)操作,而从数据库处理Select查询操作。数据库复制被用来把事务性操作导致的变更同步到其它从数据库。
以SQL为例,主库负责写数据、读数据。读库仅负责读数据。每次有写库操作,同步更新到读库。写库就一个,读库可以有多个,采用日志同步的方式实现主库和多个读库的数据同步。
1SQL Server 读写分离的配置
SQL Server提供了三种技术,可以用于主从架构之间的数据同步的实现:日志传送、事务复制和SQL 2012 中新增的功能Always On 技术。各自优劣,具体的大家自己去百度吧,这里提供网上的朋友的配置方式,仅供参考。
日志传送:SQL Server 2008 R2 主从数据库同步
(链接:http://www.it165.net/database/html/201306/4088.html)
事务复制:SQL Server 复制:事务发布
(链接:http://www.cnblogs.com/gaizai/p/3305879.html)
(图源:网络)
2C# 数据库读写操作
C#的请求数据库操作,单数据库和主从架构的数据库还是不一样的。主从架构的数据库,为了保证数据一致性,一般主库可读可写,从库只负责读,不负责写入。所以,实际C#在请求数据库时,要进行区别对待。
最简单的就是:配置两个数据库连接,然后在各个数据库调用的位置,区分读写请求相应的数据库服务器,如下图:
第二种解决方案就是判断SQL语句是写语句(Insert 、Update、Create、 Alter)还是读语句(Select)。
Demo下载:http://files.cnblogs.com/files/zhangweizhong/Weiz.DB.rar
(PS:此Demo为本人总结,跟实际生产中的DLL 不太相同,但原理是一样的,大家总结封装吧)
同时,增加相关的数据库配置
四、基于共享存储的图片服务器架构在当前这个互联网的时代,不管何种网站,对图片的需求量越来越大。尤其是电商网站,几乎都会面临到海量图片资源的存储、访问等相关技术问题。在对图片服务器的架构、扩展、升级的过程中,肯定也会碰到各种各样的问题与需求。当然这并不代表,你就必须得弄一个特别NB的图片服务架构,只要简单、高效、稳定就行。这部分我们来总结一个特别简单、高效的图片服务架构:通过共享存储的方式来实现图片服务架构。
然而,也有一些人问我,现在大型网站的图片服务器的架构已经完全不是这样了,别人家的图片系统比你这个牛逼多了,为啥不直接写那个呢?
事实是:第一,大型牛逼的系统我也不会;第二, 再牛逼的系统也是从小的架构演化过去的,没有一步到位的。这里介绍图片服务器架构虽然比较简单,但也是经过了单机时代的演化了,基本上可以满足中小型分布式网站的需求。这种架构的搭建和学习成本都极低,符合目前“短平快”的开发模式。
通过共享目录的方式实现共享存储 ,在共享目录文件服务器上配置独立域名,这样可以将图片服务器和应用服务器进行分离,来实现独立图片服务器。
优点:
-
将图片服务和应用服务分离,缓解应用服务器的I/O负载。
-
通过共享目录的方式来进行读写操作,可以避免多服务器之间同步相关的问题。
-
相对来讲很灵活,也支持扩容/扩展。支持配置成独立图片服务器和域名访问,方便日后的扩展和优化。
- 相对于更加复杂的分布式的NFS系统,这种方式是性价比高,符合目前互联网的“短平快”的开发模式。
缺点 :
-
共享目录配置有些繁琐。
-
会造成一定的(读写和安全)性能损失。
-
如果图片服务器出现问题,那所有的应用都会受到影响。同时也对存储服务器的性能要求特别高。
- 图片上传操作,还是得经过Web服务器,这对Web服务器还是有巨大的压力。
架构非常简单,基本架构如下图所示:
在存储服务器上建立一个共享目录(具体方式,我就不去重复了,自己百度吧,注意共享目录的文件安全)。
各个应用直接通过共享目录(\192.168.1.200),将图片上传到存储服务器上。
建立一个Web站点(i1.abc.com)将该共享目录通过Web站点发布出去。这样其它的应用就能访问到相关图片。
所以,各应用将文件上传到共享目录
//保存原图
//完整的地址:\192.168.1.200\lib\2016\03\04\10\IMG\4ugvvt6m9gdu.jpg
relativePath = relativeDir + fileName + imageExtension;
var absolutePath = ConfigHelper.SharePath + relativePath;
fileData.SaveAs(absolutePath);
上传成功后,可直接通过web 的方式访问:
http://i1.abc.com/lib/2016/03/04/10/IMG/4ugvvt6m9gdu.jpg
五、移动M站建设最近在一直在搞M站,也就是移动Web站点。由于是第一次,也遇到了很多问题,所以把最近了解到的东西总结一番。聊一聊什么是移动M站,以及它有什么作用和优势。
有人会问,M站和APP有什么不同?
1.APP直接在用户的移动设备上,曝光率相对较高。 而M站需打开浏览器,输入地址才能访问,所以曝光率相对较低。
2.M站的推广的渠道相比移动APP,渠道较多,方便追踪用户来源、流量入口等,方便以后的活动推广和数据分析。
3.M站用户无需安装,输入URL即可访问,而APP需要下载安装。
4.M站能够快速地通过数据分析,能快速得到用户的反馈,从而更容易根据统计数据分析和用户的需求来调整产品。
5.APP对用户更具粘性及用户体验也更好。
6.M站对于营销推广活动非常方便,转发分享方便快捷。
7.M站更新迭代产品速度和响应产品调整非常快,随时发布,而APP需要审核时间。
8.M站跨平台,无需开发安卓和iOS版,只需有浏览器即可。
所以, 我觉得,M站和客户端是相辅相成的。M站的及时性和快捷性,是APP无法比拟的。而APP的用户体验,则是M站无法做到的。目前来说两者是不可能被对方完全替代的,在互联网营销大行其道的今天,M站也越来越重要。营销活动大多以H5页面的形式展示和传播。通过M站的营销和推广,从而又促进APP的使用和推广。
目前,移动M站有倾向APP的趋势。M站会越来越像个APP,使得M站也越来越重要。而且,很多APP的展示效果,在原生代码无法实现的时候,嵌套移动H5页面也是一个很好的选择。
下面介绍几个移动M站建设的要点:
1.51Degree
51Degrees号称是目前最快、最准确的设备检测的解决方案。它是一个免费开源的.NET移动应用开发组件,可以用来检测移动设备和浏览器。甚至可以获取屏幕尺寸、输入法、加上制造商和型号信息等。从而可以选择性地被定向到为移动设备而设计的内容。由于拥有精确的移动设备的数据,所以几乎支持所有的智能手机,平板电脑等移动设备。
其实说白了,51Degree的作用就是识别客户端的设备。PC浏览器访问,就跳转到PC站,手机浏览器访问就跳转到M站。从而达到更好的用户体验。
如何将51Degree加入到现有网站?
http://51degrees.codeplex.com/wikipage?title=Enhance%20existing%20web%20site
2.架构
移动Web和传统的Web其实并没有本质的区别。说白了还是一个Web站点,使用的技术都是Html+CSS+JS。不同的是,只不过目前在Html5的大趋势下,将Html5加入到了移动M站,使得M站更像个轻APP。
3.Bootstrap
Bootstrap就不多说了,网上有很多Bootstrap的资料。它最大的优势应该就是非常流行,非常容易上手。如果缺少专业的设计或美工,那么Bootstrap是一个比较好的选择。他的用法极其简单,几乎没什么学习成本,绝对是快速开发的利器。
官网:http://getbootstrap.com/
Github:https://github.com/twbs/bootstrap/
4.几点建议
移动M站的URL要尽量和PC相同,这是可以避免同一URL在PC站可以显示,但是在手机上打开却是404;
M站写单独的TDK。
六、系统容量预估电商公司的朋友,这样的场景是否似曾相识:
运营和产品神秘兮兮的跑过来问:我们晚上要做搞个促销,服务器能抗得住么?如果扛不住,需要加多少台机器?
于是,技术一脸懵逼。
其实这些都是系统容量预估的问题,容量预估是架构师必备的技能之一。所谓,容量预估其实说白了就是系统在Down掉之前,所能承受的最大流量。这个是技术人员对于系统性能了解的重要指标。常见的容量评估包括流量、并发量、带宽、CPU、内存 、磁盘等一系列内容。这部分来聊一聊容量预估的问题。
1.几个重要参数
-
QPS:每秒钟处理的请求数。
-
并发量: 系统同时处理的请求数。
- 响应时间: 一般取平均响应时间。
很多人经常会把并发数和QPS给混淆了。其实只要理解了上面三个要素的意义之后,就能推算出它们之间的关系:QPS = 并发量 / 平均响应时间。
2.容量评估的步骤与方法
1)预估总访问量
如何知道总访问量?对于一个运营活动的访问量评估,或者一个系统上线后PV的评估,有什么好方法?
最简单的办法就是:询问业务方,询问运营同学,询问产品同学,看产品和运营对此次活动的流量预估。
不过,业务方对于流量的预估,应该就PV和用户访问数这两个指标。技术人员需要根据这两个数据,计算其他相关指标,比如QPS等。
2)预估平均QPS
总请求数=总PV*页面衍生连接数
平均QPS = 总请求数/总时间
比如:活动落地页1小时内的总访问量是30w PV,该落地页的衍生连接数为30,那么落地页的平均QPS=(30w30)/(6060)=2500。
3)预估峰值QPS
系统容量规划时,不能只考虑平均QPS,还要考虑高峰的QPS,那么如何评估峰值QPS呢?
这个要根据实际的业务评估,通过以往的一些营销活动的PV等数据进行预估。一般情况下,峰值QPS大概是均值QPS的3-5倍,如果日均QPS为1000,于是评估出峰值QPS为5000。
不过,有一些业务会比较难评估业务访问量,例如“秒杀业务”,这类业务的容量评估暂时不在此讨论。
4)预估系统、单机极限QPS
如何预估一个业务,一个服务器单机的极限QPS呢?
这个性能指标是服务器最基本的指标之一,所以除了压力测试没有其他的办法。通过压力测试,算出服务器的单机极限QPS 。
在一个业务上线前,一般都需要进行压力测试(很多创业型公司,业务迭代很快的系统可能没有这一步,那就悲剧了),以APP推送某营销活动为例(预计日均QPS为1000,峰值QPS为5000),业务场景可能是这样的:
-
通过APP推送一个活动消息;
-
运营活动H5落地页是一个Web站点;
- H5落地页由缓存Cache和数据库DB中的数据拼装而成。
通过压力测试发现,Web服务器单机只能抗住1200的QPS,Cache和数据库DB能抗住并发压力(一般来说,1%的流量到数据库,数据库120 QPS还是能轻松抗住的,Cache的话QPS能抗住,需要评估Cache的带宽,这里假设Cache不是瓶颈),这样,我们就得到了Web单机极限的QPS是1200。一般来说,生产系统不会跑满到极限的,这样容易影响服务器的寿命和性能,单机线上允许跑到QPS1200*0.8=960。
扩展说一句,通过压力测试,已经知道Web层是瓶颈,则可针对Web相关的方面做一些调整优化,以提高Web服务器的单机QPS 。
还有压力测试工作中,一般是以具体业务的角度进行压力测试,关心的是某个具体业务的并发量和QPS。
5)回答最开始那两个问题
需要的机器=峰值QPS/单机极限QPS
好了,上述已经得到了峰值QPS是5000,单机极限QPS是1000,线上部署了3台服务器:
服务器能抗住么? -> 峰值5000,单机1000,线上3台,扛不住
如果扛不住,需要加多少台机器? -> 需要额外2台,提前预留1台更好,给3台保险
3.总结
需要注意的是,以上都是计算单个服务器或是单个集群的容量。实际生产环境是由Web、消息队列、缓存、数据库等等一系列组成的复杂集群。在分布式系统中,任何节点出现瓶颈,都有可能导致雪崩效应,最后导致整个集群垮掉 (“雪崩效应”指的是系统中一个小问题会逐渐扩大,最后造成整个集群宕机)。
所以,要了解规划整个平台的容量,就必须计算出每一个节点的容量。找出任何可能出现的瓶颈所在。
七、缓存系统对于一个电商系统,缓存是重要组成部分,而提升系统性能的主要方式之一也是缓存。它可以挡掉大部分的数据库访问的冲击,如果没有它,系统很可能会因为数据库不可用导致整个系统崩溃。
但缓存带来了另外一些棘手的问题: 数据的一致性和实时性。例如,数据库中的数据状态已经改变,但在页面上看到的仍然是缓存的旧值,直到缓冲时间失效之后,才能重新更新缓存。这个问题怎么解决?
还有就是缓存数据如果没有失效的话,是会一直保持在内存中的,对服务器的内存也是负担,那么,什么数据可以放缓存,什么数据不可以,这是系统设计之初必须考虑的问题。
什么数据可以放缓存?
不需要实时更新但是又极其消耗数据库的数据。比如网站首页的商品销售的排行榜,热搜商品等等,这些数据基本上都是一天统计一次,用户不会关注其是否是实时的。
需要实时更新,但是数据更新的频率不高的数据。
每次获取这些数据都经过复杂的处理逻辑,比如生成报表。
什么数据不应该使用缓存?
实际上,在电商系统中,大部分数据都是可以缓存的,不能使用缓存的数据很少。这类数据包括涉及到钱、密钥、业务关键性核心数据等。总之,如果你发现,系统里面的大部分数据都不能使用缓存,这说明架构本身出了问题。
如何解决一致性和实时性的问题?
保证一致性和实时性的办法就是:一旦数据库更新了,就必须把原来的缓存更新。
说一说我们的缓存方案:我们目前的缓存系统:Redis(主从)+ RabbitMQ + 缓存清理服务组成,具体如下图:
缓存清理作业订阅RabbitMQ消息队列,一有数据更新进入队列,就将数据重新更新到Redis缓存服务器。
当然,有些朋友的方案,是数据库更新完成之后,立马去更新相关缓存数据。这样就不需要MQ和缓存清理作业。不过,这同时也增加了系统的耦合性。具体得看自己的业务场景和平台大小。
以上均为个人经验分享,不足之处请大伙轻点拍砖,有更好的建议欢迎留言。
热门评论
受益了。。。。。。。。。。。。。。。。。。