前言
本章主要讲述根据乐优商城项目,面试可能会问到的一些问题
问题
1.你如何理解分布式服务
我们的项目就是分布式服务,按照自己的话来说,就是把核心业务提取出来,例如订单管理,购物车管理都需使用商品管理的业务,只需要商品管理自己去对数据库进行增删改查,而购物车和订单管理直接调用商品管理即可.
这样做的优点在于:将基础服务进行提取,系统间相互调用,提高了代码的复用和代码的开发效率。
但也存在着缺点:系统间的耦合度变高,调用关系也错综复杂,难以维护。
2.如何应对高并发
- (因为是网络商城项目,最难的就是高并发,几乎都会被问到)
暂无
建议多了解了解,多看看相关文章和blog
只有高可用了才可进行高并发(应该主要是从下面括号里面去回答吧)
高并发:(分布式,静态化技术,CDN服务,缓存(数据库并发),异步并发,池化,队列(RabbitMq))
高可用:(集群:redis,负载均衡ribbon,限流(控制),降级,熔断(hystrix))
就像页面静态化技术就是解决高并发的非常有效的手段.
3.如何避免消息的丢失
- 因为项目用到了RabbitMq,这种问题也是面试的热点
1.做ACK确认,当一个消息被消费者接收以后,消费者应当发一条回执,我已经收到并消费了该条消息,那么此时,RabbitMQ才能把消息从队列中删除
但是请注意:
并不一定做了消息确认就能避免消息丢失,如果RabbitMQ挂了,消息没了怎么办呢?可能有些人会回答说那就搭集群被,一台挂了还有别的.但是面试官想得到的回答可不一定是这个.这就引出了第二条,应持久化,而我们的RabbitMQ它默认是不持久化的。
2.作消息的持久化 ,避免RabbitMQ把消息弄丢,发消息前,将消息持久化到数据库,并记录消息状态(即可靠消息服务)
但前提是:队列和Exchange也都进行了持久化.(因为消息都经历了队列和交换机,中途也可能发生消息的丢失)
- 以上两点其实已经解决了该问题的99%,那还有1%即第三点
3.采用生产者确认机制: 避免生产者因为网络问题发出了消息,但未到RabbitMQ中,那么这个也算是消息丢失.
发送消息前:();
发送消息后:();
4.如何避免消息堆积?
- 当消息处理比较耗时,生产速度越来越快,消费速度却越来越慢,消息则会堆积越来越多. 无法处理时怎么办?
1.采用WorkQueue多个消费者监听同一队列
2.接收到消息后,而是通过线程池异步消费。
5.对Redis和Memcache有没有了解,为什么选择redis?
-
Memcache无持久化: Memecache把数据全部存在内存之中,断电后会挂掉且数据不能超过内存大小。 而Redis有部份存在硬盘上,这样能保证数据的持久性(默认RDB模式)
-
Memcache只支持K-V结构,Redis有复杂的数据类型。
-
Memcache是多线程,性能比redis(单线程)差
在这里可能会有人问:多线程不是应该比单线程性能要更好吗?
这是因为Memcache大多数时间用在了切换线程上。
面试经常会问到的问题
-
在这里列举一下,因为我也还没有去特别了解.后续可能会补上
-
持久化 避免缓存击穿
-
分片(集群) 避免缓存雪崩
-
主从 哨兵 避免缓存热点,key过期
7.你们的微服务地址如果不小心暴露了怎么办?
-
分析:依照我们自己的乐优项目这个问题需要从两方面回答:首先可以说一下这个项目不太可能会出现这个问题(但面试官并不是想听你这个回答的)
重点回答万一真的暴露了怎么办呢? -
回答:
1.首先,别人不太可能知道我的微服务地址,因为我们采用的是局域网 若真的暴露了,对外暴露的只有网关,但其实zuul也并没有真的暴露,因为在我的项目中,它还经过了nginx的反向代理,所以暴露的只能是nginx,所以这样来说,其实不太可能会暴露。2.但万一暴露,那我们对服务间的访问也进行鉴权,需在后台权限系统中专门有一套权限管理页面,专门管理各个微服务以及各微服务之间的访问权限。这样的话,还需要额外定义表
一个微服务表(定义所有微服务的唯一ID以及名称信息)
一个微服务的权限表(例如记录其中一个微服务a其中可访问其他微服务的id关系,形成一个表关联),所以一个服务想访问另一个微服务,必须在后台进行授权才可以另外,需要进行服务与服务之间的身份认证:在一个微服务访问另一个微服务之前,必须先访问我们的授权中心发起请求获得权限,此微服务要携带自己的id和密码,找授权中心。然后授权中心通过服务的id密码去数据库表查看是否正确,若正确,读取服务id所对应的的权限表。看其可访问的微服务权限有哪些,若通过.写入JWt
token中发放给其他微服务,其他微服务拿到token后再访问。
8.如何解决分布式事务问题?(热点)
-
1.2PC:两阶段提交
执行阶段:
当创建订单时,向所有微服务发送消息,可以开始执行了,执行成功后,不直接提交,而是返回一个消息告诉我,执行成功还是执行失败.第二阶段:
如果所有人都执行成功,再发一个消息,你们可以提交了
如果第一阶段有人执行失败,你就告诉所有人都回滚缺点:当锁定的表很多时,性能差,
-
:补偿性事务(一般采用) try-confirm-concel
每个服务执行完后都提交,集中返回给自己,如果都执行成功了那就不管
如果提交失败,就采用失败服务的补偿方法去补偿,但若补偿方法也失败,那你还需要进行重试写重试方法或者人工介入.优缺:解决了性能问题,但是业务复杂,写一个事务还需要写补偿方法
-
3.异步确保:利用mq实现分布式事务