三面美团成功斩获offer,分享面经:Spring+Dubbo+Redis+Zookeeper+微服务

181 阅读13分钟

前言:

一线大厂一直是互联网人包括程序员梦寐以求的公司,苦于BAT大厂的进入门槛太高,无奈只能望门兴叹,所以只能苦练技能才能有机会去敲开BAT的大门。下面是一位Java程序员的亲身经历三面美团拿下了offer,特献上面试真题,以供参考学习。


第一部分. Spring专题

1、Spring怎样定义类的作用域

通过bean 定义中的scope属性来定义。

2、Spring支持的几种bean的作用域

支持以下五种bean的作用域:

  • singleton : bean在每个Spring ioc 容器中只有一个实例。(缺省默认)
  • prototype:一个bean的定义可以有多个实例。
  • request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
  • session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
  • global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

3、Spring支持的事务管理类型

  • 编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。
  • 声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需用注解和XML配置来管理事务。

4、什么是控制反转(IOC)?什么是依赖注入?

  • 控制反转(IOC) : 传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,现在由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是控制反转。
  • 依赖注入:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
  • 实现方式:构造器注入、Setter方法注入、接口注入。注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在Spring配置文件中配置 <context:annotation-config/>元素。

5、Spring由几大核心组件?

  • Bean 组件
  • Context 组件
  • Core 组件

6、Spring MVC核心工作流程 ?

  • 用户向服务器发送request请求,请求被SpringMVC中央控制器DispatcherServlet捕获;
  • DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping映射处理器,将请求发送给指定的Controller。
  • Controller执行完成后,将返回的数据信息封装到ModelAndView对象中,最后通过ViewResolver视图解析器选择一个合适的View 渲染视图返回界面。

7、spring事务隔离级别(五种面试最好全部说出来)

  • DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
  • 未提交读(read uncommited) : 脏读,不可重复读,虚读都有可能发生 。是最低的事务隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。
  • 已提交读 (read commited): 避免脏读。但是不可重复读、虚读有可能发生 。保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。Oracle 默认
  • 可重复读 (repeatable read): 这种事务隔离级别可以防止脏读,不可重复读。但是可能会出现幻象读。它除了保证一个事务不能被另外一个事务读取未提交的数据之外还避免了以下情况产生(不可重复读)。Mysql 默认
  • 串行化的 (serializable) : 这是花费最高代价、效率差但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读之外,还避免了幻象读(避免三种)。

8、Spring事务特性(四种面试最好全部说出来)

  • 原子性 (atomicity): 一个事务中所有对数据库的操作是一个不可分割的操作序列,要么全做要么全不做。
  • 一致性 (consistency): 事务的执行的前后数据的完整性保持一致.
  • 隔离性 (isolation): 一个事务执行的过程中,不应该受到其他事务的干扰
  • 持久性(durability) : 一个事物一旦提交,它对数据库的改变就是永久的

9、Spring事务七个传播特性(七种面试说一两个即可)

  • Propagation.REQUIRED (默认) 面试必须说出来这个。调用方已经存在事务,则加入到同一个事务中运行,否则,自启一个事务
  • Propagation.REQUIRES_NEW。无论何时自身都会开启新事务
  • Propagation.SUPPORTS。调用方存在事务,则加入到同一个事务中运行,若不存在事务,则以非事务的方式运行
  • Propagation.NOT_SUPPORTED。调用方存在事务,则会被挂起,直到被调用方运行完毕后,事务恢复。
  • Propagation.MANDATORY。调用方存在事务,则加入到同一个事务中运行,若不存在,则抛出异常
  • Propagation.NEVER。调用方存在事务,则抛出异常
  • Propagation.NESTED。若调用方存在事务,则运行一个嵌套事务,若调用方不存在事务,则以Propagation.REQUIRED的方式运行,即开启一个新的事务

10、简述Spring Bean的生命周期

实例化、初始化、使用、销毁。

关键词:BeanFactoryPostProcessor 、BeanPostProcessor 、init-method/destroy-method

第二部分. Dubbo面试专题

1、Dubbo的容错机制有哪些?

Dubbo官网提出总共有六种容错策略

  • Failover Cluster模式:失败自动切换,当出现失败,重试其它服务器。(默认)
  • Failfast Cluster:快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
  • Failsafe Cluster:失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
  • Failback Cluster:失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
  • Forking Cluster:并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过forks=”2”来设置最大并行数。
  • Broadcast Cluster:广播调用所有提供者,逐个调用,任意一台报错则报错。(2.1.0开始支持)通常用于通知所有提供者更新缓存或日志等本地资源信息。

总结:在实际应用中查询语句容错策略建议使用默认Failover Cluster,而增删改建议使用Failfast Cluster或者使用Failover Cluster(retries=”0”)策略防止出现数据重复添加等等其它问题。建议在设计接口时候把查询接口方法单独做一个接口提供查询。

2、使用dubbo遇到过哪些问题?

增加提供服务版本号和消费服务版本号

这个具体来说不算是一个问题,而是一种问题的解决方案,在我们的实际工作中会面临各种环境资源短缺的问题,也是很实际的问题,刚开始我们还可以提供一个服务进行相关的开发和测试,但是当有多个环境多个版本,多个任务的时候就不满足我们的需求,这时候我们可以通过给提供方增加版本的方式来区分.这样能够剩下很多的物理资源,同时为今后更换接口定义发布在线时,可不停机发布,使用版本号.引用只会找相应版本的服务,例如:

 

<dubbo:serviceinterface="com.xxx.XxxService" ref="xxxService" version="1.0"/>
<dubbo:referenceid="xxxService" interface="com.xxx.XxxService" version="1.0"/>

3、dubbo reference注解问题?

@Reference只能在SpringBean实例对应的当前类中使用,暂时无法在父类使用;如果确实要在父类声明一个引用,可通过配置文件配置dubbo:reference,然后在需要引用的地方跟引用SpringBean一样就可以了.

4、出现RpcException:No provider available for remote service异常怎么办?

  • 检查连接的注册中心是否正确
  • 到注册中心查看相应的服务提供者是否存在
  • 检查服务提供者是否正常运行

5、服务提供者没挂,但在注册中心里看不到?

首先,确认服务提供者是否连接了正确的注册中心,不只是检查配置中的注册中心地址,而且要检查实际的网络连接。

其次,看服务提供者是否非常繁忙,比如压力测试,以至于没有CPU片段向注册中心发送心跳,这种情况减小压力将自动恢复。

6、Dubbo的连接方式有哪些?

Dubbo的客户端和服务端有三种连接方式,分别是:广播,直连和使用zookeeper注册中心。

7、Dubbo广播

这种方式是dubbo官方入门程序所使用的连接方式,但是这种方式有很多问题。在企业开发中,不使用广播的方式。taotao-manager服务端配置:

 

!-- applicationContext-service.xml 文件中 -->
<!-- 提供方应用信息,用于计算机依赖关系 -->
<dubbo:application name="taotao-manager-service” />
<!-- 使用 multicast 广播暴露服务地址 -->
<dubbo:registry address="multicast://224.5.6.71234" />
<!-- 使用 dubbo 协议在 20880 协议暴露服务 -->
<dubboprotocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.taotao.manager.service.TestService" ref="testServiceImpl" />

第三部分. Redis专题

1.什么是Redis?

答:Remote Dictionary Server(Redis)是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

2.Redis的特点什么是?

  • 支持多种数据结构,如 string(字符串)、 list(双向链表)、dict(hash表)、set(集合)、zset(排序set)、hyperloglog(基数估算)
  • 支持持久化操作,可以进行aof及rdb数据持久化到磁盘,从而进行数据备份或数据恢复等操作,较好的防止数据丢失的手段。
  • 支持通过Replication进行数据复制,通过master-slave机制,可以实时进行数据的同步复制,支持多级复制和增量复制,master-slave机制是Redis进行HA的重要手段。
    单进程请求,所有命令串行执行,并发情况下不需要考虑数据一致性问题。

3.Redis数据类型有哪些?

答:

  • String(字符串)
  • Hash(hash表)
  • List(链表)
  • Set(集合)
  • SortedSet(有序集合zset)

4. Redis的配置以及持久化方案有几种?

答:以下两种

  • RDB方式
  • AOF方式

第四部分. Zookeeper专题

1. Zookeeper是什么框架

分布式的、开源的分布式应用程序协调服务,原本是Hadoop、HBase的一个重要组件。

应用场景:Zookeeper的功能很强大,应用场景很多,结合我实际工作中使用Dubbo框架的情况,Zookeeper主要是做注册中心用。

基于Dubbo框架开发的提供者、消费者都向Zookeeper注册自己的URL,消费者还能拿到并订阅提供者的注册URL,以便在后续程序的执行中去调用提供者。而提供者发生了变动,也会通过Zookeeper向订阅的消费者发送通知。

2. Zookeeper有哪几种节点类型

  • 持久:创建之后一直存在,除非有删除操作,创建节点的客户端会话失效也不影响此节点。
  • 持久顺序:跟持久一样,就是父节点在创建下一级子节点的时候,记录每个子节点创建的先后顺序,会给每个子节点名加上一个数字后缀。
  • 临时:创建客户端会话失效(注意是会话失效,不是连接断了),节点也就没了。不能建子节点。
  • 临时顺序:不用解释了吧。

3. Zookeeper对节点的watch监听通知是永久的吗?

不是。

官方声明:一个Watch事件是一个一次性的触发器,当被设置了Watch的数据发生了改变的时候,则服务器将这个改变发送给设置了Watch的客户端,以便通知它们。

为什么不是永久的,举个例子,如果服务端变动频繁,而监听的客户端很多情况下,每次变动都要通知到所有的客户端,这太消耗性能了。

一般是客户端执行getData(“/节点A”,true),如果节点A发生了变更或删除,客户端会得到它的watch事件,但是在之后节点A又发生了变更,而客户端又没有设置watch事件,就不再给客户端发送。

在实际应用中,很多情况下,我们的客户端不需要知道服务端的每一次变动,我只要最新的数据即可。

4. Zookeeper集群如果有3台机器,挂掉一台集群还能工作吗?挂掉两台呢?

记住一个原则:过半存活即可用。

集群支持动态添加机器吗

其实就是水平扩容了,Zookeeper在这方面不太好。两种方式:

  • 全部重启:关闭所有Zookeeper服务,修改配置之后启动。不影响之前客户端的会话。
  • 逐个重启:顾名思义。这是比较常用的方式。

第五部分. 微服务专题

1. 为什么要使用微服务跟踪?它解决了什么问题?

1. 微服务调用的现状?

  • 微服务的现状:随着业务的发展,单体架构变为微服务架构,并且系统规模也变得越来越大,各微服务间的调用关系也变得越来越复杂。
  • 多服务协同工作:在微服务的应用中,一个由客户端发起的请求在后端系统中会经过多个不同的微服务调用来协同产生最后的请求结果。
  • 复杂的调用链条容易出错:在复杂的微服务架构系统中,几乎每一个前端请求都会形成一-个复杂的分布式服务调用链路,在每条链路中任何一个依赖服务出现延迟超时或者错误都有可能引起整个请求最后的失败。

2. 微服务跟踪解决了什么问题?

微服务跟踪其实是一个工具,它在整个分布式系统中能跟踪一个用户请求的过程(包括数据采集、数据传输、数据存储、数据分析、数据可视化) ,捕获这些跟踪数据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。

Spring Cloud S1euth有4个特点:

  • 提供链路追踪:通过sleuth可以很清楚的看出一-个请求都经过了哪些服务。可以很方便的理清服务间的调用关系。
  • 性能分析:通过sleuth可以很方便的看出每个采样请求的耗时,分析出哪些服务调用比较耗时。当服务调用的耗时随着请求量的增大而增大时,也可以对服务的扩容提供- -定的提醒作用。
  • 数据分析,优化链路:对于频繁地调用一个服务,或者并行地调用等,可以针对业务做一些优化措施。
  • 可视化错误:对于程序未捕捉的异常,可以在zipkin界面上看到。

写在最后:

限于篇幅,文中只展示了部分的面试题,完整的面试题笔者已经整理成了一份PDF文件需要这份面试题的朋友关注下方公众号 即可领取完整的面试专题文件

以下是部分面试题截图