微服务架构
基础概念:
“请介绍一下Spring Cloud Alibaba这套组件,以及你为什么选择它?”
“Nacos除了服务注册发现,还有什么功能?和Eureka相比有什么优势?”
“API网关(Gateway)在你们项目中具体负责了哪些事情?”
深入原理:
“服务之间是如何通过OpenFeign进行通信的?它的底层原理是什么?”
“如果有一个服务节点宕机了,整个系统如何保证高可用?”
“你们是怎么设计微服务的划分原则的?如果服务间出现循环依赖怎么办?”
一、基础概念
1.“请介绍一下Spring Cloud Alibaba这套组件,以及你为什么选择它?”
Spring Cloud Alibaba是一套基于Spring Cloud的微服务解决方案,它整合了阿里巴巴的开源组件,帮助开发者快速构建,部署和管理分布式系统。
核心组件:
Nacos:用于用户服务注册与发现,以及配置管理。它可以帮助我们实现服务的动态注册和发现,同时支持动态配置更新,让微服务架构更加灵活。
Sentinal:流量控制,熔断降级组件。它可以保护系统不被突发大规模流量冲垮,实现服务的稳定性和高可用性。
Seata:分布式事物解决方案。在微服务架构中,业务操作可能涉及多个服务,Seata可以帮助我们保证数据的一致性。
RocketMQ:分布式消息中间件,用于实现应用之间的异步通信和解耦。
Dubbo:高性能RPC框架,用于服务间的远程调用。
选择Spring Cloud Alibaba的原因:适合+功能保障+完整性+当前项目使用可靠
与Spring Boot无缝集成,学习成本相对较低,可以快速上手开发。
阿里巴巴在电商场景下经历了大规模实践,面对大流量和高并发场景稳定性高。
Spring Cloud Alibaba提供了完整的服务治理方案,包括服务注册发现,配置管理,流量控制,分布式事物,可以满足企业级应用开发的多种需求。
在我们当前的项目中,我们使用了Nacos进行服务注册发现和配置管理,使用Sentinel进行流量控制,这些组件帮助我们构建了一个稳定、可靠的微服务架构。
2.“Nacos除了服务注册发现,还有什么功能?和Eureka相比有什么优势?”
配置管理功能:支持动态配置更新,可以在不重新启用的情况下更新配置,这对微服务架构十分重要。
1.动态配置更新;
2.配置版本管理;
3.灰度配置;可以针对特定的实例推送不同的配置
4.配置监听。
优势:全面+氛围
1.功能全面---多了配置管理;
2.动态配置支持;
3.动态检查机制更好,支持TCP,HTTP等多种监控检查方法。
4.支持多种部署:单机模式,集群模式等,让部署和运维更简单;
5.多语言支持,不仅支持java。
6.有个好的社区。
3.“API网关(Gateway)在你们项目中具体负责了哪些事情?”
总的来说,API网关在我们的项目中起到了统一入口、安全控制、流量管理、监控统计等重要作用
1.路由转发:API网关作为系统的统一入口,根据请求路径将请求转发到相应的微服务。
2.权限认证:API网关负责对请求进行身份验证和权限校验。
3.日志处理:API网关会记录请求的相关信息,便于后续的问题排查和监控分析。
4.跨域处理:避免每个微服务都需要单独处理跨域配置。
5.限流控制:防止某个服务因为请求量过大而崩溃。
6.链路追踪:API网关实现了请求的链路追踪,方便监控整个请求的调用链路。
7.异常处理:当后端服务出现异常或不可用时,API网关可以通过FallbackController.java提供降级处理,返回友好的错误提示。
二、深入原理
1.“服务之间是如何通过OpenFeign进行通信的?它的底层原理是什么?”
首先,我们需要在调用方服务中定义一个接口,并使用@FeignClient注解标注,指定要调用的服务名称。比如在demo01_video服务中,我们有FeedServiceClient.java这样的Feign客户端:
@FeignClient("feed-service")
public interface FeedServiceClient {// 定义要调用的接口方法@PostMapping("/feed/publish")void publishFeed(@RequestBody Feed feed);
}
然后,在需要调用远程服务的地方,我们直接注入这个Feign客户端接口,就像使用本地方法一样调用远程服务。
@Service
public class VideoService {@Autowiredprivate FeedServiceClient feedServiceClient;public void processVideo() {// 处理视频逻辑...// 像调用本地方法一样调用远程服务Feed feed = new Feed();feedServiceClient.publishFeed(feed);}
}
OpenFeign的底层原理主要包括以下几个方面:
动态代理:OpenFeign使用Java的动态代理机制,在运行时为@FeignClient标记的接口生成实现类。当我们调用接口方法时,实际上是调用了这个动态生成的代理类。
注解解析:OpenFeign会解析接口上的各种注解,如@RequestMapping、@GetMapping等,根据这些注解构建HTTP请求。
负载均衡:OpenFeign集成了Ribbon或LoadBalancer实现客户端负载均衡。当调用服务时,它会从服务注册中心获取服务实例列表,并根据负载均衡策略选择一个实例进行调用。
HTTP通信:OpenFeign底层使用Apache HttpClient或OkHttp等HTTP客户端库发送HTTP请求,与目标服务进行通信。
序列化与反序列化:对于请求参数和响应结果,OpenFeign会使用Jackson等JSON处理库进行序列化和反序列化操作。
总的来说,OpenFeign通过动态代理、注解解析、负载均衡等技术,使得服务间的调用变得更加简单和透明,开发者只需要像调用本地方法一样调用远程服务即可。
2.“如果有一个服务节点宕机了,整个系统如何保证高可用?”
1.服务注册和发现:Nacos中心会发现将其移除,防止其他服务调用。
2.客户端负载均衡:使用OpenFeign,集成了Ribbon负载均衡器,此均衡器会避开故障节点。
3.熔断降级机制:Sentinel作为流量控制组件,当某个服务调用失败率过高或者响应时间过长时,就会触发,停止对该服务的调用。
4.服务集群部署:对于关键服务,我们会部署多个实例形成集群,即使一个宕机,我们还有其他实例。
5.API网关容错处理:某个节点无响应,我们不会一直等,而是快速失败尝试其他节点。
3.“你们是怎么设计微服务的划分原则的?如果服务间出现循环依赖怎么办?”
在我们的项目中,微服务的划分主要遵循以下几个原则:
业务边界清晰:每个微服务专注于一个特定的业务领域或功能模块。比如我们将用户管理、视频处理、互动功能、Feed流等分别拆分成独立的服务。
单一职责原则:每个微服务只负责一个核心业务功能,避免功能过于复杂。
数据隔离性:每个微服务拥有独立的数据存储,避免多个服务共享同一数据库。
可独立部署:每个微服务可以独立开发、测试、部署和扩展。
团队组织匹配:微服务的划分也考虑了团队的组织结构,符合康威定律。
对于服务间循环依赖的问题,我们采取了以下几种解决方法:
合理设计服务依赖关系:在设计阶段就避免循环依赖的产生,明确服务间的上下游关系。
引入中间层:当出现循环依赖时,可以考虑引入一个新的服务来解耦两个相互依赖的服务。
使用事件驱动架构:通过消息队列(如RocketMQ、Kafka)实现服务间的异步通信,减少直接的服务调用依赖。
重新审视业务边界:如果两个服务存在循环依赖,可能是服务划分不够合理,需要重新评估是否应该合并为一个服务或者重新划分业务边界。
在我们的项目中,通过仔细的服务划分和合理的架构设计,基本避免了循环依赖的问题。当确实出现复杂的依赖关系时,我们会优先考虑通过事件驱动的方式解耦服务间的直接依赖。