职场面试题总结(06)---Feign远程调用、服务内如何进行接口调用、JVM底层原理、消息队列重复消费问题

398 阅读5分钟

1、Feign远程调用如何实现?服务不可用熔断如何实现?

简介 Feign是Netflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API。

在Spring Cloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了。Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。

Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。

Spring Cloud Feign是基于Netflix feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供这两者的强大功能外,还提供了一种声明式的Web服务客户端定义的方式。

实现步骤:

(1)导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--由于feign整合了ribbon的负载均衡,所以需要引入ribbon的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>
<!--需要从eureka拉取服务-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-netflix-eureka-client</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>

(2)启动类添加注解支持

@EnableFeignClients

(3)客户端编写

 //定义接口
    package com.sun.client;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping; 
    @FeignClient(value = "user-service")   //声明这是feign的客户端
    public interface UserFeignClient {
        @GetMapping("user")
        public String getUser();
    }

注释:这是一个接口,Feign会通过动态代理,帮我们生成实现类。这点跟mybatis的mapper很像@FeignClient,声明这是一个Feign客户端,类似@Mapper注解。同时通过value属性指定服务名称接口中的定义方法,完全采用SpringMVC的注解,Feign会根据注解帮我们生成URL,并访问获取结果改造原来的调用逻辑,不再调用UserDao:

 //实现调用
    @Autowired
    private UserFeignClient userFeignClient;
    @GetMapping("feign")
    public Object feign(){
       return userFeignClient.getUser();
    }

(4)feign自动实现负载均衡

(5)feign的重试

#feign的重试与ribbon的配置相同,只要添加相应的配置即可。
client:
  ribbon:
      MaxAutoRetries: 1	#配置首台服务器重试1次
      MaxAutoRetriesNextServer: 2#配置其他服务器重试两次
      ConnectTimeout: 500    #链接超时时间
      ReadTimeout: 2000    #请求处理时间
      OkToRetryOnAllOperations: true    #每个操作都开启重试机制

(6)feign与hystrix的集成配置熔断机制

1)添加熔断配置

feign:
     hystrix:
         enabled: true     #允许熔断

2)添加熔断处理类

实现 UserFeignClient接口

3)实现调用

2、服务内如何进行接口调用?

Requestmaping方式调用

21、JVM底层原理 在这里插入图片描述

在这里插入图片描述

3、消息队列重复消费问题?

幂等性(如何避免消息的重复消费) 概述:可能因为各种原因,导致了生产端发送了多条一样的消息给消费端,但是,消费端也只能消费一条,不会多消费。

(1)唯一ID + 指纹码机制

指纹码(就是时间戳 + 业务的一些规则, 来保证id + 指纹码在同一时刻是唯一的,不会出现重复)

唯一ID + 指纹码机制,利用数据库主键去重;

select count(1) from t_order where id = 唯一ID + 指纹码;

好处:实现简单;

坏处:高并发下有数据库写入的瓶颈;

解决方案:跟进ID进行分库分表进行算法路由;

(2)利用Redis的原子性实现

存在的问题:

我们是否需要进行数据的持久化,若需要持久化,怎么保证数据库和redis做到原子性? 若不立即持久化,都存储到redis中,如何设置同步策略?

(3)设置前置条件

加一个版本号控制。

消息队列出现错误消息怎么办?

4、RabbitMQ

RabbitMQ简介

AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。

AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。 RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

组件 在这里插入图片描述

Vhost 在这里插入图片描述

5、分布式如何保证消息一致性?

发送方确认消息机制

采用最终一致性原理

需要保证以下三要素:

a、确保生产者一定要将数据投递到MQ服务器中(采用MQ消息确认机制)。

b、确保消费者能够正确消费消息,采用手动ACK模式(注意重试、幂等性问题)。

c、如何保证第一个事务先执行,采用补偿机制,在创建一个补单消费者进行监听,如果订单没有创建成功,进行补单。(如果第一个事务中出错,补单消费者会在重新执行一次第一个事务,例如第一个事务是添加订单表,如果失败在补单的时候重新生成订单记录,由于订单号唯一,所以不会重复)。

6、如何设置事务不被Spring管理?

@Transactional,表示该类受Spring事务管理。如果该类中每个方法不需要事务管理,则在该方法前加入下面的Java代码 :

@Transactional(propagation=Propagation.NOT_SUPPORTED)

7、List遍历随机删除一个会发生什么?

在这里插入图片描述

fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。

例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。

简单来说是java为了防止出现并发异常的一个机制,但是其实在单线程下也可以产生。 多线程操作list的话建议使用CopyOnWriteArrayList,或者对迭代器加锁。