软件架构风格
质量属性与架构评估
Web架构综合考察
什么叫做架构风格?又有哪些架构风格?不同的架构风格的优劣如何?
有哪些层次的负载均衡实现?优劣如何?
有哪些层面的集群切片实现?
什么叫做小前端,大中台? 中台的优势是什么?
系统架构风格是指描述 特定软件系统“组织方式”的“惯用模式”。“组织方式”描述了系统的“组成构件”以及构件的组织结构。 惯用模式则体现众多系统共有的结构和语义。
有哪些架构风格适合交互?哪些适合高性能?哪些更容易扩展?
常见的软件构件风格有哪些?
数据流风格:就比较适合复杂的数据处理/数据密集型应用,一个一个过程的处理,彼此间耦合度低。一系列的数据处理器。一个处理器流向另一个处理器并通过数据流传递。每个处理器只考虑特定的数据处理任务,不考虑流程,处理器彼此间耦合度低。案例:图像处理、信号处理。
调用/返回风格: 就是存粹的体现一种面向过程的,过程式的编程思想。通过函数调用推动过程进行,返回值返回函数结果。一系列的函数调用和返回,组合完成复杂的功能。比较适合流程简单,直观的开发场景。
独立构件风格:将系统分解为一系列独立的组件,并通过定义接口和协议来实现组件之间的通信和交互。组件通过接口的输入输出参数完成组件通信,降低了组件间耦合度,提高组件的独立可扩展性/模块化,进而使得系统更加灵活可维护。适用于大型系统的开发场景。
常见的独立构件风格是否大多是通过消息的形式来进行进程通信,然后使得消息绑定回调函数完成事件驱动系统?
是的,独立构件风格通常会采用消息传递的方式进行组件之间的通信,同时结合事件驱动的机制来实现系统的异步和非阻塞操作。具体来说,常见的做法包括:
- 消息传递: 组件之间通过消息队列、消息总线或者直接发送消息的方式进行通信,实现了组件之间的解耦和异步通信。
- 回调函数: 组件接收到消息后,根据消息的内容调用相应的回调函数来处理消息,实现了事件驱动的系统响应机制。
- 事件驱动: 组件通过监听和处理事件来驱动系统的运行,事件可以是用户操作、系统消息或者其他组件发送的消息。
这种设计模式在分布式系统、并发编程和大规模系统开发中得到了广泛应用,它能够提高系统的可伸缩性、可扩展性和灵活性,降低系统的耦合度,从而更好地满足复杂系统的需求。
Web架构综合考察。
”高性能“、”高可用“、“可维护”、应变、安全
架构演变过程
单台机器 到 数据库与Web服务器分离。为什么会这样?
- 将数据库与Web服务器分离是为了提高系统的可扩展性、性能和安全性。分离经常是为了更好的扩展,更专注的干自己的活,各司其职、避免互相干扰。拆了之后对吧,那个Web应用可以单独横向扩展,数据库也可以单独横向扩展。
- 安全性: 将数据库与Web服务器分离可以降低系统受到攻击的风险。数据库服务器可以部署在内部网络中,通过防火墙和其他安全措施来保护数据的安全性,而Web服务器则可以部署在公共网络中,提供对外服务而不暴露数据库的直接访问。
- 管理和维护: 分离数据库和Web服务器可以简化系统的管理和维护。每个部分可以由专门的团队负责管理,降低了开发和运维的复杂度。
对应用服务器做横向扩展,分布式部署多台应用服务器,提高并发量和响应性能。
但是,从一台应用服务器到多态应用服务器,会出现什么样的问题?如果用户每次访问到不同的服务器,如何维护session一致性?如何分发流量?
- 有状态和无状态问题。
- 负载均衡
Session(会话)是指两个或多个通信终端之间建立的持续性的连接。在网络通信中,会话可以用来描述客户端和服务器之间的交互,通常涉及一系列的请求和响应。
无状态服务和有状态服务:
无状态服务(Stateless Service)是指服务本身不维护任何关于客户端状态的信息,每个请求都是独立的,服务不会存储客户端的状态信息。相反,有状态服务(Stateful Service)会在服务端维护客户端的状态信息,通过跟踪客户端的状态来处理请求。
简单来说,两者的区别在于服务是否在请求之间保留客户端的状态信息。
无状态服务(Stateless Service):
- 每个请求都是独立的,服务不会存储客户端的状态信息。
- 服务端不保存客户端的会话信息或状态,每个请求都被视为全新的、独立的请求。
- 通常采用负载均衡和无状态协议,可以简化服务的扩展和维护。
有状态服务(Stateful Service):
- 服务端会存储客户端的状态信息,以便在多次请求之间共享状态。
- 服务端可能会保存客户端的会话信息、上下文信息、状态信息等。
- 通常需要采用一些机制来管理状态信息的一致性、持久化和共享,如集群状态同步、数据库存储等。
Session 和 Cookie 是用于实现状态管理的技术,可以在有状态服务和无状态服务中使用。
Cookie 是一种客户端技术,通过在客户端存储一些信息,如会话标识符、用户首选项等,来实现客户端的状态管理。Cookie 可以在有状态服务和无状态服务中使用。在有状态服务中,服务端可以使用 Cookie 来存储客户端的会话标识符或其他状态信息,以跟踪客户端的状态。在无状态服务中,Cookie 可以用于存储客户端的会话标识符,以便服务端识别客户端。
Session 是一种服务端技术,通过在服务端存储客户端的会话信息,来实现状态管理。Session 可以在有状态服务中使用,因为服务端会存储客户端的会话信息。在无状态服务中,虽然服务端通常不会直接存储客户端的会话信息,但是可以使用一些外部存储或者数据库来存储会话信息,实现类似于有状态服务的功能。
负载均衡技术分层:有哪些网络层的负载均衡技术?
应用层负载均衡:
- http重定向。HTTP重定向就是应用层的请求转发。用户的请求到了HTTP重定向负载均衡服务器。服务器根据HTTP请求头、URL、内容等进行负载均衡和请求转发,用户收到重定向请求之后,再次请求真正的集群服务。特点:实现简单,但性能差。
- 反向代理服务器。在用户的请求到达反向代理服务器时,由反向代理服务器根据算法转发到具体的服务器。常用Nginx充当反向代理服务器。 特点:部署简单,但代理服务器可能成为性能瓶颈。
传输层/网络层负载均衡:
- DNS域名解析负载均衡。DNS域名解析负载均衡就是在用户请求DNS服务器,获取域名对应的IP地址时,DNS服务器直接给出负载均衡之后的服务器ip地址。特点:效率相较于七层负载均衡HTTP重定向高,减少维护负载均衡服务器的成本。但一个应用服务器故障,不能及时通知DNS。
- NAT(Network Address Translation,网络地址转换)负载均衡技术是一种在网络层(通常是传输层)实现负载均衡的方法,通常用于将来自外部网络的请求分发到内部网络中的多个服务器上。
常见的负载均衡算法:
- 静态负载均衡:
- 静态负载均衡算法在系统启动时就确定了服务器的分配策略,一旦分配完成,就不再进行调整。这种算法简单直观,实现成本低,适用于负载较为稳定的场景。
- 常见的静态负载均衡算法包括:
- 轮询(Round Robin):按照顺序将请求分配给各个服务器,每个请求依次轮流分配给不同的服务器。
- 加权轮询(Weighted Round Robin):根据服务器的性能或者配置,给每个服务器分配一个权重值,高性能服务器分配更多的权重,然后按照权重进行轮询分配请求。
- 随机(Random):随机选择一个服务器来处理请求,没有考虑服务器的性能和负载情况。
- 动态负载均衡:
- 动态负载均衡算法根据服务器的负载情况动态调整请求的分配策略,以实现更均衡的负载分配。这种算法通常需要收集服务器的负载信息,并根据这些信息进行决策,因此实现复杂度较高,但可以更灵活地应对不同负载情况。
- 常见的动态负载均衡算法包括:
- 最小连接数(Least Connections):选择当前连接数最少的服务器来处理请求,以保持各服务器的连接数尽可能均衡。
- 最小响应时间(Least Response Time):选择响应时间最短的服务器来处理请求,以保证用户的请求能够得到及时响应。
- 基于反馈的动态权重调整:根据服务器的负载情况和性能指标,动态调整服务器的权重值,以实现负载均衡。
动态负载均衡算法相比静态负载均衡算法更具有灵活性和适应性,可以更好地应对负载波动和服务器故障等情况。然而,动态负载均衡算法通常需要更多的计算和资源,因此在实际应用中需要权衡选择。
动态负载均衡、动态内存池和弹性线程池确实在某种程度上具有相似的特点,但它们所解决的问题和应用场景略有不同。
- 动态负载均衡:
- 动态负载均衡旨在根据系统的负载情况动态地调整请求的分配策略,以实现更加均衡和高效的负载分配。它主要用于分布式系统和网络服务中,通过监控服务器的负载情况来动态调整请求的分发,从而提高系统的性能和可用性。
- 动态内存池:
- 动态内存池是一种管理内存分配和释放的机制,它根据实际需要动态地分配和释放内存,以减少内存碎片和提高内存利用率。动态内存池通常用于优化内存分配性能,避免频繁的内存分配和释放操作带来的性能开销。
- 弹性线程池:
- 弹性线程池是一种管理线程池资源的机制,它根据当前任务的负载情况动态地调整线程数量,以保持系统的性能和资源利用率。弹性线程池通常用于处理异步任务和并发请求,根据实际需求动态地分配和回收线程资源,从而提高系统的响应能力和并发性能。
对数据层进行抽象,ORM(Object relation map)对象关系数据映射。说白了就是对数据表的操作进行面向对象的封装。为业务层提供简单易用的数据表操作接口层,实现业务层与数据层的解耦合。业务层依赖的只是ORM提供的一层接口,底层数据库做变更、修改,业务层并不关注。
缓存的应用:提高读取性能。常用的缓存中间件,memachached、redis. 缓存减少了数据库压力,提高了读取性能。
Redis技术:高性能(内存、IO模型、耗时操作的异步处理)、高可用(容灾备份、数据冗余)、高可靠(持久化)。
Redis持久化:AOF、RDB.
- 每条命令都同步写入磁盘:
- 这是最安全的策略,每条写入命令都会立即同步到磁盘上的AOF文件中。虽然保证了数据的完整性和一致性,但会带来较大的性能开销,因为每次写入都需要等待磁盘IO操作完成。
- 每秒同步一次:
- Redis会定期将AOF缓冲区中的命令刷新到AOF文件,并将文件同步到磁盘。这种策略可以提高性能,但在发生故障时可能会丢失最多一秒钟的数据。
- 每次写入命令后同步:
- 在每次写入命令后,Redis会立即将AOF缓冲区中的命令刷新到AOF文件,并将文件同步到磁盘。这种策略介于安全性和性能之间,数据的丢失量取决于操作系统和硬件的性能。
- 按照大小异步写入:
- 当AOF文件大小达到一定阈值时,Redis会触发一次AOF文件同步操作,将AOF缓冲区中的命令刷新到AOF文件,并将文件同步到磁盘。这种策略可以控制AOF文件的大小,但可能会导致较长时间内的数据丢失。
- 按照时间异步写入:
- 定期(例如每隔一定时间间隔)将AOF缓冲区中的命令刷新到AOF文件,并将文件同步到磁盘。这种策略主要用于减少磁盘IO压力,但可能会导致较长时间内的数据丢失。
Redis 的主从模式(1 master + n slave读写分离/负载均衡、应对读多写少,数据备份、主挂掉之后人工手动故障转移、恢复),sentinel/哨兵模式(自动切换、让哨兵节点进行监控故障的发生和转移,监控+通知+自动故障转移),cluster/集群模式(数据切片、横向扩展、打破单机硬件限制、适合数据量巨大的缓存场景)。
redis cluster vs. replication + sentinal
如果你的数据量很少,主要是承载高并发高性能的场景,比如你的缓存一般就几个 G,单机足够了
- replication,一个 mater,多个 slave,要几个 slave 跟你的要求的读吞吐量有关系,然后自己搭建一个 sentinal 集群,去保证 redis 主从架构的高可用性,就可以了
- redis cluster,主要是针对海量数据+高并发+高可用的场景,海量数据,如果你的数据量 很大,那么建议就用 redis cluster
数据切片,切片算法。范围切片,Hash切片,一致性Hash切片。
一致性hash环:在环上面顺时针访问最近的节点访问。
Redis 缓存淘汰策略、缓存更新、缓存雪崩、缓存击穿、缓存穿透
缓存击穿的化就是缓存中没有,数据库中有这个数据。通常发生在某个缓存过期的时候,此时恰好有大量的并发请求访问这个缓存数据,导致缓存未命中,从而直接请求数据库,造成数据库压力激增。解决办法就是针对特别热点的数据不设置过期时间。
缓存击穿通常是某个特定缓存数据的失效导致的,而缓存雪崩则是大量缓存数据同时失效引起的。
CDN (Content Distribute Network) 内容分发网络:让客户访问就近的服务器站点。
中台策略
- 中台部门提炼各业务线的共性需求,最大限度的减少“重复造轮子”。
- 中台也并非完美,中台可能出现迎合大业务、创造KPI,导致提取不出真正的共性需求。导致小业务发展缓慢。中台的轮子是不断变化的,随着业务发展不断变化。中台是某类业务的中台,不是所有业务的中台。
整体Web系统分层