1.公司微服务技术架构图
2.Springcloud五大组件分别是:
服务发现——Eureka 实现服务治理
客服端负载均衡——Ribbon/Feign(Ribbon封装形式) 主要提供客户侧的软件负载均衡算法。
断路器——Hystrix 作用:断路器,保护系统,控制故障范围。
服务网关——Zuul api网关,路由,负载均衡等多种作用
分布式配置——Spring Cloud Config/apollo(优点警告邮件通知,统一界面管理)
3.微服务跟分布式区别?
1.理念上:分布式服务架构强调的是服务化以及服务的分散化,微服务则更强调服务的专业化和精细分工,更加强调单一职责、轻量级通信(HTTP)、独立性并且进程隔离。
2.部署上:分布式的方式是根据不同机器不同业务,而微服务可以是同一个机器部署.
3.目的上:分布式:分散压力。微服务:分散能力
分布式重在资源共享与加快计算机计算速度。微服务重在解耦合,使每个模块都独立。
4.微服务对业务拆分更细粒,运维的复杂度和性能会随着服务的粒度更细而增加。
不同点:SpringCloud是一套目前比较完整微服务框架了,整合了分布式常用解决方案遇到了问题注册中心Eureka、负载均衡器Ribbon ,客户端调用工具Rest和Feign,分布式配置中心Config,服务保护Hystrix,网关Zuul Gateway ,服务链路Zipkin,消息总线Bus等。
Dubbo内部实现功能没有SpringCloud强大(全家桶),只是实现服务治理,缺少分布式配置中心、网关、链路、总线等,如果需要用到这些组件,需要整合其他框架。
SpringCloud和Dubbo区别?
相同点:SpringCloud 和Dubbo可以实现RPC远程调用框架,可以实现服务治理。
不同点:
1.Dubbo社区也不如spring cloud,2017年还停止维护,SpringCloud社区活跃,更新快;
2.Dubbo内部实现功能没有SpringCloud强大(全家桶),只是实现服务治理,缺少分布式配置中心、网关、链路等,如果需要用到这些组件,需要整合依赖其他框架。
3.SpringCloud采用的http+json的通信方式,相比Dubbo采用tcp协议,性能相对低一些.
4.Dubbo一般采用ZooKeeper作为注册中心(使用Redis需要服务器时间同步,且性能消耗过大),
SpringCloud一般采用Eureka作为注册中心;
针对分布式领域著名的CAP理论(C——数据一致性,A——服务可用性,P——服务对网络分区故障的容错性,Zookeeper保证的是CP ,但对于服务发现而言,可用性比数据一致性更加重要 ,而Eureka设计则遵循AP原则 。
使用微服务架构应该选择SpringCloud和Dubbo?
1.内部是否存在异构系统集成的问题;比如dubbo不支持跨系统调用
2.选择的框架是否满足业务需求;
3.http协议的通信对于应用的负载量会否真正成为瓶颈点;
4.社区活跃度、团队技术储备;Dubbo社区之前都暂停维护,需要自己维护
5.从业务角度以及成本来考虑。
微服务的优缺点分别是什么?说下你在项目开发中碰到的坑?
优点:
1.服务的独立部署,服务之间互不影响.
2.服务的快速启动(服务拆分细化后,依赖的库少了,代码量也少了)
3.更加适合敏捷开发:修改哪个服务只需要发布对应的服务即可,不用整体重新发布。适合敏捷开发强调迭代,循序渐进的方法进行。
4.松耦合,职责专一,由专门的团队负责专门的服务.有利于团队之间的分工明确。
5.微服务只专注于当前业务逻辑代码,不会和 html、css 或其他界面进行混合。
缺点:
1.分布式部署,调用的复杂性高,之前但应用都是本地调用进行;微服务独里部署通过http通信,会产生很多问题,比如网络问题、容错问题、调用关系等。
2.独立的数据库,需要额外分布式事务处理。当涉及多系统之间关联查询需要额外写视图,或者使用otter(分布式数据库同步系统)
3.运维难度的提升,需要专门运维人员都管理,部署发布。
4.排查问题编地困难,分布部署跟踪问题难.
5.人力资源增多
常见问题难点:
1.多库关联查询:
之前改造航变系统,需要按时间查询航变匹配到的订单,因为是微服务表在不同库里面,后面采用视图方式查询。使用otter
2.场景:同一个订单多次执行/幂等处理.
解决方案:
1.对业务单号加上唯一的索引或者组合索引,在并发的场景中,保证只有一条插入,其他插入会触发唯一所以异常而失败,返回相同结果.
2.Redis处理,每当订单请求进来会先查看Redis缓存是否存在请求单号,如果不存在则向Redis增加Key为订单号,然后进行订单系统插入处理(先去查询一下订单),并持久化到数据库,执行完则删除Redis该订单号的Key.为了防止业务处理异常,设置10SKey过期。
3.接口超时处理
接口交互主要有三种:同步,异步,消息队列(接口异步化,服务之间解藕,消峰)
接口超时原因可能时:
网络超时:网络延迟,请求时超时,服务端没有收到客户端的请求.网络问题没法处理
服务端内部处理超时可能存在DB操作、IO操作、调用其他服务超时;
同步响应超时:服务端同步返回响应给客户端超时.此时服务端已经接收了请求。网络问题没法处理
异步响应超时:服务端处理后返回结果给客户端超时。此时服务端已经处理完了请求。
解决方案:
针对客户端解决:
1.主动查询,通过主动查询去拉取超时请求的状态。根据请求流水号作为查询的条件,查询处理结果。
2.重试,需要设置重试梯度(5s,20s,1min...),以及重试次数的阈值(最多重试的次数),需要服务端幂等处理。
针对服务端解决:
针对服务断内部超时:
在优化代码提高执行速度前提下还是无法达到预期,可以采用异步响应方式,先返回接收到请求结果,内部处理后,将最终的结果通过异步通知反馈给客户端。
异步通知超时:
服务端处理后,异步处理返回结果给客户端,并要求得到接收结果信息.如果没有返回成功消息,则采用重试机制。
针对消息队列解决:
生产者超时一般都采用可靠消息服务,如RocketMq
消费者超时
各大MQ中间件都有一定的机制来保障其到消费者之间的消息不会丢失。
采用
消费者从消息中间件取走消息之后,消息中间件不会立马将该消息删除,必须要等到消费者告知消息中间件已经处理完了该消息后,消息中间件才会将消息进行删除。
可参考:
https://www.jianshu.com/p/d68d572b0613
4.接口限流(高并发大流量下保护系统)
单应用采用
令牌桶算法(设置规定数量令牌,请求获取令牌才能处理),直接使用Guava包中的RateLimiter。
PS:后面的请求就得为上一次请求买单,它需要等待桶中的令牌补齐之后才能继续获取令牌。
分布式应用:
使用Redis将每次请求当前时间(精确到秒)作为 Key 写入到 Redis 中,超时时间设置为 2 秒,Redis 将该 Key 的值进行自增。
当达到阈值时返回错误。
写入Redis的操作用Lua脚本来完成,利用Redis的单线程机制可以保证每个Redis请求的原子性。
LUA脚本思路:
1.设置限流key,限流大小,
2.获取当前流量大小redis.call('get', key)并tonumber转为为数字
3.判断数字是否大于等于限流大小,大于直接返回0.小于则redis.call("INCRBY")将key值+1.redis.call("EXPIRE", key, 2)设置过期2s
4.返回key的值。
我们项目中采用@CommonLimit注解来.
可参考:
http://ifeve.com/%E5%88%86%E5%B8%83%E5%BC%8F%E9%99%90%E6%B5%81/
eureka和zookeeper的区别:
eureka和zookeeper都可以作为分布式系统的注册中心,用于服务治理。
在CAP定理上(分布式系统各个节点的状态如何同步基本定理,C一致性,A可用性,P分区容错性),eureka基于AP,zookeeper基于CP.
点评:由于作为注册中心可用性的需求要高于一致性,所以eureka貌似要比zookeeper更合理一些
PS:
实际工作会接触到eureka,feign,hystrix
相关其他微服务面试参考:
微服务面试题