微服务是近几年非常火热的架构设计理念,大部分人认为是 Martin Fowler 提出了微服务概念,但事实上微服务概念的历史要早得多。Martin 只是将微服务进行了系统的阐述,但不能否认 Martin 在推动微服务起到的作用——微服务能火,Martin 功不可没。
微服务的起源可以追溯到 2005 年:
微服务并没有一个官方的、严格的定义,但 Martin Fowler 在他的文章中总结了微服务的关键特征:
服务组件化:围绕业务能力组织服务,通过服务而非类库来实现组件化
围绕业务组织团队:传统的组件化方式强调技术能力(如UI组件、业务逻辑组件),微服务则强调业务能力
去中心化治理:每个服务可以独立选择技术栈,不强求统一
去中心化数据管理:每个服务管理自己的数据库
基础设施自动化:强调自动化测试、自动化部署
容错性设计:假设服务会失败,设计时需要考虑降级和熔断
** evolutionary design**:服务可以独立演进,允许重写甚至删除服务
由于微服务的理念中也包含了"服务"的概念,而 SOA 中也有"服务"的概念,很多人容易将两者混淆。它们确实有相似之处,但也有本质区别:
| 维度 | SOA | 微服务 |
|---|---|---|
| 服务粒度 | 粗粒度 | 细粒度 |
| 通信协议 | 复杂(ESB) | 轻量(HTTP/REST) |
| 服务定义 | 权威标准 | 独立演进 |
| 数据管理 | 集中式 | 分散式 |
| 治理方式 | 集中管控 | 去中心化 |
微服务可以看作是 SOA 的一种轻量级实现,它摒弃了 SOA 中过于复杂的 ESB 和 WS-* 标准,采用更简单、更实用的方式来实现服务架构。
每个微服务都是独立的业务单元,可以独立开发、测试、部署和扩展。这意味着:
当某个服务成为瓶颈时,只需要扩展该服务,而不需要扩展整个系统。这大大降低了资源成本。
团队可以根据业务特点选择最合适的技术,而不是被统一的技术栈束缚。
良好的微服务设计可以实现精细的容错机制,防止故障扩散。
然而,微服务并非Silver Bullet(一击解决所有问题的理想化方案),它也带来了新的挑战:
微服务本身就是分布式系统,而分布式系统有固有的复杂性:
微服务的核心问题是如何正确地拆分系统。拆分过细会导致:
微服务需要完善的基础设施支持:
实施微服务对团队能力有较高要求:
微服务适合的场景:
单体架构更适合的场景:
以下示例演示微服务架构中的服务注册与发现机制,以及如何实现基本的负载均衡。
python"""
微服务示例:服务注册与发现、负载均衡
核心思想:服务独立运行,通过注册中心实现解耦
"""
import random
from typing import List, Dict
from dataclasses import dataclass
@dataclass
class ServiceInstance:
"""服务实例"""
id: str
host: str
port: int
weight: int = 1 # 用于加权负载均衡
class ServiceRegistry:
"""服务注册中心"""
def __init__(self):
# 服务名 -> 实例列表
self.services: Dict[str, List[ServiceInstance]] = {}
# 健康检查状态
self.health_status: Dict[str, bool] = {}
def register(self, service_name: str, instance: ServiceInstance):
"""注册服务实例"""
if service_name not in self.services:
self.services[service_name] = []
self.services[service_name].append(instance)
self.health_status[f"{service_name}:{instance.id}"] = True
print(f"[注册中心] 服务 {service_name} 的实例 {instance.id} 注册成功")
def unregister(self, service_name: str, instance_id: str):
"""注销服务实例"""
if service_name in self.services:
self.services[service_name] = [
i for i in self.services[service_name]
if i.id != instance_id
]
print(f"[注册中心] 服务 {service_name} 的实例 {instance_id} 已注销")
def discover(self, service_name: str) -> List[ServiceInstance]:
"""发现服务实例(带健康检查过滤)"""
instances = self.services.get(service_name, [])
# 只返回健康的实例
healthy = [
i for i in instances
if self.health_status.get(f"{service_name}:{i.id}", False)
]
print(f"[注册中心] 发现服务 {service_name}, 可用实例: {len(healthy)}")
return healthy
class LoadBalancer:
"""负载均衡器(轮询策略)"""
def __init__(self, registry: ServiceRegistry):
self.registry = registry
self.round_robin_index: Dict[str, int] = {}
def get_instance(self, service_name: str) -> ServiceInstance:
"""获取下一个服务实例(轮询)"""
instances = self.registry.discover(service_name)
if not instances:
raise Exception(f"无可用服务实例: {service_name}")
# 轮询选择
if service_name not in self.round_robin_index:
self.round_robin_index[service_name] = 0
index = self.round_robin_index[service_name]
instance = instances[index % len(instances)]
self.round_robin_index[service_name] = (index + 1) % len(instances)
return instance
# 测试微服务注册与发现
if __name__ == "__main__":
registry = ServiceRegistry()
lb = LoadBalancer(registry)
# 注册用户服务的多个实例
print("=== 服务注册 ===")
registry.register("user-service", ServiceInstance("inst-1", "192.168.1.10", 8080))
registry.register("user-service", ServiceInstance("inst-2", "192.168.1.11", 8080))
registry.register("user-service", ServiceInstance("inst-3", "192.168.1.12", 8080))
# 服务发现与负载均衡
print("\n=== 负载均衡测试(5次调用) ===")
for i in range(5):
instance = lb.get_instance("user-service")
print(f"第{i+1}次调用: -> {instance.host}:{instance.port}")
# 模拟实例故障
print("\n=== 模拟实例 inst-1 故障 ===")
registry.health_status["user-service:inst-1"] = False
print("实例 inst-1 已标记为不健康")
print("\n=== 故障后的服务发现 ===")
instances = registry.discover("user-service")
print(f"剩余健康实例: {len(instances)}")
输出示例:
=== 服务注册 === [注册中心] 服务 user-service 的实例 inst-1 注册成功 [注册中心] 服务 user-service 的实例 inst-2 注册成功 [注册中心] 服务 user-service 的实例 inst-3 注册成功 === 负载均衡测试(5次调用) === [注册中心] 发现服务 user-service, 可用实例: 3 第1次调用: -> 192.168.1.10:8080 [注册中心] 发现服务 user-service, 可用实例: 3 第2次调用: -> 192.168.1.11:8080 [注册中心] 发现服务 user-service, 可用实例: 3 第3次调用: -> 192.168.1.12:8080 [注册中心] 发现服务 user-service, 可用实例: 3 第4次调用: -> 192.168.1.10:8080 [注册中心] 发现服务 user-service, 可用实例: 3 第5次调用: -> 192.168.1.11:8080 === 模拟实例 inst-1 故障 === 实例 inst-1 已标记为不健康 === 故障后的服务发现 === [注册中心] 发现服务 user-service, 可用实例: 2 剩余健康实例: 2
这个示例展示了微服务架构中的核心机制:服务注册中心管理所有服务实例,客户端通过负载均衡策略选择调用哪个实例,当某个实例故障时会被自动排除在可用列表之外。