SpringCloud & Cloud Alibaba学习笔记
作者:互联网
SpringCloud Alibaba学习笔记
工程依赖:
<properties>
<springboot.version>2.2.2.RELEASE</springboot.version>
<springcloud.version>Hoxton.SR1</springcloud.version>
<springcloud.alibaba.version>2.1.0.RELEASE</springcloud.alibaba.version>
<lombok.version>1.18.12</lombok.version>
<mybatis.version>1.3.2</mybatis.version>
<mysql.version>8.0.21</mysql.version>
<druid.version>1.1.10</druid.version>
<slf4j.version>1.7.25</slf4j.version>
<logback.version>1.2.3</logback.version>
</properties>
<dependencyManagement>
<dependencies>
<!--springboot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springcloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${springcloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springcloud alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${springcloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!--slf4j-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!--logback-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
1、SpringCloud整合Zookeeper,代替Eureka
1、Linux上安装Zookeeper
2、导入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
3、主启动类上加上@EnableDiscoveryClient注解
2、OpenFeign
作用:主要用来做服务之间的调用
web客户端的接口绑定服务端的接口
OpenFeign在Feign的基础上支持SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方法产生实现类,实现类中做负载均衡并调用其它服务。
1、OpenFeign的基本使用
1、依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、主启动类上加上@EnableFeignClients注解
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OpenFeignConsumerOrderApplication80 {
public static void main(String[] args) {
SpringApplication.run(OpenFeignConsumerOrderApplication80.class,args);
}
}
3、消费端接口上加上@FeignClient(name = "服务名")与服务端接口进行绑定
-
服务端接口
@RestController
@RequestMapping("/payment")
public class PaymentController {
@Autowired
private PaymentService paymentService;
@PostMapping
public CommonResult add(@RequestBody Payment payment){
int result = paymentService.insert(payment);
if (result > 0){
return new CommonResult(200,"订单保存成功!,serverPort:" + serverPort,result);
} else {
return new CommonResult(444,"订单保存失败!,serverPort:" + serverPort);
}
}
@GetMapping
public CommonResult list(){
List<Payment> paymentList = paymentService.getPaymentList();
if (!paymentList.isEmpty()){
return new CommonResult(200,"查询成功!,serverPort:" + serverPort,paymentList);
} else {
return new CommonResult(443,"无数据!,serverPort:" + serverPort);
}
}
@GetMapping("/{id}")
public CommonResult get(@PathVariable("id") Long id){
Payment payment = paymentService.getPaymentById(id);
if (payment != null){
return new CommonResult(200,"查询成功!,serverPort:" + serverPort,payment);
} else {
return new CommonResult(443,"无数据!,serverPort:" + serverPort);
}
}
} -
消费端接口
@FeignClient(name = "服务名")
@RequestMapping("/payment")
public interface PaymentService {
@PostMapping
CommonResult add(@RequestBody Payment payment);
@GetMapping
CommonResult list();
@GetMapping("/{id}")
CommonResult get(@PathVariable("id") Long id);
}
2、OpenFeign客户端设置超时时间
OpenFeign客户端默认的超时时间为1s,超过1秒会报错
我们可以通过配置设置我们客户端的超时时间
1、application.yml配置
# 设置feign客户端的超时时间(OpenFeign默认支持Ribbon)
ribbon:
# 指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
ReadTimeout: 5000
# 指的是建立连接后从服务器读取到可用资源所用的时间
ConnectTimeout: 5000
3、OpenFeign日志增强
1、日志级别
NONE:默认的,不显示任何日志
BASIC:仅记录请求方法、URL、响应状态码及执行时间
HEADERS:除了BASIC中定义的信息除外,还有请求和响应的头信息
FULL:除了HEADERS定义的信息除外,还有请求和响应的正文及元数据
2、配置类
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
3、application.yml配置
logging:
level:
# feign日志以哪个级别监控哪个接口
com.study.springcloud.controller.FeignPaymentService: debug
3、Hystrix
导入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
1、服务降级
1、服务端
-
主启动类上加@EnableCircuitBreaker注解
-
接口上加上@HystrixCommand(fallbackMethod = "要降级调用的接口名")
2、客户端第一种解决办法
-
主启动类上加@EnableHystrix
-
application.yml配置
# 开启hystrix
feign:
hystrix:
enabled: true -
接口上加上@HystrixCommand(fallbackMethod = "要降级调用的方法名")
问题:每一个接口都要配置一个对应的服务降级的方法,代码冗余,业务逻辑也混在一块。
解决:在类上加==@DefaultProperties(defaultFallback = "要降级调用的方法名")==,接口上只要加上==@HystrixCommand==即可
3、客户端第二种解决办法
-
对Feign接口再创建一个进行服务降级的实现类与之对应,然后通过@FeignClient(name = "服务名",fallback= 降级实现类.class)的fallback 属性进行指定
2、服务熔断
@HystrixCommand(fallbackMethod = "f",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"), // 是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), // 请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 时间窗口期
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60") // 失败率达到多少后跳闸
})
3、服务限流
4、Gateway服务网关
1、Gateway三大核心理念
-
路由(Route)
-
断言(predicate)
-
过滤(Filter)
2、环境搭建
-
导入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>注意:以下jar包无需导入,如果有要去掉,否则报错
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency> -
application.yml配置
spring:
application:
name: springcloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_route # 路由的id,没有固定的规则,但要求唯一,建议配合服务名
# uri: http://localhost:8001 # 匹配后提供服务的路由地址
uri: lb://SPRINGCLOUD-PAYMENT-SERVER # 匹配后提供服务的路由地址
predicates:
- Path=/payment/** # 断言,路径相匹配则进行路由
也可以在代码里面配置,示例:
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route",
r -> r.path("/guonei")
.uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
}
3、配置自定义全局过滤器
@Component
@Slf4j
public class MyGatewayFilter implements GlobalFilter, Ordered {
/**
* 判断是否带用户名,没有则过滤
* @param exchange
* @param chain
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("***********com in MyGatewayFilter:" + new Date());
String name = exchange.getRequest().getQueryParams().getFirst("username");
if (name == null){
log.info("用户名为空,非法用户!");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
5、Config配置中心
Config也分为服务端与客户端,服务端也是单独的一个服务。
1、服务端配置
-
导入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency> -
application.yml配置
spring:
cloud:
config:
server:
git:
uri: https://..... # 远程仓库地址
# 搜索目录
search-paths:
- springcloud-config
# 读取分支
label: master -
主启动类上添加@EnableConfigServer注解
2、客户端配置
-
导入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency> -
bootstrap.yml配置文件
spring:
cloud:
# 配置中心客户端
config:
label: master # 分支名
name: springcloud-config-client # 配置文件名称
profile: dev # 读取后缀名称
uri: http://localhost:3344 # 配置中心地址 -
主启动类上添加@EnableEurekaClient注解
问题:当远程仓库配置文件内容改动后,客户端读取不到最新配置。
解决:
-
第一步:bootstrap.yml配置文件添加如下配置:
# 暴露监控端点
management:
endpoints:
web:
exposure:
include: "*" -
第二步:在我们的Controller类上加上@RefreshScope注解
-
第三步:也是最关键的一步,需要手动向客户端发送一个指定的POST请求:http://主机:端口号/actuator/refresh进行手动刷新
6、Bus消息总线
Config客户端虽然解决了动态刷新配置,但需要手动刷新,如果有多台服务就要刷新多台。如果我们只想刷新一次,全局广播怎么办呢?
什么是消息总线?
在微服务架构系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有的微服务实例都连接上来。由于该主题中产生的消息会被所有的实例监听和消费,所以称他为消息总线。在总线的各个实例,都可以广播一些需要让其它连接在该主题上的实例都知道的消息。
基本原理:
所有ConfigClient实例都监听MQ中的同一个topic(默认是springCloudBus)。但一个服务刷新数据的时候,他会把这个信息放入Topic中,这样其它监听同一个Topic的服务就能得到通知,然后去更新自身的配置。
==环境:需要消息中间件,这里使用的是RabbitMQ==
1、Config配置中心服务端配置
1、导入jar包
<!--RabbitMQ bus-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<!--Config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
2、application.yml配置
spring:
cloud:
config:
server:
git:
uri: https://... # 远程仓库地址
# 搜索目录
search-paths:
- springcloud-config
# 读取分支
label: master
# RabbitMQ相关配置
rabbitmq:
host: localhost
port: 15672
username: guest
password: guest
# rabbitmq相关配置,暴露bus,刷新配置的端点
management:
endpoints:
web:
exposure:
include: 'bus-refresh'
3、主配置类上添加@EnableConfigServer注解
2、Config配置中心客户端配置
1、导入jar包
<!--RabbitMQ bus-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<!--Config client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2、bootstrap.yml配置
spring:
application:
name: springcloud-config-client
cloud:
# 配置中心客户端
config:
label: master # 分支名
name: cloudalibaba-config-client # 配置文件名称
profile: dev # 读取后缀名称
uri: http://localhost:3344 # 配置中心地址
# RabbitMQ相关配置
rabbitmq:
host: localhost
port: 15672
username: guest
password: guest
# 暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
3、Controller类上加上@RefreshScope注解
3、配置刷新
1、全局通知刷新
向Config配置中心服务端发送指定POST请求:http://服务端ip:端口/actuator/bus-refresh
2、指定服务刷新
向Config配置中心服务端发送指定POST请求:http://服务端ip:端口/actuator/bus-refresh/{客户端服务名:端口号}
7、SpringCloud Stream
3、重复消费问题:
在Stream中处于同一group中的多个消费者是竞争关系,就能够保证消息只会被其中一个应用消费一次。
不同组是可以重复消费的
同一组内会发生竞争关系,只有其中一个可以消费
4、消费持久化:
8、Nacos
什么是Nacos?
Nacos是一个服务注册中心和配置中心,相当于等于SpringCloud的 Eureka + Config + Bus
9、Seata
TC - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
标签:spring,配置,springframework,Alibaba,Cloud,SpringCloud,org,cloud,客户端 来源: https://www.cnblogs.com/zhouqiangshuo/p/16511963.html