大型网站架构
网站架构包括:前端架构+应用层架构+服务层架构+存储层架构+后台架构+数据中心机房架构+安全架构+数据采集与监控。
前端架构
- 浏览器优化技术
并不是优化浏览器,而是通过优化响应页面,加快浏览器页面的加载和显示,常用的有页面缓存、合并HTTP 减少请求次数、使用页面压缩等。 - CDN
内容分发网络,部署在网络运营商机房,通过将静态页面内容分发到离用户最近的CDN 服务器,使用户可以通过最短路径获取内容。 - 动静分离,静态资源独立部署
静态资源,如JS,CSS 等文件部署在专门的服务器集群上,和Web 应用动态内容服务分离,并使用专门的(二级)域名。 - 图片服务
图片不是指网站Logo 按钮图标等,这些文件属于上面提到的静态资源,应该和JS CSS 部署在一起。这里的图片指用户上传的图片,如产品图片、用户头像等,图片服务同样使用独立部署的图片服务器集群,并使用独立(二级)域名。 - 反向代理
部署在网站机房,在应用服务器、静态资源服务器、图片服务器之前,提供页面缓存服务。 - DNS
域名服务,将域名解析成IP 地址,利用DNS 可以实现DNS 负载均衡,配置CDN也需要修改DNS使域名解析后指向CDN 服务器。
应用层架构
应用层是处理网站主要业务逻辑的地方。
- 开发框架
- 页面渲染
将分别开发维护的动态内容和静态页面模板集成起来,组合成最终显示给用户的完整页面。 - 负载均衡
将多台应用服务器组成一个集群,通过负载均衡技术将用户请求分发到不同的服务器上,以应对大量用户同时访问时产生的高并发负载压力。 - Session 管理
为了实现高可用的应用服务器集群,应用服务器通常设计为无状态,不保存用户请求上下文信息,但是网站业务通常需要保持用户会话信息,需要专门的.机制管理Session
使集群内甚至跨集群的应用服务器可以共享Session - 动态页面静态化
对于访问量特别大而更新又不很频繁的动态页面,可以将其静态化,即生成一个静态页面,利用静态页面的优化手段加速用户访问,如反向代理、CDN、 浏览器缓存等。 - 业务拆分
将复杂而又庞大的业务拆分开来,形成多个规模较小的产品,独立开发、部署、维护,除了降低系统耦合度,也便于数据库业务分库。按业务对关系数据库进行拆分,技术难度相对较小,而效果又相对较好。 - 虚拟化服务器
将一台物理服务器虚拟化成多台虚拟服务器,对于并发访问较低的业务,更容易用较少的资源构建高可用的应用服务器集群。
服务层架构
提供基础服务,供应用层调用,完成网站业务。
- 分布式消息
利用消息队列机制,实现业务和业务、业务和服务之间的异步消息发送及低耦合的业务关系。 - 分布式服务
提供高性能、低耦合、易复用、易管理的分布式服务,在网站实现面向服务架构SOA - 分布式缓存
通过可伸缩的服务器集群提供大规模热点数据的缓存服务,是网站性能优化的重要手段。 - 分布式配置
系统运行需要配置许多参数,如果这些参数需要修改,比如分布式缓存集群加入新的缓存服务器,需要修改应用程序客户端的缓存服务器列表配置,并重启应用程序服务器。分布式配置在系统运行期提供配置动态推送服务,将配置修改实时推送到应用系统,无需重启服务器。
存储层架构
分布式文件
网站在线业务需要存储的文件大部分都是图片、网页、视频等比较小的文件,但是这些文件的数量非常庞大,而且通常都在持续增加,需要伸缩性设计比较好的分布式文件系统。关系数据库
大部分网站的主要业务是基于关系数据库开发的,但是关系数据库对集群伸缩性的支持比较差。通过在应用程序的数据访问层增加数据库访问路由功能,根据业务配置将数据库访问路由到不同的物理数据库上,可实现关系数据库的分布式访问NoSQL 数据库
目前各种NoSQL 数据库层出不穷,在内存管理、数据模型、集群分布式管理等方面各有优势,不过从社区活跃性角度看,HBase 无疑是目前最好的。数据同步
在支持全球范围内数据共享的分布式数据库技术成熟之前,拥有多个数据中心的网站必须在多个数据中心之间进行数据同步,以保证每个数据中心都拥有完整的数据。在实践中,为了减轻数据库压力,将数据库的事务日志(或者NoSQL 的写操作Log) 同步到其他数据中心,根据Log 进行数据重演,实现数据同步。
后台架构
网站应用中,除了要处理用户的实时访问请求外,还有一些后台非实时数据分析要处理。
- 搜索引擎
即使是网站内部的搜索引擎,也需要进行数据增量更新及全量更新、构建索引等。
这些操作通过后台系统定时执行。 - 数据仓库
根据离线数据,提供数据分析与数据挖掘服务。 - 推荐系统
社交网站及购物网站通过挖掘人和人之间的关系,人和商品之间的关系,发掘潜在的人际关系和购物兴趣,为用户提供个性化推荐服务。
数据采集与监控
监控网站访问情况与系统运行情况,为网站运营决策和运维管理提供支持保障。
- 浏览器数据采集
通过在网站页面中嵌入JS 脚本釆集用户浏览器环境与操作记录,分析用户行为。 - 服务器业务数据采集
服务器业务数据包括两种,一种是采集在服务器端记录的用户请求操作日志;一种是釆集应用程序运行期业务数据,比如待处理消息数目等。 - 服务器性能数据采集
采集服务器性能数据,如系统负载、内存使用率、网卡流量等。 - 系统监控
将前述采集的数据以图表的方式展示,以便运营和运维人员监控网站运行状况,做
到这一步仅仅是系统监视。更先进的做法是根据釆集的数据进行自动化运维,自动处理
系统异常状况,实现自动化控制。 - 系统报警
如果采集来的数据超过预设的正常情况的阈值,比如系统负载过高,就通过邮件、
短信、语音电话等方式发出报警信号,等待工程师干预。
安全架构
保护网站免遭攻击及敏感信息泄露。
- Web 攻击
以HTTP 请求的方式发起的攻击,危害最大的就是XSS 和SQL 注入攻击。但是只要
措施得当,这两种攻击都是比较容易防范的。 - 数据保护
敏感信息加密传输与存储,保护网站和用户资产。
数据中心机房架构
山寨与创新的最大区别不在于是否抄袭、是否模仿,而在于对问题和需求是否真正理解与把握
在解决问题之前,能够认真思考自己面对的真正问题究竟是什么,有哪些技术方案可以选择,其基本原理是什么。
网站架构其实并不难,真正能解决问题的技术一定是简单的。
大型网站的特点:
高并发、大流量;高可用;海量数据;用户分布广泛且网络环境复杂;安全环境恶劣;需求快速变更,发布频繁;渐进式发展。
网站系统的演进:
- 单机部署
- 数据和应用分离
- 使用缓存减少数据库压力
网站访问特点和现实世界的财富分配一样遵循二八定律:80%的业务访问集中在20%
的数据上 - 应用服务器集群化
可扩展性,负载均衡 - 数据库读写分离
利用的是数据库的主从热备。写主读从。 - 加速网站访问速度:CDN和反向代理。
CDN 和反向代理的基本原理都是缓存,区别在于CDN 部署在网络提供商的机房,使
用户在请求网站服务时,可以从距离自己最近的网络提供商机房获取数据;而反向代理
则部署在网站的中心机房,当用户请求到达中心机房后,首先访问的服务器是反向代理
服务器,如果反向代理服务器中缓存着用户请求的资源,就将其直接返回给用户。 - 分布式数据库和分布式文件系统
网站更常用的数据库拆分手段是业务分库,将不同业务的数据
库部署在不同的物理服务器上。 - 使用NoSQL和搜索引擎
- 业务拆分
- 分布式服务
但事物发展到一定阶段,就会拥有自身的发展冲动,摆脱其初衷,向着使自己更强
大的方向发展。既然大型网站架构解决了海量数据的管理和高并发事务的处理,那么就
可以把这些解决方案应用到网站自身以外的业务上去。我们看到目前许多大型网站都开
始建设云计算平台,将计算作为一种基础资源出售,中小网站不需要再关心技术架构问
题,只需要按需付费,就可以使网站随着业务的增长逐渐获得更大的存储空间和更多的
计算资源。
这个世界没有哪个网站从诞生起就是大型网站;也没有哪个网站第一次发布就拥有
庞大的用户,高并发的访问,海量的数据;大型网站都是从小型网站发展而来。网站的
价值在于它能为用户提供什么价值,在于网站能做什么,而不在于它是怎么做的,所以
在网站还很小的时候就去追求网站的架构是舍本逐末,得不偿失的。小型网站最需要做
的就是为用户提供好的服务来创造价值,得到用户的认可,活下去,野蛮生长。
技术是用来解决业务问题的,而业务的问题,也可以通过业务的手段去解决。
恩,不要妄图用技术解决所有问题。
大型网站架构模式
- 分层
单一职责,上层对下层的依赖关系。 - 分割
业务纵向分割,分布式部署。 - 分布式
分层和分割都是为了便于分布式部署。
常用的分布式方案有:分布式应用和服务;分布式静态资源;分布式数据和存储;分布式计算。 - 集群
- 缓存
缓存是改善软件性能的第一手段。
使用缓存有两个前提条件,一是数据访问热点不均衡,某些数据会被更频繁的访问,
这些数据应该放在缓存中;二是数据在某个时间段内有效,不会很快过期,否则缓存的
数据就会因已经失效而产生脏读,影响结果的正确性。 - 异步
将一个业务操作分成多个阶段,每个阶段之间通过共享数据的方式异步执行进行协作。
在分布式系统中,多个服务器集群通过分布式消息队列实现异步,分布式消息队列可以看作内存队列的分布式部署。
提高系统可用性。
加快网站响应速度。
消除并发访问高峰。 - 冗余
架构要素
从性能、可用性、伸缩性、扩展性、安全这五个要素。
所谓伸缩性是指通过不断向集群中加入服务器的手段来缓解不断上升的
用户并发访问压力和不断增长的数据存储需求。
衡量架构伸缩性的主要标准就是是否可以用多台服务器构建集群,是否容易向集群
中添加新的服务器。加入新的服务器后是否可以提供和原来的服务器无差别的服务。集
群中可容纳的总的服务器数量是否有限制。
关系数据库虽然支持数据复制,主从热备等机制,但是很难做到大规模集群的可伸
缩性,因此关系数据库的集群伸缩性方案必须在数据库之外实现,通过路由分区等手段
将部署有多个数据库的服务器组成一个集群
至于大部分NoSQL 数据库产品,由于其先天就是为海量数据而生,因此其对伸缩性
的支持通常都非常好,可以做到在较少运维参与的情况下实现集群规模的线性伸缩。
扩展性是指的功能扩展,伸缩是指性能伸缩。
性能优化
System Load 即系统负载,指当前正在被CPU 执行和等待被CPU 执行的进程数目总和,是反映系统忙闲程度的重要指标。多核CPU 的情况下,完美情况是所有CPU 都在使用,没有进程在等待处理,所以Load 的理想值是CPU 的数目。当Load 值低于CPU 数目的时候,表示CPU 有空闲,资源存在浪费;当Load 值高于CPU 数目的时候,表示进程在排队等待CPU 调度,表示系统资源不足,影响应用程序的执行性能。
在Linux 系统中使用top 命令査看,该值是三个浮点数,表示最近1 分钟,10 分钟,15 分钟的运行队列平均进程数。
性能测试是一个总称,具体可细分为性能测试、负载测试、压力测试、稳定性测试。
排査一个网站的性能瓶颈和排査一个程序的性能瓶颈的手法基本相同:检査请求处
理的各个环节的日志,分析哪个环节响应时间不合理、超过预期;然后检査监控数据,
分析影响性能的主要因素是内存、磁盘、网络、还是cpuÿ 是代码问题还是架构设计不
合理,或者系统资源确实不足。
前端性能优化
主要优化手段有优化浏览器访问、使用反向代理、CDN 等。
优化浏览器访问的措施:
- 减少http请求。
HTTP 协议是无状态的应用层协议,意味着每次HTTP 请求都需要建立通信链路、进行数据传输,而在服务器端,每个HTTP 都需要启动独立的线程去处理。这些通信和服务的开销都很昂贵,减少HTTP 请求的数目可有效提高访问性能。
减少HTTP 的主要手段是合并CSS,合并JavaScript,合并图片。将浏览器一次访问需要的JavaScript CSS 合并成一个文件,这样浏览器就只需要一次请求。图片也可以合并,多张图片合并成一张,如果每张图片都有不同的超链接,可通过CSS 偏移响应鼠标点击操作,构造不同的URL - 使用浏览器缓存
对一个网站而言,CSSÿ JavaScript , Logo图标这些静态资源文件更新的频率都比较低,而这些文件又几乎是每次HTTP 请求都需要的,如果将这些文件缓存在浏览器中,可以极好地改善性能。
通过设置HTTP 头中Cache-Control 和Expires 的属性,可设定浏览
器缓存,缓存时间可以是数天,甚至是几个月。
在某些时候,静态资源文件变化需要及时应用到客户端浏览器,这种情况,可通改变文件名实现,即更新JavaScript 文件并不是更新JavaScript 文件内容,而是生成一个新的JS 文件并更新HTML 文件中的引用。
使用浏览器缓存策略的网站在更新静态资源时,应采用批量更新的方法,比如需要更新10 个图标文件,不宜把10 个文件一次全部更新,而是应一个文件一个文件逐步更
新,并有一定的间隔时间,以免用户浏览器突然大量缓存失效,集中更新缓存,造成服
务器负载骤增、网络堵塞的情况。 - 启用压缩
在服务器端对文件进行压缩,在浏览器端对文件解压缩,可有效减少通信传输的数
据量。文本文件的压缩效率可达80%以上,因此HTMLÿ CSSÿ JavaScript 文件启用GZip
压缩可达到较好的效果。但是压缩对服务器和浏览器产生一定的压力,在通信带宽良好,
而服务器资源不足的情况下要权衡考虑。 - CSS 放在页面最上面、JavaScript 放在页面最下面
但如果页面解析时就需要用到JavaScript, 这时放在底部就不合适了。
5,减少cookie传输
服务器端性能优化
- 分布式缓存
网站性能优化第一定律:优先考虑使用缓存优化性能。
产品在设计之初就需要一个明确的定位:什么是产品要实现的功能,什么
不是产品提供的特性。在产品漫长的生命周期中,会有形形色色的困难和诱惑
来改变产品的发展方向,左右摇摆、什么都想做的产品,最后有可能成为一个
失去生命力的四不像。
缓存预热
缓存穿透 - 异步
消息队列。需要注意的是,由于数据写入消息队列后立即返回给用户,数据在后续的业务校验、写数据库等操作可能失败,因此在使用消息队列进行业务异步处理后,需要适当修改业
务流程进行配合
任何可以晚点做的事情都应该晚点做。 - 使用集群。
- 代码优化
- 多线程。
启动线程数= [任务执行时间/ (任务执行时间-10 等待时间)] xCPU 内核数
最佳启动线程数和CPU 内核数量成正比,和IO 阻塞时间成反比。
如果是计算型任务,那么线程数最多不超过CPU 内核数,因为启动再多线程,CPU 也来不及调度;相反如果是任务需要等待磁盘操作,网络响应,那么多启动线程有助于提高任务并
发度,提高系统吞吐能力,改善系统性能。 - 对象复用。单例和池技术。
- 数据结果。
- 垃圾回收。
- 多线程。
存储性能优化
B+树,关系型数据库多采用此数据结构。
NoSql产品多采用LSM树作为主要数据结构。
在LSM 树上进行一次数据更新不需要磁盘访问,在内存即可完成,速度远快于B+
树。当数据访问以写操作为主,而读操作则集中在最近写入的数据上时,使用LSM树可以极大程度地减少磁盘的访问次数,加快访问速度。
RAID,通过使用RAID 技术,实现数据在多块磁盘上的并发读写和数据备份。
RAID 技术在传统关系数据库及文件系统中应用比较广泛,但是在大型网站比
较喜欢使用的NoSQLÿ 以及分布式文件系统中,RAID 技术却遭到冷落。
高可用性优化
4个9也就是一年中大约最多53 分钟不可用。
主要手段是数据和服务的冗余备份及失效转移。
分级管理,部署隔离。
超时设置。
异步调用。
服务降级。
幂等性设计。
CAP 原理认为,一个提供数据服务的存储系统无法同时满足数据一致性
(Consistency)、数据可用性(Availibility )、分区耐受性即可扩展性(Patition Toleranceÿ 系统具有跨网络分区的伸缩性)这三个条件。
通常我们必须去保证A可用性和P扩展性,某种程度上放弃C一致性。
数据最终一致性,这是数据一致性中较弱的一种,数据可能不一致,但经过一段时间的自我恢复和修正,数据达到最终一致。
数据备份,冷备和热备。热备又分同步热备和异步热备。
失效转移操作由三部分组成:失效确认、访问转移、数据恢复。
伸缩性优化
实现负载均衡的基础技术:
- HTTP 重定向
这种负载均衡方案的优点是比较简单。缺点是浏览器需要两次请求服务器才能完成
一次访问,性能较差;重定向服务器自身的处理能力有可能成为瓶颈,整个集群的伸缩
性规模有限;使用HTTP302 响应码重定向,有可能使搜索引擎判断为SEO 作弊,降低搜
索排名。因此实践中使用这种方案进行负载均衡的案例并不多见。 - DNS 域名解析负载均衡
事实上,大型网站总是部分使用DNS 域名解析,利用域名解析作为第一级负载均衡
手段,即域名解析得到的一组服务器并不是实际提供Web 服务的物理服务器,而是同样
提供负载均衡服务的内部服务器,这组内部负载均衡服务器再进行负载均衡,将请求分
发到真实的Web 服务器上。 - 反向代理负载均衡
- IP 负载均衡
- 数据链路层负载均衡
这种数据传输方式又称作三角传输模式,负载均衡数据分发过程中不修改IP 地址,
只修改目的mac 地址,通过配置真实物理服务器集群所有机器虚拟IP 和负载均衡服务器
IP 地址一致,从而达到不修改数据包的源地址和目的地址就可以进行数据分发的目的
是目前大型网站使用最广的一种负载均衡手段。在Linux 平台上最好的链路层负载均衡开源产品是LVS ( Linux Virtual Server )。
分布式缓存
一致性哈希
计算机领域有句话:计算机的任何问题都可以通过增加一个虚拟层来解决。
。那么在实践中,一台物理服务器虚拟为多少个虚拟服务器节点合适呢?太多会影响
性能,太少又会导致负载不均衡,一般说来,经验值是150,当然根据集群规模和负载均
衡的精度需求,这个值应该根据具体情况具体对待。
关系型数据库
使用开源中间件,如Cobar。原理是在数据库之上又加了一层。是一个分布式数据库的访问代理。
当前分布式数据库无法解决的问题是,无法跨库Join,更无法实现跨库事务。
所以需要从业务上避免分布式数据库的缺点:避免事务或者利用事务补偿机制代替数据库事务。分解数据访问逻辑避免Join操作。
还有一类分布式数据库可以支持JOIN 操作执行复杂
的SQL 査询,如GreenPlumÿ 但是这类数据库的访问延迟比较大(可以想象,JOIN 操作
需要在服务器间传输大量的数据), 因此一般使用在数据仓库等非实时业务中。
NoSql
NoSQL数据库产品都放弃了关系数据库的两大重要基础:以关系代数为基础的结构化査询语言
( SQL ) 和事务一致性保证(ACID )。而强化其他一些大型网站更关注的特性:高可用性
和可伸缩性。
可扩展性架构
设计网站可扩展架构的核心思想是模块化,并在此基础之上,降低模块间的耦合性,
提高模块的复用性。
- 利用分布式消息队列降低系统耦合性
- 利用分布式服务框架,如Dubbo
- 搭建开放平台建设网站生态圈
API接口,协议转换,安全,审计,路由,流程
安全架构
常见攻击
XSS,跨站点脚本攻击。恶意脚本执行。
防御:消毒(特殊字符转义)
httponly,防止XSS 攻击者窃取Cookie。
注入攻击,消毒,预编译
CSRF,跨站点请求伪造。其核心是利用了浏览器Cookie 或服务器Session 策略,盗取用户身份。
防御:表单Token,验证码,referer check(请求来源检查)
web应用防火墙
ModSecurity
加密
- 单项散列加密
常用的单向散列算法有MD5ÿ SHA 等。单向散列算法还有一个特点就是输入的任何
微小变化都会导致输出的完全不同,这个特性有时也会被用来生成信息摘要、计算具有
高离散程度的随机数等用途。 - 对称加密
常用的对称加密算法有DES 算发、RC 算法等 - 非对称加密
非对称加密的常用算法有RSA 算法
信息过滤
- 文本匹配
正则表达式的效率一般较差,仅适用于短文本及低并发场景。
高并发时使用的公幵的算法有很多,基本上都是Trie 树的变种,空间和时间复杂度都比较好
的有双数组Trie 算法等。
秒杀系统架构
网站如果为秒杀时的最高并发访问量进行设计部署,就需要比正常运营多得多的服务器,而这些服务器在绝大部分时候都是用不着的,浪费惊人。所以网站的秒杀业务不能使用正常的网站业务流程,也不能和正常的网站交易业务共用服务器,必须设计部署专门的秒杀系统,进行专门应对。
技术挑战
- 对现有网站业务冲击。
如果部署在一起,稍有不慎全业务瘫痪。 - 高并发下的应用、数据库负载。
- 突然增加的网络及服务器带宽
- 直接下单
下单页面也是一个普通的URL, 如果得到这个URL, 不用等到秒杀开始就可以下单了。
应对策略
- 独立部署
2,秒杀产品页面静态化
使其不需要经过web服务器和数据库服务器。
3,租借秒杀活动带宽 - 动态生成随机下单页面URL
为了避免用户直接访问下单页面URL. 需要将该URL 动态化,即使秒杀系统的开发
者也无法在秒杀开始前访问下单页面的URL. 办法是在下单页面URL 加入由服务器端生
成的随机数作为参数,在秒杀开始的时候才能得到。
架构设计
- 如何控制秒杀按钮的点亮
解决办法是使用JavaScript 脚本控制,在秒杀商品静态页面中加入一个JavaScript 文
件引用,该JavaScript 文件中加入秒杀是否开始的标志和下单页面URL 的随机数参数,
当秒杀开始的时候生成一个新的JavaScript 文件并被用户浏览器加载,控制秒杀商品页面
的展示。这个javaScript 文件使用随机版本号,并且不被浏览器、CDN 和反向代理服务
器缓存。
2,只允许用户的第一个下单请求到达服务器
并且服务器接收到的单量超过设定值后,其他的请求直接秒杀结束。
如果服务器出错,直接秒杀结束页面。
经验教训
写日志导致磁盘满
- 控制业务日志级别warn
- 某些第三方包也会打太多错误日志,要关闭
- 自己的业务日志和第三方的日志要分开配置
数据库load高
原因:首页访问了数据库
- 首页访问频繁,不要直接访问数据库
- 首页最好应该做出静态的
高并发下锁超时
- 减小粒度
- 谨慎使用
缓存
缓存服务器宕机,数据库压力陡增引发宕机。
- 缓存服务器也很重要,大家普遍不够重视
应用启动不同步引发故障
原因:应用程序Web 环境使用Apache+JBoss 的模式,用户请求通过Apache 转
发JBossÿ 在发布时,Apache 和JBoss 同时启动,由于JBoss 启动时需要加载很多应用并
初始化,花费时间较长,结果JBoss 还没有完全启动,Apache 就已经启动完毕开始接收
用户请求,大量请求阻塞在JBoss 进程中,最终导致JBoss 崩溃。除了这种Apache 和JBoss
启动不同步的情况,网站还有很多类似的场景,都需要后台服务准备好,前台应用才能
启动,否则就会导致故障。
大文件读写独占磁盘
有几个文件非常大,有数百兆,读写这些大文件一
次需要几十秒,这段时间,磁盘基本被这个文件操作独占,导致其他用户的文件操作缓慢。
- 大文件和小文件区分存储,区别对待。
架构师
架构师作为项目组最资深的专业技术人员,是项目组开发测试工程师的前辈。从架
构师的身上,工程师可以看到自己的未来,因此架构师在做人做事方面需要严格要求自
己,做好表率。
关注人而不是产品
一定要坚信:一群优秀的人做一件他们热爱的事,一定能取得成功。不管过程多么
曲折,不管外人看来多么不可思议不靠谱。
领导的真谛:寻找一个值得共同奋斗的目标,营造一个让大家都能最大限度
发挥自我价值的工作氛围。
没有懒惰的员工,只有没被激发出来的激情。所有强迫员工加班的管理者都应该为
自己的无能而羞愧。
发觉人的优秀
是事情成就了人,而不是人成就了事。指望优秀的人来帮自己成事,不如做成一件
事让自己和参与的人都变得优秀。
共享美好蓝图
架构师要和项目组全体成员共同描绘一个蓝图,这个蓝图是整个团队能够认同的,
是团队共同奋斗的目标。
蓝图应该是表述清楚的:产品要做什么、不做什么、要达到什么业务目标,都需要
描述清楚。
蓝图应该是形象的:产品能为用户创造什么价值、能实现什么样的市场目标、产品
最终会长什么样,都需要形象地想象出来。
蓝图应该是简单的:不管内部还是外部沟通,都能一句话说明白:我们在做什么。
蓝图应该写在软件架构设计文档的扉页、写在邮件的签名档、写在内部即时通信群
的公告上。
在项目过程中,架构师要保持对目标蓝图的关注,对任何偏离蓝图的设计和决定保持警惕,错误的偏离要及时修正,必要的变更要经过大家讨论,并且需要重新获得大家
的认同。
共同参与架构
架构师需要对系统架构负责,但并不是说一定要架构师自己完成架构设计,并要项
目团队严格遵守架构决策。
把架构和架构师凌驾于项目和项目组之上,只会让架构师变成孤家寡人,让架构曲
局和寡。
- 不要只有架构师一个人拥有架构
- 让其他人维护框架与架构文档
学会妥协
不要企图在项目中证明自己是正确的,一定要记住,你是来做软件的,不是来当老
大的。所以不要企图去证明自己了不起,永远也别干这种浪费时间、伤害感情的事
很多时候,对架构和技术方案的反对意见,其实意味着架构和技术方案被关注、被
试图理解和接受。架构师不应该对意见过于敏感,这时架构师应该做的是坦率地分享自
己的设计思路,让别人理解自己的想法并努力理解别人的想法,求同存异。
对于技术细节的争论应该立即验证而不是继续讨论,当讨论深入到技术细节的时候
也意味着问题已经收敛,对于整体架构设计,各方意见正趋于一致。
而当大家不再讨论架构的时候,表明架构已经融入到项目、系统和开发者中了,架
构师越早被项目组遗忘,越表示架构非常成功;项目组越离不开架构师,越表示架构还
有很多缺陷。
成就他人
架构师作为团队的技术领导者,在项目过程中不要去试图控制什么,带着一个弹性
的计划和蓝图推进,团队会管好他们自己。你越是强加禁令,队伍就越是没有纪律;你
越是强制,团队就越是不能独立自主;你越是从外面寻找帮助,大家就越是没有信心。
发现问题,寻找突破
其实即使是在一流的技术团队里,也一定有数不清的问题,只是人们习惯了这些问
题,以至于无视它们的存在。正所谓“鱼是最后一个看见水的”,天天面对这些问题,反
而不觉得有什么问题。
提出问题,寻求支持
问题被发现,它只是问题发现者的问题,而不是问题拥有者的问题,如果想要解决一个问题,就必须提出这个问题,让问题的拥有者知道问题的存在。
找对关键人
- 把“我的问题”表述成“我们的问题”
- 给上司提封闭式问题,给下属提开放式问题
不要问上司“你觉得该怎么办?”这种没有建设性的开放式问题,给上司
提问题是希望能够得到他的支持,而不是带着一头雾水等他去指点迷津。公司
付你薪水不是让你睁着迷茫的眼睛卖萌。给上司提问应该是“你觉得A 和B 两
个方案哪个更好?”这种封闭式问题。 - 指出问题而不是批评人
如果在合作中出现问题,告诉他问题的存在和紧迫性,而不是责问他为什
么出现问题。 - 用赞同的方式提出问题
所谓直言有讳是指想要表达的意图要直截了当说明白,不要兜圈子,但是
在表达方式上要有所避讳,照顾到当事人的感受。
解决问题,达成绩效
在解决我的问题之前,先解决你的问题
先解决别人的问题有几个好处:
你帮别人解决了问题,礼尚往来,别人也会帮你解决问题。
在帮别人解决问题的过程中,熟悉了情况,后面解决自己的问题也就得
心应手了。
解决别人的问题时使用的是你的解决方案,这个方案在你的控制之中,
将来往这个方案里再塞一些东西解决自己的问题,手到擒来。适当的逃避问题