结合实例谈项目架构设计

作为一个移动端开发人员来讲,是很难接触到后端项目架构的,所幸,从2015年开始,负责部分管理工作,参与了项目架构相关的工作。项目从小到大,架构也越来越复杂,特别是最近做的一个跨国型项目,涉及到国内国外服务器的部署,尤为复杂。本文结合这些项目实践,介绍基于阿里云的后端架构设计。(部分内容为引用他人的文章,文中已有说明,咱是尊重版权的)







1.基础架构:

2015年初,团队做了一个美食项目,业务逻辑比较简单,主要是实现用户、餐馆、美食三元素的增删改查及三者之间的关联查询。后端程序采用的是php,前端面对的是iOS和Android两款App。当时购买了一台阿里云ECS服务器,在该服务器上安装了MySQL以用于数据存储。应用程序、数据库、文件等所有资源都在一台服务器上,网站架构如下图所示:



此架构简单,适用于项目初期,访问量比较小情况。这里着重要说一下的是,此项目中涉及到资源文件的存储但并没有用到OSS服务器,我们的做法是在客户端在上传图片文件的时候,接口程序会将图片压缩为所需的多种尺寸,并保存在对应的文件夹下,前端再取图片的时候在URL后拼接对于的尺寸即可访问。如客户端上传了一张图片,程序会压缩为30*30,120*120,240*240三种尺寸,客户端根据界面需要采用xxxxx_30.png的方式访问,这个功能在阿里云的OSS服务器上有现成的服务,无需自己压缩。


2.应用与数据分离架构:

2015年底,团队开始做了一个图片社交项目,其功能是全部模仿Instagram,但是内容主要针对的是服装、奢侈品。用户通过手机拍摄一些奢侈品、服装相关的视频、图片,并添加对应的下载链接,发布到平台后,用户可以看到其他所有人发布的内容,并可以根据链接购买。
这个项目中涉及到大量视频、图片的处理,这里我们实现了应用服务、数据服务、资源服务的分离。我们购买了四台阿里云服务器,分别是两台ECS、一台OSS、一台RDS,其结构如下图:





3.集群式部署初级架构
2016年我们开始做一个大型的在线教育平台项目,经历一年的磨合,项目趋于稳定,我们的服务器架构也日臻完善。本想总结一下服务器的架构,在下笔之前在网上看到了他人总结的一篇文章 项目架构设计总结,再此先向作者表示敬意,以下是引用的这篇文章的部分内容:


 --------------------------------------引用有此处开始--------------------------------------



 项目背景
 
项目的前端主要为ios应用以及一些web管理系统,后端的职能主要为前端提供数据接口。我个人在项目中主要负责整个后端的架构设计、服务器运维、php开发等一系列后端工作,因为主要是我一个人负责,在一定程度上也减少了许多沟通成本。
 
 总体架构
 
 项目后端架构使用阿里云服务搭建,其中RDS为主从集群,并配备灾备实例。ECS可根据业务量动态弹性伸缩,其余服务均采用单实例的方式远程调用。
 



 
 VPC
 
 搭建VPC的原因有以下几点

 1.可以将业务数据库和业务服务器放置在可以自己掌握的同一内网,可以提高一些安全性。
 2.阿里云服务之间通过内网访问的流量是不收费的。所以在选购服务时,带宽可以选择流量版,这样在保证带宽速率的同时,还可以极大的减少运维费用。
 举个例子:同样一台ECS,在同为百兆带宽的情况下,每月的费用如下图:
 
 按固定带宽



 按使用流量
 


 当然,能这样的做的原因也是因为在这个架构中,ECS仅处理业务逻辑,几乎不存储文件资源。大部分静态资源,如视频图片等,都是存储在OSS上。如果存放静态资源,比如下视频或图片什么的,流量一多那就很亏了。
 3.内网访问,稳定而且速度快。
 
 业务数据层
 
 RDS

 项目一开始,RDS选购的是共享型单实例的,随着业务量的提升,可以多区域部署只读实例。另外,保险起见,主实例可以配有一个灾备实例,防止意外发生。
 
 Redis
 提到阿里云的这个Redis,不得不吐槽一句,它竟然是不支持主从的,只能单实例,不过,用它做数据缓存,还真是蛮不错的选择,响应速度非常快。而且,因为是放置在内网的且只能内网访问,所以安全性也很高。
 
 MongoDB
 结构型数据,主要存储档案式的数据,比如每个用户的操作行为,以档案式记录并进行统计分析,方便下一阶段的项目做个性化服务。另外一些关联复杂的数据,也可以用MongoDb存储,可以提高访问速度。还有,一些对软件应用版本比较敏感的数据也可以存在MongoDB中,比如a版本拿到A数据,b版本拿到B数据,而这个AB数据都是由很多关联关系复杂的数据所组成,如果把这些数据根据版本号存储在不同的MongoDB档案中,需要时,直接根据版本号拿就可以了,这样就避免了很多的mysql查询。
 
 静态资源
 
 OSS + CDN

 OSS存储静态资源,CDN(内容分发网络)可以加速静态资源的下载速度。至于资源链接地址,客户端可以通过接口访问从后端业务数据库中拿到。
 服务器安全
 
 运维层面

 1.选购了阿里云的web防火墙和态势感知的服务。这两个服务可以实时监控服务器状态,识别并跟踪攻击来源和类型,可以说,用这两个工具也节省了很多人力成本。阿里云还有其它安全类产品,可以根据项目选购,使用起来也都很方便。
 2.配置firewalld。
 
 业务层面
 针对接口访问的安全性,主要做了以下工作
 1.签名验证:防止伪造请求
 2.访问频次限制:计数器是用phpredis制作的毫秒级计数器
 3.https访问
 4.部分敏感数据,使用RSA非对称加密
 
 服务器集群
 
 主ECS

 通过这台ECS,可以管理其它从属的ECS,并查看状态。安装的主要工具为ansible。
 如果不需要用这台ECS来做负载均衡的话,可以配置白名单连接,只允许管理员ip才能访问。
 
 从属ECS
 这类ECS服务器只存放逻辑代码,所以当需求量增加时,只需增加此类服务器的个数即可。而且,在增加个数时,可以使用之前制作好的镜像,创建多台相同环境的ECS服务器。每台ECS的web环境为nginx1.10和php7,微服务容器环境用的docker。
 
 负载均衡
 负载均衡可以采用两种方式
 1.购买阿里云的负载均衡实例(注意要买带公网ip的)。由该负载均衡实例接收请求后,会分发到内部服务器。
 2.在某台具有外网ip的ECS上使用nginx部署负载均衡服务。
 
 个人更倾向第一种,毕竟管理起来比较方便,节省人力。
 
 使用到的第三方服务
 
 Coding

 后端的所有代码都是放在Coding上的,喜欢Coding的原因有三个。
 1.私有git仓库没有个数限制。
 2.有ios客户端且比较好用。
 3.操作界面好看。
 
 后端代码的自动部署是通过Coding的webhook实现的
 具体操作可以去看这篇博客《利用Coding的webhook自动部署项目》。
 
 实现的场景:代码的自动部署与持续集成。
 当我提交代码到开发分支上时,测试服务器上会自动更新开发分支上的代码。
 当我把开发代码合并到主分支上时,正式服务器会自动拉取master分支上的代码,可谓是方便快捷。
 jenkins 之类的工具虽然也尝试过,但是感觉部署起来很不方便,不够定制化,而且还消耗了一部分服务器资源。
 
 
 后端逻辑层架构
 
 接口

 项目起初的接口是基于phalapi框架开发,现在逐步过渡到基于laravel5.3开发。
 项目起初选择phalapi的原因
 1.phalapi框架是轻量级的接口发框架,开发起来比较便捷、快速,尤其是那个依赖注入挺好用的。
 2.phalapi框架有很多现成的扩展可以使用,不用去找,而且这些也能基本满足业务的需要。我个人还基于这个框架开发了两个扩展,一个是关于使用workman的,一个是关于使用gearman的。
 其中gearman是用来异步处理请求的,详细介绍可以看这篇博客《基于Phalapi框架的gearman扩展(异步并发)》
 根据业务量提高性能
 
 http请求的并发性能可以通过增加ECS实现,针对部分耗时较长且无须即时回调的请求,可以用gearman异步处理。
 数据库的并发连接数可以通过增加配置来提高,也可以通过创建只读实例进行读写分离,提高数据处理能力。再往后,可能需要搭建hadoop管理数据库集群,不过等用上hadoop的时候,应该已经不是项目初期了,至少数据量得是TB级的了。
 其它还可以采用优化nginx配置,优化linux内核,采用高速固态硬盘等等的手段。
 #总结评价
 这套架构基本上可以完全满足项目初期的业务需要,而且所有的云服务费用总和也非常少(相比于自建服务器机房)。随着业务量的提升,可以逐步升级配置以应对需求,还可以在短时间内临时性的提高并发处理能力。总结起来就是省钱、省时、省力气。

 ----------------------------------------引用到此为止--------------------------------------




4.集群式部署国际化架构


随着业务的扩展,最近我们的项目需要发布到海外市场,原有的服务器架构已经不能满足市场的需求。由于之前并未接触如此大的项目,对海外市场服务器的部署非常不了解,在跟阿里云架构师沟通的基础上,我们得出两种解决方案:


方案一:
阿里云有一款叫全球加速的产品,该产品不用购买和部署海外服务器,只需购买全球加速服务,阿里云接入其自建的全球骨干网络,据说可实现海外访问100ms的延时。不过此种方式,成本较高,我们选择了放弃,其结构如下图:


方案二:


第二种方案就是在海外部署服务器,其结构如下图:


在上一种架构的基础上,在所需要的点购买ECS服务器,海外节点通过香港入口访问国内的RDS和Redis。同时在海外对应的节点部署CDN,用于访问OSS服务器时的加速,海外用户访问对应节点的CDN,CDN通过香港入口访问OSS服务器,并将所访问的对象文件缓存到对应的节点,当用户下次再次访问该对象时,直接从对应的CDN节点缓存中获取,以此方式提高访问速度。