springcloud面试题2
什么是微服务
微服务就是将单体的应用分成多个应用程序,这样多个应用程序就成为微服务,每个微服务运行在自己的进程中,并且使用轻量级的机制通信.这些服务围绕业务能力来划分,并通过自动化部署机制来独立部署.这些服务可以使用不同编程语言,不同数据库,保证最低限度的集中式管理
优点
- 耦合低,不会影响其他模块的开发
- 减轻团队成本,可以并行开发,不用关注其他人如何开发,专注自己的开发
- 配置简单,不用写过多的配置文件
- 跨平台,可以用任何语言开发
- 每个微服务可以有自己的独立数据库也有公用数据库
缺点
- 部署麻烦,给运维带来一定的麻烦
- 针对数据管理比较麻烦,因为微服务可以每个微服务使用一个数据库
- 系统集成测试比较麻烦
- 性能监控麻烦
springcloud中的组件
对比 | springcloud Netflix | springcloudalibaba |
---|---|---|
网关 | zuul网关 | GetWay |
注册中心 | eureka(不再更新),ZooKeeper | 阿里nacos |
配置中心 | config注册中心 | 阿里NAcos |
客户端软负载均衡 | Ribbon | |
熔断器 | Hystrix | sentinel |
什么是服务的雪崩
一个服务依赖于另一个服务,如果这个功能服务挂掉了,那么依赖的服务就不能再用了,这种我们称之为雪崩
在大型互联网项目中,某个服务发生宕机时,调用这个服务的其他服务也会发生宕机,大型项目的微服务之间调用是互通的,这样服务的不可用逐步扩大到各个服务器中,从而使整个项目的服务器宕机崩溃,雪崩的原因主要有
- 单个服务的代码存在bug
- 请求访问量激增导致服务发生崩溃
- 服务器硬件故障导致部分服务不可用
在服务器雪崩时,可以进行熔断,限流,降级,服务隔离,服务监控等操作
降级
当某个微服务的响应时间过长,或者用不了了,要把错误信息返回回来,而不是一直卡在那,所以在服务端需要对嗲欧总不了的服务做降级
防止客户端一直等待,直接返回一个友好的提示给客户端
具体操作:在服务调用方法添加依赖,启动类加入注解@EnableHystrix
熔断
熔断是对雪崩效应的一种微服务链路保护机制,是在服务降级的基础上更直接的一种保护方式,当一个统计时间范围内的请求失败量达到设定值或当前错误率达到设定错误率的阈值时开启断路,之后的请求直接走fallback方法,在设定的时间后尝试恢复
限流
顾名思义就是限制某个微服务的使用流量
hystrix通过线程池的方式来管理你的微服务调用,他默认是一个线程池(10大小)管理你所有的服务
一个线程可用理解为一个请求,当10请求同事访问,都没有得到要响应的时候,就会自动调用fallback方法
服务隔离
在使用tomcat容器时,http服务器共用一个线程池,当http服务访问后端出现响应慢异常时,造成了服务响应延迟.当多个请求几种在这一个服务商时,这会导致该服务调用的所有线程被阻塞,知道线程池中线程都被耗尽,导致整个服务崩溃
例如上图所示,假如线程池中有10个线程,我们提供两个http服务1和2,分别调用后端服务A和B,正常情况下,服务1和2在调用完A和B,之后,会释放资源进入线程池中;假如后端服务A出现异常 ,调用服务A的线程出现阻塞情况,并且恰好大量服务持续调用服务1,那调用服务2的线程在回收完之后,会立马被服务1占用,并且这十个线程都处理阻塞状态,线程池中的线程被 耗光殆尽。这时,我们再发请http请求时,不管是请求1还是请求2,由于线程池中没有可用线程,因为所有的调用服务都会失败,整个系统就处理瘫痪状态。
使用hystrix后,如上图所示,hystrix会为http服务1和2分别分配两个线程为5的线程池,在上述同样的情况下,假如服务A出现故障,http1服务受阻,那池程池1中的五个线程被耗尽;与此同时,线程池2中的线程,由于服务B一切正常 ,所以线程可以不断循环回收,以此来保证http服务2不受影响。
服务隔离一般分为两种方案,一是线程隔离,一是信号量隔离
线程池隔离使用场景 ,一般为第三方应用,并发量较大的情况下使用
信号量隔离使用场景,一般为内部调用,并发量较小的情况下使用
线程隔离和信号量隔离
hystrix的隔离策略有俩种,分别是线程隔离和信号量隔离
Thread(线程隔离):使用方式:HystrixCommand将会在单独的线程上执行,并发请求线程池中线程数量的限制
Semaphore(信号量隔离):HysrixCommand将会在调用线程上执行,开销相对较小,并发请求接受信号量的个数限制
配置:hystrix.command.default.execution.isolation.strategy 隔离策略,默认是Thread, 可选Thread|Semaphore
hystrixCommand线程
线程池隔离:
1、调用线程和hystrixCommand线程不是同一个线程,并发请求数受到线程池(不是容器tomcat的线程池,而是hystrixCommand所属于线程组的线程池)中的线程数限制,默认是10。
2、这个是默认的隔离机制
3、hystrixCommand线程无法获取到调用线程中的ThreadLocal中的值
信号量隔离:
1、调用线程和hystrixCommand线程是同一个线程,默认最大并发请求数是10
2、调用数度快,开销小,由于和调用线程是处于同一个线程,所以必须确保调用的微服务可用性足够高并且返回快才用
请求并发量大,耗时短,采用信号量隔离策略这类服务返回通常非常快,不会占用容器线程太长时间,而且也减少了线程切换的一些开销,提高了缓存服务的效率
线程池方式下业务请求线程和执行依赖的服务的线程不是同一个线程;信号量方式下业务请求线程和执行依赖服务的线程是同一个线程
总结
限号量隔离的方式是限制了总的并发次数,每一次请求过来,请求线程调用依赖服务的线程是同一个线程,那么如果不涉及远程RPC调用(没有网络开销),则使用信号量隔离,更为轻量,开销更小
线程池隔离
优点
- 使用线程池隔离可以完全隔离依赖的服务,请求线程可以快速放回
- 当线程池出现问题时,线程池是独立的不会影响其他服务和接口
- 当失败服务变得再次可用时,线程池清理并可立即恢复,而不需要一个长时间的恢复
- 独立的线程池提高了并发性
缺点:增加cpu开销.每个命令涉及到排队,调度和上下文切换都在一个单独线程上运行的
线程池隔离情况
请求并发量大(计算量大,或读数据库):采用线程池隔离策略,这样的话,可以保证大量的容器tomcat线程可用,不会由于服务原因,一直处于阻塞或等待状态,快速失败返回
比如我们现在有3个业务调用分别是查询订单、查询商品、查询用户,且这三个业务请求都是依赖第三方服务-订单服务、商品服务、用户服务。三个服务均是通过RPC调用。当查询订单服务,假如线程阻塞了,这个时候后续有大量的查询订单请求过来,那么容器中的线程数量则会持续增加直致CPU资源耗尽到100%,整个服务对外不可用,集群环境下就是雪崩。如下图
订单服务不可用
整个tomcat容器不可用.png
Hystrix是如何通过线程池实现线程隔离的
Hystrix通过命令模式,将每个类型的业务请求封装成对应的命令请求,比如查询订单->订单Command,查询商品->商品Command,查询用户->用户Command。每个类型的Command对应一个线程池。创建好的线程池是被放入到ConcurrentHashMap
当第二次查询订单请求过来的时候,则可以直接从Map中获取该线程池。具体流程如下图:
与dubbo的区别
dubbo具有调度,发现,监控,治理,等功能,支持相当丰富的服务治理能力.在dubbo架构下,注册中心对等集群,并会缓存服务列表已被数据库失效是继续提供发现功能,本身的服务发现结构具有很强的可用性与健壮性,足够支持高访问量网站
虽然Dubbo ⽀持短连接⼤数据量的服务提供模式,但绝⼤多数情况下都是使⽤⻓连接⼩数据量的模式提供服务使⽤的。所以,对于类似于电商等同步调⽤场景多并且能⽀撑搭建Dubbo 这套⽐较复杂环境的成本的产品⽽⾔,Dubbo 确实是⼀个可以考虑的选择。但如果产品业务中由于后台业务逻辑复杂、时间⻓⽽导致异步逻辑⽐较多的话,可能Dubbo 并不合适。同时,对于⼈⼿不⾜的初创产品⽽⾔,这么重的架构维护起来也不是很⽅便。
Spring Cloud由众多⼦项⽬组成,如Spring Cloud Config、Spring Cloud Netflix、Spring Cloud Consul 等,提供了搭建分布式系统及微服务常⽤的⼯具,如配置管理、服务发现、断路器、智能路由、微代理、控制总线、⼀次性token、全局锁、选主、分布式会话和集群状态等,满⾜了构建微服务所需的所有解决⽅案。⽐如使⽤Spring Cloud Config 可以实现统⼀配置中⼼,对配置进⾏统⼀管理;使⽤Spring Cloud Netflix 可以实现Netflix 组件的功能 - 服务发现(Eureka)、智能路由(Zuul)、客户端负载均衡(Ribbon)。
Dubbo 提供了各种 Filter,对于上述中“⽆”的要素,可以通过扩展 Filter 来完善。
dubbo的开发难度较⼤,原因是dubbo的jar包依赖问题很多⼤型⼯程⽆法解决。