微服务学习——大厂面试题总结
目录
19.谈一谈Spring Cloud Gateway的处理流程
20.你了解Spring Cloud gateway的一些高级功能嘛?
1.微服务的优缺点分别是什么?说下你在项目开发中碰到的坑
【老师解读】:
- 关于这种题,还有第二题,我们可以从架构演进的角度切入,从最初的单体架构讲起,详细的讲讲。因为优缺点一定是在某个基础上进行比较得出来的结论。
- 除此之外,本题也是考察面试者对微服务是否了解,为什么要用微服务,通过项目中的坑考察是否真正有做过微服务项目,所以常用的组件和基本的微服务调用关系图,这些要清楚,在这个基础上,介绍自己的坑。另外不能光说问题还要把这个问题的解决方法说一下。
- 如果没做过微服务项目,那么自己根据所学的知识,模拟一个问题出来,只要证明我们用过会用,并且在这个基础上对架构还有一定的理解,就合格了。
优点
精解:
- 本身特点:足够内聚、松耦合、易独立部署、功能小而精
- 开发特点:效率高、团队小、不限语言、可融合最新技术
详解:
-
每个服务足够内聚,足够小,代码容易理解这样能聚焦一个指定的业务功能或业务需求
-
开发简单、开发效率提高,一个服务可能就是专一的只干一件事。
-
微服务能够被小团队单独开发,这个小团队是2到5人的开发人员组成。
-
微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的。
-
微服务能使用不同的语言开发。
-
微服务允许容易且灵活的方式集成自动部署,通过持续集成工具,如Jenkins, Hudson, bamboo 。
-
微服务易于被一个开发人员理解,修改和维护,这样小团队能够更关注自己的工作成果。
-
易于和第三方集成,微服务允许你利用融合最新技术。
-
微服务只是业务逻辑的代码,不会和HTML,CSS 或其他界面组件混合。
-
每个微服务都有自己的存储能力,可以有自己的数据库。也可以有统一数据库。
缺点
精解:
随着服务数量增加,管理复杂,部署复杂,服务器需要增多,服务间通信和调用压力增大,运维压力增大,人力资源增多,系统依赖增强,数据一致性问题,性能监控。
详解:
-
开发人员要处理分布式系统的复杂性
-
多服务运维难度,随着服务的增加,运维的压力也在增大
-
系统部署依赖
-
服务间通信成本
-
数据一致性
-
系统集成测试
-
性能监控
坑
- 排查问题难度加大:服务模块多、多环境多服务实例、多环境多数据库
- 代码项目打开窗口过多
- 易迷糊
2.请说一下SOA与微服务的区别?
一、bai架构划分不同
1、SOA强调按水平架构划分为:前、后端、数据库、测试等;
2、微服务强调按垂直架构划分,按业务能力划分,每个服务完成一种特定的功能,服务即产品。
二、技术平台选择不同
1、SOA应用倾向于使用统一的技术平台来解决所有问题;
2、微服务可以针对不同业务特征选择不同技术平台,去中心统一化,发挥各种技术平台的特长。
三、系统间边界处理机制不同
1、SOA架构强调的是异构系统之间的通信和解耦合;(一种粗粒度、松耦合的服务架构);
2、微服务架构强调的是系统按业务边界做细粒度的拆分和部署。
四、主要目标不同
1、SOA架构,主要目标是确保应用能够交互操作;
2、微服务架构,主要目标是实现新功能、并可以快速拓展开发团队。
拓展:
架构Evolution过程:
单体架构(all in one)---> 水平拆分/SOA架构 ---> 微服务架构 ---> Kubernetes云原生架构(微服务迁到云原生)---> ServiceMesh(服务网络架构,下一代微服务架构,云原生架构:istio) ---> serverless 架构(无服务架构)
1、单体架构:所有业务都在同一个应用中,没有进行任何拆分,所有的请求都集中在同一个服务器上面,压力较大;因此这样的架构适合并发较小的架构;同时因为在同一个服务器中,服务器内存、CPU资源,会造成服务性能问题
如图:

2、水平拆分/SOA架构
在单体架构的基础上,进行业务拆分,分为水平拆分和垂直拆分。
水平拆分根据逻辑对系统进行分层,讲一个大的单体应用程序拆分成多个小应用,每个小应用作为单独的jar包,需要时使用时,引入相关的jar包即可。

弊端:
随着访问量的增大,单体应用只能依靠增加节点来应对,但是这时候会发现并不是所有的模块都会有比较大的访问量,我们只希望增加访问量较大的模块,此时单体应用的水平拆分就做不到了,垂直拆分就应用而生了。
解决:
垂直应用架构,就是将原来的的一个应用拆分成几个应用,以提升效率。这样拆分完毕之后,只需要针对访问量大的应用增加节点就可以了。如图:

优点:
系统拆分实现了流量分担,解决了并发问题,而且可以针对不同模块进行优化和扩展,一个系统的问题暂不会影响到其他系统,提高容错效率。
缺点:
系统之间相互独立,会有重复的开发任务。
3、微服务架构
可以理解为微服务架构就是水平拆分和垂直拆分的一种结合。
TODO
3.微服务的优点是什么
4.什么是Netflix Feign?它的优点是什么?
- Feign 是受到 Retrofit,JAXRS-2.0 和 WebSocket 启发的 java 客户端联编程序。
- Feign 的第一个目标是将约束分母的复杂性统一到 http apis,而不考虑其稳定性。
- 使用Netflix Feign 可以使调用变得轻松和简单
- 如果Netflix Feign Ribbon依赖关系也在类路径中,那么Fegin默认也会负责负载平衡。
新版本Spring Cloud 更新为了OpenFeign。
在 employee-consumer 的例子中,我们使用了 employee-producer 使用 REST模板公开的 REST 服务。
- 但是我们必须编写大量代码才能执行以下步骤
- (1)使用功能区进行负载平衡。
- (2)获取服务实例,然后获取基本 URL。
- (3)利用 REST 模板来使用服务。
5.对注册中心说法正确的是——?
- 在实践中,注册中心不能因为自身的任何原因破坏服务之间本身的可连通性
- 注册中心与服务调用链路是弱依赖的,只有服务发布扩容时才依赖
- 注册中心可以不是CP类型,不一定要求数据强一致性
解释:服务调用的链路应该是弱依赖注册中心,必须仅在服务发布、机器上下线,服务扩缩容等必要时才依赖注册中心,不能因为自身的原因破坏服务之间本身的可连通性。
比如,如果注册中心挂了宕机了,那么服务A调用服务B链路不应该受到影响。怎么做到?比如Eureka Client 存在着缓存机制,Eureka Client在启动时会全量拉取服务列表,并保持在本地缓存中,根据服务列表就可以调用服务,即时注册中心挂了,也不影响服务的调用,前提是调用的服务地址没有发生变化。
6.rcp远程调用信息维度有哪些?
包括接口与方法、参数、协议、版本号等。
7.远程调用设计应当包含的组件?
提供者、消费者、注册中心
【拓展】
远程调用一定要想到RPC,那么什么是RPC呢?RPC是指远程过程调用,比如说两台服务器A、B,一个应用部署在A服务器上,想要调用B 服务器上的应用,由于不在一个内存空间,不能直接调用,需要通过网络传递该调用的数据。
那么我们设计RPC 框架时,需要考虑哪些问题呢?
1、要进行远程调用,那我们首先要知道要调用谁?
- 那么这个”谁“的管理,我们通常会单独用一个组件进行管理,比如注册中心,它会记录下服务提供者和服务调用者的相关信息,并将这些信息推送给服务提供者或者服务调用者。
-
同时为了保证系统的执行效率,这些注册信息都是记录在内存里,我们试想下,如果这些注册信息丢失,整个系统将会不可用,因此远程调用管理组件需要提供安全可靠的服务。
-
另外在管理这些服务时,还需要有一定的健康检测,即心跳机制。
2、网路传输层
-
远程调用我们需要通过网络传递,相关的数据都需要通过网络传输,因此就需要有一个网络传输层,比如netty。
3、序列化和反序列化
-
在本地调用时,我们只需要把参数压到栈里,然后去栈里读就行。但是在远程过程调用时,服务不在一个内存空间,需要通过网络传递。不管数据是存储到硬盘还是进行网络通讯,都需要转化为二进制;
-
序列化就是将正在运行的对象转化为可以存储和传输的二进制数据;而反序列化是可以将这些二进制数据反向还原成原来的对象信息。
-
还原的对象还是可以被程序操作的,而我们设计的远程调用框架传递就是不同系统之间可以相互使用的程序代码,所以我们需要使用序列化和反序列化技术。
4、负载均衡/集群容错
-
在分布式环境中,为了避免单点故障,通常一个业务会部署在多台机器上。
-
为了实现流量均衡,提高服务的可用性,我们在调用服务的时候,还需要一定的负载均衡和集群容错来保证,帮我们提供适合的提供者。
8.为什么需要服务治理?
【解读】
-
服务模块与服务模块之间有着千丝万缕的关系,但服务模块在业务中各有权重,所以,我们需要明确各个服务模块的重要等级,分配好资源,也就是对服务进行治理。
-
服务治理是主要针对分布式服务框架的微服务,处理服务调用之间的关系、服务发布和发现、故障监控与处理,服务的参数配置、服务降级和熔断、服务使用率监控等。
-
比如订单模块在电商系统中属于比较重要的模块,如果出问题将会直接影响整个系统的运行;
-
而一个普通的查询服务模块可能也重要,但它的重要等级就没有订单这么重要,所以我们可以根据业务流量预估,将服务规范化,事前做好服务分割,做好服务监控,确保系统的可用性。
【答案】
-
过多的服务URL配置困难
-
负载均衡分配节点压力过大的情况下也需要部署集群
-
服务依赖混乱,启动顺序不清晰
-
过多服务导致性能指标分析难度较大,需要监控
-
故障定位与排查难度较大
9.微服务都有哪些高可用设计的手段?
【解读】
-
一般对外提供服务的系统需要硬件,软件相结合,理想状态下,大型网站应该在任何时候都可以正常访问,都能正常对外提供服务。好的系统要求能够保证,7x24小时运行,全年持续运行故障停运时间累计不能超过10小时,系统缺陷率每1,000小时最多发生1次故障。我们有一套专门评定网站可用性的指标,常用 N 个 9 来评估系统的可用性,如图。所以如何提高可用性,是我们需要迫切解决的问题。

-
首先,需要从架构级别考虑,在规划的时候,就考虑可用性。不同层级使用的策略不同,一般采用冗余备份和失效转移解决高可用问题。
-
应用层:一般设计为无状态的,对于每次请求,使用哪一台服务器处理是没有影响的。一般使用负载均衡技术(需要解决Session同步问题)实现高可用。
-
服务层:负载均衡,分级管理,快速失败(超时设置),异步调用,服务降级,幂等设计等。
-
数据层:冗余备份(冷,热备[同步,异步],温备),失效转移(确认,转移,恢复)。数据高可用方面著名的理论基础是CAP理论(持久性,可用性,数据一致性[强一致,用户一致,最终一致])
【答案】
1、负载均衡 (故障转移)
2、限流
3、降级
4、隔离(线程隔离,进程隔离,集群隔离,机房隔离,读写分离,动静分离,热点隔离…)
5、超时、重试
6、压测与预案
10.下方属于CP的是?()
A.Zookeeper B.Kafka C.Consul D.MySQL E.Eureka
【解读】
- zookeeper是cp,任何时刻对ZooKeeper的访问请求都能得到一致的数据结果,但是它不能保证每次服务请求的可用性,比如进行leader选举时集群都是不可用的。
-
Kafka提供了一些配置,用户可以根据具体的业务需求,进行不同的配置,使得Kafka满足AP或者CP,或者它们之间的一种平衡。
-
consul,遵循CP原则,服务注册稍慢,由于其一致性导致了在Leader挂掉时重新选举期间整个consul不可用。
-
我们在搭建mysql 的时候,集群保障的是高可用,一般是一种AP模型。
11.有关分布式问题追踪说明正确的是( )
a 追踪服务与服务之间的性能问题
b 追踪服务与服务之间的调度异常问题
c 追踪服务中的dump数据
d 分析服务与服务之间调度的合理性
【解读】
dump数据不属于链路追踪的任务范畴
【拓展】
-
稍微扩展下 随着分布式系统规模的越来越大,各微服务间的调用关系也变得越来越复杂。一般情况 下,一个由客户端发起的请求在后端系统中会经过许多不同的微服务调用才能完成最终处理,将结果返回给用户, 而这些调用过程形成了一个复杂的分布式服务调用链路。
-
那么也就带来一系列问题:怎么样快速发现并定位问题?怎么样判断故障影响范围?各部分调用链路性能是怎样的?对于这些问题,通过分布式服务跟踪系统可以解决。
-
我们需要对服务进行跟踪监控,并记录跟踪信息,大概分为以下三个维度:度量(`Metrics`):用于监控和报警;分布式追踪(Tracing):用于记录系统中所有的跟踪信息;日志(Logging):记录每个服务只能中离散的信息;
-
这里介绍下相关概念:
-
Trace:服务追踪的追踪单元是从客户发起请求(request)抵达被追踪系统的边界开始,到被追踪系统向客户返回响应(response)为⽌的过程
-
Span:由于每次Trace都可能会调用数量不定、坐标不定的多个服务,为了能够记录具体调用了哪些服务,以及调用的顺序、开始时点、执行时长等信息,每次开始调用服务前都要先埋入一个调用记录,这个记录称为一个“跨度”(Span)。
-
每⼀个Span都会有⼀个唯⼀跟踪标识 Span ID,若⼲个有序的 span 就组成了⼀个 trace。
Span可以认为是⼀个⽇志数据结构,在⼀些特殊的时机点会记录了⼀些⽇志信息,⽐如有时间戳、spanId、TraceId,parentIde等。
-
Trace ID:为了实现请求跟踪,当请求发送到分布式系统的⼊⼝端点时,只需要服务跟踪框架为该请求创建⼀个唯⼀的跟踪标识Trace ID,同时在分布式系统内部流转的时候,框架始终保持该唯⼀标识,直到返回给请求⽅⼀个Trace由⼀个或者多个Span组成,每⼀个Span都有⼀个SpanId,Span中会记录TraceId,同时还有⼀个叫做ParentId,指向了另外⼀个Span的SpanId,表明⽗⼦关系,其实本质表达了依赖关系
-
Span ID:为了统计各处理单元的时间延迟,当请求到达各个服务组件时,也是通过⼀个唯⼀标识SpanID来标记它的开始,具体过程以及结束。对每⼀个Span来说,它必须有开始和结束两个节点,通过记录开始Span和结束Span的时间戳,就能统计出该Span的时间延迟,除了时间戳记录之外,它还可以包含⼀些其他元数据,⽐如时间名称、请求信息等
12.服务端限流的策略有哪些方式?
- 连接限流
- 信号量限流
- 线程池限流
- 参数限流
【拓展】
- 限流主要的作用是保护服务节点或者集群后面的数据节点,防止瞬时流量过大使服务和数据崩溃造成不可用;
-
限流算法一般分为两种,一种就是请求总量计数,一种就是时间窗口限流,比如令牌桶算法和漏牌桶算法。
13.解决跨语言传输序列化产品有哪些?
- json
- xml
- protobuf
- thrift
【拓展】
- XML是一种常用的序列化和反序列化协议,具有跨机器,跨语言等优点。
-
JSON起源于弱类型语言Javascript, 它的产生来自于一种称之为”Associative array”的概念,与XML相比,其协议比较简单,解析速度比较快。但是采用JSON进行序列化的额外空间开销比较大,对于大数据量服务或持久化,需要更大的内存和磁盘开销,这种场景不适合。
-
Thrift是一个高性能,轻量级RPC服务框架,并不仅仅是序列化协议,其产生是为了满足当前大数据量、分布式、跨语言、跨平台数据通讯的需求。相对于JSON和XML而言,Thrift在空间开销和解析性能上有了比较大的提升,但是由于Thrift的序列化被嵌入到Thrift框架里面,Thrift框架本身并没有透出序列化和反序列化接口,这导致其很难和其他传输层协议共同使用(例如HTTP)。
-
Protobuf是一个纯粹的展示层协议,可以和各种传输层协议一起使用; 但是由于Protobuf产生于Google,所以目前其仅仅支持Java、C++、Python三种语言,且支持的数据类型相对较少,不支持常量类型。目前也没有一个专门支持Protobuf的RPC框架。
这里给出一些选型建议:
以上描述的几种序列化产品都各自具有相应的特点,适用于不同的场景:
1、对于公司间的系统调用,如果性能要求在100ms以上的服务,可以考虑使用xml;
2、基于Web browser的Ajax,以及Mobile app与服务端之间的通讯,首选JSON;对于性能要求不太高,或者传输数据载荷不是很大的的运用场景,也可以考虑使用JSON;
3、对于调试环境比较恶劣的场景,采用JSON或XML能够极大的提高调试效率,降低系统开发成本。
4、当对性能和简洁性有极高要求的场景,推荐Protobuf,Thrift;
5、如果需要提供一个完整的RPC解决方案,推荐Thrift;
6、如果序列化之后需要支持不同的传输层协议,或者需要跨防火墙访问的高性能场景,推荐Protobuf;
14.容错保护的本质是为了什么?
A、保护服务器,保证最大限度的服务能力。
B、保护服务器,防止服务器崩溃
C、保证服务的可扩展性。
D、其他服务出现故障时,主要业务能正常提供服务
【拓展】
-
我们都知道,在单体应用的架构下一旦程序发生了故障,那么整个应用可能就没法使用了,所以我们要把单体应用拆分成具有多个服务的微服务架构,来减少故障的影响范围。
-
但是在微服务架构下,有一个新的问题就是,由于服务数变多了,假设单个服务的故障率是不变的,那么整体微服务系统的故障率其实是提高了的,比如服务的雪崩。
-
那么在这种情况下,为了保证微服务架构的可用性,所以需要一定的容错隔离方案。
15.谈谈你对微服务配置中心的理解
在微服务体系中,服务的数量以及配置信息的日益增多,比如各种服务器参数配置、各种数据库访问参数配置、各种环境下配置信息的不同、配置信息修改之后实时生效等等,传统的配置文件方式或者将配置信息存放于数据库中的方式已无法满足开发人员对配置管理的要求,如:
安全性:配置跟随源代码保存在代码库中,容易造成配置泄漏
时效性:修改配置,需要重启服务才能生效
局限性:无法支持动态调整:例如日志开关、功能开关
16.Nacos⽀持的三种配置加载⽅案?
Namespace(名称空间)方案
通过命名空间实现环境区分
DataID方案
通过指定spring.profile.active和配置文件的DataID,来使不同环境下读取不同的配置,读取配置时,使用的是默认命名空间public,默认分组(default_group)下的DataID。 默认情况,Namespace=public,Group=DEFAULT GROUP,默认Cluster是DEFAULT
Group方案
通过Group实现环境区分
17.下面哪种情况,我们可以借助网关解决?
A 客户端会多次请求不同的微服务
B 存在跨域请求,在一定场景下处理相对复杂
C 难以重构,随着项目的迭代,可能需要重新划分微服务
D 某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难
正确答案是 ABCD
2.下面说法错误的是?
A 网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 网关这一层
B API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 网关来做
C 网关其中一个作用是安全 ,只有网关系统对外进行暴露,微服务可以隐藏在内网,通过防火墙保护
D spring-cloud-gateway, 是spring 出品的 基于spring 的网关项目,集成断路器,路径重写,但是整体性能不如Zuul好
正确答案是 D
spring-cloud-gateway, 是spring 出品的 基于spring 的网关项目,集成断路器,路径重写,整体性能要比Zuul好
现在一般使用spring-cloud-gateway 代替 zuul 作为网关
18.谈一谈微服务网关Gateway的三大核心概念
Route(路由):路由是构建网关的基本模块,它由ID、目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由
Predicate(断言):参考的是Java8的java.util.function.Predicate 开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
Filter(过滤):指的是Spring框架中GatewayFilyter的实例,使用过滤器,可以在请求被路由前或者之后进行修改
匹配方式就叫断言,实现这个匹配方式就叫filter,对外表现出来就是路由的功能。
19.谈一谈Spring Cloud Gateway的处理流程
客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway Web Handler。
Handler再通过指定的过滤器链来讲请求发送到我们实际的服务执行业务逻辑,然后返回。 过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑
Filter 在 “pre” 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等;在 “post” 类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等,有着非常重要的作用
20.你了解Spring Cloud gateway的一些高级功能嘛?
实现熔断降级
为什么要实现熔断降级?
在分布式系统中,网关作为流量的入口,因此会有大量的请求进入网关,向其他服务发起调用,其他服务不可避免的会出现调用失败(超时、异常),失败时不能让请求堆积在网关上,需要快速失败并返回给客户端,想要实现这个要求,就必须在网关上做熔断、降级操作。
为什么在网关上请求失败需要快速返回给客户端?
因为当一个客户端请求发生故障的时候,这个请求会一直堆积在网关上,当然只有一个这种请求,网关肯定没有问题(如果一个请求就能造成整个系统瘫痪,那这个系统可以下架了),但是网关上堆积多了就会给网关乃至整个服务都造成巨大的压力,甚至整个服务宕掉。因此要对一些服务和页面进行有策略的降级,以此缓解服务器资源的的压力,以保证核心业务的正常运行,同时也保持了客户和大部分客户的得到正确的相应,所以需要网关上请求失败需要快速返回给客户端。
分布式限流
从某种意义上讲,令牌桶算法是对漏桶算法的一种改进,桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行,如果桶中令牌数达到上限,就丢弃令牌,所以就存在这种情况,桶中一直有大量的可用令牌,这时进来的请求就可以直接拿到令牌执行,比如设置qps为100,那么限流器初始化完成一秒后,桶中就已经有100个令牌了,这时服务还没完全启动好,等启动完成对外提供服务时,该限流器可以抵挡瞬时的100个请求。所以,只有桶中没有令牌时,请求才会进行等待,最后相当于以一定的速率执行
更多推荐
所有评论(0)