Token
/**
* jwt工具类
*/
public class JWTUtils {
// 签发人
private static final String ISSUSER = "itbaizhan";
//过期时间 5分钟
private static final long TOKEN_EXPIRE_TIME = 5*60*1000;
private static final String KEY = "WEAWEA..ASDA-=";
/**
* 生成令牌
*/
public static String token(){
Date now = new Date();
Algorithm algorithm =Algorithm.HMAC256(KEY);
//创建JWT
String token = JWT.create()
//签发人
.withIssuer(ISSUSER)
.withIssuedAt(now)
.withExpiresAt(new Date(now.getTime() + TOKEN_EXPIRE_TIME))
.sign(algorithm);
return token;
}
public static boolean verify(String token){
try {
Algorithm algorithm = Algorithm.HMAC256(KEY);
//1.验证令牌
JWTVerifier verifier = JWT.require(algorithm)
//签发人
.withIssuer(ISSUSER)
.build();
verifier.verify(token);
return true;
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (JWTVerificationException e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) {
//1.生成令牌
// String token = token();
// System.out.println(token);
boolean verify = verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpdGJhaXpoYW4iLCJleHAiOjE2NTgyNDM2NjgsImlhdCI6MTY1ODI0MzM2OH0.C7yjrLgaBvCg0WYMrQymJotkfaAOURGogn04Yb6oIXQ");
System.out.println(verify);
}
}
Spring cloud stream
消费方法
分组消费消息
分组消费:该组中只有一个消费者能够消费该信息 轮询
生产者配置:
消费者的配置:
SpringCloudAlibaba
解压nacos并且指定路径
启动服务器
sh startup.sh -m standalone 端口号默认8848
jps:查看进程
启动服务器 注意: standalone代表着单机模式运行
docker下载
docker pull nacos/nacos-server
docker run --name nacos -d -p 8848:8848 -e MODE=standalone -e NACOS_SERVER_IP=192.168.66.100 nacos/nacosserver
实战
openfeign远程调用
server:
port: 80
spring:
application:
name: order-consumer
cloud:
nacos:
discovery:
#Nacos服务地址
server-addr: 192.168.176.100:8848
feign:
client:
config:
default:
#网络连接阶段超时时间
connectTimeout: 1000
#服务远程调用响应超时时间
readTimeout: 2000
远程调用需要加loaderbalancer
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Tfm4Dom-1661264866941)(C:\Users\caituxinchu\AppData\Roaming\Typora\typora-user-images\image-20220729230106266.png)]
被调用的请求
服务降级
诸如服务产生超时报错 这时可以使用降级兜底方法
<!-- 引入sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
feign:
sentinel:
enabled: true
使用Dubbo注册 (代替Openfeign)
Dubbo不需要控制层,只需要一个实现类注册上去就可以调用
Dubbo注册生产者
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<!-- dubbo依赖包-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.itbaizhan</groupId>
<artifactId>cloud-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
yml:配置
server:
port: 8001
spring:
#解决循环依赖问题
main:
allow-bean-definition-overriding: true
allow-circular-references: true
application:
name: payment-provider-dubbo
#nacos注册
cloud:
nacos:
discovery:
#Nacos服务器地址
server-addr: 192.168.176.100:8848
#dubbo配置
dubbo:
scan:
base-packages: com.itbaizhan.service
registry:
#注册地址
address: nacos://192.168.176.100:8848
timeout: 10000
protocol:
#Dubbo暴露的协议的配置dubbo
name: dubbo
#端口从20880开始自增
port: -1
Dubbo注册只需要实现接口就能注册到Dubbo中
@DubboService(timeout = 5000,methods = {@Method(name = "index",retries = 2)})
public class PaymentServiceImpl implements IPaymentService {
@Override
public String index() {
return null;
}
}
Dubbo的消费者
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<!-- 公共抽离出来的接口-->
<dependency>
<groupId>org.itbaizhan</groupId>
<artifactId>cloud-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- dubbo依赖包-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
</dependencies>
#yml配置
server:
port: 80
spring:
#解决循环依赖问题
main:
allow-bean-definition-overriding: true
allow-circular-references: true
application:
name: payment-consumer-dubbo
#nacos注册
cloud:
nacos:
discovery:
#Nacos服务器地址
server-addr: 192.168.176.100:8848
#dubbo配置
dubbo:
cloud:
#订阅服务的服务名 * 订阅所有服务 订阅多个可以使用逗号
subscribed-services: "*"
registry:
#注册地址
address: nacos://192.168.176.100:8848
timeout: 10000
protocol:
#Dubbo暴露的协议的配置dubbo
name: dubbo
#端口从20880开始自增
port: -1
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired
private OrderService orderService;
// 测试Dubbo的远程调用
@GetMapping("index")
public String index(){
return orderService.index();
}
}
/**
* 订单业务层
*/
@Service
public class OrderService {
//支付服务远程调用Dubbo的实现类
@DubboReference
private IPaymentService iPaymentService;
public String index(){
return iPaymentService.index();
}
}
Dubbo服务降级
####### 6中服务降级策略
分布式配置中心
配置文件名:服务名-环境.文件后缀 consumer-dev-yaml
组不同 配置文件不同 (区别不用的项目)
使用组来区分不同的项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kQPZ3EPA-1661264866946)(C:\Users\caituxinchu\AppData\Roaming\Typora\typora-user-images\image-20220730224432080.png)]
分布式配置中心
server:
port: 3344
spring:
application:
name: nacos-config
cloud:
nacos:
discovery:
server-addr: 192.168.176.100:8848
config:
#Nacos服务器地址
server-addr: 192.168.176.100:8848
#命名空间 不指定命名空间默认为public 指定命名空间的UUID
namespace: 49963e38-2296-42e4-9cb4-bccf14418c1b
#不指定就是默认的DEFAULT_GROUP
group: DEFAULT_GROUP
#文件名 spring-application-name
prefix: nacos-config
#prefix: spring.application.name
#后缀
file-extension: yaml
#指定环境 为dev 如果没写环境就可以不必指定
profiles:
active: dev
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 分布式配置中心的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 引入bootstrap.yml配置包-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
</dependencies>
动态刷新
@RefreshScope 只需要加载主启动类上即可
将Dubbo服务对接分布式配置中心
同样都需要加入配置中心依赖和bootstrap依赖
消费者
spring: application: name: payment-provider-dubbo main: allow-bean-definition-overriding: true allow-circular-references: true cloud: nacos: config: #Nacos服务器地址 server-addr: 192.168.176.100:8848 #命名空间 不指定命名空间默认为public 指定命名空间的UUID namespace: 49963e38-2296-42e4-9cb4-bccf14418c1b #不指定就是默认的DEFAULT_GROUP group: DEFAULT_GROUP #文件名 spring-application-name prefix: payment-provider-dubbo #prefix: spring.application.name #后缀 file-extension: yaml #指定环境 为dev 如果没写环境就可以不必指定 profiles: active: dev
spring:
application:
name: payment-consumer-dubbo
main:
allow-bean-definition-overriding: true
allow-circular-references: true
cloud:
nacos:
config:
#Nacos服务器地址
server-addr: 192.168.176.100:8848
#命名空间 不指定命名空间默认为public 指定命名空间的UUID
namespace: 49963e38-2296-42e4-9cb4-bccf14418c1b
#不指定就是默认的DEFAULT_GROUP
group: DEFAULT_GROUP
#文件名 spring-application-name
prefix: payment-consumer-dubbo
#prefix: spring.application.name
#后缀
file-extension: yaml
#指定环境 为dev 如果没写环境就可以不必指定
profiles:
active: dev
分布式流量防护
服务雪崩
解决方案
内部流量控制:
- 服务降级(C调用D响应过长、服务异常,我们在服务内部执行一段降级逻辑)
- 服务熔断(多次服务调用异常累积 在一定时间段中异常超过一定数量停止对目标服务进行调用,所有访问直接执行降级逻辑)
外部流量控制:
- 进行限流 一旦访问量超过阈值,请求就都会被fast fail 。
Setinel搭建
java -Dserver.port=8878 -Dcsp.sentinel.dashboard.server=192.168.176.100:8878 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.3.jar
Sentinel控制台
docker pull docker.io/bladex/sentinel-dashboard
docker run --name sentinel --restart=always -d -p 8888:8858 docker.io/bladex/sentinel-dashboard
Sentinel流控:直接 快速失败
关联规则
链路规则
默认只会对Controller层进行监控,
如果想对service层进行监控则需要加上注解@SentinelResource("goods ")
对goods的 /query/goods入口进行限流
冷启动 预热模式
冷启动主要用来解决服务刚刚启动 ,一切资源尚未初始化
排列等待(处理突发流量)
分布式流量防护 (热点参数限流)
分布式流量防护 (线程隔离)
避免高并发引起的服务故障 通过外部流量控制
- 线程池隔离:给每个服务调用业务分配一个线程池,利用线程池本身实现隔离效果
- 信号量隔离(sentinel默认):不创建线程池,而是计数器模式,记录业务使用的线程数量,达到信号量上限 时,禁止新的请求。
分布式流量防护 (熔断降级)
熔断降级策略
慢调用
业务的响应时长(RT)大于指定时长的请求认定为慢调用请求。在 指定时间内,如果请求数量超过设定的最小数量,慢调用比例大于 设定的阈值,则触发熔断。
异常比例、异常数
统计指定时间内的调用,如果调用次数超过指定请求数,并且出现 异常的比例达到设定的比例阈值(或超过指定异常数),则触发熔 断。
异常比例
异常数
授权规则
白名单:允许访问
黑名单:不允许访问
使用网管请求服务
server:
port: 9090
spring:
application:
name: gateway #应用名字
cloud:
nacos:
discovery:
server-addr: 192.168.176.100:8848
gateway:
routes:
- id: payment # 路由名字 当前页面不重复即可
uri: lb://payment-provider-sentinel #lb是负载均衡
predicates:
- Path=/payment/* #断言匹配即可跳到uri地址
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId
>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Eureka自带loadbalancer 但是loadbalancer没有 需要引入负载均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
- 注意: sentinel不管请求者从哪里来,返回值永 远是default,也就是说一切请求的来源都被认为是一样的值 default。因此,我们需要自定义这个接口的实现,让不同的请 求,返回不同的origin。所以在这里写一个配置类
top
BlockException拦截Sentinel降级
分布式事务处理
本地事务是在一台机器上,分布式事务是在不同机器上的。
原子性:要么全部成功,要么全部失败,具有原子性。
一致性: A转给B100,转账前相加的金额和转账后相加的金额一致。
隔离性:两个事务之间,相互不干扰。
持久性:该事物的更改会被更改到数据库中,不会被回滚。
分布式事物处理_分布式事务产生的场景
垮JVM进程
订单微服务生成订单的时候会调用库存微服务来减少库存。各个微服务是部署在不同JVM进程中,此时就会产生因跨JVM进程而导致的分布式事务问题。
跨数据库实例
退款会调用订单数据库和交易数据库,需要通过不同的数据库连接会话来操作数据库中的数据,因此产生了分布式事务。
多个服务数据库
例如,订单微服务和库存微服务访问同一个数据库也会产生分 布式事务,原因是:多个微服务访问同一个数据库,本质上也 是通过不同的数据库会话来操作数据库,此时就会产生分布式 事务。