1、springcloud概述
springcloud是将市面上比较好用的一些组件纳入到体系当中,方便程序员使用。
1、eureka:注册与发现
2、ribbon:同一个serviceid 负载均衡访问
3、feigh:优雅调用http
4、hystrix:服务熔断产品,可以做到服务降级,如果遇到超时或者异常的情况可以跳转到降级方法
5、sentinel:服务熔断产品,和hystrix不同的是,可以用控制台的方式配置限流,熔断等信息,更灵活
6、gateway:网关,只需要访问该服务,就可以跳转到其他服务。并且可以在该服务上配置路由和过滤器,也就更方便了权限鉴定
2、自己做分布式遇到的问题
1、地址维护
2、负载均衡
3、配置统一管理
4、链路追踪
3、eureka
1、eureka简介
提供注册与发现,核心为以下内容:
1、eureka server
提供服务与发现
2.、service provider
服务提供方,将自身注册到eureka,供消费者使用
3、service consumer
消费服务
2、配置eureka
1、配置父pom.xml
<!--父工程jar-->
<!--标识是一个springboot项目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--springboot 自动配置 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.1.11.RELEASE</version>
<scope>compile</scope>
</dependency>
<!--提供springboot组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!--springcloud版本-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2、配置eureka下的pom.xml
<!--eureka配置-->
<!--eureka-server-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
3、配置application.xml
不需要将自己注册到eureka,也不需要从eureka获取数据
server:
port: 9000
eureka:
instance:
hostname: localhost #主机
client:
register-with-eureka: false #是否将自己注册到eureka
fetch-registry: false #是否从注册中心获取数据
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
4、启动类
@SpringBootApplication
@EnableEurekaServer //启动一个eureka
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class,args);
}
}
3、配置提供方
1、引入eureka client
<!--表明是一个eurekaclient-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2、注册到eureka和配置eureka地址
server:
port: 8080
spring:
application:
name: service-goods #服务名称
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/ #配置eureka的链接
fetch-registry: false #不从eureka获取数据
register-with-eureka: true #将自己注册到eureka
4、配置消费方
1、引入pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
2、application.yml
修改服务名称,修改为从eureka获取数据,和不把自己注册到eureka
3、发送请求
注入DiscoveryClient可以获得serviceid的信息
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
ServiceInstance serviceInstance = instances.get(0);
String host = serviceInstance.getHost();//路径
int port = serviceInstance.getPort(); //端口
5、配置集群
1、多个eureka互相注册,注册自己到eureka上和从eureka获取数据
2、提供端和消费端注册多个eureka,逗号拼接
6、其他问题
1、提供方ip地址方式注册到eureka
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port}
2、提供方设置心跳与宕机时间
默认提供方每30秒向eureka发送心跳,90秒没有心跳则表示宕机
lease-expiration-duration-in-seconds: 10 #10秒没有心跳就表示宕机
lease-renewal-interval-in-seconds: 5 #每5秒发送一次心跳
3、自我保护机制
如果eureka 发现所有的服务都不可用,则会触发自我保护机制,不会剔除服务
eureka配置
server:
enable-self-preservation: false #关闭自我保护机制
eviction-interval-timer-in-ms: 4000 #4秒一次剔除服务
4、ribbon负载均衡
1、基本操作
1、在RestTemplate上加@LoadBalanced
2、可以用serviceid获取访问到数据
2、修改负载均衡策略
1、com.netflix.loadbalancer.RoundRobinRule:轮询 (默认)
2、com.netflix.loadbalancer.RandomRule:随机
3、com.netflix.loadbalancer.RetryRule:重试策略,指定超时时间,超过超时时间,直接访问另外一个
4、com.netflix.loadbalancer.WeightedResponseTimeRule :权重
5、com.netflix.loadbalancer.BestAvailableRule:最佳策略,请求的是请求量最小的ip
6、com.netflix.loadbalancer.AvailabilityFilteringRule:找到可用的ip,轮询
消费方修改配置文件
service-product:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡策略为随机
5、feigh优雅调用http
1、feign调用方式
1、消费方注入依赖
<!--feigh-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
2、消费方application添加注解开启feign
@EnableFeignClients
3、添加feignClient,需要是一个接口
1、添加注解,传入服务id
@FeignClient("service-goods")
2、添加@requestMapping
@FeignClient("service-goods")
public interface GoodsClient {
@RequestMapping("/goods/get/{id}")
String getById(@PathVariable("id") Long id);
}
4、将client注入到controller,就可以调用了
2、注意事项
1、内部本身就是轮询方式,如果需要修改负载均衡方式,和ribbon修改的配置一样。feign是ribbon的改进
2、消费方打印日志
feign:
client:
config:
service-goods: #服务名称
loggerLevel: FULL #日志等级
logging:
level:
com.springcloud.order.feigh.GoodsClient: debug #对该接口增加日志
6、hystrix熔断
1、hystrix特性
1、线程隔离
保证了线程与线程之间的访问效率不会互相收到影响
2、跳闸机制
错误达到一定层度,停止访问该请求
3、资源隔离
请求到达一定程度,直接返回失败
4、监控
可以实时看到成功,失败,超时等请求
5、回退机制
访问失败,可以直接回退
6、自我修复
熔断器开启一段时间,自动进入半开状态
2、操作
1、restTemplate操作
1、消费者引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
2、激活hystrix
@EnableCircuitBreaker
3、增加降级方法,如果默认1秒内没有返回消息,降级方法参数可以和执行的方法一致,可以获取到执行方法的参数
/**
* 降级方法
* 和需要降级的,返回值,参数一致
* */
public String orderCallBack(Long goodsId){
return "触发降级方法";
}
4、执行的方法上增加降级的方法名称
@HystrixCommand(fallbackMethod = "orderCallBack")
5、也可以指定默认的降级方法
1、类上增加注解,但是需要注意,该方法不能有参数
@DefaultProperties(defaultFallback = "orderCallBack")
2、方法上的@HystrixCommand为空
6、修改链接超时时间
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 #链接超时时间 3秒没有返回逻辑 自动触发降级逻辑
2、feign配置
1、feign配置开启hystrix组件
hystrix:
enabled: true
2、对feign接口添加callback实现类
@Component
public class GoodsClientCallback implements GoodsClient {
@Override
public String getById(Long id) {
return "熔断降级方法";
}
}
3、在feign接口的@FeignClient增加fallback返回类
@FeignClient(value = "service-goods",fallback = GoodsClientCallback.class)
3、监控信息
1、引入依赖
<!--hystrix监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
2、暴露所有接口
management:
endpoints:
web:
exposure:
include: '*' #暴露所有接口
3、访问该接口就可以查询到所有熔断的内容
http://localhost:8081/actuator/hystrix.stream
4、启动类上增加注解
@EnableCircuitBreaker // 开启熔断
@EnableHystrixDashboard //开启hystrix的web监控平台
5、输入连接,打开监控平台,输入stream结尾的链接,就可以图形化方式看到熔断情况
6、可以搭建工程监控所有的熔断
1、新建工程turbine
2、添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
3、yml配置
server:
port: 8031
spring:
application:
name: turbine #服务名称
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/ #配置eureka的链接
instance:
prefer-ip-address: true #使用ip地址注册
turbine:
app-config: service-order #监管的服务
cluster-name-expression: "'default'"
4、启动类增加注解
@SpringBootApplication
@EnableTurbine
@EnableHystrixDashboard
5、打开http://localhost:8031/hystrix/链接,输入 http://localhost:8031/actuator/hystrix.stream,即可看到监控的信息
4、断路器
请求20次,如果二分之一的请求都报错,断路器打开,所有请求进入降级方法,5秒一次释放一个请求,如果该请求可以访问,则关闭断路器
5、隔离级别
1、线程池隔离(默认)
线程池处理当前请求,堆积的请求进入线程池队列
坏处:线程会有开销
好处:新进入的请求会进入线程池队列等待处理
2、信号量隔离
对线程数进行计数,到达最大线程数,以后的线程不做处理
hystrix:
command:
default:
execution:
isolation:
strategy: ExecutionIsolationStrategy.SEMPHORE #信号量隔离
# strategy: ExecutionIsolationStrategy.THREAD #线程池隔离
7、Alibaba sentinel
1、简介
支持信号量隔离,并发限流,可以做到很好的限流。可以灵活的控制流量控制,异常控制
2、配置
1、下载sentinel-dashboard-1.8.1.jar
https://github.com/alibaba/Sentinel/releases
2、cmd执行命令启动
java -Dserver.port=8808 -Dcsp:sentiel.dashboard.server=localhost:8808=Dproject.name=sentinel-dashboard -jar jar包名称
http:.//localhost:8808 打开
3、登录 默认账号密码 sentinel/sentinel
4、引入依赖,需要先注意版本
1、父工程引入alibaba的依赖 放入dependencyManagement中
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
2、要监控的工程增加依赖
<!--子工程引入sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel</artifactId>
</dependency>
3、配置sentinel连接
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8808
3、配置降级
1、可以单独配置熔断降级和异常降级
@SentinelResource(
blockHandler = "orderBlockCallBack", // 熔断降级
fallback = "orderFallBack" //异常降级
)
2、sentinel控制台配置降级规则
3、持久化配置文件,下次启动还能看到该配置
spring:
cloud:
sentinel:
datasource:
ds1:
file:
file: classpath:flowrule.json #配置本地规则
data-type: json
rule-type: flow
4、新增文件flowrule.json,配置以下内容,启动自动初始化规则:
[
{
"resource": "orderFindById",
"controlBehavior": 0,
"count": 1,
"grade": 1,
"limitApp": "default",
"strategy": 0
}
]
4、对feign的支持
1、引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、开启对sentinel的支持
feign:
sentinel:
enabled: true
3、feignClient指定发生熔断触发的类
@FeignClient(value = "service-goods",fallback = GoodsClientCallback.class)
7、gateway微服务网关
1、路由配置
1、创建工程 gateway_server,导入坐标,但由于和spring-boot-starter-web依赖冲突,需要将spring-boot-starter-web从父级移除,放到需要的包中
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
2、配置断言,转发到该服务器
spring:
cloud:
gateway:
routes:
- id: goods-service #随意填入
uri: http://127.0.0.1:8082
predicates:
- Path=/goods/** #断言 会拼接到ip后面
3、动态路由
动态的跳转到每个服务商,而不需要再去配置。其实就是从eureka中获取服务地址,而不再写死
1、添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2、添加eureka的信息,表明自己需要去拉取数据
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/ #配置eureka的链接
fetch-registry: true #从eureka获取数据
register-with-eureka: false #不将自己注册到eureka
3、 将uri修改为服务的id
uri: lb://service-goods
4、配置自动加后缀转发到服务器
例如:localhost:8080/服务名称/服务地址
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启根据名称自动转发
lower-case-service-id: true #小写
2、过滤器
分为单个url进行路由(gatewayFilter)和所有url进行路由(globalFilter)
1、gatewayFilter
可以为原始请求的参数,ip,请求头等信息进行路由
2、globalFilter
可以做权限鉴定,运行所有的服务,都会经过该过滤器。
以下代码为需要加userId的参数才可以过过滤器
@Component
public class LoginFilter implements GlobalFilter, Ordered {
/**
* 过滤器中的业务
* @param exchange
* @param chain
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("执行了登录过滤器");
String userId = exchange.getRequest().getQueryParams().getFirst("userId");
if(userId == null){
System.out.println("没有登录");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
//请求结束
return exchange.getResponse().setComplete();
}
//返回参数给下一个过滤器
return chain.filter(exchange);
}
/**
* 指定过滤器的顺序 返回值约小 优先级越高
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
3、gateway限流算法
1、计数器限流
当一段时间内超过设定的线程数,则关闭线程的访问
坏处:会有线程丢失
2、漏桶算法
网关内部维护一个队列,根据设置的输出频率,发出线程
坏处:不能应对突发流量
3、令牌桶算法
在桶的基础上增加了令牌的概念。例如一个桶最多可以有100个令牌,一个线程用一个令牌,一秒一次向桶中增加令牌。这样就能应对高并发也能有一定突发流量。
例如此时来了101个请求,100个请求可以正常访问,1个请求进入没有令牌不能访问,1秒后有令牌了,也就去访问了
4、gateway限流实现
可以用filter限流或者、sintinel限流
8、链路追踪
1、介绍
将请求还原成调用链路,进行日志记录,可以根据链路追踪查看每个节点的耗时情况
2、sleuth(死璐思)链路追踪
1、将依赖放到需要追踪的服务上,包括网关
<!--链路追踪-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
2、将日志配置放到需要追踪的服务上
logging:
level:
root: info
org.springframework.web.servlet.DispatcherServlet: DEBUF
org.springframework.cloud.sleuth: DEBUF
3、zipkin 展示链路追踪
1、下载
https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/
2、启动
java -jar zipkin-server-2.12.9-exec.jar
3、访问
4、给每个需要追踪的添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
5、给每个需要追踪的添加配置
spring:
zipkin:
base-url: http://127.0.0.1:9411/ #路径
sender:
type: web #发送类型
sleuth:
sampler:
probability: 1 #采样比
6、需要去掉sentinel的支持,去掉sentinel的依赖,配置文件中去掉sentinel相关配置
9、springCloudStream与rocketmq
1、介绍
给消息中间件解耦,通过在生产者和消费者中间增加一层“绑定层”,生产者通过“通道”发送,如果换消息中间件,只需要更换绑定器即可
2、生产者配置
1、添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、添加配置文件
server:
port: 7001
spring:
application:
name: rocket-producer #服务名称
cloud:
stream:
rocketmq:
binder: #绑定器
name-server: 192.168.149.134:9876
bindings:
output: #指定topic
destination: stream-test-topic
group: group1 #分组 同一个分组只有一个可以获得消息
3、添加工具类
@Component
@EnableBinding(Source.class)
public class MessageUtils {
@Autowired
private MessageChannel output;
public void send(Object obj){
//创建一个消息
boolean send = output.send(MessageBuilder.withPayload(obj).build());
}
}
3、消费者配置
1、加入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、加入配置
server:
port: 7003
spring:
application:
name: rocket-producer #服务名称
cloud:
stream:
rocketmq:
binder: #绑定器
name-server: 192.168.149.134:9876
bindings:
input: #指定topic 为input
destination: stream-test-topic
group: group1 #分组 同一个分组只有一个可以获得消息
3、监听代码
@Component
@EnableBinding(Sink.class)
public class MessageListener {
@StreamListener(Sink.INPUT)
public void input(String message){
System.out.println("接收的消息为:" + message);
}
}
10、springcloudconfig配置中心
1、配置
1、将配置文件复制到码云上,修改名字为 名称-pro dev 等
2、引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
3、引入配置
server:
port: 10000
spring:
application:
name: config-server #服务名称
cloud:
config:
server:
git:
uri: https://gitee.com/hanjievvvp/config-restory.git
4、启动类加 @EnableConfigServer 注解之后,启动项目就可以访问云上的配置文件了
5、其他项目删除application.yml,新增bootstrap.yml
spring:
cloud:
config:
name: goods #配置文件名称前半部分
profile: dev #配置文件名称后半部分
lable: master #分支
uri: http://localhost:10000
6、新增依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2、配置手动刷新
1、需要手动刷新的服务上增加
<!--config自动刷新-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、需要手动刷新的类上增加注解@RefreshScope
3、配置中增加动态刷新开关
management:
endpoints:
web:
exposure:
include: refresh #开启动态刷新
4、修改配置后,用post发送请求到该链接:http://localhost:8082/actuator/refresh