系统架构设计五要素
- 可用性:通常用几个9来衡量可用性,比如QQ的4个9,即99.99%,一年中最多53分钟不可用。
- 性能: 衡量指标有响应时间、吞吐量、TPS、QPS、系统性能计数器。
- 伸缩性:不需要改变系统架构设计,仅通过改变服务器数量就可以扩大或减小系统服务处理能力。
- 扩展性:对现有系统影响最小的情况下,系统功能可持续扩展或提升的能力,符合高内聚、低耦合和开闭原则(对扩展开放,对修改关闭)。
- 安全性:保证系统的安全,避免恶意攻击,防止信息泄漏,系统防刷,敏感词过滤
如何设计完美系统架构
一个好的系统架构一定能够满足上面的五个要素,同时还能适应当前业务快速发展,具有一定的技术前瞻性和通用性;不要为了技术而使用一些不通用的技术,遇到问题无法解决;不要为了架构而架构,进行过渡设计,比如业务只需要造一条小船过河,你却花三年时间设计了一个航空母舰。只要能够是适应当前业务快速发展的架构就是一个好的架构,而架构也总是在随着业务的发展在不断演变。一句话总结就是没有最好的架构,只有最适合当前业务发展的架构。
高可用设计
- 系统设计为无状态模式,支持横向扩展,实现异地多活部署。通过软件或硬件负载均衡实现流量分发和故障转移,防止出现单点故障。
- 按照领域驱动设计思想对系统进行微服务拆分,实现横向和纵向拆分,方便模块块开发维护,并进行故障隔离。
- 接口设计阶段做好系统限流,降级和熔断措施,服务接口实现自动或手动failover故障转移。比如nginx限流,jsf限流,降级开关,Hystrix 限流 降级和熔断。
- 实现系统数据托底功能,系统故障时仍然可以对外提供托底数据查询服务,比如nginx的代理缓存托底配置。
- 做好系统监控配置,提前配置好方法性能监控,服务器端口存活监控,服务器进程存活监控,JVM堆内存、线程数和垃圾回收监控告警策略。还要做好服务器硬件层面的CPU、内存、磁盘可用率和网络质量相关的TCP重传数监控告警策略。
- 做好系统流量预警分析,每日可以进行系统流量分析与系统历史流量峰值和压测结果峰值进行对比分析,提前发送流量预警分析报告,实现服务器的提前扩容。
- 提前制定好系统应急预案,在应急预案汇总整理好系统的各种突发情况出现的时的应对解决方案,比如服务器流量摘除,服务器一键扩容,打开关闭降级开关,执行主从切换,或是联系对应运维解决。
- 系统应急预案制定完成后,还要进行事故模拟演练,验证系统应急预案的可执行性,演练完成后在总结优化我们的应急预案执行流程。
- 经常关注手机、邮箱收到的告警信息,并及时响应处理,还要根据实际情况对告警阈值进行动态调整,防止出现误报和瞒报。
- 系统自动化发布,预发布验证,支持灰度发布和线上系统多版本回滚功能。
- 接口设置合理的超时时间和重试机制,幂等性设计,避免因为一个接口超时发生雪崩效应。
- 数据存储层一主多从跨机房部署,并实现主从自动故障切换和实时数据备份,比如mysql、redis的主从数据同步
高并发设计
- 系统无状态设计,支持横向扩展集群部署,数据库层面实现读写分离,提高整体并发能力。
- 增加多级缓存,redis缓存、jvm缓存、nginx缓存、CDN缓存和浏览器缓存,实现网络加速,尽量将缓存前置,减少后端服务器压力,还可以提前进行缓存预热。
- 对象池复用,比如使用数据库连接池、HttpClient连接池,单例模式对象使用,减少实例化过程和垃圾回收消耗。
- 对象序列化优化 不要使用JDK原生序列化方式,可以采用json,protobuf、protostuff等,提升序列化和反序列化速度,减少序列化结果大小,提升网络传输性能。
- 串行执行优化为并行执行,可以采用JAVA8的并行流,线程池等技术实现请求的并行处理。
- 重量级锁优化为细粒度锁或无锁设计,比如使用乐观锁、读写锁、分段锁等技术,还可以根据任务ID取模分配,ThreadLocal缓存,原子操作类,CAS,disruputor无锁队列等无锁设计避免锁竞争,提升系统整体并发能力。
- 优化I/O模型,可以采用NIO或AIO替换传统的BIO,实现非阻塞请求,比如使用netty,tomcat配置NIO连接器。
- 系统实现动静分离,静态数据可以考虑页面静态化处理,并利用Nginx的零拷贝技术加速访问。
- JVM调优配置,设置合理的JVM参数,包括堆内存大小,线程栈内存,垃圾回收器以及垃圾回收线程配置。
- 精简系统日志输出内容,只打印必要日志,并且同步输出日志设置为异步方式。
- 数据异构和数据冗余设计,减少系统交互次数和数据表关联查询次数。
- 数据库分库分表设计和查询索引优化
- 前端减少合并http请求,启用压缩,减少Cookie传输,比如静态资源启用独立域名。
伸缩性设计
- 系统纵向拆分,将业务处理流程上的不同部分进行分离部署,实现系统伸缩性。比如分离服务层和接入层,实现公共服务的复用,接入层和服务层分别独立集群部署。
- 系统横向拆分,基于高内聚低耦合原则,将不同的耦合性较低业务模块分离部署,比如订单模块和商品模块分别独立集群部署。
- 系统应用都是无状态设计,不存储请求上下文信息,用户的请求发送到集群内任意一台服务器处理结果都是相同的。
- 利用负载均衡设备进行请求分发,实现网站的伸缩性,还可以提高系统可用性,Nginx反向代理负载均衡,DNS域名解析负载均衡,IP负载均衡,数据链路层负载均衡,算法:轮询,加权轮询,随机,最少连接,源地址散列。
- 基于分布式缓存客户端实现的一致性Hash算法进行缓存key路由,Redis的服务端集群分片管理功能。
- Mysql数据库的主从同步,读写分离,还有分库分表解决方案,比如支持数据库分库分表的的开源框架Amoeba,Cobar和sharding-jdbc。
扩展性
- 考虑事件驱动架构,通过在低耦合的模块直接传输事件消息,以保持模块的松散耦合,并借助事件消息的通信完成模块间的合作,比如分布式消息队列降低系统耦合性。
- 利用分布式服务框架打造可复用的业务中台,系统进行横向和纵向拆分,各业务模块独立部署,降低系统耦合性,将复用的业务拆分出来,独立部署为分布式服务,对外赋能,减少重复造轮子。
- 数据库设计可扩展,比如预留一些冗余字段,或者是json格式存储数据方便加减字段。
安全性
- XSS攻击 跨站点脚本攻击(Cross Site Script),解决方案:对用户的参数进行消毒处理,比如特殊字符转义处理,HttpOnly属性设置,防止js访问cookie。
- SQL注入攻击,解决方案:对用户请求参数进行过滤处理,过滤掉危险指令,使用预编译手段进行参数绑定防止sql注入,比如Mybatis使用#{}替换${}。
- CSFR攻击 跨站点请求伪造(Cross Site Request Forgery), 解决方案:增加表单Token验证用户身份,使用验证码验证用户身份,增加请求Referer验证,检查请求来源。
- 文件上传校验,设置上传文件白名单,只允许上传可靠的文件类型。
- 修改服务器默认错误页面跳转到专门的错误页面。
- 敏感信息进行加密存储,比如密码、姓名、身份证、银行卡信息等,散列算法要增加随机盐或使用对称加密算法或非对称加密算法,密钥安全保存。
- 设置系统访问黑名单,恶意流量加入黑名单,防止浪费服务器性能。
- 对用户提交的内容进行敏感词过滤处理。
- 对外提供的接口进行数据权限验证,防止出现数据越权漏洞。
网友评论