面试题大全1.5-微服务部分

微服务部分

    • 三.微服务部分
      • 相关概念
        • 什么是集群 8-23
        • 什么是负载均衡 8-23
        • 什么是分布式 8-23
        • 分布式集群举例
        • 集群和分布式的区别,分别解决什么问题8-24
        • 说一下你理解的微服务8-24
        • 什么是CAP理论 , 哪些技术用到AP,哪些用到CP 8-24
        • 什么是强一致性和最终一致性 8-24
        • 什么是Base理论 8-25
        • 分布式是否属于微服务?
      • SpringCloud
        • 讲一下你们公司微服务解决方案8-25
        • 说一说Spring Cloud有哪些常用组件8-25
        • Spring Cloud的优缺点?8-25
        • 什么是服务注册 8-26
        • 什么是服务发现 8-26
        • 什么是服务续约 8-26
        • 如果服务挂了,注册中心要等到90s后剔除,那么在剔除前的这段时间内,挂掉的服务有可能还是会被调用,怎么处理? 8-26
        • 你知道EurekaClient服务发现和服务续约每隔30s做一次请求是用什么技术实现的吗? 8-27
        • Ribbon是什么,Ribbon的工作原理讲一下 8-27
        • 说一下 Ribbon的工作原理 8-27
        • Ribbon有哪些负载均衡算法,怎么配置 8-27
        • OpenFeign和Ribbon的区别 8-28
        • OpengFiegn的工作流程 8-28
        • 为什么要使用Eureka 为什么要使用Ribbon 为什么要使用config配置中心 8-28
        • 为什么Feign的客户端接口没有写实现类也可以直接被依赖注入 8-28
        • 介绍一下Hystrix 8-29
        • 什么是熔断,什么是降级 8-29
        • 什么是资源隔离? 8-29
        • 资源隔离中信号量和线程池的区别? 8-29
        • 对于CAP理论,Eureka选择的是AP还是CP?它保证了一致性还是可用性? 8-30
        • 说一下Eureka的自我保护 8-30
        • 你们项目是如何做服务降级的?8-30
        • Zuul有哪几类Filter,他们的执行顺序是怎么样的? 8-30
        • 在Zuul中做登录检查如何实现?8-31
        • 在Zuul中如何做限流?8-31
        • 配置中心解决什么问题? 8-31
        • EureakServer的搭建流程 8-31
        • Ribbon的整合流程 9-1
        • Feign的整合流程 9-1
        • Hystrix的整合流程 9-1
        • Zuul的整合流程 9-1
        • ConfigServer的整合流程 9-2
        • 你们微服务项目的技术栈描述一下 9-2
        • 浏览器发起一个请求,在你的微服务项目中的怎么去执行的? 9-2
        • 说下Ribbon和Feign的区别呢 9-2
        • Spring,SpringBoot和SpringCloud的关系以及区别 9-3
      • 分布式事务
        • 什么是分布式事务 9-3
        • 分布式事务你知道哪些解决方案? 这些方案如何选型 9-3
        • 什么是2pc 9-3
        • Seata相比传统2PC有什么区别,以及优点? 9-4
        • Seata的TC,TM,RM的含义,以及作用? 9-4
        • 你知道TCC吗,它有什么样的优缺点? 9-4
        • 解释一下Seata的工作原理 9-4
        • 你能简单描述一下你在项目中是如何集成Seata的吗 9-5
        • 没有Seata或者TCC这些事务框架,你可以怎么处理事务?9-5
      • 分布式锁
        • 你说一下什么是分布式锁 9-5
        • 分布式锁有哪些解决方案 9-5
        • Redis如何实现分布式锁,用什么命令
        • Redis实现分布式锁可能会出现什么问题,如何解决
        • 你项目中怎么使用分布式锁的
        • 了解Redission的看门狗原理吗?
        • 你在项目中如果使用ZK实现分布式锁的?
      • 秒杀系统
        • 秒杀的整体流程详细说一下
        • 你们这个秒杀QPS是多少
        • 你们是怎么保证这么高的QPS的
        • 如果流量更高,比如:每秒10W请求,应该怎么处理
        • 说一下支付超时处理方案?延迟队列和死信队列是什么意思?
        • 整个秒杀流程你用到了哪些队列
        • 秒杀成功,返回给用户的数据是什么?
        • 怎么防止表达重复提交
        • 你们怎么处理超卖
        • 如果一个接口需要耗时1s,导致后续的请求堵塞,怎么处理
        • 如何提高接口的qps
        • 项目并发高处理过不过来怎么办
      • 订单支付
        • 点击确认订单背后的业务流程
        • 你们使用支付平台的哪些接口
        • 你接入不同的支付平台,支付方式也会有些不一样,可以使用什么设计模式
        • 订单超时使用quartz来做是有性能问题的,怎么处理
        • 如果延迟队列在退库存的时候,正好用户下单成功,怎么办?
        • 如果用户正好在付款切付款成功了,这个时候订单自动超时了,怎么办
        • 如果异步通知失败怎么办(掉单)
        • 接口幂等一般怎么设计?
      • 认证授权
        • 讲一下你们的登录实现方案
        • 三方登录流程讲一下
        • 为什么要使用SpringSecurity
        • Security中怎么授权
        • 说一下security中的的filter
        • 说一下security的认证原理
        • 非对称加密,什么是数字签名 9-14
        • Oauth2的四种授权模式 9-14
        • 讲一下你们的微服务授权方案 你还知道有哪些方案吗? 9-14
        • 讲一下你们微服务认证授权的整体流程 9-14
        • 你们为啥要用JWT 9-15
        • Oauth2认证,如果Token过期了你们是怎么处理的 9-15
        • Oauth2认证,如果Token被盗了怎么办?9-15

三.微服务部分

相关概念

什么是集群 8-23

关键字:每个服务器都能独立运行
集群是将应用复制成多个相同的应用,一起来工作,从而提高工作能力。即将多个应用程序分散在不同的服务器,每个服务器都独立运行相同的代码。可以分散服务器压力解决高并发的问题,同时也能预防单节点故障,即一台服务器故障不影响其他服务器正常运行,但没有解决单体应用代码臃肿,业务复杂,维护性差等等问题

什么是负载均衡 8-23

关键字:

使用了集群后,解决高并发同时有一个新的问题,就是客户端的请求如何分配到多台服务。因此需要通过负载均衡器,比如Nginx,使用负载均衡算法比如轮询、权重、随机等等将请求路由到不同的服务器

什么是分布式 8-23

分布式是将应用按照业务类型拆分成多个子应用,每个子应用部署在不同的服务器上单独运行,子应用之间通过API相互调用。

可以分散服务器压力解决高并发问题,同时可以解决单体应用代码臃肿、业务复杂、维护性差等等问题,但是不能防止单节点故障,比如一个子应用故障,整个应用就能不完整运行

分布式集群举例

如果一个任务由10个子任务组成,每个子任务单独执行需1小时,则在一台服务器上执行该任务需10小时。

采用分布式方案,提供10台服务器,每台服务器只负责处理一个子任务,不考虑子任务间的依赖关系,执行完这个任务只需一个小时。(这种工作模式的一个典型代表就是Hadoop的Map/Reduce分布式计算模型)

而采用集群方案,同样提供10台服务器,每台服务器都能独立处理这个任务。假设有10个任务同时到达,10个服务器将同时工作,10小时后,10个任务同时完成,这样,整身来看,还是1小时内完成一个任务!

集群和分布式的区别,分别解决什么问题8-24

集群是将一个应用程序复制多份,部署在多台服务器上,每个服务器中的程序都是完整的,可以独立运行

分布式是将一个应用程序拆分成多个子程序,分别部署在多台服务器上,每个服务器中的程序都是不完整的,所有服务器需要相互通信相互协调才能完成最终的业务

集群能解决高并发问题,同时能防止单节点故障,即一台服务器宕机不影响其他服务器的正常运行

分布式也能解决高并发问题,但不能防止单节点故障,即一台服务器宕机了,整体业务就无法完成

集群无法解决项目本身的代码臃肿、业务复杂等等问题,分布式能降低模块之间的耦合

实际应用中,我们可以将分布式和集群相结合,比如分布式某个子程序的负载很高,可以单独对这个子程序做集群

说一下你理解的微服务8-24

微服务可以是一个分布式系统,它将单体应用进行细粒度拆分,形成多个微服务,每个服务独立运行,每个服务也都可以有自己的数据库,服务之间使用HTTP通信,互相协调完成整个系统的业务。

它的优点是服务之间解耦合,不同的服务可以有不同的编程语言,技术选型多元化,支持敏捷开发

他的缺点是分布式事务很复杂,部署麻烦,技术成本高,服务间通信对性能也有一定的损耗

什么是CAP理论 , 哪些技术用到AP,哪些用到CP 8-24

CAP理论指的是,在一个分布式系统中,一致性,可用性,分区容错性,三个要素最多只能同时实现两点。

分区容错性是分布式系统的内在要求,因此我们通常会在一致性和可用性之间做取舍。

满足CP,也就是满足一致性和容错性,舍弃可用性,如果系统允许有段时间失效就可以考虑。常见的如Redis,Nacos,ZooKeeper

满足AP,也就是满足可用性和容错性,舍弃一致性,如果系统允许出现短暂时间的不一致可以考虑。常见的如MySQL,Eureka
举例

什么是强一致性和最终一致性 8-24

关键字:实时同步,最终会同步

强一致性是指数据在多个副本中总数实时同步的,如果能容忍数据在多个副本中在一定的延迟时间内同步,则是弱一致性

最终一致性则不要求数据什么时候同步,但是最终会同步即可。通常情况下我们在分布式领域选择会牺牲了强一致性,会采用最终一致性

什么是Base理论 8-25

关键字:数据最终要保证一致性

Base指的是基本可用,软状态,最终一致性。它是对CAP中的AP的扩展,意思是说当出现故障部分服务不可用时,要保证核心功能可用,允许在一段时间内数据不一致,但最终要保证一致性。满足Base理论的事务也叫柔性事务

分布式是否属于微服务?

答案是属于。微服务的意思也就是将模块拆分成一个独立的服务单元通过接口来实现数据的交互。但是微服务不一定是分布式,因为微服务的应用不一定是分散在多个服务器上,他也可以是同一个服务器。这也是分布式和微服务的一个细微差别。

SpringCloud

讲一下你们公司微服务解决方案8-25

关键字:Springcloud Netflix,Eureka,Ribbon/OpenFeign,Hystrix,Zuul,Config,Bus,Sleuth

我司正在使用的是第一代微服务方案,Springcloud Netflix全家桶。

它是使用Eureka做服务注册与发现,也就是解决服务之间通信问题,

使用Ribbon/OpenFeign做客户端的负载均衡,也就是解决将请求路由到微服务集群的问题,

使用Hystrix断路器的熔断、降级来解决单节点故障,

使用Zuul做服务网关,将它作为整个微服务的大门,来实现登录、权限检查等业务,

使用Config分布式配置中心,来统一管理配置所有微服务的配置文件,

使用Bus消息总线给各个微服务广播消息,可以实现各个微服务配置的自动刷新,

使用Sleuth链路追踪,来实时监控各个微服务建的调用关系,快速定位故障节点

说一说Spring Cloud有哪些常用组件8-25

关键字:Eureka,Ribbon/OpenFeign,Hystrix,Zuul,Config,Bus,Sleuth

Eureka:做服务注册与发现,用来解决服务之间通信问题,

Ribbon/OpenFeign:用做客户端的负载均衡,也就是解决将请求路由到微服务集群的问题,

Hystrix:断路器,它的熔断、降级策略用来解决单节点故障,

Zuul:做服务网关,它是整个微服务的大门,可以用来实现登录、权限检查等业务,

Config:分布式配置中心,用来统一管理配置所有微服务的配置文件,

Bus:消息总线,用来给各个微服务广播消息,可以实现各个微服务配置的自动刷新,

Sleuth:链路追踪,用来实时监控各个微服务建的调用关系,快速定位故障节点

Spring Cloud的优缺点?8-25

关键字:优点:无耦合,HTTP,扩展,敏捷开发。缺点:繁琐,部署,技术成本,性能损耗

微服务相对单体应用来说

优点

  • 服务之间无耦合,代码简单方便开发维护,服务之间升级维护互不影响
  • 轻量级HTTP通信机制,不同的服务可以采用不同的编程语言
  • 有极强的扩展能力,业务量大的服务可以再次拆分服务,或者也可以集群部署
  • 支持时下流行的敏捷开发并做了优化

缺点

  • 分布式事务繁琐
  • 部署麻烦,开发人员的学习成本高
  • 技术成本高,开发人员需要花更多的时间学习相关技术
  • 微服务间的通信存在对性能的损耗问题
什么是服务注册 8-26

关键字:保存微服务的端口、ip。。

Eureka是一个服务注册与发现的组件,翻译成人话就是管理所有微服务的通讯录的组件。它包含注册中心,客户端两部分组成。客户端在启动的时候会向注册中心发送一条自我介绍信息,比如端口,ip等等,在注册中心就会保存一张所有微服务的通讯录。这就叫服务注册

什么是服务发现 8-26

关键字:根据微服务通讯录找到另一个微服务

微服务会定期的从客户端拉取一份微服务通讯录,到本地缓存起来,默认是30s一次。当一个微服务向另一个微服务发起调用,直接根据本地的通讯录找到对方的服务名,发送HTTP请求。这个就叫服务发现

什么是服务续约 8-26

关键字:剔除

微服务会定时(默认30s)发送心跳请求,告诉注册中心,自己还处于存活状态,那么服务中心就不会将其从清单中删除,否则,当微服务宕机或者网络故障等因素,没有在规定时间(默认90s)内提交心跳请求,注册中心就会将它从通讯录中删除。

如果服务挂了,注册中心要等到90s后剔除,那么在剔除前的这段时间内,挂掉的服务有可能还是会被调用,怎么处理? 8-26

关键字:修改时间,加快频率。熔断降级。集群

第一,可以修改注册中心剔除服务时间,同时加快服务续约心跳请求的频率

第二,可以使用Hystrix的熔断降级机制,当某个服务不可访问,快速失败,并返回托底数据

第三。重试,提供者集群

你知道EurekaClient服务发现和服务续约每隔30s做一次请求是用什么技术实现的吗? 8-27

使用了ScheduledThreadPoolExecutor线程池定时任务来实现

服务发现是先判断是否开启了服务发现功能(默认是开启的),获取定时任务的间隔时间(默认是30s),然后初始化服务发现的定时任务,间隔时间可以在yml中修改

服务续约是先判断是否开启服务注册功能(默认是开启的),获取定时任务间隔时间(默认是30s),然后初始化心跳请求的定时任务,间隔时间可以在yml中修改

Ribbon是什么,Ribbon的工作原理讲一下 8-27

Ribbon是一个客户端负载均衡器,它可以按照负载均衡算法,向多个服务发起调用。当一个微服务有多个集群时,就可以使用它做请求负载均衡,通常结合RestTemplate来使用

说一下 Ribbon的工作原理 8-27

消费者会30/次注册中心拉取服务注册清单缓存到本地,当消费者需要调用一组提供者集群服务时,Ribbon会根据提供者服务名,在本地缓存的服务地址清单里找到这一组服务的通讯地址,然后按照负载均衡算法(默认是轮询),选择其中的一个通讯地址,发起http调用服务。

Ribobn内部通过LoadBalancerInterceptor拦截RestTemplate发起的请求,然后交给RibbonLoadBalancerClient负载均衡客户端做负载均衡,RibbonLoadBalancerClient把选择服务的工作交给ILoadBalancer负载均衡器 ,ILoadBalancer会调用 IRule负载均衡算法类来选择服务。之后RibbonLoadBalancerClient把选择好的服务交给LoadBalancerRequest去发请求。

Ribbon有哪些负载均衡算法,怎么配置 8-27

RoundRobinRule:简单轮询,ribbon默认规则

AvailabilityFilteringRule:忽略短路状态和并发过高的服务器

WeightedResponseTimeRule:根据服务器响应时间作为权重,响应时间越长权重越小

ZoneAvoidanceRule:根据区域选择

BestAvailableRule:忽略短路的服务器,选择并发较低的服务器

RandomRule:随机选择一个可用服务器

Retry:重试机制的选择逻辑

OpenFeign和Ribbon的区别 8-28

OpenFeign整合了Ribbon和Hystrix,屏蔽了Ribbon拼接URL,参数的细节,使用声明式编程,让服务调用变得更加简单,OpenFiegn底层也是走的Ribbon的负载均衡策略。推荐使用OpenFeign

OpengFiegn的工作流程 8-28

首先,当程序启动时,@EnableFeignClient会扫描@FeignClient注解的接口,并交给Spring容器管理。

当发起请求时,会使用jdk动态代理,并为每个方法都生成相应的RequestTemplate,同时封装http信息,包括url和请求参数等,

最后把RestTemplate交个HttpClient发送请求,使用ribbon的负载均衡发起调用

为什么要使用Eureka 为什么要使用Ribbon 为什么要使用config配置中心 8-28

在微服务系统中,各个服务之间是需要进行网络通信的,那么他们相互调用就得知道对方的通信地址。eureka就是专门来做做服务注册与发现,解决服务之间通信问题的

当一个微服务做了集群,也就是同一个服务名会对应多个地址,那么我们在调用的时候,应该调用哪一个就成了问题,Ribbon是一个负债均衡器,它可以按照负债均衡算法,向多个服务发起调用。当一个微服务有多个集群时,就可以使用它做请求的分发

在微服务系统中,服务数量很多,而每个服务都有自己的配置文件,管理起来很麻烦。用了配置中心就可以帮我们集中管理配置文件,它支持本地配置文件,也支持将配置文件放到远程仓库如git集中管理

为什么Feign的客户端接口没有写实现类也可以直接被依赖注入 8-28

自动注入的实例其实是一个jdk动态代理对象,Feign会为每个方法生成相应的requestTemplate,它根据服务名找到对应的服务,根据返回值类型、形参列表匹配相应的接口,然后封装url、请求参数,最后生成request请求,使用Ribbon负载均衡发起调用

介绍一下Hystrix 8-29

关键字:熔断器,熔断降级

Hystrix意为熔断器,它可以将出现故障的服务,通过熔断、降级等手段隔离开,这样不影响整个系统的主业务。它可以防止由单节点异常导致整个微服务故障,如果遇到故障时,快速失败,熔断的同时可以返回拖底数据达到服务降级的目的

什么是熔断,什么是降级 8-29

关键字:熔断:保护机制,短路,降级拖底数据。降级:不可以,返回拖底数据;

熔断,是对服务链路的一种保护机制,当链路上的某个服务不可访问时,服务就会触发降级返回拖底数据,同时当失败率到达一个阈值,就标记该服务为短路状态,当请求访问时直接熔断。直到检查到该服务能正常访问时,就快速恢复

降级,是当某个服务不可访问时,我们返回一些事先准备好的数据给客户端,比如说,友情提示服务暂不可用,请骚后重试,这样用户体验就上去了

什么是资源隔离? 8-29

关键字:限流,线程池隔离:当前请求。信号量隔离:记录。

指的是限制某一个分布式服务的资源使用,可以理解为限流,也就是限制某个服务的请求数量。它包括线程池隔离和信号量隔离

线程池隔离,是指用一个线程池来存储当前请求,可以通过设置线程池最大线程数最大排队队列数来限制请求数量

信号量隔离:是指用一个计数器来记录当前有多少个线程在运行,请求进来计数器就增加1,超过最大信号量,就直接返回

资源隔离中信号量和线程池的区别? 8-29

关键字:同一个线程,开销大小

线程池方式是异步处理,它与调用线程不是同一个线程

信号量方式是同步处理,与调用线程是同一个线程

线程池方式由于需要排队,调度,线程切换,因此开销较大,信号量方式无需切换线程,开销较小

对于CAP理论,Eureka选择的是AP还是CP?它保证了一致性还是可用性? 8-30

CAP理论指的是,一个分布式系统中,一致性,可用性,分区容错性,三个要素只能同时实现两点。Eureka选择的是AP,它是弱一致性的,保证了可用性和分区容错性,放弃了数据一致性。也就是说当多个Eureka之间不可通信时,需要保证服务可用,正常提供服务注册发现功能,但是网络恢复后最终还是会同步的。

说一下Eureka的自我保护 8-30

为了防止服务被误删除,Eureka不会立即删除过时的服务数据。这种机制可能会导致客户端从注册中心获取到已经下线的服务并发起调用而导致错误,因此在开发阶段我们可以关闭自我保护机制。在生产环境中,我们需要打开自我保护,因为它可以防止因为网络波动,服务没有及时续约而造成的服务误删除问题。

你们项目是如何做服务降级的?8-30

比如在秒杀业务中,需要实时从redis中查询库存,通过设置hystrix的最大信号量,以此来防止redis雪崩。当并发过高,请求数超过最大信号量,触发降级,直接向客户端返回兜底数据:”活动太火爆啦,请骚后重试“

Zuul有哪几类Filter,他们的执行顺序是怎么样的? 8-30

zuul按照执行顺序,分为pre前置过滤,route路由过滤,post后置过滤,error异常后过滤

正常流程是请求先经过前置过滤器,到达路由过滤器进行路由,路由到各种微服务执行请求,返回结果后经过后置过滤,返回用户

异常流程,如果再整个过程中出现异常,都会进入error异常过滤器,处理完毕后经过post过滤器返回用户,如果error自己出现异常,最终也会通过post过滤器返回用户,如果post过滤器出现异常,也会跳转到error过滤器,然后直接返回用户

在Zuul中做登录检查如何实现?8-31

可以通过继承ZuulFilter抽象类,自定义pre类型的过滤器,shouldFilter方法中可以定义需要放行的资源,run方法中检查请求头中的token信息,如果没有token,就响应到客户端未登录的信息,并组织filter继续往后执行

在Zuul中如何做限流?8-31

方式一:可以通过继承ZuulFilter抽象类自定义pre过滤器,加上限流算法,来实现

方式二:可以通过hystrix的资源隔离模式,设置线程池最大连接数或者最大信号量来实现

方式三:常用,Ratelimit,使用令牌桶算法。。。

配置中心解决什么问题? 8-31

GJZ:集中管理

在分布式系统中,服务数量很多,而每个服务都有自己的配置文件,管理起来很麻烦。配置中心是个好东西,可以帮我们集中管理配置文件,它支持本地配置文件,也支持将配置文件放到远程仓库如git集中管理。

EureakServer的搭建流程 8-31

第一步,导入eureka-server依赖,以及springboot的web环境依赖。

第二布,主启动类上打注解,@EnableEurekaServer,开启eureka服务端功能

第三步,yml配置文件中,配置注册中心的端口号,主机名,注册中心地址

Ribbon的整合流程 9-1

第一步,导入ribbon依赖

第二部,给RestTemplate的Bean定义方法上,加上注解@LoadBalanced,让这个restTemplate有负载均衡的功能

第三步,修改restTemplate调用服务的url,将目标主机名换成目标服务名

Feign的整合流程 9-1

第一步,导入openfeign依赖

第二部,主配置类加注解,@EnableFeignClients,开启feign支持

第三步,定义feign客户端接口,并加上注解@FeignClient(“目标服务名”),接口中定义方法,该方法与目标服务的对应方法的方法名,返回值类型,形参列表,url路径要一致

Hystrix的整合流程 9-1
  • 第一步,导入hystrix依赖

  • 第二部,主启动类加注解,@EnableCircuitBreaker,开启熔断功能

  • 第三步,在需要开启熔断功能的方法上,加注解@HystrixCommand(fallbackMethod=“xxx”),xxx是降级方法

  • 第四步,定义降级方法,方法名需要和fallbackMethod的值一致,形参列表和返回值类型需要和目标方法一致

feign整合Hystrix:

  • 第一步,yml中配置,feign.hystrix.enable=true,开启hystrix功能

  • 第二部,@FeignClient标签中,定义fallback或者fallbackFactory,指定降级类

  • 第三步,

如果是fallback,就实现feign接口,并覆写接口中的方法作为降级方法

如果是fallbackFactory,就实现FallbackFactory接口,同时指定泛型为feign接口,覆写create方法,返回一个feign接口的匿名内部类,类中写降级方法

Zuul的整合流程 9-1

第一步,导入zuul依赖

第二步,主启动类上加注解@EnableZuulProxy,开启zuul功能

第三步,yml中配置,统一访问前缀prefix,禁用通过服务名方式访问服务ignoredServices,配置路由routes指定某个服务使用某个路径来访问

ConfigServer的整合流程 9-2

配置中心服务端配置:

​ 第一步,导入config-server依赖

​ 第二步,主启动类加注解,@EnableConfigServer,开启配置中心

​ 第三步,配置文件中,配置远程仓库地址,仓库账号密码

客户端配置:

​ 第一步,导入config-client依赖

​ 第二步,创建bootstrap.yml配置文件,配置中心地址config.uri,要拉取的配置文件名name,环境名profile

你们微服务项目的技术栈描述一下 9-2

​ 前端门户系统:HTML + JQuery + CSS

​ 前端管理系统:VUE + ElementUI

​ 后端系统:基于SpringCloud微服务框架(Eureka+OpenFeign+Hystrix+Zuul+Config)

+MyBatisPlus+SpringMVC+Redis+ElasticSearch+RabbitMQ+AlicloudOSS

浏览器发起一个请求,在你的微服务项目中的怎么去执行的? 9-2

浏览器发起的所有请求首先通过Nginx,通过负载均衡算法,路由给zuul集群,然后通过zuul前置过滤,作登录校验后,它会从配置中心拉取的通讯地址中,根据url匹配到对应的服务,然后使用ribbon发起restful调用。微服务间也可以通过feign相互调用,最终执行完任务,返回浏览器

说下Ribbon和Feign的区别呢 9-2

Ribbon和Feign都是SpringCloud Netflix中实现负载均衡的组件,不同点在于

Ribbon是需要我们手动构建http请求,根据目标服务名通过负载均衡算法直接调用目标服务,

Feign是采用接口的方式,将需要调用的目标服务方法定义成抽象方法,路径,服务名,形参列表,返回值类型需要保持一致。我们只需要调用接口中的方法就可以了。它会自动帮我们生成jdk动态代理,为每个方法生成RequestTemplate并封装url和请求参数,使用负载均衡算法发起调用

Ribbon的实现方式,一般配合RestTemplate发起http请求,我们需要在注册RestTemplate的Bean的方法上加@LoadBalanced,使它具有负载均衡的能力

Feign的实现方式,是在主启动类上加@EnableFeignClients,在客户端接口上加注解@FeignClient

Spring,SpringBoot和SpringCloud的关系以及区别 9-3

Spring是一个开源的轻量级控制反转和面向切面编程的容器框架。轻量级是说它开发使用简单,功能强大。控制反转是指将对象的创建,销毁控制交给ioc容器,方便解耦合,降低维护难度,面向切面编程是指将相同的逻辑横向抽取出来,可以对一些通用业务如事务,日志进行集中管理。

Springboot是一个基于spring的框架,对spring做了大量简化,使开发流程更快,更高效。比如它大量简化maven依赖,基于注解配置(JavaConfig)无需XML,内嵌Tomcat,部署流程简单,打包和部署更加灵活,允许独立运行

SpringCloud是基于SpringBoot实现的,用于微服务架构中管理和协调服务的,它是一系列框架的有序集合,它为开发者提供了一系列工具,例如服务发现与注册,配置中心,网关,负载均衡,熔断器,链路追踪等等,让微服务架构落地变得更简单

分布式事务

什么是分布式事务 9-3

分布式事务,指的是在分布式环境中,一个请求可能涉及到对多个数据库的写操作,要保证多数据库的一致性就需要用到分布式事务

分布式事务你知道哪些解决方案? 这些方案如何选型 9-3

图解

常见的分布式事务解决方案,2PC,TCC,可靠消息最终一致性,最大努力通知

2PC,它将整个事务流程分为两个阶段,P指的是准备阶段,C指的是提交阶段。它是一个阻塞协议,不适用于并发较高,事务生命周期长的分布式事务。

TCC,它是基于补偿性事务的AP系统的一种实现,补偿也就是说先按照预定方案执行,如果失败了就走补偿方案。它可以自己定义数据操作的粒度,但是对应用的侵入性强,可以用在登录送积分,送优惠券等等场景

可靠消息最终一致性,指的是当事务发起方执行完本地事务后,就发出一条消息通知其他参与方,并且他们一定能接收到消息并处理事务。适合执行周期长,并且实时性要求不高的场景

最大努力通知,是在不影响主业务的情况下,尽可能的保证数据的一致性,它适用于一些最终一致性敏感度低的业务,比如支付结果通知

什么是2pc 9-3

2PC,是将整个事务流程分为两个阶段,P指的是准备阶段,C指的是提交阶段。它常见的标准有XA,JTA,Seata

由DTP模型定义事务管理器TM和资源管理器RM之间通讯的接口规范叫做XA,它规定的交互方式是酱紫的:应用程序AP通过TM提交和回滚事务,TM通过XA接口来通知RM数据库事务的开始,结束,提交,回滚

2PC能保证分布式事务的原子性,但是也有很多缺陷

比如,在第一阶段,如果参与者迟迟不回复协调者,就会造成事务的阻塞,性能不好

比如,在第二阶段,如果事务协调者发出提交事务指令后宕机,一部分参与者收到消息提交了事务,另一部分没有收到消息没有提交事务,这就会导致数据不一致

再比如,在第二阶段,如果事务协调者发出提交事务指令后宕机,收到指令的参与者也宕机了,我们就不能确定事务的执行结果,究竟有没有提交

Seata相比传统2PC有什么区别,以及优点? 9-4

Seata是由阿里中间件团队发起的开源项目Fescar更名而来,是一个开源的分布式事务框架,它通过对本地关系数据库的分支事务协调,来驱动完成全局事务

Seata的主要优点是性能好,不会长时间占用链接资源,对业务零入侵

与传统的2PC的区别主要两方面

在架构层次方面,传统的2PC方案的RM本质就是数据库自身,而Seata的RM是以jar包形式作为中间件层部署在应用程序上

在两阶段提交上方面,传统2PC方案是在第二阶段完成才释放资源,而Seata是在第一阶段就将本地事务提交,提高了效率

Seata的TC,TM,RM的含义,以及作用? 9-4

TC:事务协调器,它是独立的中间件,需要独立部署运行,它维护全局事务的运行状态,接收TM指令发起全局事务的提交与回滚,负责与RM通信协调各各分支事务的提交或回滚

TM:事务管理器,TM需要嵌入应用程序中工作,它负责开启一个全局事务,并最终向TC发起全局提交或全局回滚的指令

RM:控制分支事务,负责分支注册、状态汇报,并接收事务协调器TC的指令,驱动分支事务的提交和回滚

你知道TCC吗,它有什么样的优缺点? 9-4

TCC是基于补偿型事务的AP系统的一种实现。补偿指的先按照事先预定的方案去执行,如果失败了就走补偿方案

它的优点是异步执行效率高,它能对分布式事务中的各个资源分别锁定,分别提交与释放

它的缺点是对应用的侵入性强,改动成本高,实现难度大

解释一下Seata的工作原理 9-4

SpringCloudAlibaba极简入门-分布式事务实战seata
Seata有三个角色:

  • TM任务管理器(Transaction Manager),负责开启,提交,回滚事务的发起,
  • TC事务协调器(Transaction Coordinator) ,接收TM的指令通知RM提交或者回滚事务
  • RM资源管理器(Resource Manager),控制着分支事务的提交和回滚

Transcation ID(XID) : 由事务协调者创建的全局唯一的事务ID

假设有服务A需要调用服务B,且两个服务都需要修改各自的数据库,A服务作为程序入口充当TM和RM,B服务控制着分支事务充当RM。

  • A服务的TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID

  • A服务的RM向TC注册分支事务,并将其纳入XID对应全局事务的管辖

  • A服务执行分支事务,写undolog日志,向TC上报事务状态

  • 当调用B服务时,B服务的RM向TC注册分支事务,该分支事务执行,然后写undolog,向TC上报事务状态

  • 服务执行完毕A服务的TM向TC发送commit或者rollback指令

  • TC接收到指令,向参与事务的RM发送指令

  • 事务参与者RM受到commit指令,删除undolog日志。 如果是rollback指令就根据undolog回滚

成功事务:(undolog日志,图中有错)
面试题大全1.5-微服务部分_第1张图片
异常事务:
面试题大全1.5-微服务部分_第2张图片

你能简单描述一下你在项目中是如何集成Seata的吗 9-5

事务协调器:安装并启动Seata客户端

主业务端:

  • 第一步,导入Seata依赖

  • 第二步,yml中配置事务组名,同时需要添加配置文件file.conf,registry.conf,需要注意yml中事务组名与file.comf中的事务组名一致

  • 第三步,配置DataSource,需要适用Seata对DataSource进行代理

  • 第四步,数据库中添加undolog日志表

  • 第五步,业务方法上加注解@GlobalTransactional(rollbackFor = Exception.class)注解

事务参与者:

  • 前四步与主业务端相同,第五步不需要了
没有Seata或者TCC这些事务框架,你可以怎么处理事务?9-5

不用框架就要自己实现,如果业务要求强一致性这个不太好做,需要协调多个数据库的同时提交和回滚.如果是业务不要求强一致性,我可以参照TCC思想 ,可以考虑自己实现异步写数据库方案,如果失败可以做补偿.当然这个要根据业务特性来,很多大公司都是自己封装事务框架.

分布式锁

你说一下什么是分布式锁 9-5

分布式锁是在分布式/集群环境中解决多线程并发造成的一系列数据安全问题.所用到的锁就是分布式锁,这种锁需要被多个应用共享才可以,通常使用Redis和zookeeper来实现。

分布式锁有哪些解决方案 9-5

分布式锁常用的三种方案:

基于数据库实现:通常基于主键,或者唯一索引来实现分布式锁,但是性能比较差,一般不建议使用

基于Redis :可以使用setnx来加锁 ,但是需要设置锁的自动删除来防止死锁,所以要结合expire使用.为了保证setnx和expire两个命令的原子性,可以使用set命令组合。

另外释放锁在finally中调用del删除锁,而删除锁前需要判断该锁是否是当前线程加的锁以免误删除锁,需要通过get获取锁然后进行判断,但是需要保证get判断或和del删除锁的原子性,可以使用LUA脚本实现。

总之自己封装Redis的分布式锁是很麻烦的,我们可以使用Redissoin来实现分布式锁,Redissoin已经封装好了。

基于zookeeper : 使用临时顺序节点实现,线程进来都去创建临时顺序节点,第一个节点的创建线程获取到锁,后面的节点监听自己的上一个节点的删除事件,如果第一个节点被删除,释放锁第二个节点就成为第一个节点,获取到锁。

在项目中可以使用curator,这个是Apache封装好的基于zookeeper的分布式锁方案。

Redis如何实现分布式锁,用什么命令

可以使用setnx来加锁 ,但是需要设置锁的自动删除来防止死锁,所以要结合expire使用.为了保证setnx和expire两个命令的原子性,可以使用set命令组合。

Redis实现分布式锁可能会出现什么问题,如何解决

添加锁和设置过期时间可以使用set命令进行组合,达到原子性加锁

需要用lua解决删除和判断锁的原子性,否则可能会删除掉别人的锁。

Redis集群环境中,redis节点挂掉可能会导致加锁失败,可以使用Redisson的红锁来解决。

你项目中怎么使用分布式锁的

自己封装Redis的分布式锁是很麻烦的,我们可以使用Redissoin来实现分布式锁,Redissoin已经封装好了

了解Redission的看门狗原理吗?

Redisson对分布式锁进行了封装,对于锁超时问题,它提供了看门狗进行锁时间的续期,底层使用了定时任务每10s检查一下,如果业务还未执行完成,未释放锁,就进行超时时间续期。

你在项目中如果使用ZK实现分布式锁的?

基于zookeeper : 使用临时顺序节点实现,线程进来都去创建临时顺序节点,第一个节点的创建线程获取到锁,后面的节点监听自己的上一个节点的删除事件,如果第一个节点被删除,释放锁第二个节点就成为第一个节点,获取到锁。

在项目中可以使用curator,这个是Apache封装好的基于zookeeper的分布式锁方案。

秒杀系统

秒杀的整体流程详细说一下

秒杀的商品和库存是缓存到Redis的,库存使用信号量,做的是秒杀预减库存方案。用户发起秒杀,直接走Redis秒杀商品,满足资格就预减库存,然后预创订单写入Redis。整个秒杀流程是不做数据罗库的。

此时把订单号返回给客户端,用户带着订单号进入订单确认页面进行下单,用户确认下单,再把Redis中的预创订单写入订单数据,同时做库存同步。紧接着就是调用支付接口做支付。

你们这个秒杀QPS是多少

我们用户量不是很大,我进去的时候是50多W的用户,要求的是能抗住5000的QPS,线上环境实际的QPS是3千多,具体的不清楚,因为是经理他们在看,我开发完这个功能在本地jemeter压测的能达到1500的吞吐量。在线上环境做做集群什么的还是很容易达到5千以上的。

你们是怎么保证这么高的QPS的

第一个是纯Redis秒杀,库存和商品本身都是使用Redis缓存,库存使用过的是信号量来保证原子性,订单也是放到Redis,用户确认订单后才入库。基于纯Redis秒杀,然后再做做集群上几千是很容易的。

如果流量更高,比如:每秒10W请求,应该怎么处理

Lvs+Nginx集群+下游服务集群。如果流量再高,就使用CDN分流。

说一下支付超时处理方案?延迟队列和死信队列是什么意思?

支付超时使用MQ延迟队列来处理,把消息投递到一个设置了过期时间的队列中,达到过期时间消息会被转发给另外一个“死信队列”

设置了过期时间的队列就是延迟队列,过期的消息叫着死信消息,存放死信消息的队列叫死信队列。

整个秒杀流程你用到了哪些队列

下单业务中用到了一个低劣,订单超时用到一个队列,支付结果处理用到一个队列。

秒杀成功,返回给用户的数据是什么?

预创订单号,前台通过这个订单号来进行下单。

怎么防止表达重复提交

表单重复提交一般都用令牌机制嘛,在上一个页面生成一个随机令牌存储到Redis,然后把令牌带入表单页面,提交订单时把令牌带到后台,后台先去Redis比对令牌,然后进行下单逻辑,下单后就把令牌从Redis删除。 如果是重复提交,那么Redis中已经没有令牌,就会下单失败。

你们怎么处理超卖

Redisson分布式锁,信号量来保证库存不超卖,它也是一种分布式锁,它能够保证多线程在扣减信号量的时候程原子性减,然后保证不会加成负数。

如果一个接口需要耗时1s,导致后续的请求堵塞,怎么处理

这种就是要提高接口的响应速度,减少和数据库的交互,可以基于Redis优化,或者使用MQ异步方案进行处理。

如何提高接口的qps

一方面:提高并发数

1.多线程,尽量用线程池 (线程个数:CPU核数 / (1 - 阻塞系数(IO密集型接近1,计算密集型接近0)))

2.适当调整连接数(Tomcat,Redis,Mysql等连接数)

3.集群

二方面:提高接口响应速度

1.减少和数据库交互,使用Redis代替

2.使用异步方案,比如MQ

3.使用并发编程,多个线程同时工作

4.减少服务的调用链

5.实在要连数据库,考虑数据库优化

项目并发高处理过不过来怎么办

前端优化:

  • 使用页面静态化技术由Nginx实现动静分离、
  • CDN加速加快响应速度、
  • 使用验证码使流量错峰等手段最大限度的降低并发

后端优化:

  • Nginx+LVS负载,也可以多机房部署,分流
  • 从架构上使用分布式、集群分散并发量,
  • 从数据结构上使用缓存如Redis减少数据读写时间,
  • 从处理方式上采用如RabitMQ队列实现异步响应,
  • 资源隔离比如使用Hystrix的信号量隔离来限流,同时做好备用方案比如Hystrix的熔断降级策略等等

订单支付

点击确认订单背后的业务流程
  • 用户确认好支付方式,收获地址,点击确认订单,会把商品编号,支付方式,搜索地址作为参数提交到后台
  • 后台做了参数校验后会去准备订单数据,如:计算价格,然后构建订单和订单明细
  • 然后保存订单和订单明细,同时需要扣减库存,以及保存支付单,该支付单用作支付申请用,也有可能还会做一些其他业务比如赠送积分什么的 , 然后返回结果,一般是返回订单号。
  • 然后页面发起支付请求,调用支付中心接口,支付接口根据支付单构建支付申请,此时会返回一个html表单
  • 把html表单交给浏览器去提交,就会进入收银台-也就是支付页面,用户登录自己的账号进行支付。
  • 在接下来就是异步回调处理了,需要做签名检查,参数核对比如金额核对,收款人,付款人核对
  • 再接着就是根据支付结果处理业务了,比如:修改业务单和支付单状态,保存支付流水等。
  • 我们的系统是把支付结果扔给MQ,其他微服务来消费然后做相关的业务处理。
你们使用支付平台的哪些接口
  • 支付接口
  • 订单查询接口- 根据订单号查询支付状态,对账的时候用
  • 下载账单接口 -也是用作对账,只是下载某个时间段的账单
  • 取消订单接口 - 我们平台订单自动取消的时候,也会调用支付平台的取消功能
  • 退款功能
你接入不同的支付平台,支付方式也会有些不一样,可以使用什么设计模式

不同的平台接入流程是一样的,但是每个具体的步骤不同,可以使用模板模式+策略模式来实现。

订单超时使用quartz来做是有性能问题的,怎么处理

你说的是空扫描和延迟问题吧,小项目数据量少到无所谓,如果是数据量很多,可以使用MQ延迟队列来解决

如果延迟队列在退库存的时候,正好用户下单成功,怎么办?

这就是 典型的分布式场景下,多个线程对同一个数据的并发操作,可以使用分布式锁来实现,我们使用的redission的RLOCK重入锁来实现的。

如果用户正好在付款切付款成功了,这个时候订单自动超时了,怎么办

这个加锁也不一定能解决,我们是在平台订单超时的时候会调用支付宝的取消订单接口尝试去取消订单。如果确实出现用户支付成功,但是平台订单自动超时了,那么我们会在异步回调中进行判断,然后调用支付平台的退款接口。

如果异步通知失败怎么办(掉单)

我们后天提供了一个对账功能,是根据订单流水号去支付平台查询订单的支付结果状态,根据这个支付结果重新走一遍异步通知需要处理的业务流程。

接口幂等一般怎么设计?

幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同 ,对于查询和删除操作天然就是幂等的。

对于插入操作我们可以找到数据的唯一标识进行查重,比如:保存一个用户我们可以判断用户的手机号是否已经存在了,如果已经存在就不要再重复保存。

对于修改才做也是同样的道理,比如:支付成功需要把某个订单状态修改为已支付,那么我们在修改之前应该根据唯一订单号查询这个订单的状态是否已经被修改,如果已经被修改就不要重复修改了。为了防止并发操作,可以把判断逻辑放到synchronized代码块中。

认证授权

讲一下你们的登录实现方案

我之前做过一个单体应用,使用过的是Redis来做登录,当用户第一次发起登录请求,后台生成一个token保存到Redis中

将生成的token返回给用户端

用户端使用用浏览器中的localStorage保存token

通过axios的拦截器,给每次请求的请求头都加上token

服务端收到token,就能在Redis中找到对应的数据

三方登录流程讲一下

1.用户发起微信登录请求

2.后端获取请求二维码的连接,重定向到扫码界面

3.用户使用微信扫一扫并同意授权

4.后端回调获取授权码,并将授权码作为参数,重定向到前端跳转页面

5.前端将授权码返回后端,后端根据授权码获取token

6.后端根据token获取openId

7.根据openId查询微信用户表

  • 如果查到有用户信息,且已关联本地账户,就默认登录
  • 如果有查到用户信息,但没有关联本地账户,就跳转本地账户绑定页面,
  • 如果没有查到用户信息,就向微信平台发起请求查询用户基本信息,添加到微信用户信息表,再跳转本地账户绑定页面

8.执行绑定逻辑时,根据手机号判断是否有本地账户,如果有就直接绑定,如果没有就自动注册再绑定,绑定成功后就默认登录

为什么要使用SpringSecurity

它主要是对登录和授权的流程做了封装,简化我们的代码量,也提供了很多功能,比如:认证授权结果处理,记住我等。总之用来器是很简单的。

Security中怎么授权

包括了web授权和方法授权,我们一般使用方法授权,注解的方式比较灵活。需要在配置类上打注解@EnableGlobalMethodSecurity(prePostEnabled = true)开启全局方法授权支持,然后再需要授权的方法是打授权注解@PreAuthorize

说一下security中的的filter

SecurityContextPersistenceFilter:请求开始会从SecurityContextRepository中获取SecurityContext对象并设置给SecurityContextHolder,在请求完处理成后将SecurityContextHolder持有的SecurityContext再保存到配置好的SecurityContextRepository中,同时清除SecurityContextHolder中的SecurityContext

UsernamePasswordAuthenticationFilter:默认拦截“/login”登录请求,将请求中的认证信息包括用户名,密码封装成UsernamePasswordAuthenticationToken,然后调用AuthenticationManager的认证方法进行认证

BasicAuthenticationFilter:处理 HTTP 请求的 BASIC 授权标头,如果身份验证成功,就把生成的Authentication对象放入SecurityContextHolder。如果设置了记住我,下次访问就不会走这里来了

RememberAuthenticationFilter:记住我,调用RememberMeServices的autoLogin方法自动登录

AnonymousAuthenticationFilter:匿名filter,检测SecurityContextHolder有没有Authentication对象,如果没有,就会创建一个AnonymousAuthenticationToken并保存到SecurityContextHolder

ExceptionTranslationFilter:处理filter链中的所有AccessDeniedException和AuthenticationException

FilterSecurityInterceptor:继承自AbstractSecurityInterceptor,通过调用AccessDecisionManager.decide方法进行授权

说一下security的认证原理

首先,请求会经过UsernamePasswordAuthenticationFilter拦截,请求的用户名密码会封装成UsernamePasswordAuthenticationToken,过滤器将token提交给认证管理器AuthenticationManager进行认证

然后,认证管理器调用AuthenticationProvider进行认证,AuthenticationProvider再调用UserDetailsService获取到数据库中存储的用户信息UserDetails,然后调用密码编码器对密码进行比较,认证成功后封装Authentication

再后来,请求回到UsernamePasswordAuthenticationFilter,调用SecurityContextHolder将Authentication对象封装成SecurityContext并保存到SecurityContextHolder中

最后,请求回到SecurityContextPersistenceFilter,它会调用SecurityContextRepository将SecurityContext对象存储起来,再清理掉SecurityContextHolder中的信息

非对称加密,什么是数字签名 9-14

非对称加密是一种算法,指的是加密和解密时使用不同的密钥,其中私钥不可公开,公钥可以公开。

数字签名就是在非对称加密的基础上,使用私钥加密,公钥解密,主要用来防止数据被篡改,实现安全传输的目的

Oauth2的四种授权模式 9-14

oauth协议是一个安全的开放授权标准,与传统的授权方式相比,它不会使第三方触及到用户的账号信息,Oauth2有四种授权模式

一、授权码模式:它是功能最完整,流程最严密的授权模式

二、简化模式:它简化了授权码模式,跳过了授权码这个步骤

三、密码模式:通过用户名密码的方式来换取Token , 前三种都可以用作三方登录

四、客户端模式: 以客户端的名义直接向服务器申请Token,这种需要对客户端绝对信任才可以,比如系统内容获取Token

讲一下你们的微服务授权方案 你还知道有哪些方案吗? 9-14

我们使用的是Spring Cloud Oauth2 ,它整合了SpringSecurity+Oauth2+JWT,主要分为两块配置:认证服务器-负责颁发token,资源服务-器负责校验Token和资源授权

我们项目是资源服务器去校验Token,也可以将Token校验工作交给网关统一校验,资源服务器只负责授权工作。

另外常见的授权方案还有,CAS单点登录,用户只用在某个服务上登录,访问其他服务时就不需要登录了,这就要求每个面向用户的服务都必须于认证服务交互,会产生大量重复的工作

分布式会话,它是将用户认证信息存储在共享容器比如redis中,通常会以会话作为key,当用户访问微服务时,就从redis中获取认证信息。这对安全存储有较高的要求,复杂度高

讲一下你们微服务认证授权的整体流程 9-14

关键词:认证中心-》password -》httpclient ->security的认证流程-》oauth2 -》回令牌 -》带令牌 -》校验令牌 -》方法授权

  • 浏览器带着用户名和密码访问认证中心的登录方法
  • 登录方法会拼接一个基于password模式的获取Token的url
  • 使用httpclient把请求发出去,请求会到达认证服务器
  • 认证服务器会走security的认证流程完成认证,以及加载用户的权限
  • 然后认证服务器会走oauth2生成令牌,令牌会基于JWT令牌转换器加密
  • 最后把令牌返回给浏览器,浏览器把Token存储到LocalStorage中,当然设置到cookie中也可以
  • 接下来就是浏览器会向资源服务器发送请求,请求头会通过axios前置拦截添加上Token
  • 资源服务器会对Token进行校验,也是用令牌转换器解析Token
  • 然后拿到Token中的授权信息,进行方法授权,如果有权限就可以正常执行方法
你们为啥要用JWT 9-15

一个字,安全,我们做了认证授权后,每次客户端访问资源服务器,都需要远程调用认证服务器进行token的校验和授权,才能访问到资源。这是很消耗性能的,因此我们考虑将签名信息直接保存到客户端,那就不需要每次都向认证服务器认证授权了。

但是这有有一个新的问题,这些敏感数据赤裸裸的存到客户端不安全!而JWT就能解决这个问题。它支持非对称加密算法对信息加密,保证了信息安全

另外,JWT以json对象的形式传递信息,解析更方便

可以在令牌中定义内容,方便扩展

Oauth2认证,如果Token过期了你们是怎么处理的 9-15

首先,我们会在前端设置axios后置拦截,检查是否是token过期,判断一下如果返回401,就代表token过期了

然后从localStorage中获取刷新refresh_token,并发送请求获取新的token

后台接收到前台的刷新token请求,拼接完整的刷新token的url,发送http请求获取到新的token并返回客户端

客户端收到新的token就把旧的token覆盖掉,最后把之前的请求再重新发送一次

Oauth2认证,如果Token被盗了怎么办?9-15

关键词:过期时间,ip,
首先,我们需要对token设置过期时间,这个时间可以根据需要设置短一点
然后,可以在token中加入客户身份标识,比如客户的ip地址,如果短时间内ip地址频繁变动,就标记为异常状态,并给用户发送信息,提示账户有风险
Token都能被盗,那这个就是用户自己的问题了。

你可能感兴趣的:(java面试题,微服务,java,服务器)