1.1 什么是微服务?
1.2 微服务之间是如何独立通讯的?
1.3 SpringCloud 和 Dubbo有那些区别?
1.4 SpringBoot 和 SpringCloud,请谈谈你对他们的理解
1.5 什么是服务熔断?什么是服务降级?
1.6 微服务的优缺点分别是什么?说下你在项目开发中遇到的坑
1.7 你所知道的微服务技术栈有哪些?列举一二
1.8 Eureka和Zookeeper都可以提供服务注册与发现的功能,请说说两者的区别 …
什么是微服务?
微服务(Microservice Architecture) 是近几年流行的一种架构思想,关于它的概念很难一言以蔽之。
究竟什么是微服务呢?我们在此引用ThoughtWorks 公司的首席科学家 Martin Fowler 于2014年提出的一段话:
原文:https://martinfowler.com/articles/microservices.html
汉化:https://www.cnblogs.com/liuning8023/p/4493156.html
再来从技术维度角度理解下:
微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个微服务提供单个业务功能的服务,一个服务做一件事情,从技术角度看就是一种小而独立的处理过程,类似进程的概念,能够自行单独启动或销毁,拥有自己独立的数据库。
微服务
强调的是服务的大小,它关注的是某一个点,是具体解决某一个问题/提供落地对应服务的一个服务应用,狭义的看,可以看作是IDEA中的一个个微服务工程,或者Moudel。IDEA 工具里面使用Maven开发的一个个独立的小Moudel,它具体是使用SpringBoot开发的一个小模块,专业的事情交给专业的模块来做,一个模块就做着一件事情。强调的是一个个的个体,每个个体完成一个具体的任务或者功能。
微服务架构
一种新的架构形式,Martin Fowler 于2014年提出。 微服务架构是一种架构模式,它体长将单一应用程序划分成一组小的服务,服务之间相互协调,互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务之间采用轻量级的通信机制(如HTTP)互相协作,每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境中,另外,应尽量避免统一的,集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具(如Maven)对其进行构建。
优点
缺点
https://github.com/dubbo
https://github.com/spring-cloud 对比结果:
最大区别:Spring Cloud 抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式 严格来说,这两种方式各有优劣。虽然从一定程度上来说,后者牺牲了服务调用的性能,但也避免了上面提到的原生RPC带来的问题。而且REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这个优点在当下强调快速演化的微服务环境下,显得更加合适。 品牌机和组装机的区别 社区支持与更新力度的区别
总结:二者解决的问题域不一样:Dubbo的定位是一款RPC框架,而SpringCloud的目标是微服务架构下的一站式解决方案。
官网:http://projects.spring.io/spring-cloud/
SpringCloud没有采用数字编号的方式命名版本号,而是采用了伦敦地铁站的名称,同时根据字母表的顺序来对应版本时间顺序,比如最早的Realse版本:Angel,第二个Realse版本:Brixton,然后是Camden、Dalston、Edgware,目前最新的是Hoxton SR4 CURRENT GA通用稳定版。
自学参考书:
一个父工程带着多个Moudule子模块
MicroServiceCloud父工程(Project)下初次带着3个子模块(Module)
在IDEA中创建数据库连接
创建springcloud-api 导入依赖
创建Dept 不知道为啥lombok导入会导致后面网页查询失败,所以老老实实地用alt+ins吧
配置application.yml
mybatis-config.xml
DeptDao.java
DeptMapper.xml
启动类
导入依赖
配置文件 application.yml
Eureka 包含两个组件:Eureka Server 和 Eureka Client.
Eureka Server 提供服务注册,各个节点启动后,回在EurekaServer中进行注册,这样Eureka Server中的服务注册表中将会储存所有课用服务节点的信息,服务节点的信息可以在界面中直观的看到.
Eureka Client 是一个Java客户端,用于简化EurekaServer的交互,客户端同时也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,将会向EurekaServer发送心跳 (默认周期为30秒) 。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除掉 (默认周期为90s).
三大角色
1. eureka-server 创建springcloud-eureka-7001 pom.xml 配置
application.yml
访问 http://localhost:7001/
设置springloucd-provider-dept-8001 1.导入Eureca依赖
2.application中新增Eureca配置
3.为主启动类添加@EnableEurekaClient注解
1.修改Eureka上的默认描述信息
2.配置关于服务加载的监控信息
application.yml中添加配置
主启动类中加入@EnableDiscoveryClient 注解
1.初始化 创建pringcloud-eureka-7002、springcloud-eureka-7003 模块
2.集群成员相互关联 配置一些自定义本机名字,找到本机hosts文件并打开
在集群中使springcloud-eureka-7001关联springcloud-eureka-7002、springcloud-eureka-7003 完整的springcloud-eureka-7001下的application.yml 如下
springcloud-eureka-7002,springcloud-eureka-7003也是一样改成关联另外两个
通过springcloud-provider-dept-8001下的yml配置文件,修改Eureka配置:配置服务注册中心地址
1. 回顾CAP原则
RDBMS (MySQLOraclesqlServer) ===> ACID
NoSQL (RedisMongoDB) ===> CAP
2. ACID是什么?
3. CAP是什么?
4. CAP理论的核心
5. 作为分布式服务注册中心,Eureka比Zookeeper好在哪里?
Zookeeper保证的是CP
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接收服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但zookeeper会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30-120s,且选举期间整个zookeeper集群是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因为网络问题使得zookeeper集群失去master节点是较大概率发生的事件,虽然服务最终能够恢复,但是,漫长的选举时间导致注册长期不可用,是不可容忍的。
Eureka保证的是AP
Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时,如果发现连接失败,则会自动切换至其他节点,只要有一台Eureka还在,就能保住注册服务的可用性,只不过查到的信息可能不是最新的,除此之外,Eureka还有之中自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
Ribbon是什么?
springcloud-consumer-dept-80向pom.xml中添加Ribbon和Eureka依赖
在application.yml文件中配置Eureka Eureka配置
主启动类加上@EnableEurekaClient注解,开启Eureka
自定义Spring配置类:ConfigBean.java 配置负载均衡实现RestTemplate
修改conroller:DeptConsumerController.java
1.创建两个数据库:db02,db03 1.新建两个服务提供者Moudle:springcloud-provider-dept-8003、springcloud-provider-dept-8002
2.参照springcloud-provider-dept-8001 依次为另外两个Moudle添加pom.xml依赖 、resourece下的mybatis和application.yml配置,Java代码,修改application.yml下的8001端口号和instance-id: springcloud-provider-dept-8001,数据库db02,db03,修改主启动类名称
访问[http://localhost/customer/dept/list
以上这种每次访问http://localhost/consumer/dept/list随机访问集群中某个服务提供者,这种情况叫做轮询,轮询算法在SpringCloud中可以自定义。
在springcloud-provider-dept-80模块下的ConfigBean中进行配置,切换使用不同的规则
随机访问服务器
MyRule.java
主启动类开启负载均衡并指定自定义的MyRule配置类
自定义的规则(这里我们参考Ribbon中默认的规则代码自己稍微改动):MyRandomRule.java
访问:http://localhost/customer/dept/list 自定义随机访问服务器,但快速访问服务器会蹦!
Feign是声明式Web Service客户端,它让微服务之间的调用变得更简单,类似controller调用service。SpringCloud集成了Ribbon和Eureka,可以使用Feigin提供负载均衡的http客户端
只需要创建一个接口,然后添加注解即可~ Feign,主要是社区版,大家都习惯面向接口编程。这个是很多开发人员的规范。调用微服务访问两种方法
Feign能干什么?
Feign默认集成了Ribbon
在springcloud-api下创建DeptClientserver.java,添加依赖
创建springcloud-consumer-fdept-feign模块 拷贝springcloud-consumer-dept-80模块下的pom.xml,resource,以及java代码到springcloud-consumer-feign模块,并添加feign依赖。
根据个人习惯而定,如果喜欢REST风格使用Ribbon;如果喜欢社区版的面向接口风格使用Feign.
Feign 本质上也是实现了 Ribbon,只不过后者是在调用方式上,为了满足一些开发者习惯的接口调用习惯!
分布式系统面临的问题
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出”,如果扇出的链路上某个微服务的调用响应时间过长,或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几十秒内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以达到单个依赖关系的失败而不影响整个应用程序或系统运行。 我们需要,弃车保帅!
随着大容量通信量的增加,单个后端依赖项的潜在性会导致所有服务器上的所有资源在几秒钟内饱和。
官网资料:https://github.com/Netflix/Hystrix/wiki
什么是服务熔断? 熔断机制是赌赢雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阀值缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是:
服务熔断解决如下问题:
入门案例 新建springcloud-provider-dept-hystrix-8001模块并拷贝springcloud-provider-dept–8001内的pom.xml、resource和Java代码进行初始化并调整。
导入hystrix依赖
调整yml配置文件
prefer-ip-address: false:
修改controller
主启动类添加熔断注解
因此,为了避免因某个微服务后台出现异常或错误而导致整个应用或网页报错,使用熔断是必要的
什么是服务降级? 服务降级是指 当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理,或换种简单的方式处理,从而释放服务器资源以保证核心业务正常运作或高效运作。说白了,就是尽可能的把系统资源让给优先级高的服务。 资源有限,而请求是无限的。如果在并发高峰期,不做服务降级处理,一方面肯定会影响整体服务的性能,严重的话可能会导致宕机某些重要的服务不可用。所以,一般在高峰期,为了保证核心功能服务的可用性,都要对某些服务降级处理。比如当双11活动时,把交易无关的服务统统降级,如查看蚂蚁深林,查看历史订单等等。
**服务降级主要用于什么场景呢?**当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保证重要或基本的服务能正常运行,可以将一些 不重要 或 不紧急 的服务或任务进行服务的 延迟使用 或 暂停使用。
由上图可得,当某一时间内服务A的访问量暴增,而B和C的访问量较少,为了缓解A服务的压力,这时候需要B和C暂时关闭一些服务功能,去承担A的部分服务,从而为A分担压力,叫做服务降级。
服务降级需要考虑的问题
自动降级分类
1)超时降级:主要配置好超时时间和超时重试次数和机制,并使用异步机制探测回复情况
2)失败次数降级:主要是一些不稳定的api,当失败调用次数达到一定阀值自动降级,同样要使用异步机制探测回复情况
3)故障降级:比如要调用的远程服务挂掉了(网络故障、DNS故障、http服务返回错误的状态码、rpc服务抛出异常),则可以直接降级。降级后的处理方案有:默认值(比如库存服务挂了,返回默认现货)、兜底数据(比如广告挂了,返回提前准备好的一些静态页面)、缓存(之前暂存的一些缓存数据)
4)限流降级:秒杀或者抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)。
入门案例
在模块下的service包中新建降级配置类
在中指定降级配置类
在springcloud-consumer-dept-feign模块中开启降级:
熔断,降级,限流: 熔断:依赖的下游服务故障触发熔断,避免引发本系统崩溃;系统自动执行和恢复 降级:服务分优先级,牺牲非核心服务(不可用),保证核心服务稳定;从整体负荷考虑; 限流:限制并发的请求访问量,超过阈值则拒绝;
新建springcloud-consumer-hystrix-dashboard模块 添加依赖
主启动类
给模块下的主启动类添加如下代码,添加监控
什么是zuul? Zull包含了对请求的路由(用来跳转的)和过滤两个最主要功能:
注意:Zuul 服务最终还是会注册进 Eureka
提供:代理 + 路由 + 过滤 三大功能!
Zuul 能干嘛?
新建springcloud-zuul模块,并导入依赖
配置application.yml:增加了zuul配置
可以看出Zull路由网关被注册到Eureka注册中心中了!
我们看到,微服务名称被替换并隐藏,换成了我们自定义的微服务名称mydept,同时加上了前缀yang,这样就做到了对路由fan访问的加密处理!
Dalston.RELEASE
Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server,您可以在所有环境中管理应用程序的外部属性。客户端和服务器上的概念映射与Spring 和抽象相同,因此它们与Spring应用程序非常契合,但可以与任何以任何语言运行的应用程序一起使用。随着应用程序通过从开发人员到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。很容易添加替代实现,并使用Spring配置将其插入。
分布式系统面临的–配置文件问题
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务,由于每个服务都需要必要的配置信息才能运行,所以一套集中式的,动态的配置管理设施是必不可少的。spring cloud提供了configServer来解决这个问题,我们每一个微服务自己带着一个application.yml,那上百个的配置文件修改起来,令人头疼!
spring cloud config 为微服务架构中的微服务提供集中化的外部支持,配置服务器为各个不同微服务应用的所有环节提供了一个中心化的外部配置。
spring cloud config 分为服务端和客户端两部分。
服务端也称为 分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密,解密信息等访问接口。
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理。并且可用通过git客户端工具来方便的管理和访问配置内容。
spring cloud config 分布式配置中心能干嘛?
集中式管理配置文件 不同环境,不同配置,动态化的配置更新,分环境部署,比如 /dev /test /prod /beta /release 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息 当配置发生变动时,服务不需要重启,即可感知到配置的变化,并应用新的配置 将配置信息以REST接口的形式暴露
spring cloud config 分布式配置中心与GitHub整合
由于spring cloud config 默认使用git来存储配置文件 (也有其他方式,比如自持SVN 和本地文件),但是最推荐的还是git ,而且使用的是 http / https 访问的形式。
git命令:
将本地git仓库springcloud-config文件夹下新建的application.yml提交到码云仓库:
新建springcloud-config-server-3344模块导入pom.xml依赖
resource下创建application.yml配置文件,Spring Cloud Config服务器从git存储库(必须提供)为远程客户端提供配置:
定位资源的默认策略是克隆一个git仓库(在spring.cloud.config.server.git.uri),并使用它来初始化一个迷你SpringApplication。小应用程序的Environment用于枚举属性源并通过JSON端点发布。
HTTP服务具有以下格式的资源:
将本地git仓库springcloud-config文件夹下新建的config-client.yml提交到码云仓库: 注意,下面只能是三个横—
新建一个springcloud-config-client-3355模块,并导入依赖
resources下创建application.yml和bootstrap.yml配置文件 是系统级别的配置
系统级别的配置
是用户级别的配置
用户级别的配置
创建controller包下的 用于测试
测试:
这里配置文件内容不再列举直接到代码中看把。
新建模块,并将原来的模块下的内容拷贝的该模块。
1.清空该模块的配置,并新建连接远程配置
2.在pom.xml中添加spring cloud config依赖
3.主启动类
新建springcloud-config-dept-8001模块并拷贝springcloud-provider-dept-8001的内容
同理导入依赖、清空 、新建配置文件并配置