SpringCould
官方地址:http://projects.spring.io/spring-cloud/
文章目录
微服务核心基础
-
网关
-
服务注册发现
-
配置中心
-
链路追踪
-
负载均衡器
-
熔断
常见的微服务框架
- 调用方与被调用方
一个接口一般充分着这两个角色。例如订单接口可以调用用户接口,同时它也被调用。
服务提供者provider: 启动的时候向注册中心上报自己的网络信息。
服务消费者consumer: 启动的时候向注册中心上报自己的网络信息,拉取provider的相关网络信息。
-
dubbo
官方地址:http://dubbo.apache.org/#!/?lang=zh-cn
dubbo一般与zookeeper + springmvc/springboot整合使用。
通信方式: rpc (长连接)调用速度会快点。
注册中心: zookeper/redis。zookeper是分布式系统中的协调系统,可提供的服务主要有:配置服务、名字服务、分布式同步、组服务等。
配置中心:diamond 。淘宝内部使用的一个管理持久配置的系统,它的特点是简单、可靠、易用。
一般是电商项目,例如秒杀活动。这类要求调用速度高。dubbo调用速度快,但是组件不够齐全。 -
SpringCould
官网地址: http://projects.spring.io/spring-cloud/
通信方式:http restful
注册方式:eruka/consul
配置中心:config
断路器:hystrix
网关:zuul
分布式追踪系统:sleuth+zipkin
例如饿了么,订单系统。这类并发不是特别高的。
核心组件
注册中心
在微服务架构中最重要的组件就是注册中心。注册中心就是服务的管理,用于存储发布的服务信息,它的核心是服务注册表,心跳机制动态维护。
服务注册表记录当前可用的微服务实例的网络信息数据库,是服务发现机制的主要核心,服务注册表查询api、管理api,使用查询api获得可用服务的实例,使用管理api实现注册、注销。
心跳机制动态维护简单来说就是检查该接口集群某节点是否存活着。接口集群节点会定时发送心跳到注册中心,注册中心通过获取其心跳判断该节点是否依旧活着。
分布式CAP
CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得 [1] 。
一致性C:在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)。就是在同一时间的数据保持完全的一致。(数据一致性)
可用性A:负载过大,集群依旧能响应客户端读写请求。就像微博一样,当某某明星结婚了,突然涌入了一波粉丝的围观痛哭。这么大的负载依旧能正常访问。(正常响应时间)
分区容错性P:高可用性。当一个节点挂了不影响其他的节点。机器故障、网络故障、机房停电等异常情况下仍然能够满足一致性和可用性。(多节点部署)
在分布式系统中最多实现以上两点。由于当前的网络硬件肯定会出现延迟丢包等问题,分区容错性是必须实现的。就只能在一致性以及可用性中进行决择。(话说为什么只能实现两点。)
- C A 满足,P不能满足:
数据的同步需要时间,在正常时间内进行响应。机器越少,数据同步越快,可用性越高。而P需要多机器部署节点。 - C P满足,A 不能满足:
数据的同步C 需要时间,也可以进行多节点P的机器。这种情况下就很难进行正常时间内的响应。 - A P 满足,C不满足:
首先要在正常时间内响应,但是机器那么多,同步的时候数据时间会很长。这数据一致性就很难进行保证了。
注册中心选择
-
Zookeeper
CP设计(一致性,分区可容忍性)。当节点失效时候,会进行选举领导。当节点半数不可用时则无法提供服务。可用性无法满足!就像打仗时候,将军挂了换一个有能力的将军。一半士兵都挂了那还打什么呀,跑吧!打不过,打不过。(要求一致性就选Zookeeper 例如:金融行业)
-
Eureka
AP原则。去中心化,无主从节点。一个节点挂了,自动切换其他节点可用使用。就像是张全蛋说的,检查samsong手机就充电如果爆了就换下一个质检员。(要求可用性就用Eureka 例如:电商系统)
Eureka
- Eureka Service: 服务注册中心负责服务列表的注册、维护和查询等功能。
- Service Provider:服务提供者即(Eureka Client),负责将所提供的服务向Eureka Sevice进行注册、续约和注销等操作。注册时所提供的数据包括服务名、机器ip、端口号、域名等,从而能够使服务消费方能够找到。例如budget-service、auth-service。
- Service Consumer :服务消费者(Eureka Client),获取相应的服务列表,以便能够发起服务调用。同时它也可以向Eureka Server注册本身所提供的服务。例如budget-service、auth-service。
服务发现:Eureka Server
Start Eureka:
http://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#spring-cloud-eureka-server
1.首先使用IDEA创建新的项目
New ->Project->Spring Initializr ->Next->Cloud Discovery ->Eureka Server
2.添加注解 @EnableEurekaServer
@SpringBootApplication
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
3.增加配置application.yml
Standalone Mode(单例模式即单节点)
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
Ribbon与Feign
常用的调用方式一般是RPC、Rest(Http)。
RPC:
- 远程过程调用,像调用本地服务(方法)一样调用服务器的服务
- 支持同步、异步调用
- 客户端和服务器之间建立TCP连接,可以一次建立一个,也可以多个调用复用一次链接
- PRC数据包小
- protobuf、thrift
rpc:编解码,序列化,链接,丢包,协议
Rest(Http):
- http请求,支持多种协议和功能
- 开发方便成本低
- http数据包大
java开发:HttpClient,URLConnection
Ribbon与Feign一般是选择Fegin。它默认集成了ribbon,写起来思路清晰简洁,采用注解方式进行配置,配置熔断等方式方便。
Netflix-断路器Hystrix(豪猪)
在一个分布式系统里,一个服务依赖多个服务,可能出现调用某个服务失败。例如超时、异常等。如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,通过Hystrix就可以解决。
当某个服务响应太慢或者说挂掉了, 请求在堆积。Hystrix控制超时时间。例如一秒未进行响应后将断开,而不是排队。如果后续有一半请求依旧超时,那么会将该服务标记不可用,将不在调用。之后会尝试调用该服务,判断是否可用。
hystrix能够进行服务降级,服务熔断,服务限流,接近实时的监控。提供了熔断、隔离、Fallback、cache、监控等功能
https://github.com/Netflix/Hystrix
https://github.com/Netflix/Hystrix/wiki
Feign结合Hystrix断路器
Hystrix
-
加入依赖
注意:网上新旧版本问题,所以要以官网为主,不然部分注解会丢失最新版本 2.0<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
-
增加注解
启动类里面增加注解
@EnableCircuitBreaker //开启hystrixR熔断机制的支持 -
api方法上增加 @HystrixCommand(fallbackMethod = “saveOrderFail”)
可以在follbackMethod定义错误后续处理,例如发送短信等。
Feign中集成了Hystrix,提供对其的支持。
1)开启feign支持hystrix (注意,一定要开启,旧版本默认支持,新版本默认关闭)
feign:
hystrix:
enabled: true
2)FeignClient(name=“xxx”, fallback=xxx.class ), class需要继承当FeignClient的类
3)编写fallback实现类
Hystrix配置参数 HystrixCommandProperties
修改配置方式
- 修改配置文件yml
- 修改类注解 commanProperties
常用配置参数
1.execution.isolation.strategy 隔离策略
this.executionIsolationStrategy = getProperty(propertyPrefix, key, "execution.isolation.strategy", builder.getExecutionIsolationStrategy(), default_executionIsolationStrategy);
- THREAD 线程池隔离(默认)
- SEMAPHORE 信号量
信号量适用于接口高并发高的情况,如每秒数千次调用的情况,导致线程开销过高,通常只适用于非网络调用,执行速度块。
2.execution.isolation.thread.timeoutInMilliseconds 超时时间 (默认:1000)
this.executionTimeoutInMilliseconds = getProperty(propertyPrefix, key, "execution.isolation.thread.timeoutInMilliseconds", builder.getExecutionIsolationThreadTimeoutInMilliseconds(), default_executionTimeoutInMilliseconds);
private static final Integer default_executionTimeoutInMilliseconds = 1000;
3.execution.timeout.enabled 超时时间 (默认:开启)
this.executionTimeoutEnabled = getProperty(propertyPrefix, key, "execution.timeout.enabled", builder.getExecutionTimeoutEnabled(), default_executionTimeoutEnabled);
private static final Boolean default_executionTimeoutEnabled = true;
4.execution.isolation.semaphore.maxConcurrentRequests 隔离策略为信号量时,如果达到最大并发数时后续请求将被拒绝,默认是10。
this.executionIsolationSemaphoreMaxConcurrentRequests = getProperty(propertyPrefix, key, "execution.isolation.semaphore.maxConcurrentRequests", builder.getExecutionIsolationSemaphoreMaxConcurrentRequests(), default_executionIsolationSemaphoreMaxConcurrentRequests);
断路器Dashboard监控仪表盘
-
加入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
启动类增加注解
@EnableHystrixDashboard
-
配置文件增加endpoint
management: endpoints: web: exposure: include: "*"
-
访问入口
http://localhost:8781/hystrix Hystrix Dashboard输入: http://localhost:8781/actuator/hystrix.stream
-
参考资料
默认开启监控配置
https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-security-actuator配置文件类: spring-configuration-metadata.json
微服务网关zuul
API Gateway是系统唯一对外的入口,介于客户端与服务端之前的中间层,处理非业务功能,提供路由请求、鉴权、监控、缓存、限流等功能。简单理解它就是检票口或者售票处。
基本使用
-
加入依赖
-
启动类加入注解 @EnableZuulProxy
Zuul 网关过滤器
1、路由名称定义问题
路由映射重复覆盖问题
2、Http请求头过滤问题
ZuulProperties
private Set sensitiveHeaders = new LinkedHashSet<>( Arrays.asList(“Cookie”, “Set-Cookie”, “Authorization”));
3、过滤器执行顺序问题 ,过滤器的order值越小,越先执行
4、共享RequestContext,上下文对象
自定义Zuul过滤器实现登录鉴权
- 新建类实现ZuulFilter,重写方法
- 在类顶部加注解@Component
@Component
public class LoginFilter extends ZuulFilter {
/**
* FilterConstants 过滤器常量
* 过滤器类型:( PRE_TYPE:前置过滤器 POST_TYPE:后置过滤器)
* @return
*/
@Override
public String filterType() {
return PRE_TYPE;
}
/**
* 过滤器顺序越小,越先执行
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 过滤器是否生效: true、flase
* @return true : 执行run() 业务逻辑 flase:放行
*/
@Override
public boolean shouldFilter() {
//进行登录校验、是否拦截路径
/*
* 注意: 请求是否拦截?
* 项目大:ACL(访问控制列表) 动态匹配
* 项目小:if("/order/api/query".equalsIgnoreCase(request.getRequestURI()))
*/
return false;
}
/**
* 过滤器生效执行业务逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
return null;
}
}
Zuul高并发接口限流
在过年的时候,那高速就突然暴涨了好几倍,然后过不了多久你走高速比走国道还要慢,甚至万一有点事故。这种时候几乎是不能走了。那就需要开始限流。
常见的限流算法
参考文档:https://www.jianshu.com/p/0d7ca597ebd2
- 漏桶算法
漏桶算法思路很简单,请求先进入到漏桶里,漏桶以一定的速度出水,当水请求过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。 - 令牌桶算法
令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。
谷歌guava框架
Guava RateLimiter基于令牌桶算法,我们只需要告诉RateLimiter系统限制的QPS是多少,那么RateLimiter将以这个速度往桶里面放入令牌,然后请求的时候,通过tryAcquire()方法向RateLimiter获取许可(令牌)。
/**
* 订单限流
*/
@Component
public class OrderRateLimiterFilter extends ZuulFilter {
//每秒产生1000个令牌
private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000);
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return -4;
}
@Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//只对订单接口限流
if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())){
return true;
}
return false;
}
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
if(!RATE_LIMITER.tryAcquire()){
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
}
return null;
}
}
分布式链路追踪系统Sleuth、ZipKin
当你在微服务项目中去调用多模块或者依赖多接口,然后就这样阵亡了。一般通过打日志来进行埋点、远程服务器通过Linux查看日志。我们就需要一些可以帮助理解系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题,这就是所谓的 APM(应用性能管理)。分布式链路追踪系统记录了所有系统的调用和依赖,以及这些依赖之间的关系和性能。能够快速定位和解决问题。
Sleuth组件
官方文档: http://cloud.spring.io/spring-cloud-static/Finchley.SR1/single/spring-cloud.html#sleuth-adding-project
Sleuth是专门用于记录链路数据的开源组件。
[order-service,96f95a0dd81fe3ab,852ef4cfcdecabf3,false]
1、第一个值,spring.application.name的值
2、第二个值,96f95a0dd81fe3ab ,sleuth生成的一个ID,叫Trace ID,用来标识一条请求链路,一条请求链路中包含一个Trace ID,多个Span ID
3、第三个值,852ef4cfcdecabf3、spanid 基本的工作单元,获取元数据,如发送一个http
4、第四个值:false,是否要将该信息输出到zipkin服务中来收集和展示。
配置
超时配置:
默认optons readtimeout是60,但是由于hystrix默认是1秒超时
#修改调用超时时间
feign:
client:
config:
default:
connectTimeout: 2000
readTimeout: 2000