最近换工作,面试了几家公司,被问到了很多微服务相关的问题,从基础概念到架构设计,从服务治理到分布式事务,从监控到部署,几乎覆盖了微服务的方方面面。
今天这篇文章,就来整理一下我面试中被问到的微服务相关的问题,以及我的回答思路,希望能给正在准备面试或者想学习微服务的朋友一些参考。
一、微服务基础概念
问题1:什么是微服务?微服务和单体架构有什么区别?
这是最基础的问题,几乎每次面试都会问。
我的回答思路是:微服务是一种架构风格,把一个大型的单体应用拆分成多个小型的、独立的服务,每个服务运行在自己的进程中,服务之间通过轻量级的机制通信,通常是HTTP REST API或者消息队列。每个服务围绕具体的业务能力构建,并且可以独立部署、独立扩展、独立技术栈。
和单体架构的区别主要有:
- 单体架构是把所有功能都放在一个应用里,一起部署一起扩展;微服务是把功能拆分成多个服务,每个服务独立部署独立扩展。
- 单体架构技术栈统一,所有模块用同一种技术;微服务每个服务可以用不同的技术栈,更灵活。
- 单体架构修改一个小功能就要重新部署整个应用,影响范围大;微服务修改一个服务只需要部署那个服务,影响范围小。
- 单体架构数据库通常是一个,所有模块共享;微服务每个服务可以有自己的数据库,数据独立。
- 单体架构架构简单,适合小型项目;微服务架构复杂,需要处理分布式系统的各种问题,适合大型项目。
问题2:微服务有什么优缺点?
优点:
- 服务独立,每个服务可以独立开发、独立部署、独立扩展,开发效率高。
- 技术栈灵活,每个服务可以用最适合的技术,不用被统一技术栈限制。
- 故障隔离,一个服务出问题不会影响整个系统,系统的可用性更高。
- 易于扩展,哪个服务压力大就扩展哪个服务,不用整个应用一起扩展,资源利用率高。
- 团队独立,每个团队负责一个或几个服务,职责清晰,沟通成本低。
缺点:
- 架构复杂,分布式系统本身就很复杂,需要处理网络延迟、分布式事务、服务发现、负载均衡等各种问题。
- 运维成本高,服务数量多,需要部署、监控、管理的东西也多,对运维的要求很高。
- 调试困难,一个请求可能经过多个服务,出问题的时候排查起来很麻烦,需要链路追踪等工具支持。
- 数据一致性难,每个服务有自己的数据库,跨服务的数据一致性很难保证,需要用分布式事务或者最终一致性。
- 服务间通信开销,服务之间通过网络通信,有网络延迟和带宽开销,性能不如单体架构的本地调用。
问题3:什么样的项目适合用微服务?
不是所有项目都适合用微服务,微服务也不是银弹。适合用微服务的项目通常有这些特点:
- 项目规模大,业务复杂,团队人数多,单体架构已经难以维护和扩展。
- 业务模块之间相对独立,拆分之后耦合度低,不会有太多跨服务的调用。
- 对可用性和扩展性要求高,需要某个模块独立扩展或者独立部署。
- 团队有足够的技术能力,能处理分布式系统的各种问题,有完善的运维和监控体系。
不适合用微服务的项目:
- 项目规模小,业务简单,团队人数少,用单体架构更简单高效。
- 业务模块之间耦合度很高,拆分之后会有大量的跨服务调用,反而增加了复杂度。
- 团队技术能力不足,没有分布式系统的经验,也没有完善的运维和监控体系,用微服务反而会出很多问题。
我的建议是,不要为了微服务而微服务,先从单体架构开始,等业务发展到一定规模,单体架构确实遇到瓶颈了,再考虑拆分成微服务,而且要循序渐进,不要一下子全拆了。
二、服务拆分
问题4:微服务怎么拆分?拆分的原则是什么?
服务拆分是微服务架构中最重要也最难的一步,拆得不好,后面会有很多问题。
拆分的原则主要有:
- 单一职责原则,每个服务只负责一个业务领域的功能,职责清晰,不要把不相关的功能放在一个服务里。
- 高内聚低耦合,服务内部的功能紧密相关,服务之间的耦合度尽量低,减少跨服务的调用。
- 按业务能力拆分,按照业务领域来拆分服务,比如订单服务、用户服务、商品服务、支付服务等,而不是按技术层拆分。
- 独立部署独立扩展,每个服务应该能独立部署和扩展,不会因为部署一个服务而影响其他服务。
- 数据独立,每个服务有自己的数据库,不要共享数据库,服务之间通过接口交互数据。
- 拆分粒度适中,不要拆得太粗,也不要拆得太细,太粗了就和单体差不多,太细了服务数量太多,运维和管理成本很高。
具体的拆分方法,可以用领域驱动设计(DDD)的方法,先识别业务领域,划分限界上下文,每个限界上下文对应一个微服务。也可以先从单体架构开始,随着业务的发展,逐步把一些独立的模块拆分成微服务,这样更稳妥。
问题5:服务拆分的时候,怎么处理跨服务的查询和事务?
跨服务的查询:
- 可以用API网关做聚合,网关调用多个服务,把结果聚合之后返回给前端,这样前端只需要调用一次。
- 可以用数据冗余,把一些需要频繁查询的数据冗余到需要的服务里,通过事件同步更新,避免跨服务查询。
- 可以用CQRS模式,命令和查询分离,查询的时候直接查冗余的读库,不用跨服务调用。
跨服务的事务:
- 尽量避免跨服务的事务,在拆分的时候就尽量把需要事务的功能放在同一个服务里。
- 如果确实需要跨服务事务,可以用分布式事务的方案,比如两阶段提交(2PC)、三阶段提交(3PC)、TCC(Try-Confirm-Cancel)、Saga模式等。
- 对于一致性要求不高的场景,可以用最终一致性,通过消息队列或者事件驱动的方式,保证数据最终一致,不用强一致性。
我的建议是,尽量避免分布式事务,因为分布式事务复杂度高,性能差,能不用就不用。在服务拆分的时候,就考虑好事务的边界,把需要强一致性的功能放在同一个服务里,跨服务的用最终一致性。
三、服务注册与发现
问题6:什么是服务注册与发现?为什么需要?
在微服务架构中,服务数量很多,每个服务可能有多个实例,实例的地址可能会动态变化,比如服务重启、扩容、缩容等。如果服务之间调用的时候,写死对方的地址,那么对方地址变化的时候,就要修改代码重新部署,很不方便。
服务注册与发现就是用来解决这个问题的。服务启动的时候,把自己的地址和端口注册到注册中心,注册中心维护所有服务的地址列表。服务调用的时候,先从注册中心获取目标服务的地址列表,然后根据负载均衡策略选择一个地址进行调用。如果服务实例下线了,注册中心会把它从地址列表中移除,这样就不会调用到已经下线的实例。
常见的注册中心有Eureka、Nacos、Consul、Zookeeper等。
问题7:Eureka、Nacos、Consul、Zookeeper有什么区别?怎么选?
这几个注册中心的区别主要在一致性模型、功能特性、性能等方面。
Eureka:是Netflix开源的,AP模型,保证可用性,不保证强一致性,节点之间是对等的,没有主从。功能比较单一,主要就是服务注册与发现,不支持配置中心。现在已经停止维护了,不太推荐新项目使用。
Nacos:是阿里开源的,既支持AP也支持CP,可以切换。功能很丰富,不仅支持服务注册与发现,还支持配置中心,支持DNS和RPC两种服务发现模式,支持权重、灰度、流量保护等高级功能。性能很好,支持大规模的服务实例。现在很流行,推荐使用。
Consul:是HashiCorp开源的,CP模型,保证强一致性,用Raft算法选主。功能也比较丰富,支持服务注册与发现、配置中心、健康检查、KV存储等,还支持多数据中心。性能也不错,但是比Nacos稍差一些。
Zookeeper:是Apache开源的,CP模型,保证强一致性,用ZAB算法。 originally是用来做分布式协调的,也可以用来做注册中心,但是不是专门为注册中心设计的,性能和功能都不如专门的注册中心,而且不支持健康检查,需要自己实现。现在不太推荐用Zookeeper做注册中心,Dubbo以前默认用Zookeeper,现在也支持Nacos了。
怎么选:如果是新项目,推荐用Nacos,功能丰富,性能好,国内用的人多,文档和资料也多。如果已经在用Consul的生态,或者需要多数据中心,可以用Consul。如果是老项目用Eureka,可以继续用,但是不建议新项目用。Zookeeper就不推荐做注册中心了。
四、服务通信
问题8:微服务之间的通信方式有哪些?怎么选?
微服务之间的通信方式,主要分为同步通信和异步通信两大类。
同步通信:
- REST HTTP:最常用的方式,用HTTP协议,JSON格式,简单易用,跨语言,调试方便,但是性能一般,因为HTTP协议开销比较大。
- gRPC:基于HTTP/2,用Protobuf序列化,性能好,效率高,支持流式通信,但是需要定义IDL,学习成本稍高,调试不如REST方便。
- Dubbo RPC:阿里开源的RPC框架,用自定义的TCP协议,性能很好,支持多种序列化方式,但是主要是Java生态,跨语言支持不好。
异步通信:
- 消息队列:用Kafka、RocketMQ、RabbitMQ等消息队列,服务之间通过消息异步通信,解耦,削峰填谷,但是有消息延迟,不能立即得到结果。
- 事件驱动:基于事件的架构,服务发布事件,其他服务订阅事件,松耦合,扩展性好,但是调试和排查问题比较困难。
怎么选:
- 如果需要立即得到响应,比如查询接口,用同步通信,REST或者gRPC。
- 如果不需要立即响应,比如通知、日志、数据同步等,用异步通信,消息队列。
- 如果是内部服务之间的调用,对性能要求高,可以用gRPC或者Dubbo。
- 如果需要跨语言,或者对外提供接口,用REST HTTP更通用。
- 如果需要解耦和削峰,用消息队列。
我的建议是,大部分场景用REST HTTP就够了,简单易用,调试方便。对性能要求特别高的内部调用,可以考虑gRPC。异步的场景用消息队列。不要为了用某个技术而用,根据实际场景选择。
问题9:REST和gRPC有什么区别?
主要区别:
- 协议:REST用HTTP/1.1,gRPC用HTTP/2,HTTP/2支持多路复用、头部压缩、流式通信,性能更好。
- 序列化:REST通常用JSON,文本格式,可读性好,但是序列化效率低,体积大;gRPC用Protobuf,二进制格式,序列化效率高,体积小,但是可读性差。
- 性能:gRPC性能比REST好很多,因为HTTP/2和Protobuf的开销小,连接可以复用。
- 易用性:REST更简单易用,不用定义IDL,直接写接口就行,调试也方便,用浏览器或者curl就能调;gRPC需要定义proto文件,生成代码,学习成本稍高,调试需要专门的工具。
- 流式通信:gRPC支持四种流式通信模式(一元、服务端流、客户端流、双向流),REST不支持原生的流式通信,只能用SSE或者WebSocket。
- 浏览器支持:REST天然支持浏览器,gRPC需要用gRPC-Web才能在浏览器里用,支持不如REST好。
怎么选:内部服务之间的高性能调用,用gRPC;对外提供接口,或者需要浏览器调用,用REST。
五、负载均衡
问题10:什么是负载均衡?有哪些负载均衡策略?
负载均衡就是把请求分发到多个服务实例上,让每个实例的负载尽量均衡,提高系统的吞吐量和可用性。
常见的负载均衡策略:
- 轮询(Round Robin):按顺序依次分配给每个实例,简单公平,适合所有实例性能差不多的情况。
- 加权轮询(Weighted Round Robin):给每个实例设置权重,权重高的分配更多的请求,适合实例性能不一样的情况。
- 随机(Random):随机分配给一个实例,简单,但是可能不均匀。
- 最少连接(Least Connections):分配给当前连接数最少的实例,适合请求处理时间差异大的情况。
- 一致性哈希(Consistent Hash):根据请求的某个特征(比如用户ID)哈希,相同特征的请求总是分配到同一个实例,适合需要会话保持的场景,而且实例增减的时候影响范围小。
- 最快响应(Fastest Response):分配给响应时间最短的实例,适合对响应时间敏感的场景。
负载均衡又分为服务端负载均衡和客户端负载均衡。服务端负载均衡是在服务端做,比如Nginx、F5,客户端不知道有多少实例,所有请求都发到负载均衡器,由负载均衡器分发。客户端负载均衡是在客户端做,比如Ribbon、Spring Cloud LoadBalancer,客户端从注册中心获取实例列表,然后自己选择一个实例调用,不需要中间的负载均衡器。
微服务架构中,通常用客户端负载均衡,因为服务实例是动态变化的,客户端负载均衡更灵活,而且少了一层网络开销。
六、服务熔断与降级
问题11:什么是服务熔断?什么是服务降级?有什么区别?
服务熔断和降级都是用来提高系统可用性的,防止雪崩效应,但是它们的侧重点不一样。
服务熔断:是指当某个服务出现故障,响应慢或者错误率高的时候,调用方为了保护自己,不再调用这个服务,直接返回错误或者默认值,等服务恢复了再恢复调用。就像电路中的保险丝,电流过大的时候自动断开,保护电路。熔断通常是自动的,根据错误率、响应时间等指标自动触发和恢复。
服务降级:是指当系统压力大的时候,为了保证核心功能的可用性,主动关闭一些非核心功能,或者降低非核心功能的服务质量,把资源让给核心功能。比如电商大促的时候,关闭评论、推荐等非核心功能,保证下单、支付等核心功能正常。降级通常是主动的,可以是自动触发,也可以是手动开关。
区别:
- 熔断是调用方的自我保护,因为被调用方出问题了,所以不调用了;降级是系统的整体保护,因为系统压力大,所以主动关闭一些功能。
- 熔断是被动触发的,因为被调用方出问题了才触发;降级可以是主动的,也可以是被动的。
- 熔断通常是在调用链路层面,针对某个服务;降级通常是在业务层面,针对某个功能。
常见的熔断和降级框架有Hystrix、Resilience4j、Sentinel等。Hystrix已经停止维护了,现在推荐用Resilience4j或者Sentinel,Sentinel是阿里开源的,功能更丰富,国内用的人多。
问题12:什么是雪崩效应?怎么避免?
雪崩效应是指在微服务架构中,一个服务出问题,导致调用它的服务也出问题,然后一层一层往上传,最终导致整个系统都不可用,就像雪崩一样。
比如,用户服务出问题了,响应很慢,订单服务调用用户服务的时候,线程都阻塞在等待用户服务响应,订单服务的线程池满了,也无法处理其他请求了,然后调用订单服务的支付服务也出现同样的问题,最后整个系统都不可用了。
避免雪崩效应的方法:
- 服务熔断:当某个服务出问题的时候,调用方自动熔断,不再调用,保护自己。
- 服务降级:系统压力大的时候,主动关闭非核心功能,保证核心功能。
- 超时设置:调用其他服务的时候,设置合理的超时时间,不要无限等待,避免线程被长时间占用。
- 限流:对服务的请求量进行限制,超过阈值就拒绝或者排队,防止服务被打垮。
- 线程池隔离:不同的服务调用用不同的线程池,一个服务出问题不会耗尽所有线程,不影响其他服务的调用。
- 舱壁模式:和线程池隔离类似,把系统资源隔离开,一个部分出问题不影响其他部分。
七、分布式事务
问题13:什么是分布式事务?有哪些解决方案?
分布式事务是指在分布式系统中,一个业务操作涉及多个服务或者多个数据库,需要保证这些操作要么全部成功,要么全部失败,保证数据的一致性。
常见的分布式事务解决方案:
- 两阶段提交(2PC):有一个事务协调者,第一阶段,协调者问所有参与者能不能提交,参与者执行事务但是不提交,返回可以或者不可以;第二阶段,如果所有参与者都返回可以,协调者让所有参与者提交,否则让所有参与者回滚。优点是强一致性,缺点是同步阻塞,性能差,协调者单点故障,可能出现数据不一致。
- 三阶段提交(3PC):在2PC的基础上增加了一个阶段,分为CanCommit、PreCommit、DoCommit三个阶段,解决了2PC的同步阻塞问题,但是还是有协调者单点和数据不一致的问题,而且更复杂,实际用的不多。
- TCC(Try-Confirm-Cancel):把事务分成三个阶段,Try阶段尝试预留资源,Confirm阶段确认提交,Cancel阶段取消回滚。每个服务都要实现这三个接口,由事务管理器协调。优点是性能好,没有锁,缺点是开发成本高,每个服务都要写三个接口,而且要处理幂等、空回滚、悬挂等问题。
- Saga模式:把一个长事务拆分成多个本地事务,每个本地事务有对应的补偿操作,按顺序执行,如果某个步骤失败了,就按相反的顺序执行补偿操作,回滚之前的操作。优点是性能好,没有长事务,适合长流程的业务,缺点是只能保证最终一致性,不能保证隔离性,可能出现脏读,而且补偿操作开发成本高。
- 本地消息表:在本地事务里,把业务操作和消息记录放在同一个本地事务里,然后异步把消息发送到消息队列,消费者消费消息执行后续操作。如果消息发送失败,定时任务重试,保证最终一致性。优点是简单易用,性能好,缺点是消息表和业务表耦合,只适合最终一致性的场景。
- 事务消息:RocketMQ支持事务消息,和本地消息表类似,但是把消息存在消息队列里,不用本地消息表,通过事务回查机制保证消息和本地事务的一致性。优点是不用维护本地消息表,更优雅,缺点是依赖支持事务消息的消息队列。
怎么选:
- 对一致性要求特别高的场景,而且服务数量少,可以用2PC或者TCC。
- 长流程的业务,对一致性要求不是特别高,可以用Saga模式。
- 大部分业务场景,用最终一致性就够了,可以用本地消息表或者事务消息,简单实用。
我的建议是,尽量避免分布式事务,在服务拆分的时候就把需要强一致性的功能放在同一个服务里。如果确实需要跨服务,优先用最终一致性,不要追求强一致性,因为强一致性的分布式事务性能差,复杂度高。
八、API网关
问题14:什么是API网关?有什么作用?
API网关是微服务架构中的一个统一入口,所有的外部请求都先经过API网关,然后由网关转发到对应的服务。
API网关的作用:
- 路由转发:把请求转发到对应的后端服务,客户端不用知道每个服务的地址,只需要知道网关的地址就行。
- 负载均衡:网关可以对后端服务做负载均衡,把请求分发到多个实例。
- 统一认证授权:在网关层统一做登录验证、权限校验,不用每个服务都做一遍。
- 限流熔断:在网关层做限流和熔断,保护后端服务,防止被打垮。
- 日志监控:在网关层统一记录请求日志,做监控统计,不用每个服务都做。
- 协议转换:可以把外部的HTTP请求转换成内部的gRPC或者Dubbo调用,或者反过来。
- 请求聚合:可以把多个后端服务的结果聚合起来返回给客户端,减少客户端的调用次数。
- 灰度发布:可以在网关层做灰度发布,把一部分流量导到新版本,验证没问题再全量发布。
常见的API网关有Nginx、Kong、Spring Cloud Gateway、Zuul、APISIX等。Zuul1已经比较老了,性能差,现在推荐用Spring Cloud Gateway或者Kong、APISIX,这些都是基于异步非阻塞的,性能好。
九、配置中心
问题15:什么是配置中心?为什么需要?
配置中心就是用来统一管理所有服务的配置的地方。微服务架构中,服务数量多,每个服务都有自己的配置,如果配置都写在代码里或者配置文件里,修改配置就要重新打包部署,很不方便,而且不同环境的配置也不好管理。
配置中心的作用:
- 统一管理:所有服务的配置都放在配置中心,统一管理,方便查找和修改。
- 动态刷新:修改配置之后,不需要重新部署,服务能自动感知配置变化,动态刷新,很方便。
- 环境隔离:不同环境(开发、测试、生产)的配置分开管理,互不影响。
- 版本管理:配置的修改有历史记录,可以查看和回滚,出了问题可以快速回滚到之前的版本。
- 权限控制:配置的修改有权限控制,不是谁都能改,防止误操作。
- 加密存储:敏感配置(比如数据库密码)可以加密存储,更安全。
常见的配置中心有Nacos、Apollo、Consul、Spring Cloud Config等。Nacos和Apollo功能都比较完善,国内用的人多,推荐使用。Spring Cloud Config功能比较简单,需要配合Git使用,不太推荐。
十、链路追踪
问题16:什么是链路追踪?为什么需要?
链路追踪是用来追踪一个请求在微服务架构中的完整调用链路的。在微服务架构中,一个请求可能经过多个服务,出问题的时候,很难定位是哪个服务出了问题,也很难知道每个服务的耗时和调用关系。链路追踪就是用来解决这个问题的。
链路追踪的原理是,给每个请求分配一个唯一的TraceID,请求经过每个服务的时候,都带上这个TraceID,同时生成一个SpanID记录当前服务的调用,服务之间调用的时候,把TraceID和SpanID传过去,这样就能把整个调用链路串起来。
链路追踪的作用:
- 问题定位:出问题的时候,根据TraceID就能看到整个调用链路,快速定位是哪个服务出了问题。
- 性能分析:可以看到每个服务的耗时,找到性能瓶颈,优化慢的服务。
- 依赖分析:可以看到服务之间的调用关系,了解系统的依赖结构。
- 错误统计:可以统计每个服务的错误率,发现有问题的服务。
常见的链路追踪工具和规范有Zipkin、Jaeger、SkyWalking、OpenTelemetry等。SkyWalking是国产的,功能丰富,对Java生态支持好,国内用的人多,推荐使用。OpenTelemetry是现在的标准,越来越多的工具支持。
十一、监控告警
问题17:微服务架构的监控要监控哪些东西?
微服务架构的监控,比单体架构复杂很多,需要监控的东西也多,主要包括:
- 基础设施监控:服务器的CPU、内存、磁盘、网络等,还有容器、K8s的状态。
- 中间件监控:数据库、缓存、消息队列、注册中心、配置中心等中间件的状态和性能指标。
- 服务监控:每个服务的QPS、响应时间、错误率、线程池、JVM指标(如果是Java)等。
- 业务监控:业务指标,比如订单量、支付成功率、用户活跃度等,和业务相关的指标。
- 链路监控:调用链路的追踪,每个服务的耗时和错误情况。
- 日志监控:集中收集和分析所有服务的日志,方便查询和告警。
监控工具常用的有Prometheus+Grafana做指标监控,ELK(Elasticsearch+Logstash+Kibana)或者Loki做日志监控,SkyWalking或者Jaeger做链路追踪,Alertmanager做告警。
告警很重要,监控到异常之后要及时告警,通知相关人员处理,避免小问题变成大故障。告警要分级,不同级别的告警用不同的通知方式,比如紧急的打电话或者短信,一般的发邮件或者企业微信。还要避免告警风暴,不要什么都告警,只告警真正需要处理的问题。
十二、容器化部署
问题18:微服务为什么通常和Docker、K8s一起用?
微服务和Docker、K8s是天生一对,因为微服务的服务数量多,如果每个服务都手动部署和管理,运维成本会非常高。Docker和K8s能很好地解决微服务的部署和运维问题。
Docker的作用:
- 环境一致性:把应用和依赖打包成镜像,在任何环境运行都是一样的,不会出现"在我机器上能跑"的问题。
- 快速部署:镜像启动很快,秒级启动,部署和扩容都很快。
- 资源隔离:每个容器运行在独立的环境,互不影响,一个服务出问题不会影响其他服务。
- 镜像管理:镜像可以版本管理,回滚方便,出了问题可以快速回滚到之前的版本。
K8s的作用:
- 服务编排:管理大量的容器,自动调度容器到合适的节点上。
- 自动伸缩:根据负载自动扩容缩容,高峰期自动加实例,低峰期自动减实例,节省资源。
- 自愈能力:容器挂了自动重启,节点挂了自动把容器迁移到其他节点,保证服务可用。
- 服务发现和负载均衡:内置服务发现和负载均衡,不用额外部署注册中心和负载均衡器。
- 滚动更新和回滚:支持滚动更新,发布新版本不影响业务,出了问题可以快速回滚。
- 配置和密钥管理:内置ConfigMap和Secret,管理配置和敏感信息。
所以,微服务+Docker+K8s是现在的标准组合,Docker解决打包和环境问题,K8s解决部署和运维问题,微服务解决架构和开发问题,三者结合,才能充分发挥微服务的优势。
十三、写在最后
以上就是我面试中被问到的微服务相关的问题,以及我的回答思路,涵盖了微服务的基础概念、服务拆分、服务注册与发现、服务通信、负载均衡、熔断降级、分布式事务、API网关、配置中心、链路追踪、监控告警、容器化部署等各个方面,几乎是微服务的全景了。
当然,微服务是一个非常庞大和复杂的领域,还有很多细节和深入的内容,这篇文章只是一个面试题的整理,每个点都没有展开太细。如果想深入学习,还需要看更多的资料,做更多的实践。
面试的时候,回答这些问题,不要只背概念,要结合自己的实际项目经验,说说你在项目中是怎么做的,遇到了什么问题,怎么解决的,这样回答才更有说服力,也更能体现你的实际能力。
最后,祝正在准备面试的朋友都能拿到心仪的offer,也祝正在学习微服务的朋友都能学有所成。如果这篇文章对你有帮助,欢迎分享给更多的人。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录