微服务架构的演变
1. 单体架构(Monolithic)
- 阶段描述:在单体应用时代,整个应用程序被设计为一个项目,并在一个进程内运行。这种架构方式开发简单,便于集中管理,但随着应用的复杂化,其缺点逐渐显现。
- 主要特点:
- 开发简单,集中管理。
- 部署成本低
- 难以维护,升级困难,无法快捷迭代。
2. 垂直拆分
- 阶段描述:为了应对单体架构的维护难题,开始出现垂直拆分的做法,即将应用按照功能或业务线拆分为多个独立的部分,每部分独立部署和维护。
- 主要特点:
- 独立部署和维护,提高了部分灵活性。
- 但仍可能保持单体模式思维,容易形成重复建设。
3. 分布式服务
- 阶段描述:随着业务规模的扩大,系统开始采用分布式服务架构,将一系列服务组装成系统,每个服务独立部署、独立运行、独立开发和维护。
- 主要特点:
- 强调服务的独立性和隔离性。
- 提高了系统的可扩展性和容错性。
4. 面向服务架构(SOA)
- 阶段描述:面向服务架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过定义良好的接口和协议将这些服务联系起来。
- 主要特点:
- 实现了服务的标准化和可重用性。
- 提高了系统的灵活性和可维护性。
5. 微服务架构
- 阶段描述:微服务架构是SOA的进一步发展和细化,它将大型应用程序拆分为一组小型、独立的服务,每个服务都围绕特定的业务功能进行设计、开发、部署和扩展。
- 主要特点:
- 服务拆分:应用程序被拆分为多个小型服务,每个服务负责一个明确的业务功能。
- 独立部署:每个服务都可以独立进行部署和升级,不会影响其他服务的正常运行。
- 分布式通信:服务之间通过轻量级的通信机制进行交互,如RESTful API、消息队列等。
- 自治性:每个服务都是自治的,可以使用不同的技术栈和数据库,独立进行开发和维护。
- 可扩展性:可以根据需求独立扩展特定的服务,而不必扩展整个应用程序。
- 高可用性:一个服务的故障不会影响整个系统的运行,提高了系统的容错性和可用性。
- 技术多样性:不同的服务可以使用适合自身需求的技术栈,选择最佳的工具和技术。
- 团队自治:每个服务团队可以独立做出决策和创新,加快开发和部署速度。
6. 云原生微服务架构
- 阶段描述:随着云原生技术的兴起,如Docker、Kubernetes等,微服务架构得到了更为完善的支撑,形成了云原生微服务架构。
- 主要特点:
- 强调服务的无状态性和独立性,使得服务更容易在云环境中进行扩展和管理。
- Kubernetes等容器编排工具成为核心组件,用于容器的编排和管理。
- Service Mesh(如Istio)等新技术为微服务提供了更为完善的治理功能,如服务发现、负载均衡、故障注入、可观测性和安全等。
认识微服务
微服务(Microservices)是一种软件架构设计模式,它将大型复杂的应用程序拆分成多个小型、自治的服务单元。这些服务单元可以独立部署、扩展和维护,每个服务单元都专注于完成一个特定的业务功能或任务。基于微服务形成的软件架构风格称为微服务架构(Microservices Architecture),它涵盖了使用微服务构建应用程序的全套原则、模式和最佳实践。
SpringCloud
Spring Cloud是一套分布式微服务架构的一站式解决方案,它提供了一套简单易用的编程模型,使我们能在Spring Boot的基础上轻松地实现微服务系统的构建。
- 定义:Spring Cloud并不是某一门技术,而是一系列微服务解决方案或框架的有序集合。它将市面上成熟的、经过验证的微服务框架整合起来,并通过Spring Boot的思想进行再封装,屏蔽掉其中复杂的配置和实现原理,最终为开发人员提供了一套简单易懂、易部署和易维护的分布式系统开发工具包。
- 性质:Spring Cloud的中文社区网站有http://springcloud.cn/和Spring Cloud中文网-官方文档中文版等,提供了丰富的资源和文档支持。
拆分与远程调用
一、服务拆分
服务拆分是将一个大的应用程序拆分成多个小的、独立的服务的过程,每个服务专注于解决特定的业务问题。服务拆分的目的是为了提高系统的可维护性、可扩展性和灵活性。
拆分原则
- 单一职责原则:每个服务应该只负责一项业务功能,确保服务的职责单一。
- 模块化设计:将功能相似的模块放在同一服务中,确保服务内部的模块之间存在高内聚低耦合的关系。
- 业务边界划分:根据业务需求划分服务边界,确保服务之间的功能和数据的拆分不会导致业务逻辑混乱或重复。
- 垂直拆分:将服务按照业务领域进行垂直拆分,每个服务都有明确的业务范围和职责,这样可以提高系统的可扩展性和维护性。
拆分步骤
- 明确服务边界:根据业务功能和需求,明确每个服务的职责和边界。
- 划分服务模块:将应用程序中的功能模块按照服务边界进行划分。
- 实现服务接口:为每个服务定义清晰的接口,确保服务之间的交互明确和一致。
- 部署和运行服务:将每个服务独立部署在不同的服务器或容器中,并确保服务的长时间稳定运行。
二、远程调用
服务提供者(Provider)
服务提供者是一个运行在网络上,能够响应并处理来自服务消费者的请求的应用程序或服务。它通常会对外暴露一个或多个API接口,这些接口定义了可供远程调用的方法。服务提供者负责处理这些方法的逻辑,并返回相应的结果给服务消费者。
服务消费者(Consumer)
服务消费者是一个需要调用远程服务来完成其业务逻辑的应用程序或服务。它不会直接执行所需的业务逻辑,而是通过远程调用的方式,向服务提供者发送请求,并等待响应结果。服务消费者通常使用某种形式的客户端库或框架来发送请求和接收响应,这些库或框架封装了远程调用的底层细节,使得开发者可以更方便地进行远程通信。
远程调用是微服务架构中服务之间通信的重要方式。在Spring Cloud中,远程调用通常通过HTTP REST API、Feign客户端、消息队列等方式实现。
远程调用流程
- 服务注册与发现:服务启动后,会向注册中心(如Eureka、Nacos等)注册自己的信息,包括服务地址、端口、元数据等。其他服务通过注册中心可以发现和获取服务信息。
- 负载均衡:在调用服务时,通过负载均衡器(如Ribbon、LoadBalancer等)将请求均匀地分发到不同的服务实例上,提高系统的整体性能和稳定性。
- 服务调用:客户端通过HTTP REST API、Feign客户端等方式向服务提供者发送请求,服务提供者处理请求并返回结果。
- 熔断与降级:为了防止服务调用失败导致整个系统崩溃,可以使用熔断器(如Hystrix、Resilience4j等)进行熔断和降级处理。当服务调用失败或超时达到一定阈值时,熔断器会开启熔断状态,将请求直接返回或执行备用逻辑。
常用组件
- Feign:Feign是一个声明式的Web服务客户端,它使得编写Web服务客户端变得更加简单。通过创建接口并使用注解来配置它,可以定义服务之间的通信方式。
- Ribbon:Ribbon是一个客户端负载均衡器,它可以在多个服务实例之间提供智能的负载均衡。
- Hystrix:Hystrix是一个用于处理分布式系统的延迟和容错的库。它通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点。
- Nacos:Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。它提供了服务发现、配置管理、服务管理等关键能力。
Eureka
一、Eureka的组成
Eureka架构主要包括Eureka Server(服务端,注册中心)和Eureka Client(客户端)两大部分。
- Eureka Server:
- 作用:作为服务注册中心,负责维护服务实例的注册信息,并提供服务实例的查询功能。暂存地址 调用时给服务块发送地址
- 功能:
- 服务注册:服务实例启动时,会向Eureka Server注册自己的信息,包括服务名、IP地址、端口号等。
- 服务续租:服务实例定期(默认30秒)向Eureka Server发送心跳,以续租其租约,表明自己仍然可用。
- 服务注销:服务实例关闭时,会向Eureka Server发送注销请求,Eureka Server将此实例从注册列表中移除。
- 服务列表获取:服务消费者从Eureka Server获取服务列表,并根据负载均衡策略选择一个服务实例进行调用。
- Eureka Client:
- 分类:Eureka Client分为服务提供者(Provider)和服务消费者(Consumer)两类。
- 服务提供者:
- 在启动时向Eureka Server注册自己的信息。
- 每隔一定时间(默认30秒)向Eureka Server发送心跳,以维持其租约。
- 服务消费者:
- 通过Eureka Server查找可用的服务实例。
- 从Eureka Server获取服务列表,并根据负载均衡策略选择一个服务实例进行调用。
二、Eureka的特性
- 高可用:Eureka Server支持集群部署,多个Eureka Server实例相互注册,形成高可用的服务注册中心。
- 容错性:Eureka Client在与Eureka Server进行通信时,如果某个Eureka Server宕机,Eureka Client会自动切换到其他Eureka Server进行通信。
- 负载均衡:Eureka与Ribbon等客户端负载均衡器结合使用,可以实现服务的负载均衡。
- 健康检查:Eureka Server通过心跳机制来检查服务实例的健康状态,如果服务实例在预定时间内未发送心跳,Eureka Server会将其标记为不健康或已下线。
三、Eureka的应用场景
Eureka适用于微服务架构中的服务注册与发现场景。在微服务架构中,服务实例数量众多,且经常需要动态地添加或删除服务实例。Eureka通过提供注册中心的功能,使得服务实例能够动态地注册和注销,同时服务消费者也能够通过Eureka Server方便地获取服务列表并进行服务调用。
四、Eureka的使用
在使用Eureka时,通常需要搭建Eureka Server,并在服务提供者和服务消费者中引入Eureka Client依赖。服务提供者在启动时会自动向Eureka Server注册自己的信息,服务消费者则通过Eureka Server获取服务列表并进行服务调用。
五、Eureka的故障处理
Eureka提供了多种故障处理机制,以确保系统的稳定性和可用性。例如,当服务实例出现故障时,Eureka Server会将其从注册列表中移除,避免其他服务消费者继续调用该故障实例。同时,服务消费者可以通过实施重试机制、启用熔断机制等方式来应对服务故障。
Eureka Server(注册中心)
<!--XML-->
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <!-- 添加Spring Boot启动器依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 其他依赖 -->
</dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Your-Spring-Cloud-Version</version> <!-- 替换为你的Spring Cloud版本 --> <type>pom</type> <scope>import</scope> </dependency> </dependencies>
</dependencyManagement>
//启动类上添加@EnableEurekaServer注解:
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配置:##########
server: port: 8761 eureka: client: register-with-eureka: false fetch-registry: false server: wait-time-in-ms-when-sync-empty: 0
Eureka Client(服务注册)
<!--pom.xml-->
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- 添加你的服务所需的依赖,比如web starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 其他依赖 -->
</dependencies> <dependencyManagement> <!-- 与Eureka Server相同 -->
</dependencyManagement>
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication
@EnableDiscoveryClient
public class ServiceApplication { public static void main(String[] args) { SpringApplication.run(ServiceApplication.class, args); }
}
server: port: 8080 spring: application: name: my-service eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ instance: hostname: localhost prefer-ip-address: true
Ribbon
Ribbon是Spring Cloud生态系统中一个用于客户端的负载均衡器,它基于Netflix Ribbon实现。Ribbon的主要功能是在微服务架构中,通过提供一系列的负载均衡策略,将客户端的请求智能地分发到后端服务的多个实例上,从而提高系统的可用性和扩展性。
Ribbon的核心功能
- 负载均衡:
- Ribbon可以将用户请求根据一定的策略(如轮询、随机等)分发到后端服务的多个实例上,以达到负载均衡的效果。
- 它支持多种负载均衡策略,允许用户根据实际需求进行选择和配置。
- 服务调用:
- 在微服务架构中,Ribbon通常与RestTemplate等客户端工具一起使用,方便地进行服务间的调用。
- 通过在RestTemplate上添加
@LoadBalanced
注解,可以轻松地实现服务的负载均衡调用。
创建一个配置类来显式地设置IRule
Bean:
@Bean
public IRule customRule() {
return new CustomRule();
}
通过在application.yml
或application.properties
文件中设置属性
myclient: ribbon: NFLoadBalancerRuleClassName: com.example.CustomRule
Ribbon的负载均衡策略
Ribbon支持多种负载均衡策略,常见的包括:
- 轮询(RoundRobinRule):
- 默认策略,按顺序依次选择服务实例进行调用。
- 随机(RandomRule):
- 随机选择一个服务实例进行调用,这种策略可以确保请求尽量均匀地分布到各个服务实例上。
- 权重分配(WeightedResponseTimeRule):
- 根据服务实例的响应时间等性能指标动态调整权重,优先调用权重较高的服务实例。
- 最少活跃调用数(BestAvailableRule):
- 选择当前活跃调用数最少的服务实例进行调用,以减少等待时间。
- 一致性哈希(ConsistentHashRule):
- 通过一致性哈希算法选择服务实例,这种策略可以保证相同请求在一段时间内总是被转发到同一个服务实例上,适用于需要会话保持的场景。
- 饥饿加载
饥饿加载(Eager Loading)是软件开发中常用的一种加载数据或资源的策略,其主要特点是在需要之前就预先加载所有可能需要的数据或资源。以下是对饥饿加载的详细解析:
-
定义与特点
- 定义:饥饿加载指的是在应用程序启动或对象初始化阶段,就加载所有可能需要使用的数据,无论这些数据在实际运行中是否会被用到。
- 特点:
- 预加载:在需要之前就完成数据的加载,确保数据在首次访问时能够快速响应。
- 减少延迟:由于数据已经预先加载到内存中,因此在首次访问时可以避免加载数据导致的延迟。
- 内存消耗:可能会浪费内存资源,因为预先加载了大量数据,其中一部分可能并未被实际使用。
- 启动时间:对于大型数据集或复杂对象图,饥饿加载可能导致应用程序的启动时间延长。
Ribbon的工作原理
- 服务发现:
- Ribbon通常与Eureka等服务注册与发现中心配合使用。服务实例在启动时将自己注册到Eureka Server上,Ribbon客户端从Eureka Server获取服务实例的注册信息。
- 负载均衡:
- Ribbon客户端在获取到服务实例的注册信息后,根据配置的负载均衡策略选择一个服务实例进行调用。
- 请求转发:
- 将客户端的请求转发到选中的服务实例上,并处理响应结果。
Ribbon的配置
Ribbon的配置可以通过配置文件或代码的方式进行:
- 配置文件方式:在application.yml或application.properties中配置Ribbon的相关属性,如负载均衡策略等。
- 代码方式:在微服务的启动类中通过编写配置类来定义Ribbon的Bean,并设置相应的负载均衡策略。