嗨,你好呀,我是猿java
什么是微服务? {#什么是微服务?}
微服务架构的核心理念是将单体应用程序拆分为多个小型服务,每个服务都是一个独立的进程,通常通过轻量级的通信机制(如HTTP/REST、消息队列等)进行交互。每个微服务都拥有自己的数据存储,可以选择最适合其功能的数据库类型。
微服务架构的模型可以抽象成下图:
微服务主要包含以下 5个特点:
1. 单一职责原则
微服务的设计理念强调每个服务模块应该聚焦于完成一项特定的任务或功能,遵循单一职责原则。这意味着每个微服务应该解决某一特定业务领域的问题,使得服务更易于开发、维护和理解。
2. 独立部署
微服务可以独立部署和更新,而无需影响整个系统。这样一来,可以更快地响应业务需求的变化,部署新的功能也更加便捷。
3. 去中心化管理和治理
在微服务架构中,基础设施和服务的开发由不同的团队负责,这样各个团队可以根据自身的技术栈独立决定如何实现服务,并采用适合的技术进行治理。去中心化的治理模型支持团队的敏捷性和创新。
4. 自治性
每个微服务都是自治的,拥有自己独立的数据存储和业务逻辑。这种自治性使得服务之间的耦合度降低,从而提高了系统的鲁棒性。
5. 轻量级通信
微服务之间的通信通常是轻量级的,常用的协议有HTTP/REST、gRPC、AMQP等。这些协议以其跨平台和灵活性著称,适合复杂分布式环境下的服务交互。
如何搭建? {#如何搭建?}
技术栈 {#技术栈}
- Spring Boot:用于构建微服务的基础框架。
- Spring Cloud:用于实现服务治理、配置管理和负载均衡。
- Eureka:用于服务注册和发现。
- Feign:用于服务间通信。
- Ribbon:用于客户端负载均衡。
- Hystrix:用于服务容错处理。
服务治理是微服务架构中的核心部分,负责服务注册、发现、负载均衡和熔断等功能,Spring Cloud提供了一整套用于服务治理的工具,其中Eureka是实现服务注册与发现的核心组件。
设计过程 {#设计过程}
本文,我们将通过设计一个简单的订单管理系统来演示微服务架构的搭建,该系统包含以下微服务:
- Eureka Server:Eureka Server是服务注册中心,各个微服务将自身注册到Eureka Server,其他服务通过Eureka Server发现这些服务。
- Order Service:订单服务,用于处理订单相关操作。
- User Service:用户服务,用于处理用户相关操作。
整个模型如下:
实现步骤 {#实现步骤}
Eureka Server {#Eureka-Server}
Eureka 是服务注册中心,它是微服务架构中的核心组件,用于提供服务注册与发现的功能。Eureka之间是 Peer to Peer 的关系,其核心原理如下图:
- 创建一个Spring Boot项目并添加 Eureka Server依赖:
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
|
- 在主应用类中启用Eureka Server:
|---------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11
| import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
|
- 配置
application.yml
:
|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9
| server: port: 8761 eureka: client: register-with-eureka: false fetch-registry: false server: wait-time-in-ms-when-sync-empty: 0
|
Order Service {#Order-Service}
接着,创建一个订单服务,订单服务负责处理订单的创建、更新和查询等操作。
- 创建一个Spring Boot项目并添加Eureka Client依赖:
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
|
- 在主应用类中启用Eureka Client:
|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11
| import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
|
- 配置
application.yml
:
|---------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11
| server: port: 8081 spring: application: name: order-service eureka: client: service-url: defaultZone: http://localhost:8761/eureka/
|
- 实现订单控制器:
|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11
| import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class OrderController { @GetMapping("/orders/{orderId}") public String getOrder(@PathVariable String orderId) { return "Order details for order id: " + orderId; } }
|
User Service {#User-Service}
接着,创建一个用户服务,用户服务负责处理用户的创建、更新和查询等操作。
实现步骤 {#实现步骤-1}
-
创建一个Spring Boot项目并添加Eureka Client依赖(与订单服务相同)。
-
在主应用类中启用Eureka Client(与订单服务相同)。
-
配置
application.yml
:
|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11
| server: port: 8082 spring: application: name: user-service eureka: client: service-url: defaultZone: http://localhost:8761/eureka/
|
- 实现用户控制器:
|---------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11
| import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/users/{userId}") public String getUser(@PathVariable String userId) { return "User details for user id: " + userId; } }
|
服务间通信 {#服务间通信}
在微服务架构中,服务间通信是必不可少的,我们将使用 Feign进行服务间通信,Feign是一个声明式的 HTTP客户端,可以简化 HTTP API的调用,通过Feign,我们可以像调用本地方法一样调用远程服务。
在订单服务中调用用户服务 {#在订单服务中调用用户服务}
- 添加Feign依赖:
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
|
- 启用 Feign客户端:
|------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10
| import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
|
- 创建Feign客户端接口:
|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9
| import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(name = "user-service") public interface UserClient { @GetMapping("/users/{userId}") String getUser(@PathVariable("userId") String userId); }
|
- 在订单控制器中使用 Feign客户端:
|---------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import org.springframework.web.bind.annotation.RestController; @RestController public class OrderController { private final UserClient userClient; public OrderController(UserClient userClient) { this.userClient = userClient; } @GetMapping("/orders/{orderId}") public String getOrder(@PathVariable String orderId) { String userDetails = userClient.getUser("123"); return "Order details for order id: " + orderId + ", User Details: " + userDetails; } }
|
因此,userClient.getUser("123");
就是调用了UserClient
接口的getUser
方法,这样就可以在订单控制器中直接调用用户服务。
负载均衡 {#负载均衡}
Ribbon是 Spring Cloud Netflix提供的客户端负载均衡器,使用 Feign时,Ribbon已经默认集成,因此无需额外配置。
熔断器 {#熔断器}
Hystrix是由 Netflix开源的一个库,用于处理分布式系统中的延迟和容错问题,它通过隔离服务之间的调用,防止故障在系统中蔓延,从而提高系统的弹性和稳定性。Hystrix的主要原理和功能如下:
1. 隔离和熔断
- 线程池隔离:Hystrix为每个依赖服务调用分配一个独立的线程池,这样即使某个服务调用出现问题(如响应缓慢或失败),也不会占用主应用程序的线程资源,从而影响其他服务的调用。
- 信号量隔离:除了线程池隔离,Hystrix还支持信号量隔离,通过限制并发调用的数量来实现资源隔离。
- 熔断器:类似于电路中的断路器,Hystrix的熔断器在检测到服务调用失败率超过设定阈值时,会暂时中断对该服务的调用。熔断器有三种状态:
关闭:正常状态,允许请求通过。
打开:当失败率超过阈值时,阻止请求通过,直接返回错误。
半开:经过一段时间后,允许部分请求通过以测试服务是否恢复。
2. 失败处理和降级
降级策略:当服务调用失败或熔断器打开时,Hystrix支持提供降级方法来返回默认值或执行备用逻辑。这确保了即使服务不可用,系统也能继续运行。
3. 监控和告警
- 实时监控:Hystrix提供了实时的监控功能,通过Hystrix Dashboard可以查看每个服务调用的成功、失败、超时、熔断等指标。
- 告警:通过集成监控系统,如Prometheus或Grafana,可以设置告警规则,及时通知运维人员处理异常。
4. 请求缓存和批量请求
- 请求缓存:Hystrix可以缓存相同请求的结果,以减少重复调用。
- 批量请求:支持将多个请求合并为一个批量请求,从而提高调用效率。
在 Feign中使用 Hystrix {#在-Feign中使用-Hystrix}
- 添加Hystrix依赖:
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
|
- 启用Hystrix:
|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11
| import org.springframework.cloud.netflix.hystrix.EnableHystrix; @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients @EnableHystrix public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
|
- 在Feign客户端中实现熔断器:
|---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13
| @FeignClient(name = "user-service", fallback = UserClientFallback.class) public interface UserClient { @GetMapping("/users/{userId}") String getUser(@PathVariable("userId") String userId); } @Component class UserClientFallback implements UserClient { @Override public String getUser(String userId) { return "User service is currently unavailable."; } }
|
总结 {#总结}
本文介绍了如何使用 Java和Spring Boot构建一个简单的微服务架构,重点介绍了服务注册与发现、服务间通信、负载均衡和熔断器的实现。通过这个示例,我们可以了解到微服务架构的基本原理和实现过程。在实际应用中,我们可能需要根据具体需求对架构进行调整和优化,比如增加更多的微服务、使用分布式配置中心、链路追踪等功能。
微服务架构虽然带来了很多好处,但同时也引入了分布式系统的复杂性,因此在设计和实现时需要仔细权衡和考虑。
交流学习 {#交流学习}
最后,把猿哥的座右铭送给你:投资自己才是最大的财富。 如果你觉得文章有帮助,请帮忙转发给更多的好友,或关注公众号:猿java,持续输出硬核文章。