进行web开发时应该考虑的架构性因素
功能实现
这个自不必说。
性能与可伸缩性
根据预期的访问量,评估机器负载情况。如果在可预期的未来一台服务器可以撑得住,则没必要使用多台服务器。需要对多个环节进行性能评估:web服务器、逻辑服务器、DB等等。同时每个环节都可以考虑是否需要缓存。
在web服务器层面,有一个重要的点,即系统的 URL 选择。首先,要尽最大可能避免访问量差别很大的系统共用一个域名。因为随着系统的发展,很有可能需要对访问量大的系统进行扩容。扩容引入分流机制。如果这两个系统共用同一个域名,且 URL 的区分度不高,会对分流机制造成很大的障碍。虽然说有些系统或模块(或页面)的 URL 相对可变,但是对于开放给外部(尤其是公司外部)访问的 URL 来说,变更是不可能的。这种类型的 URL 本质上是 API。这又牵扯到另外一个主题:《API 设计》。这里暂且 pass。
在逻辑服务器层面,切记读写分离,如果预计系统不需要多台服务器,也该为读写分离留下后路。还有一点需要关注的是,不同的服务之间互相访问,不要直接以 ip:端口 的形式,而尽量以域名的方式。如果是用前者,后期扩容时,也可以引入虚拟 ip 补救。
在 DB 层面,考虑是否需要引入 memcache 或 redis 之类的缓存。考虑是否需要做 M-S。另外,考虑 DB 层是直接对上层暴露 ip 端口,还是引入一个抽象层(如虚拟 ip)。再者,做库表设计时,考虑是否应该分库、分表。
在引入了多服务器架构之后,随之而来的是数据同步与合并问题。比如,A 服务器上产生了一张图片,可能需要把它同步到 B 服务器上。或者数据库需要做 M-S 同步。需要合并的,最典型是日志。如果日志分散在许多台机器上,定位问题和分析日志都显得非常麻烦,需要有一种合并机制。还有一个也是很重要的点,即 session 的合并。同一个用户,可能第一次请求到 A 服务器上,下一次请求到 B 服务器上,如何使这两台机器能共享一个 session,是一个需要解决的问题。一个解决方案是使用 redis 存储会话信息。
在多服务器架构下,动态脚本和静态文件分离是一个比较好的经验。这里的分离指使用不同的域名,代码文件放在不同的机器上。这是因为动态脚本和静态文件的性能属性差别比较大。将它们分开可以对它们使用不同的部署策略。例如,静态文件可以更有效地利用浏览器缓存。
可用性
可用性这个方面,有很多与上一个重叠的地方,因为都涉及到多服务器。他们之间的区别是:可伸缩性考虑的是系统能不能撑得住很大的访问量,以及当访问量意外性的出现暴增时,系统能否快速提升自身的处理能力来进行响应。而可用性关注的问题是:这个服务的重要性如何?如果特别重要,怎么保证它不会挂?
提升可用性的常用手段之一是引入冗余灾备措施。同样涵盖上面提到的那几个环节。如果要引入冗余,切记重点关注两个问题:1,单点故障;2,跨机房。
单点故障。假设把架构设计成:前端两台 web 服务器,域名通过 dns 解析到这两台机器上,逻辑服务器也两台,但是 DB 只有一台。那么 DB 这个环节就是一个单点。如果 DB 服务器挂掉,整个系统都会挂掉。前面设计了两台 web 服务器和两台逻辑服务器都没有任何意义。
然后说一下跨机房。跨机房是一个很大的挑战,除非十分必要,否则尽量不要使用跨机房架构。因为通常情况下,我们几乎不可能把所有的服务都在两个地方部署一份。99.99% 会出现这样的情况:部署了跨机房的系统,需要访问另外一个只在一个机房有部署的服务。这个时候,其中一个机房必须通过通道访问另外一个机房。这样,两个机房就不是完全一样的了。此外,两个机房的数据、日志等都需要同步、合并。这些都会使运维的难度大大提高。
除了冗余之外,考虑可用性,还应想到监控措施。监控有多种方法。常用的方法有:
1,日志或数据分析。服务器上后台跑进程,不停地对日志或类日志的数据进行分析,一旦发生异常,报警。
2,代码中植入对服务或接口的监控。当用代码访问一个服务时,检查其响应。如果响应异常,报警。
3,心跳式轮询检测。每隔一段时间向服务发送特殊的请求,检查其响应。如果响应异常,报警。
4,服务器负载监控。例如 CPU、内存、硬盘、IO、cgi 进程数等等。有些情况下这些工作有运维工程师去做。
5,代码中植入对响应时间的统计,并另起后台进程,对响应时间进行监控。
其中,1、2、4、5是系统内部的监控,3是系统外部监控。系统内部监控可以更加细致,能监控到一些外部监控不到的东西。但是,一旦系统本身挂掉(例如服务器挂了),内部监控也会失效。
可扩展性
这个方面涉及到软件的逻辑架构,更多的与业务相关。考虑可扩展性的目的是为了应对需求变更。这要求首先对需求有较深入的了解,并且能够大致把握到需求变更的方向。这之后,在代码结构层面,为预期的变更方向留下空间。要求设计者具有非常丰富的编码经验和对设计模式有深刻的理解。
可调试性
这个方面容易被忽略,却是非常重要的一环。web 系统的部署环境和交互流程越来越复杂,有时候定位一个线上问题非常困难。通常是开发环境无法重现,同时又获得不到足够的信息进行定位。因此这个因素应该在系统设计时就考虑进去:当出现问题时,如何方便地进行定位和调试?这里分服务端和页面两个部分考虑。
日志不必说,是重要的信息来源。服务端写日志,需要对日志进行有效的组织(这里也是一门学问)。
另外,服务端需要注意的一点,是统一的错误码处理。错误码管理混乱会影响问题的定位。最好的情况是,错误码分得很细,并且保证绝对无重复。这样,开发一拿到错误码,立刻就能大概判断出问题所在。
再者,服务端,可能需要备好调试工具。可以理解为后门,但是只有经过授权才能使用。
前端写不了日志是个大问题,需要另寻途径把错误信息拿到手。最差的方法是牺牲部分用户体验,把错误码以某种方式展示出来,然后通过询问用户来获得错误码。这种方式不建议使用。更好的做法是,在前端搜集错误信息,然后通过接口上报到服务器进行存储。
可测试性
可测试性和可调试性的区别是什么?可调试性考虑的问题是:系统上线运行之后,如何快速定位并处理线上出现的问题;可测试性考虑的问题是:测试人员怎么测这个系统。
在开发之前就考虑测试,一来是未雨绸缪,为将来的测试阶段提供便利;二来有利于提高代码质量。关于这一点,实践过TDD的人都心领神会。
安全
安全的重要性再怎么强调都不为过。xss、csrf、sql注入、敏感信息泄露、刷接口、重放等等等等。安全领域涉及到的东西很多。
数据统计与后台
考虑系统是否需要后台管理、是否需要收集数据进行统计分析,这些都会影响到系统的设计。后台管理者通常在经过授权之后会得到高权限,因此系统设计上需要区分角色。而数据的收集容易导致所谓的“霰弹式修改”,引起系统的快速腐烂。
进行web开发时应该考虑的架构性因素的更多相关文章
- Golang Web开发时前端出现谜之空白换行的坑
在使用Golang做Web开发时,有时候渲染出来的模板在前台显示时会出现一些奇怪的空白换行,具体特征就是查看css样式表并没有相关定义的空白部分. 分析: 查看出现问题页面的网页源代码,复制空白换行部 ...
- Ionic进行PC端Web开发时通过脚本压缩提高第一次加载效率
1. 问题 1.1. 问题上下文描述: 基于Ionic进行PC端的Web应用开发: 使用Tomcat作为最终服务发布容器. 1.2. 问题描述: 编译后main.js的大小为4-6MByte.(集成第 ...
- java web开发时的绝对路径与相对路径
相对路径 不以/开头的路径为相对路径,使用相对路径时的路径为当前访问的文件的父目录,即如果现在访问文件的路径为http://localhost:8080/项目名/目录/文件,那么使用相对路径时路径前缀 ...
- WEB开发时Browser控件得到C:\fakepath\ 的解决方式
IE9中JS获得文件上传控件的路径不对,为:C:\fakepath\ 原来要修改: 工具 -> Internet选项 -> 安全 -> 自定义级别 -> 将本地文件上载至服务 ...
- [工具]web开发时自动刷新网页:liveReload
传统网页开发流程:用sublime text写好代码,运行,发现问题,再回到sublime text修改,运行…如此往复,十分繁琐.今天看到有人(<LiveReload>讓Sublime ...
- HTML5 web开发时遇到的一个奇葩问题。
昨天做了一个手机端的H5 页面. 首先就是各种兼容测试,调整修复..一系列操作之后,拿过来N多手机神马华为.小米.三星.水果5.6.plus,一番测试之后.嗯,还不错,稍作等待之后就上线了. 这是分割 ...
- JFinal Web开发学习(二)目录、架构、package设计
package分类 config是JFinal的项目配置 controller是控制器 handler可以设置全局处理器,例如判断用户请求中是否直接请求 FreeMarker的模板文件ftl或者htm ...
- Eclipse进行Java web开发时,可能会出现这样的错误:The superclass javax.servlet.http.HttpServlet was not found on the Java Build Path
我们遇到的错误显示如下: 我们右击有错误提示的文件夹,如下: 我们点击”配置构建路径“,如下: 我们再点击”添加库“,如下: 我们选中上图中标出的选项,再点击下一步,如下: 我们再 ...
- Web开发中B/S架构和C/S架构的区别
在web开发中有两种基本架构,即C/S架构和B/S架构那么这两种架构有什么区别呢?那么就一起来看看吧. C/S架构图: B/S架构图: C/S架构是 浏览/服务器端的交互,是早期的一种分布式架构,在该 ...
随机推荐
- X11 fluxbox窗口管理器
/********************************************************************************* * X11 fluxbox窗口管理 ...
- 在VM上安装centOS后的网络配置
花了点时间,研究了下VM上的linux虚拟机的网络配置问题.1.环境主机:winXP SP2,家庭宽带,局域网连到路由器,ip地址为192.168.1.101. 虚拟机:centOS(redhat l ...
- 20155117王震宇 2016-2017-2 《Java程序设计》第七周学习总结
教材学习内容总结 时间度量 格林尼治标准时间(GMT):现在GMT已不作为标准时间使用. 世界时(UT):借助观测远方星体跨过子午线而得,受地球自转速度影响. 国际原子时(TAI):铯原子辐射振动幅度 ...
- <frameset>框架集中不同<frame>之间的调用【js代码中】
top:永远指分割窗口最高层次的浏览器窗口;parent:包含当前分割窗口的父窗口,本文将围绕js中top.parent.frame进行讲述及他们的应用案例 引用方法top: 该变量永远指分割窗口最高 ...
- baidu手机浏览器安卓4.5版公布:由于快,所以爱
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDUyMzk4OA==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- Digester库使用总结
1.Digester是Apache软件基金会的Jakarta项目下的子Commons项目下的一个开源项目,Digester API包含3个包:org.apache.commons.digester,提 ...
- 【转】每天一个linux命令(28):tar命令
原文网址:http://www.cnblogs.com/peida/archive/2012/11/30/2795656.html 通过SSH访问服务器,难免会要用到压缩,解压缩,打包,解包等,这时候 ...
- Java中 @Override 的作用
@Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: 可以当注释用,方便阅读: 编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错.例如,你如 ...
- Anaconda 使用(解决python包管理与环境管理)
Anaconda完全入门指南(对python环境和原理,讲的比较透彻):https://www.jianshu.com/p/eaee1fadc1e9 用pip一个一个安装第三方库费时费力,还需要考虑兼 ...
- Python之包管理工具:distutils、setuptools、distribute、setup.py、easy_install、easy_install、pip
在安装Python包的过程中,经常涉及到distutils.setuptools.distribute.setup.py.easy_install.easy_install和pip等等. 介绍:htt ...