1.什么是微服务?
微服务(Microservices)是一种软件架构风格,将一个大型应用程序划分为一组小型、自治且松耦合的服务。每个微服务负责执行特定的业务功能,并通过轻量级通信机制(如HTTP)相互协作。每个微服务可以独立开发、部署和扩展,使得应用程序更加灵活、可伸缩和可维护。
在微服务的架构演进中,一般可能会存在这样的演进方向:单体式-->服务化-->微服务。
单体服务一般是所有项目最开始的样子:
后来,单体服务过大,维护困难,渐渐演变到了分布式的SOA:
需要注意的是,微服务是一种特定的架构风格,而SOA是一种设计原则。微服务可以看作是对SOA思想的一种具体实践方式,但并不等同于SOA。
微服务与单体服务的区别在于规模和部署方式。微服务将应用程序拆分为更小的、自治的服务单元,每个服务都有自己的数据库和代码库,可以独立开发、测试、部署和扩展,带来了更大的灵活性、可维护性、可扩展性和容错性。
2.微服务带来了哪些挑战?
微服务架构不是万金油,尽它有很多优点,但是对于是否采用微服务架构,是否将原来的单体服务进行拆分,还是要考虑到服务拆分后可能带来的一些挑战和问题:
简单说,采用微服务需要权衡这些问题和挑战,根据实际的需求来选择对应的技术方案,很多时候单体能搞定的也可以用单体,不能为了微服务而微服务。
3.现在有哪些流行的微服务解决方案?
目前最主流的微服务开源解决方案有三种:
这三种方案有什么区别吗?
三种方案的区别:
特点 |
Dubbo |
Spring Cloud Netflix |
Spring Cloud Alibaba |
开发语言 |
Java |
Java |
Java |
服务治理 |
提供完整的服务治理功能 |
提供部分服务治理功能 |
提供完整的服务治理功能 |
服务注册与发现 |
ZooKeeper/Nacos |
Eureka/Consul |
Nacos |
负载均衡 |
自带负载均衡策略 |
Ribbon |
Ribbon\Dubbo负载均衡策略 |
服务调用 |
RPC方式 |
RestTemplate/Feign |
Feign/RestTemplate/Dubbo |
熔断器 |
Sentinel |
Hystrix |
Sentinel/Resilience4j |
配置中心 |
Apollo |
Spring Cloud Config |
Nacos Config |
API网关 |
Higress/APISIX |
Zuul/Gateway |
Spring Cloud Gateway |
分布式事务 |
Seata |
不支持分布式事务 |
Seata |
限流和降级 |
Sentinel |
Hystrix |
Sentinel |
分布式追踪和监控 |
Skywalking |
Spring Cloud Sleuth + Zipkin |
SkyWalking或Sentinel Dashboard |
微服务网格 |
Dubbo Mesh |
不支持微服务网格 |
Service Mesh(Nacos+Dubbo Mesh) |
社区活跃度 |
相对较高 |
目前较低 |
相对较高 |
孵化和成熟度 |
孵化较早,成熟度较高 |
成熟度较高 |
孵化较新,但迅速发展 |
在面试中,微服务一般主要讨论的是Spring Cloud Netflix,其次是Spring Cloud Alibaba,Dubbo更多的是作为一个RPC框架来问。
4.说下微服务有哪些组件?
微服务给系统开发带来了一些问题和挑战,如服务调用的复杂性、分布式事务的处理、服务的动态管理等。为了更好地解决这些问题和挑战,各种微服务治理的组件应运而生,充当微服务架构的基石和支撑。
微服务的各个组件和常见实现:
注册中心
5.注册中心是用来干什么的?
注册中心是用来管理和维护分布式系统中各个服务的地址和元数据的组件。它主要用于实现服务发现和服务注册功能。
总结一下注册中心的作用:
6.SpringCloud可以选择哪些注册中心?
SpringCloud可以与多种注册中心进行集成,常见的注册中心包括:
7.说下Eureka、ZooKeeper、Nacos的区别?
特性 |
Eureka |
ZooKeeper |
Nacos |
开发公司 |
Netflix |
Apache 基金会 |
阿里巴巴 |
CAP |
AP(可用性和分区容忍性) |
CP(一致性和分区容忍性) |
既支持AP,也支持CP |
功能 |
服务注册与发现 |
分布式协调、配置管理、分布式锁 |
服务注册与发现、配置管理、服务管理 |
定位 |
适用于构建基于 HTTP 的微服务架构 |
通用的分布式协调服务框架 |
适用于微服务和云原生应用 |
访问协议 |
HTTP |
TCP |
HTTP/DNS |
自我保护 |
支持 |
- |
支持 |
数据存储 |
内嵌数据库、多个实例形成集群 |
ACID 特性的分布式文件系统 ZAB 协议 |
内嵌数据库、MySQL 等 |
健康检查 |
Client Beat |
Keep Alive |
TCP/HTTP/MYSQL/Client Beat |
特点 |
简单易用、自我保护机制 |
高性能、强一致性 |
动态配置管理、流量管理、灰度发布等 |
可以看到Eureka和ZooKeeper的最大区别是一个支持AP,一个支持CP,Nacos既支持既支持AP,也支持CP。
8.Eureka实现原理了解吗?
Eureka的实现原理,大概可以从这几个方面来看:
其它的注册中心,如Nacos、Consul等等,在服务注册和发现上,实现原理都是大同小异。
9.Eureka Server怎么保证高可用?
Eureka Server保证高可用,主要通过这三个方面来实现:
Eureka Server
笔者认真维护了 5 年多的 JavaGuide(开源 Java学习+面试指南)共有 447 位贡献者了,star 也来到了 136k+,真心感谢大家的支持!
笔者几乎每天都会持续完善这个项目的内容,处理 issue 和 pr。如果觉得 JavaGuide 的内容对你有帮助的话,还请点个免费的 star,这是对我最大的鼓励!
配置中心
10.为什么微服务需要配置中心?
微服务架构中的每个服务通常都需要一些配置信息,例如数据库连接地址、服务端口、日志级别等。这些配置可能因为不同环境、不同部署实例或者动态运行时需要进行调整和管理。
微服务的实例一般非常多,如果每个实例都需要一个个地去做这些配置,那么运维成本将会非常大,这时候就需要一个集中化的配置中心,去管理这些配置。
11.SpringCloud可以选择哪些配置中心?
和注册中心一样,SpringCloud也支持对多种配置中心的集成。常见的配置中心选型包括:
12.Nacos配置中心的原理了解吗?
配置中心,说白了就是一句话:配置信息的CRUD。
配置中心
具体的实现大概可以分成这么几个部分:
13.Nacos配置中心长轮询机制?
一般来说客户端和服务端的交互分为两种:推(Push)和拉(Pull),Nacos在Pull的基础上,采用了长轮询来进行配置的动态刷新。
在长轮询模式下,客户端定时向服务端发起请求,检查配置信息是否发生变更。如果没有变更,服务端会"hold"住这个请求,即暂时不返回结果,直到配置发生变化或达到一定的超时时间。
具体的实现过程如下:
通过长轮询的方式,Nacos客户端能够实时感知配置的变化,并及时获取最新的配置信息。同时,这种方式也降低了服务端的压力,避免了大量的长连接占用内存资源。
远程调用
14.能说下HTTP和RPC的区别吗?
严格来讲,HTTP和不是一个层面的东西:
一些RPC框架比如gRPC,底层传输协议其实也是用的HTTP2,包括Dubbo3,也兼容了gRPC,使用了HTTP2作为传输层的一层协议。
如果硬要说区别的话,如下:
HTTP |
RPC |
|
定义 |
HTTP(超文本传输协议)是一种用于传输超文本的协议。 |
RPC(远程过程调用)是一种用于实现分布式系统中不同节点之间通信的协议。 |
通信方式 |
基于请求-响应模型,客户端发送请求,服务器返回响应。 |
基于方法调用模型,客户端调用远程方法并等待结果。 |
传输协议 |
基于TCP协议,可使用其他传输层协议如TLS/SSL进行安全加密。 |
可以使用多种传输协议,如TCP、UDP等。 |
数据格式 |
基于文本,常用的数据格式有JSON、XML等。 |
可以使用各种数据格式,如二进制、JSON、Protocol Buffers等。 |
接口定义 |
使用RESTful风格的接口进行定义,常用的方法有GET、POST、PUT、DELETE等。 |
使用IDL(接口定义语言)进行接口定义,如Protocol Buffers、Thrift等。 |
跨语言性 |
支持跨语言通信,可以使用HTTP作为通信协议实现不同语言之间的通信。 |
支持跨语言通信,可以使用IDL生成不同语言的客户端和服务端代码。 |
灵活性 |
更加灵活,适用于不同类型的应用场景,如Web开发、API调用等。 |
更加高效,适用于需要高性能和低延迟的分布式系统。 |
在微服务体系里,基于HTTP风格的远程调用通常使用框架如Feign来实现,基于RPC的远程调用通常使用框架如Dubbo来实现。
15.那Feign和Dubbo的区别呢?
这两个才是适合拿来比较的东西:
Feign |
Dubbo |
|
定义 |
Feign是一个声明式的Web服务客户端,用于简化HTTP API的调用。 |
Dubbo是一个分布式服务框架,用于构建面向服务的微服务架构。 |
通信方式 |
基于HTTP协议,使用RESTful风格的接口进行定义和调用。 |
基于RPC协议,支持多种序列化协议如gRPC、Hessian等。 |
服务发现 |
通常结合服务注册中心(如Eureka、Consul)进行服务发现和负载均衡。 |
通过ZooKeeper、Nacos等进行服务注册和发现,并提供负载均衡功能。 |
服务治理 |
不直接提供服务治理功能,需要结合其他组件或框架进行服务治理。 |
提供服务注册与发现、负载均衡、容错机制、服务降级等服务治理功能。 |
跨语言性 |
支持跨语言通信,可以使用HTTP作为通信协议实现不同语言之间的通信。 |
支持跨语言通信,通过Dubbo的IDL生成不同语言的客户端和服务端代码。 |
生态系统 |
集成了Spring Cloud生态系统,与Spring Boot无缝集成。 |
拥有完整的生态系统,包括注册中心、配置中心、监控中心等组件。 |
适用场景 |
适用于构建RESTful风格的微服务架构,特别适合基于HTTP的微服务调用。 |
适用于构建面向服务的微服务架构,提供更全面的服务治理和容错机制。 |
需要注意的是,Feign和Dubbo并不是互斥的关系。实际上,Dubbo可以使用HTTP协议作为通信方式,而Feign也可以集成RPC协议进行远程调用。选择使用哪种远程调用方式取决于具体的业务需求和技术栈的选择。
16.说一下Fegin?
Feign是一个声明式的Web服务客户端,它简化了使用基于HTTP的远程服务的开发。
Feign是在RestTemplate 和 Ribbon的基础上进一步封装,使用RestTemplate实现Http调用,使用Ribbon实现负载均衡。
Feign的主要特点和功能包括:
@FeignClient(name = "example", url = "https://api.example.com")public interface ExampleService { @GetMapping("/endpoint") String getEndpointData();}
17.为什么Feign第一次调用耗时很长?
主要原因是由于Ribbon的懒加载机制,当第一次调用发生时,Feign会触发Ribbon的加载过程,包括从服务注册中心获取服务列表、建立连接池等操作,这个加载过程会增加首次调用的耗时。
ribbon: eager-load: enabled: true clients: service-1
那怎么解决这个问题呢?
可以在应用启动时预热Feign客户端,自动触发一次无关紧要的调用,来提前加载Ribbon和其他相关组件。这样,就相当于提前进行了第一次调用。
18.Feign怎么实现认证传递?
比较常见的一个做法是,使用拦截器传递认证信息。可以通过实现RequestInterceptor接口来定义拦截器,在拦截器里,把认证信息添加到请求头中,然后将其注册到Feign的配置中。
@Configurationpublic class FeignClientConfig { @Bean public RequestInterceptor requestInterceptor() { return new RequestInterceptor() { @Override public void apply(RequestTemplate template) { // 添加认证信息到请求头中 template.header("Authorization", "Bearer " + getToken()); } }; } private String getToken() { // 获取认证信息的逻辑,可以从SecurityContext或其他地方获取 // 返回认证信息的字符串形式 return "your_token"; }}
19.Fegin怎么做负载均衡?Ribbon?
在Feign中,负载均衡是通过集成Ribbon来实现的。
Ribbon是Netflix开源的一个客户端负载均衡器,可以与Feign无缝集成,为Feign提供负载均衡的能力。
Ribbon通过从服务注册中心获取可用服务列表,并通过负载均衡算法选择合适的服务实例进行请求转发,实现客户端的负载均衡。
客户端负载均衡
20.说说有哪些负载均衡算法?
常见的负载均衡算法包含以下几种:
常见负载均衡算法
常见的负载均衡器,比如Ribbion、Gateway等等,基本都支持这些负载均衡算法。
关于Dubbo,后面会单独出一期。
服务容灾
21.什么是服务雪崩?
在微服务中,假如一个或者多个服务出现故障,如果这时候,依赖的服务还在不断发起请求,或者重试,那么这些请求的压力会不断在下游堆积,导致下游服务的负载急剧增加。不断累计之下,可能会导致故障的进一步加剧,可能会导致级联式的失败,甚至导致整个系统崩溃,这就叫服务雪崩。
服务雪崩
一般,为了防止服务雪崩,可以采用这些措施:
22.什么是服务熔断?什么是服务降级?
什么是服务熔断?
服务熔断是微服务架构中的容错机制,用于保护系统免受服务故障或异常的影响。当某个服务出现故障或异常时,服务熔断可以快速隔离该服务,确保系统稳定可用。
它通过监控服务的调用情况,当错误率或响应时间超过阈值时,触发熔断机制,后续请求将返回默认值或错误信息,避免资源浪费和系统崩溃。
服务熔断还支持自动恢复,重新尝试对故障服务的请求,确保服务恢复正常后继续使用。
什么是服务降级?
服务降级是也是一种微服务架构中的容错机制,用于在系统资源紧张或服务故障时保证核心功能的可用性。
当系统出现异常情况时,服务降级会主动屏蔽一些非核心或可选的功能,而只提供最基本的功能,以确保系统的稳定运行。通过减少对资源的依赖,服务降级可以保证系统的可用性和性能。
它可以根据业务需求和系统状况来制定策略,例如替换耗时操作、返回默认响应、返回静态错误页面等。
有哪些熔断降级方案实现?
目前常见的服务熔断降级实现方案有这么几种:
框架 |
实现方案 |
特点 |
Spring Cloud |
Netflix Hystrix |
- 提供线程隔离、服务降级、请求缓存、请求合并等功能- 可与Spring Cloud其他组件无缝集成- 官方已宣布停止维护,推荐使用Resilience4j代替 |
Spring Cloud |
Resilience4j |
- 轻量级服务熔断库- 提供类似于Hystrix的功能- 具有更好的性能和更简洁的API- 可与Spring Cloud其他组件无缝集成 |
Spring Cloud Alibaba |
Sentinel |
- 阿里巴巴开源的流量控制和熔断降级组件- 提供实时监控、流量控制、熔断降级等功能- 与Spring Cloud Alibaba生态系统紧密集成 |
Dubbo |
Dubbo自带熔断降级机制 |
- Dubbo框架本身提供的熔断降级机制- 可通过配置实现服务熔断和降级- 与Dubbo的RPC框架紧密集成 |
23.Hystrix怎么实现服务容错?
尽管已经不再更新,但是Hystrix是非常经典的服务容错开源库,它提供了多种机制来保护系统:
Hystrix服务容错六大机制
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;/*** 服务降级示例**/@Servicepublic class MyService { @HystrixCommand(fallbackMethod = "fallbackMethod") public String myServiceMethod() { // 实际的服务调用逻辑 // ... } public String fallbackMethod() { // 降级方法的逻辑,当服务调用失败时会执行此方法 // 可以返回默认值或执行其他备用逻辑 // ... }}
24.Sentinel怎么实现限流的?
Sentinel通过动态管理限流规则,根据定义的规则对请求进行限流控制。具体实现步骤如下:
// 原本的业务方法.@SentinelResource(blockHandler = "blockHandlerForGetUser")public User getUserById(String id) { throw new RuntimeException("getUserById command failed");}// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用public User blockHandlerForGetUser(String id, BlockException ex) { return new User("admin");}
private static void initFlowQpsRule() { List
Sentinel控制台
Sentinel总体框架-来源官网
Sentinel采用的什么限流算法?
Sentinel使用滑动窗口限流算法来实现限流。
滑动窗口限流算法是一种基于时间窗口的限流算法。它将一段时间划分为多个时间窗口,并在每个时间窗口内统计请求的数量。通过动态地调整时间窗口的大小和滑动步长,可以更精确地控制请求的通过速率。
滑动窗口限流可以查看前面的分布式篇。
Sentinel怎么实现集群限流?
Sentinel利用了Token Server和Token Client的机制来实现集群限流。
开启集群限流后,Client向Token Server发送请求,Token Server根据配置的规则决定是否限流。T
服务网关
25.什么是API网关?
API网关(API Gateway)是一种中间层服务器,用于集中管理、保护和路由对后端服务的访问。它充当了客户端与后端服务之间的入口点,提供了一组统一的接口来管理和控制API的访问。
API网关的主要功能包括:
……
通过使用API网关,可以简化前端与后端服务的交互,提供统一的接口和安全性保障,同时也方便了服务治理和监控。它是构建微服务架构和实现API管理的重要组件之一。
26.SpringCloud可以选择哪些API网关?
使用SpringCloud开发,可以采用以下的API网关选型:
……
27.Spring Cloud Gateway核心概念?
Gateway原理
在Spring Cloud Gateway里,有三个关键组件:
我们再来看下Spring Cloud Gateway的具体工作流程:
SpringCloud工作流程图-来源官方文档
又有两个比较重要的概念:
链路追踪
28.为什么要用微服务链路追踪?
在微服务中,有的山下游可能有十几个服务,如果某一环出了问题,排查起来非常困难,所以,就需要进行链路追踪,来帮助排查问题。
SkyWalking界面
通过链路追踪,可以可视化地追踪请求从一个微服务到另一个微服务的调用情况。除了排查问题,链路追踪黑还可以帮助优化性能,可视化依赖关系、服务监控和告警。
29.SpringCloud可以选择哪些微服务链路追踪方案?
Spring Cloud提供了多种选择的微服务链路追踪方案。以下是一些常用的方案:
这些方案都可以与 Spring Cloud Sleuth 进行集成,Spring Cloud Sleuth 是 Spring Cloud 中的一个组件,提供了在微服务调用时生成追踪信息的能力。
分布式事务
分布式事务可以查看前面的分布式基础篇。
30.Seata支持哪些模式的分布式事务?
Seata以下几种模式的分布式事务:
31.了解Seata的实现原理吗?
Seata的实现原理主要包括三个核心组件:事务协调器(Transaction Coordinator)、事务管理器(Transaction Manager)和资源管理器(Resource Manager)。
Seata的实现原理基于两阶段提交(Two-Phase Commit)协议,具体的机制如下:
Seata的事务执行流程是什么样的?
Seata事务的执行流程可以简要概括为以下几个步骤:
全局事务ID和分支事务ID是怎么传递的?
全局事务ID和分支事务ID在分布式事务中通过上下文传递的方式进行传递。常见的传递方式包括参数传递、线程上下文传递和消息中间件传递。具体的传递方式可以根据业务场景和技术选型进行选择和调整。
Seata的事务回滚是怎么实现的?
Seata的事务回滚是通过回滚日志实现的。每个参与者在执行本地事务期间生成回滚日志,记录了对数据的修改操作。
当需要回滚事务时,事务协调器向参与者发送回滚请求,参与者根据回滚日志中的信息执行撤销操作,将数据恢复到事务开始前的状态。
回滚日志的管理和存储是Seata的核心机制,可以选择将日志存储在不同的介质中。通过回滚日志的持久化和恢复,Seata确保了事务的一致性和恢复性。
服务监控
32.你们的服务怎么做监控和告警?
我们使用Prometheus和Grafana来实现整个微服务集群的监控和告警:
Dashboard
33.你们的服务怎么做日志收集?
日志收集有很多种方案,我们用的是ELK:
简单说,这三者里Elasticsearch提供数据存储和检索能力,Logstash负责将日志收集到ES,Kibana负责日志数据的可视化分析。
使用ELK进行微服务日志收集的一般流程如下:
除了应用最广泛的ELK,还有一些其它的方案比如Fluentd、Graylog、Loki、Filebeat,一些云厂商也提供了付费方案,比如阿里云的sls