服务反模式与实际案例分析
1. 服务反模式介绍
1.1 事务集成反模式
在库存出现问题时,订购服务需要执行补偿操作来处理。为了合理地完成这一操作,服务可能需要保存一些关于库存水平等相关数据,以便自主做出合理决策。
Sagas 模式可以通过通信反转模式进行增强,使服务能够根据自身操作发送事件,并订阅其他事件,从而创建编排场景。例如在订购场景中,订购服务发布有新订单需要处理的事件,库存服务监听该事件。当库存服务确保商品准备好后,会发布相应事件,订购服务则可以通知客户订单已准备好。
Sagas 和通信反转模式都实现了最终一致性系统,即放宽了各服务决策的时间限制,这通常也符合业务的一般运作方式。比如在订购场景中,当订购服务处理订单时,向客户发送订单已收到的额外通知可能是更好的做法。
不过,跨服务事务对于大多数分布式系统来说通常不是一个好主意。但在基于 SOA 原则构建的封闭系统中,有可能在不受到事务集成带来的刚性和性能问题影响的情况下实现。即便如此,最好还是使用编排引擎在服务外部控制事务范围,这样至少可以在同一位置处理事务范围和业务流程的总体流程。但需要注意的是,即使是封闭系统也会随时间演变。
1.2 旧路重走反模式
每当有新概念出现时,技术供应商的营销部门就会用新的流行词重新包装他们现有的产品。开发者虽然大多能识别产品初期的炒作,但在设计中却很难发现自己也在犯同样的错误。
1.2.1 示例分析
以下是一个看似基于“SOA”的架构示例:
| 组件 | 描述 |
| — | — |
| 数据服务 | 数据库被包装在 Web 服务或 RESTful 接口中 |
| 实体 | 处理客户和账户业务逻辑的部分 |
| CRUD 服务接口 | 提供创建、读取、更新、删除操作的接口 |
但实际上,这并不是一个真正的 SOA 架构,而是一个 n 层/ n 级架构。数据层很可能是物理层,实体和服务接口可能位于应用服务器层,属于业务逻辑中的两个逻辑层。
1.2.2 后果
将 n 层架构称为 SOA,如果只是名称错误,可能除了损害 SOA 的声誉外没有其他危害。但问题在于,这些层和级通常被实现为服务,具有契约和实现的分离,可能作为自主服务运行等。这就导致了“旧路重走”反模式,即使用 SOA 工具和承担 SOA 开销来实现非 SOA 架构,付出了 SOA 的代价却没有获得 SOA 的好处。
不获得 SOA 好处意味着无法获得所需的灵活性,也不能通过将解决方案分解为更小、更易管理的部分来简化系统。而 SOA 的代价包括设计和运行时的更多投入,例如增加的延迟(由于序列化、反序列化、通信等额外层),以及每个组件局部复杂性的增加。
1.2.3 原因
“旧路重走”反模式主要是由于对 SOA 理解不足,同时可能受到供应商将 SOA 相关技术宣传为 SOA 本身的误导。最明显的误解是将 Web 服务与 SOA 服务直接关联,实际上 SOA 服务可以通过多种技术实现,而且在很多场景下其他技术比 Web 服务更好。此外,从其他架构风格向 SOA 过渡的系统,如果架构师没有意识到问题,也可能出现这种反模式。
1.2.4 重构
重构这种反模式的关键是首先识别它,并承认自己是在将旧的架构强行套上 SOA 的外衣。可以通过思考分布式计算的谬误来帮助识别问题,如果所认为的“SOA”假设了其中一个或多个谬误,那么很可能它并不是真正的 SOA。
不幸的是,重构这种反模式并不容易,通常需要重新设计而不仅仅是重构,而且没有直接的方法。本质上,需要更好地理解 SOA 的原则和约束,并相应地进行重新设计。
1.2.5 已知例外
与其他反模式不同,很难想到“旧路重走”反模式在哪些情况下是可以接受的。其主要症状是开发过程中会遇到很多阻碍,因为实际上并没有实现 SOA。如果现有的架构适合当前问题并能很好地工作,就应该继续使用;如果转向 SOA 是因为原架构有问题,不要期望用新工具和技术重复原架构就能解决问题。
1.3 常见反模式总结
常见的向 SOA 迁移时可能遇到的反模式包括:
- Knot:服务通过点对点集成紧密耦合。
- Nanoservice:服务划分得太小,导致服务难以管理。
- Transactional Integration:事务跨越服务边界,使服务耦合在一起。
- Same Old Way:错误地认为自己在使用 SOA 架构,实际上是用 SOA 工具实现非 SOA 架构。
2. 案例分析:视觉搜索系统
2.1 系统需求
该系统允许进行视觉搜索,其工作原理是用户看到感兴趣的事物后,用手机拍照并发送给服务,然后获取相关信息。与 Google Goggles 相比,它有两个关键区别:
- 支持多种方式发送图像,包括视频电话、短信、电子邮件和各种平台的应用程序(Google Goggles 仅支持应用程序)。
- 是面向内容提供商的 OEM 白标软件即服务(SaaS)解决方案,提供视觉搜索功能。
系统的主要业务服务包括:
- 多种视觉搜索服务:如 3G 视频通话图像搜索、应用程序图像搜索、电子邮件图像搜索、短信图像搜索。
- 其他服务:如计费、广告活动管理、交互管理等。
2.2 服务导向与 SOA 的区别
服务导向是一种分析企业架构某些方面的方法,主要关注功能分解、业务流程和数据架构,将业务能力和功能分解为业务级服务,这些服务的组合和交互构成了业务流程。
SOA 是一种架构风格,关注构建相互连接的粗粒度组件,强调灵活性和组合性。服务导向确定的业务服务和业务流程是软件层面架构、技术映射和实现的需求,而 SOA 则用于实现这些需求。两者相关但不一定是一一对应的关系。
2.3 质量属性
质量属性场景有助于我们理解如何设计解决方案,它可以帮助我们更好地理解需求、构建测试以验证质量、对架构进行优先级排序和评估等。以下是系统的一些质量属性和场景,以及可能适用的模式:
| 质量属性 | 场景 | 候选模式 |
| — | — | — |
| 可扩展性 | 随着用户数量增加,系统能正常运行 | 相关扩展性模式 |
| 安全性 | 保护用户数据不被泄露 | 安全相关模式 |
| 响应性 | 快速响应用户请求 | 响应性相关模式 |
通过对系统功能和质量属性的了解,我们可以进入更重要的部分——解决方案的设计。接下来我们将看到如何结合多种模式来构建一个完整的解决方案。
下面是一个简单的视觉搜索系统业务服务交互的 mermaid 流程图:
graph LR
A[用户] -->|发送图像| B[视觉搜索服务]
B -->|处理图像| C[结果分析]
C -->|生成结果| D[返回结果给用户]
B -->|库存检查| E[库存服务]
E -->|反馈库存情况| B
B -->|计费| F[计费服务]
F -->|反馈计费结果| B
3. 解决方案设计
3.1 模式组合思路
为了构建一个完整的视觉搜索系统解决方案,需要结合多种之前介绍过的模式。这些模式各自处理不同方面的问题,如安全性、可扩展性和集成性等。通过合理组合这些模式,可以满足系统的各种需求。
3.2 具体模式应用
3.2.1 安全性模式
为了保护用户数据不被泄露,采用身份验证和授权模式。用户在使用视觉搜索服务时,需要通过电子邮件进行身份验证。具体步骤如下:
1. 用户在应用程序或其他客户端输入电子邮件地址。
2. 系统向该电子邮件地址发送验证链接或验证码。
3. 用户点击链接或输入验证码完成身份验证。
4. 验证通过后,系统根据用户的角色和权限授予相应的访问权限。
3.2.2 可扩展性模式
为了应对随着用户数量增加而带来的系统压力,采用负载均衡和分布式存储模式。具体操作如下:
- 负载均衡:使用负载均衡器将用户请求均匀分配到多个服务器上,避免单个服务器过载。负载均衡器可以根据服务器的负载情况、响应时间等因素进行动态调整。
- 分布式存储:将用户上传的图像和相关数据分散存储在多个节点上,提高数据的存储容量和可靠性。同时,使用分布式文件系统可以方便地进行数据的读写和管理。
3.2.3 集成模式
为了实现系统中各个服务之间的协同工作,采用消息队列和服务编排模式。具体流程如下:
- 消息队列:用户发送的图像和请求首先进入消息队列,各个服务从消息队列中获取任务进行处理。消息队列可以实现服务之间的异步通信,提高系统的响应性和可靠性。
- 服务编排:使用编排引擎对各个服务的执行顺序和逻辑进行管理。例如,在进行视觉搜索时,先调用图像识别服务进行图像分析,然后根据分析结果调用相关的业务服务,如库存查询、计费等。
3.3 模式实现示例
以下是一个简单的 Python 代码示例,展示了如何使用消息队列(RabbitMQ)实现服务之间的通信:
import pika
# 连接到 RabbitMQ 服务器
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
# 声明一个队列
channel.queue_declare(queue='image_search_queue')
# 定义消息处理函数
def callback(ch, method, properties, body):
print("Received image for search: %r" % body)
# 这里可以调用图像识别服务进行处理
# 处理完成后可以将结果发送到其他队列
# 消费消息
channel.basic_consume(queue='image_search_queue', on_message_callback=callback, auto_ack=True)
print('Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
3.4 模式与开发生命周期的结合
在开发过程中,需要根据系统的需求和质量属性选择合适的模式。具体步骤如下:
1. 需求分析:明确系统的功能需求和质量属性,如安全性、可扩展性、响应性等。
2. 模式选择:根据需求分析的结果,选择合适的模式来满足这些需求。例如,如果需要提高系统的可扩展性,可以选择负载均衡和分布式存储模式。
3. 设计实现:将选择的模式应用到系统的设计和实现中,确保各个模式之间的协同工作。
4. 测试验证:对系统进行测试,验证模式的有效性和系统的性能是否满足需求。
以下是一个模式选择的决策表:
| 需求 | 候选模式 | 选择理由 |
| — | — | — |
| 安全性 | 身份验证和授权模式 | 保护用户数据不被泄露 |
| 可扩展性 | 负载均衡和分布式存储模式 | 应对用户数量增加带来的压力 |
| 响应性 | 消息队列和服务编排模式 | 提高系统的响应速度和可靠性 |
3.5 解决方案总结
通过结合多种模式,我们可以构建一个完整的视觉搜索系统解决方案。这些模式在不同方面发挥作用,共同满足系统的功能需求和质量属性。在实际开发过程中,需要根据具体情况选择合适的模式,并确保它们之间的协同工作。
下面是一个模式组合实现视觉搜索系统的 mermaid 流程图:
graph LR
A[用户请求] -->|发送到消息队列| B[消息队列]
B -->|分配任务| C[图像识别服务]
C -->|分析结果| D[业务服务调用]
D -->|库存查询| E[库存服务]
D -->|计费| F[计费服务]
E -->|结果反馈| D
F -->|结果反馈| D
D -->|最终结果| G[返回给用户]
H[负载均衡器] -->|均衡请求| I[多个服务器]
J[分布式存储系统] <-->|数据读写| I
综上所述,在构建复杂的系统时,合理组合和应用各种模式是解决问题的关键。通过案例分析,我们可以看到如何将理论上的模式应用到实际的开发中,从而提高系统的性能和可靠性。同时,在开发过程中要始终关注系统的需求和质量属性,不断优化和调整模式的应用,以确保系统能够满足不断变化的业务需求。
超级会员免费看
8206

被折叠的 条评论
为什么被折叠?



