SpringCloud微服务入门
注:个人的学习是通过视频的讲解、阅读相关数据、进行实践、记录笔记进行的,希望与君共勉。个人的实验环境是Windows7,64位,内存16G,建议16G否则效果很差。
下面是我启动三个注册中心,一个路由网关一个服务器端进行测试,使用内存启动后占11~12G
前提条件:在进行接下来的实现希望读者知道java的一些知识、mybatis、spring、springboot、mysql、json、maven等相关的知识。
如果读者没有学过maven,可以花几分钟读简单看一看maven创建项目的一篇博客:
如果有什么需要的maven的依赖可以进行搜索
springCloud官方网站,有各种的组件:
SpringCloud配置中文网址
注:SpringCloud 是一种生态,用来解决为服务中的一些问题
实现之前必须确定自己的SpringBoot与自己的SpringCloud版本号是否对应,如果不对应就会有各种错误。
微服务中的主要问题
1.微服务较多,客户端如何访问?
2.服务器端之间的交互方式?
3.服务雪崩,服务器挂掉怎么办?
4.服务多是如何管理的?
我们带着问题去进行学习,最后我们对于技术有一个宏观的把控
基本概念:API网关、HTTP/RPC、注册与发现、熔断机制(问题产生的根本原因:网络不可靠)
下面是一些常见的面试中的问题:
微服务之间如何通讯?
1.SpringCloud和Dubbo的区别?
Doubbo只是为了实现服务治理,而Spring Cloud是一种生态,是微服务的一种架构,实现了微服务的方方面面,服务治理知识其中一部分
微服务核心 | Dubbo | Spring Cloud |
---|---|---|
服务注册中心 | Zookeeper、Redis | SpringCloud Netflix Eureka |
服务调用方式 | RPC | REST API |
服务网关 | 无 | Spring Cloud Netflix Zuul |
断路器 | 不完善 | Spring Cloud Netflix Hystrix |
分布式配置 | 无 | Spring Cloudconfig |
分布式追踪系统 | 无 | Spring Cloud Sleuth |
消息总线 | 无 | Spring Cloud Bus |
数据流 | 无 | Spring Cloud Stream |
批量任务 | 无 | Spring Cloud Task |
2.SpringBoot和Spring Cloud的理解
Spring是一个快速的开发框架,可以通过maven依赖的继承方式,快速整合第三方的常用框架,完全采用注解化,简化xml配置。
SpringCloud是一整套的微服务框架,是一种生态,是一系列框架的集合。springCloud依赖springboot
3.什么是服务熔断?什么是服务降级?(正文中有答案)
4.微服务的优缺点是什么?
可以参考网上的教程:
优点:
1.每个服务都比较简单,只关注一个业务功能
2.微服务架构方式是松耦合的,可以提供更高的灵活性
3.微服务可以通过最佳及最合适的不同的编程语言与工具进行开发
4.每个微服务可由不同的团队独立开发,互不影响,加快推出市场的速度
5.微服务架构是持续交付的巨大推动力,允许在频繁发布不同服务同时保持系统其它部分的可用性和稳定性
缺点:
1.运维的开销以及成本的增加
2.需要有一定的开发运维一体化技术
3.隐式的接口及接口匹配问题
4.代码重复问题
5.分布式系统的复杂性
6.一部机制
5.你知道的微服务技术栈有哪些?
微服务开发条目 | 实现的技术 |
---|---|
服务开发 | SpringBoot、Spring、SpringMvc |
服务配置与管理 | Netflix公司的Arcaius、阿里的Diamond |
服务注册与发现 | Eureka、consul、Zookeeper |
服务调用 | Rest、RPC、gRpc |
服务熔断器 | Hystrix、Envoy |
负载均衡 | Ribbon、Nginx |
服务接口调用 | Fegin |
消息队列 | Kafka、RabbitMQ、ActiveMq |
服务配置中心管理 | SpringCloudConfig、chef |
服务路由 | Zuul |
服务监控 | Zabbix、Nagious、Metrics、Specataor |
全链路追踪 | Zipkin、Brave、Dapper |
服务部署 | Docker、Openstack、Kubernetes |
数据流操作开发包 | SpringCloud Stream(封装Redis、Rabbit、Kafka) |
事件消息总线 | SpringCloud BUS |
6.eureka和zookeeper都可以提供服务注册与发现的功能,区别是什么?
CAP理论支出,一个分布式系统不可能同时满足C(一致性)、A(可用性)、P(容错性),分区容错性P在分布式系统中是必须保证的,因此我们只能在A和C之间权衡。
eureka保证AP原则;zookeeper保证CP
zookeeper可以容忍注册中心返回几分钟以前的注册信息,但不能接受服务直接挂掉,主服务器挂掉后其他的节点进行选举产生一个新的领导者,选举时间中服务不可用,服务瘫痪,导致长期服务不可以注册
Eureka首先保证了可用性,Eureka的各个节点是平等的,几个节点挂掉不会影响正常的节点工作,剩余的节点依旧可以提供注册和查询,只要注册中心有一台服务器可以使用,就可以保证注册中心的可用。
Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,不会像zookeeper那样使得整个注册服务瘫痪
微服务中一般分为三大角色:
服务注册中心:用于提供服务的注册与发现
服务提供者:将自身的服务注册到服务中心
服务的消费者:从服务注册中心获取服务
Eureka服务注册与发现(相当于Zookeeper)
Eureka是一个Netflix的一个子模块,也是核心模块之一。Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移,服务注册与发现对于微服务是相当重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务器调用的配置文件了,功能类似于Dubbo的注册中心。
原理讲解:
Eureka的基本架构:
SpringCloud封装了NetFlix公司开发的Eureka模块来实现服务注册和发现
Eureka采用CS架构设计,EurekaServer作为服务注册功能的服务器,用来服务使得注册
Eureka的客户端连接到EurekaServer并维持心跳连接。这样系统维护人员就可以通过EurekaServer来监控系统各个微服务是否正常运行,SpringCloud的一些其他模块就可以通过EurekaServer来发现系统中的其他微服务,并执行相关的逻辑
自我保护机制:
某一时刻一个微服务不能够使用时,eureka不会立刻清理,依旧会对该微服务的信息进行保存。
默认情况下,Eureka在一定的时间内没有接收到某个服务实例的心跳,EurekaServer将会注销该实例,但是当网络分区故障发生时,微服务与Eureka之间无法进行正常通信,以上行为将会非常危险,因为微服务本身是健康的,此时本不应该注销这个服务。Eureka的自我保护机制来解决这个问题,当EurekaServer节点在短时间内丢失过多的客户端时,那么这个节点就会进入自我保护模式,一旦进入自我保护模式,EurekaServer就会保护服务注册表中的信息,不再删除服务注册表中的数据。当网络故障恢复后,该EurekaServer节点会自动退出自我保存模式。自我保护模式是一种应用网络异常的安全保护措施,宁可同时保留所有的服务,也不盲目注销任何健康的微服务。
可以手动设置取消自我保护模式:eureka.server.enable-self-preservation = false禁止自我保护模式。
CAP原则:
RDBMS(mysql、oracle、sqlserver)——-ACID
NoSql(redis、Mongdb)—–CAP
ACID:
原子性:Atomicity 一致性:Consistency
隔离性:Isolation 持久性:Durability
CAP:
强一致性:Consitency 可用性:Availability 分区容错性:Partition toleration
CAP三者只能满足两个。
CAP核心:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性。
一般都是两个满足,
CA:单点集群,满足一致性,可用性的系统,通常可扩展性比较差
CP:满足一致性,分区容错性的系统,通常性能不是特别高
AP:满足可用性,分区容错性系统,通常可能对一致性要求低一些
Eureka实现的是AP原则、Zookeeper实现遵循的是CP
Ribbon:
ribbon是什么?
SpringCloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具
主要功能是提供客户端的软件负载均衡算法,将NetFlix的中间层服务连接在一起,Ribbon的客户端组件提供一系列完整的配置:连接超时、重试等。就是在配置文件中列出负载均衡LoadBalancer后的所有机器,Ribbon会基于某种规则去连接这些机器。
常见的负载均衡算法:(不是值Ribbon中的负载均衡算法,与之相关)
1.轮询均衡(Round Robin):每次来自网络的请求轮流分配给内部服务器,从1到N然后重新开始,这种均衡算法适合服务组中的所有服务器都有相同的硬件配置并且平均服务请求相对均衡的情况
2.权重轮询均衡(Weighted Round Robin):根据服务器不同的处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。简单来说就是使得每个服务器有不同的使用率,高性能使用率更高
3.随机均衡(Random):将请求随机分配给内部的服务器
4.权重随机均衡(Weight Random):此种均衡算法类似于权重轮循算法,不过在处理请求分担时是个随机选择的过程。
5.响应速度均衡(Response Time探测时间):负载均衡设备对内部各服务器发出一个探测请求(例如 Ping),然后根据内部中各服务器对探测请求的最快响应时间来决定哪一台服务器来响应客户端的服务请求。
6.最少连接数均衡(Last Connection):最少连接数均衡算法对内部中需负载的每一台服务器都有一个数据记录,记录当前该服务器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器,使均衡更加符合实际情况,负载更加均衡。此种均衡算法适合长时处理的请求服务,如 FTP。
7.处理器能力均衡(cpu、内存):把服务请求分配给内部中处理负荷(根据服务器 CPU 型号、 CPU 数量、内存大小及当前连接数等换算而成)最轻的服务器
8.DNS响应均衡(Flash DNS):把此域名解析成各自相对应服务器的 IP 地址并返回给客户端, 则客户端将以最先收到的域名解析 IP 地址来继续请求服务,而忽略其它的 IP 地址响应
9.哈希算法:一致性 Hash,相同参数的请求总是发到同一提供者。当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
10.IP地址散列:管理发送方 IP 和目的地 IP 地址的散列,将来自同一发送方的分组(或发送至同一目的地的分
组)统一转发到相同服务器的算法。 保证来自相同客户端的通信能够一直在同一服务器中进行处理。11.URL散列:通过管理客户端请求 URL 信息的散列,将发送至相同 URL 的请求转发至同一服务器的算法
客户端配置Ribbon:导入依赖,添加配置,添加注解@LoadBalance
Feign负载均衡:是声明式的webService客户端,它让微服务之间的调用变得简单,类似于controller调用service,springCloud集成了Ribbon和Eureka,可以使用Feign时提供负载均衡的http客户端,需要创建一个接口并添加注解。
//使用Feign需要写一个接口,对其接口进行注解配置
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER")
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id);
@GetMapping("/dept/list")
public List<Dept> queryAll();
@PostMapping("/dept/add")
public boolean addDept(Dept dept);
}
feign是通过接口和注解的方式,ribbon是通过微服务的名称来进行负载均衡,Ribbon+RestTemplate是利用RestTemplate对Http请求的封装处理,形成了一套模板化的调用方法,实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口或被多处调用,因此通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务调用。Feign在此基础上进行了进一步的封装,使用它定义和实现依赖服务接口的定义,在Feign实现下,我们只需要创建一个接口并使用注解的方式配置它,简化了SpringCLoud Ribbon,自行封装服务调用客户端的并发量。
常用的负载均衡的软件有Nginx、LVS
服务雪崩:多个服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出”,如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,引起系统崩溃,即所谓的雪崩效应。
Hystrix服务熔断: 服务降级、服务熔断、服务限流、接近实时监控
Hystrix是一个处于分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等。Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控,向调用方式返回一个服务预期的、可处理的备选响应,而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证服务调用方线程不会被长时间不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
当 Hystrix Command 请求后端服务失败数量超过一定比例(默认 50%), 断路器会
切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态
一段时间后(默认 5 秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况,
如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix 的断路器
就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效
请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力
//服务端程序,服务端在服务有网络延时或者异常因此的服务熔断进行备选处理
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@HystrixCommand(fallbackMethod = "hystrixGet")
@GetMapping("/dept/get/{id}")
public Dept get(@PathVariable("id") Long id){
Dept dept = deptService.queryById(id);
if(dept == null){
throw new RuntimeException("id=>"+id+",不存在用户,或者信息无法找到");
}
return dept;
}
//备选方法
public Dept hystrixGet(@PathVariable("id") Long id){
return new Dept().setDeptno(id)
.setDeptname("id=>"+id+"没有对应的信息,null")
.setDb_source("没有对应的数据库信息");
}
}
Hystrix是服务器端的处理:
/**
* @author itxing
* @create 2020/5/16-spring_cloud
*/
@SpringBootApplication
@EnableEurekaClient //配置Eureka客户端,自动将服务配置到注册中心
@EnableDiscoveryClient//服务发现
@EnableCircuitBreaker //注解断路器
public class DeptProviderHytris {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHytris.class,args);
}
}
Hystrix-dashboard:监控页,使用时需要确认服务端的信息是否有actuator监控信息
服务降级:是在客户端进行
//在接口处添加服务降级处理的实现类信息
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id);
@GetMapping("/dept/list")
public List<Dept> queryAll();
@PostMapping("/dept/add")
public boolean addDept(Dept dept);
}
服务降级实现类如下,服务降级是由客户端访问过高引起部分服务进行暂停用来处理高并发的服务,因此使用Feign尽心相关的配置:
/**
* @author itxing
* @create 2020/5/16-spring_cloud
*
* 服务降级
*/
public class DeptClientServiceFallbackFactory implements FallbackFactory {
@Override
public Object create(Throwable throwable) {
return new DeptClientService() {
@Override
public Dept queryById(Long id) {
return new Dept().setDeptno(id)
.setDeptname("id=>"+id+" 没有对应的信息,客户端使用降级,服务暂时停止")
.setDb_source("数据源暂时关闭");
}
@Override
public List<Dept> queryAll() {
return null;
}
@Override
public boolean addDept(Dept dept) {
return false;
}
};
}
}
客户端的yaml的配置:
server:
port: 8002
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka8003.com:8003/eureka/,http://eureka8004.com:8004/eureka/,http://eureka8005.com:8005/eureka/
feign:
hystrix:
enabled: true
API网关:
API Gateway是一个服务器,也可以说是进入系统的唯一节点。与设计模式中的Facade模式相似,APIGateWay封装内部系统的架构,并且提供API给各个客户端,还有其他的功能,例如:授权、监控、负载均衡、缓存、请求分片和管理、静态响应处理。API网关负责请求转发、合成和协议转换,通过调用多个微服务来处理一个请求以及聚合多个服务的结果。请求转发、响应合并、协议转换、数据转换、安全认证。
Zuul路由网关: 功能是路由+过滤
Zuul路由包含了请求的路由和过滤两个最主要的功能。路由功能是将一些具体的请求转发到具体的微服务实例上,是实现外部访问同一入口的基础,而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础。zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获取其他服务消息。
application.yml与bootstrap.yml区别是:前者是用户级别的配置,后者是系统级别的配置
SpringBoot启动类上需要加入注解:@EnableZuulProxy
路由网关的yaml配置:
server:
port: 9527
spring:
application:
name: springcloud-zuul
eureka:
client:
service-url:
defaultZone: http://eureka8003.com:8003/eureka/,http://eureka8004.com:8004/eureka/,http://eureka8005.com:8005/eureka/
instance:
instance-id: zuul9527.com
prefer-ip-address: true
info:
app.name: itxing-springcloud
company.name: itxing.com
zuul:
routes:
mydept.serviceId: spring-provider-dept
mydept.path: /mydept/**
ignored-services: "*"#springcloud-provider-dept
prefix: /itxing
扩展:
REST(Resource Representational State Transfer):资源表述性状态转移
HTTP动作设计:
GET:从服务器取出资源
POST:在服务器新建一个资源
PUT:在服务器更新一个资源,PUT更新整个对象
PATCH:在服务器更新一个资源,只更新个别属性
DELETE:从服务器删除资源
HEAD:获取一个资源的元数据,比如一个资源的hash值或最后修改日期
OPTIONS:获得客户端针对一个资源能够实施的操作(获取该资源的api)
状态码:
200 服务器成功返回用户请求的数据 201 用户新建或修改数据成功
202 表示一个请求已经进入后台排队 204 用户删除数据成功
400 用户发出的请求有错误,服务器没有进行新建或修改数据的操作
401 表示用户没有权限,令牌、密码等问题
403 用户得到授权但访问被禁止 404 用户请求的是不存在的记录
406 用户请求的资源被永久删除,且不会再得到 410 用户请求的资源被永久删除,且不会再得到
422 当创建一个对象时,发生一个验证错误 500 服务器发生错误,用户将无法判断发出的请求是否成功
Accept属于请求头,Content-Type属于实体头,只出现在Request中,表示自己希望接收到什么样的数据类型。