阅读 1416

Spring Cloud Alibaba从入门到精通,史上最全面的讲解(下篇)

Spring Cloud Alibaba从入门到精通,史上最全面的讲解(下篇)

九. 消息驱动的微服务-Spring Cloud Alibaba

9.1 Spring实现异步的方法

9.2 引入MQ后的架构演进

  • 引入MQ后,一些同步耗时的地方可以用异步处理,MQ作为一个中间件连接两个地方

9.3 MQ适用场景

  • 异步处理
  • 流量削峰填谷
  • 解耦微服务

9.4 MQ的选择

  • MQ的种类:
    • Kafka
    • RabbitMQ
    • RocketMQ
    • ActiveMQ
  • 手记:MQ的选择
  • RocketMQ成功案例: 参考

9.5 搭建RocketMQ

9.6 搭建RocketMQ控制台

9.7 RocketMQ的术语与概念

  • 术语/概念: 在这里插入图片描述

    在这里插入图片描述

9.8 RocketMQ进阶

9.9 Spring消息编程模型01

  • 在项目中使用RocketMQ:
    1. 引入依赖: 在这里插入图片描述

    2. 写注解: 无注解

    3. 写配置: 在这里插入图片描述

    4. 引入RocketTemplate: 在这里插入图片描述

    5. 发送消息: 在这里插入图片描述

    不指定group会报异常,后期不知是否会处理这种;

  • 工具类的使用:
    1. RocketMQ: RocketMQTemplate
    2. ActiveMQ/Artemis:JmsTemplate
    3. RabbitMQ:AmqpTemplate
    4. Kafka: KafkaTemplate

9.10 Spring消息编程模型02

  • 我们已经编写好了消息的生产者,接下来我们来编写消息的消费者:
  • 步骤如下:
    1. 引入依赖:
      	<dependency>
      		<groupId>org.apache.rocketmq</groupId>
      		<artifactId>rocketmq-spring-boot-starter</artifactId>
      		<version>2.0.3</version>
      	</dependency>
      复制代码
    2. 写配置,在application.yml中编写:
      	rocketmq:
      		name-server:127.0.0.1:9876
      复制代码

      name-server的值根据每个人自身实际的ip及端口来填写,以我们安装的rocketmq地址来决定

    3. 创建接收消息的对象:
      	@Data
      	@NoArgsConstructor
      	@AllArgsConstructor
      	@Builder
      	public class UserAddBOnusMsgDTO{
      	
      		/**
      		 * 为谁加积分
      		 */
      		private Integer userId;
      		/**
      		 * 加多少积分
      		 */
      		private Integer bonus;
      	
      	}
      复制代码
    4. 创建消息监听类:
      @Service
      @RocketMQMessageListener(consumerGroup= "consumer-group",topic= "add-bonus")
      public class AddBonusListener implements RocketMQListener<UserAddBonusMsgDTO>{
      	@Override
      	public void onMessage(UserAddBonusMsgDTO message){
      		System.out.println(message.getUserId())
      		System.out.println(message.getBonus())
      	}
      }
      复制代码

      注意:consumerGroup在生产者中是写到配置文件中的,在消费者中是在此处进行指定的。topic在生产者中是发送消息的时候添加,在此处是接收监听类的时候指定,这两个都必须带上;

  • 官方文档中对各类MQ的使用方法总结
  • 消费者各个MQ的注解简单总结:
    • RocketMQ: RocketMQMessageListener
    • ActiveMQ/Artemis:JmsListener
    • RabbitMQ: RabbitListener
    • Kafka: KafkaListener

9.11 分布式事务01

  • 以前解决事务的办法: @Transactional(rollbackFor= Exception.class) 当发现了Exception异常,就进行回滚
  • 存在的问题:
    • 图示: 在这里插入图片描述
    • 问题概述:当我们的逻辑代码中,不仅仅对数据库做了处理,一些场景下我们需要同时进行消息发送和与MySQL进行交互的功能;此图中,我们首先进行了消息发送,然后再把消息写入缓存,那么就会导致: 如果写入缓存的时候,代码执行失败,回滚操作只能回滚数据库,消息已经被消费者监听到了并做了处理了。
  • RocketMQ实现事务的流程: 在这里插入图片描述

    简单来说RocketMQ实现分布式事务的原理是: 执行到应该发送消息的时候,它并未发送,而是处于“准备发送”阶段,当所有的代码都已执行完毕且无异常时,则进行完全发送,此刻消息消费者才能监听到消息;

  • 概念术语解答:
    • 半消息(Half(Prepare) Message)
      • 暂时无法消费的消息。生产者将消息发送到了MQ server,但这个消息会被标记为“暂不能投递”状态,先存储起来;消费者不会去消费这条消息
    • 消息回查(Message Status Check)
      • 网络断开或生产者重启可能会导致丢失事务消息的第二次确认。当MQ Server发现消息长时间处于半消息状态时,将向消息生产者发送请求,询问该消息的最终状态(提交或回滚)
    • 消息三态:
      • Commit:提交事务消息,消费者可以消费此消息
      • Rollback: 回滚事务消息,broker会删除该消息,消费者不能消费
      • UNKNOWN: broker需要回查确认该消息的状态

9.12 分布式事务02- 编码

  1. 到数据库中新增一张表,用来记录 RocketMQ的事务日志: 在这里插入图片描述

    • 执行代码:
      	create table rocketmq_transaction_log(
      		id int auto_increment comment 'id' primary key, 
      		transaction_Id varchar(45) not null comment '事务id',
      		log varchar(45) not null comment '日志')
      复制代码
  2. 消息生产者编写:发送半消息:

    // 首先可以判断,当前面代码执行成功后再执行此代码,此处略
    // 发送半消息
    String transactionId=UUID.randomUUID().toString()
    this.rocketMQTemplate.sendMessageInTransaction(
    	"tx-add-bonus-group","add-bonus",MessageBuilder.withPayload(
    		UserAddBonusMsgDTO.builder().userId(share.getUserId)
    		.bonus(50)
    		.build()
    	).setHeader(RocketMQHeaders.TRANSACTION_ID,transactionId)
    	  .setHeader("share_id",id)
    	.build(),
    	auditDTO
    )
    复制代码

    此处 "tx-add-bonus-group","add-bonus" 组名及topic是由自己指定的,可根据实际改变。auditDTO、share_id是根据业务需要所传入的数据,auditDTO在消息监听类中可以直接强转使用,share_id的数据可以直接从请求头中获取;

  3. 消息消费者编写:

    	@RocketMQTransactionListener(txProducerGroup = "tx-add-bonus-group")
    	@RequiredArgsConstructor(onConstructor = @_(@Autowired))
    	public class AddBonusTransactionListener implements RocketMQLocalTransactionListener{
    		
    		@Override
    		public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg)
    		String transactionId(String)headers.get(RocketMQHeaders.TRANSACTION_ID);
    		Integer shareId= Integer.valueOf((String)headers.get("share_id"))
    		try{
    			this.shareService.auditByIdInDB(shareId,(ShareAuditDTO) arg)
    			return RocketMQLocalTransactionState.COMMIT;
    		}catch(Exception e){
    			return RocketMQLocalTransactionState.ROLLBACK;
    		}
    	}
    	// 编写回查代码,当我们
    	@Override
    	public RocketMQLocalTransactionState checkLocalTransaction(Message msg){
    		return null;
    		}
    	}
    复制代码

    当我们执行成功,则执行RocketMQLocalTransactionState.COMMIT,失败则ROLLBACK。但是有这样一种情况,比如我们已经执行完逻辑代码,正准备COMMIT提交,此时突然停电了,导致数据已经存入,但是却没有提交成功。所以我们需要一个回查方法,checkLocalTransaction()是一个回查方法,它会去里面进行判断是否执行成功。结合我们已经建立的RocketMQ事务表,我们可以进行回查操作,代码看下方:

    // auditByInDB具体方法内容如图所示: 在这里插入图片描述

  4. 新建一个存入方法,我们之前的存入方法,没有将事务数据加入日志表,我们可以这样改造: 当数据存入的时候,将数据存入日志表;回查方法就进行回查,如果没有存入则表示执行失败:

    @Autowired
    private RocketmqTransactionLogMapepr rocketmqTransactionLogMapepr;
    
    @Transactional(rollbackFor= Exception.class)
    public void auditByIdWithRocketMqLog(Integer id, ShareAuditDTO auditDTO, String transactionId){
    	this.auditByIdInDB(id,auditDTO);
    	this.rocketmqTransactionLogMapper.insertSelective(
    		RocketmqTransactionLog.builder().transactionId(transactionId)
    		.log("审核分享")
    		.build()
    	);
    }
    复制代码
  5. 消息消费者重写:

    
    	@Autowired
    	private ShareService shareService;
    	@Autowired
    	priavte RocketmqTransactionLogMapper rocketmqTransactionLogMapper;
    	@RocketMQTransactionListener(txProducerGroup = "tx-add-bonus-group")
    	@RequiredArgsConstructor(onConstructor = @_(@Autowired))
    	public class AddBonusTransactionListener implements RocketMQLocalTransactionListener{
    		
    		@Override
    		public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg)
    		String transactionId(String)headers.get(RocketMQHeaders.TRANSACTION_ID);
    		Integer shareId= Integer.valueOf((String)headers.get("share_id"))
    		try{
    			this.shareService.auditByIdWIthRocketMqLog(shareId,(ShareAuditDTO) arg,transactionId)
    			
    			return RocketMQLocalTransactionState.COMMIT;
    		}catch(Exception e){
    			return RocketMQLocalTransactionState.ROLLBACK;
    		}
    	}
    	// 编写回查代码,当我们
    	@Override
    	public RocketMQLocalTransactionState checkLocalTransaction(Message msg){
    		MessageHeaders headers= msg.getHeaders();
    		String transactionId= (String) headers.get(RocketMQHeaders.TRANSACTION_ID);
    		// 查询是否存了事务数据
    		this.rocketmqTransactionLogMapper.selectOne(RocketmqTransactionLog.builder().transactionId(transactionId).build());
    		// 判断是否提交
    		if(transactionLog != null){
    			return RocketMQLocalTransactionState.COMMIT;
    		}
    		return RocketMQLocalTransactionState.ROLLBACK;
    		}
    	}
    复制代码

    使用header和arg可以传参

9.13 Spring Cloud Stream 是什么?

  • 是一个用于构建消息驱动的微服务的框架
  • 架构: 在这里插入图片描述

9.14 Spring Cloud Stream 编程模型

  • 概念:
    1. Destination Binder(目标绑定器)
      • 与消息中间件通信的组件
    2. Destination Bindings(目标绑定)
      • Binding是连接应用程序跟消息中间件的桥梁,用于消息的消费和生产,由binder创建
    3. Message(消息)
  • 编程模型图: 在这里插入图片描述

当消息生产者使用Kafka发送消息,那只能用Kafka来接收消息。当使用SpringCloudStream来处理消息的话,我们接收Kafka的消息,可以使用其他的消息中间件来进行接收。SpringCloudStream对消息进行了一层封装,所以我们不需要去关心生产者用的是什么消息中间件。

9.15 Spring Cloud Stream 代码-消息生产者

  • 编写生产者:
    1. 添加依赖:
      	<dependency>
      		<groupId>org.springframework.cloud</groupId>
      		<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
      	</dependency>
      复制代码
    2. 添加注解(在启动类上添加注解):
      • 添加@ EnableBing(Source.class) 注解,如图所示:
      在这里插入图片描述
    3. 写配置(application.yml):
      	spring:
      		cloud:
      			stream:
      				rocketmq:
      					binder:
      						name-server: 127.0.0.1:9876
      				bindings:
      					output:
      						# 用来指定topic
      						destination: stream-test-topic
      复制代码
    4. 生产者发送消息:
      	@GetMapping("test-stream")
      	public String testStream(){
      		this.source.output()
      			.send(
      				MessageBuilder
      					.withPayload("消息体")
      					.build()
      			);
      		return "success";
      	}
      复制代码
    5. 检查是否成功发送。
      • 在控制台中我们可以查看此组下是否有已发送过的消息: 在这里插入图片描述
      • 如果控制台在一直打印日志的话,我们可以降低日志级别: 在这里插入图片描述

9.16 Spring Cloud Stream 消息消费者

  • 编写消费者:
    1. 添加依赖:
      	<dependency>
      		<groupId>org.springframework.cloud</groupId>
      		<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
      	</dependency>
      复制代码
    2. 添加注解(在启动类上添加注解):@EnableBinding(Sink.class) 在这里插入图片描述
    3. 写配置(application.yml):
      	spring:
      		cloud:
      			stream:
      				rocketmq:
      					binder:
      						name-server: 127.0.0.1:9876
      				bindings:
      					input:
      						destination: stream-test-topic
      						group: binder-group  # 这里的group 一定要设置; 如果使用的不是rocketmq的话,这里可以不用设置,可以留空
      复制代码
    4. 监听消费类:
      	@Service
      	@Slf4j
      	public class TestStreamConsumer{
      		@StreamListener(Sink.INPUT)
      		public void receive(String messageBody){
      			log.info("通过stream收到了消息: messageBody = {}");
      
      		}
      	}
      复制代码

9.17 Spring Cloud Stream 接口自定义:消息生产者

  • 接口:
    	public interface MySource{
    		String MY_OUTPUT= "my-output";
    		
    		@Output(MY_OUTPUT)
    		MessageChannel output();
    	}
    复制代码
  • 启动类上,**@EnableBinding注解上引入 MySource.class,如图所示: 在这里插入图片描述
  • 加配置: 在这里插入图片描述
  • 定义接口,发送消息: 在这里插入图片描述

使用自定义的接口我们可以进行消息的收发;

9.18 Spring Cloud Stream 接口自定义:消息消费者

  1. 创建方法: 在这里插入图片描述
  2. 启动类中引入: 在这里插入图片描述
  3. 配置类修改: 在这里插入图片描述
  4. 使用自定义接口:消息消费监听,如图所示: 在这里插入图片描述

9.19 消息过滤

9.20 Spring Cloud Stream 的监控

  • Spring Cloud Actuator为我们提供了三个端点来监控Stream:
    1. /actuator/bindings
    2. /actuator/channels
    3. /actuator/health

9.21 Spring Cloud Stream 异常处理

  • 错误处理手记
  • 定义全局异常处理的办法如下:
    	@StreamListener("errorChannel")
    	public void error(Message<?> message){
    		ErrorMessage errorMessage= (ErrorMessage) message;
    		log.warn("发生异常,errorMessage = {}",errorMessage);
    	}
    复制代码

9.22 Spring Cloud Stream + RocketMQ实现分布式事务

  • SpringCloud Stream 本身没有实现分布式事务,它与RocketMQ结合则是使用RocketMQ的分布式事务。它若与其他结合,则使用其他消息中间件的分布式事务。
  • Spring Cloud Stream 的分布式事务改造如图:
    1. 发送者从rocketRestTemplate改为source: 在这里插入图片描述

    2. 在配置文件中定义组合事务: 在这里插入图片描述

    3. 消息的监听定义组名称时,一定要与配置文件中的保持一致,如图所示: 在这里插入图片描述

十. Spring Cloud Gateway

10.1 为什么要使用网关

  • 在不使用Gateway的情况下,当我们直接与微服务通信的情况下,需要每个服务都进行网关登录验证,同时需要解决各个服务的登录状态的同步等功能;
  • 使用Gateway可以对外暴露一个域名,微服务无论增加多少,都只需要指向一个网关即可,它可以统一对外进行登录、校验、授权、以及一些拦截操作;

10.2 Spring Cloud Gateway 是什么?

  • 它是SpringCloud的网关(第二代),未来会取代Zuul(第一代)
  • 基于Netty、Reactor以及WebFlux构建(所以它启动会比其他微服务一般要快)
  • 它的优点:
    • 性能强劲: 它的性能是第一代网关Zuul 1.x的1.6倍! 性能PK
    • 功能强大:内置了很多实用功能,比如转发、监控、限流等
    • 设计优雅、易扩展
  • 它的缺点:
    • 依赖Netty与Webflux,不是Servlet编程模型,有一定适应成本
    • 不能在Servlet容器下工作,也不能构建成WAR包
    • 不支持Spring Boot 1.x

10.3 编写Spring Cloud Gateway

  • 创建项目 gateway,此处省略
    • pom.xml:

      1. 父工程依赖: 在这里插入图片描述

      2. 定义SpringCloud版本、gateway依赖: 在这里插入图片描述

      3. SpringCloudAlibaba等引入: 在这里插入图片描述

      4. 加入Nacos、Actuator依赖: 在这里插入图片描述

    • application.yml配置:

      1. 配置端口及nacos、gateway配置: 在这里插入图片描述

      2. 配置Actuator相关配置: 在这里插入图片描述

    • 启动gateway

gateway是基于Netty,所以启动速度非常快。从上面就已经可以进行服务转发了,因为gateway:discovery:locator:enabled:true 可以自动让服务转发到对应的路径去;

  • 转发规律:访问${GATEWAY_URL}/{微服务X}/路径 会转发到微服务X的/路径

10.4 核心概念

  • Route(路由):
    • Spring Cloud Gateway 的基础元素,可简单理解成一条转发的规则。包含:ID、目标URL、Predicate集合以及Filter集合。
  • Predicate(谓词):即 java.util.function.Predicate,Spring Cloud Gateway 使用Predicate实现路由的匹配条件
  • Filter(过滤器): 修改请求以及响应
  • 路由配置示例:
    • 在这里插入图片描述

10.5 架构剖析

  • 架构图: 在这里插入图片描述
  • 源码: 在这里插入图片描述

10.6 内置路由谓词工厂详解(Route Predicate Factories)

10.7 自定义路由谓词工厂

  • 自定义路由谓词工厂类必须以PredicateFactory结尾命名
  • 大致步骤:
    • 继承 AbstractRoutePredicateFactory<自定义配置对象>
    • 添加构造方法
    • 重写抽象方法
    • 配置中添加配置规则

10.8 内置过滤器工厂详解

10.9 自定义过滤器工厂

  • 内容介绍:
    1. 过滤器生命周期
    2. 自定义过滤器工厂的方式
    3. 核心API
    4. 编写一个过滤器工厂
  • 过滤器生命周期:
    • pre: Gateway 转发请求之前
    • post: Gateway 转发请求之后
  • 自定义过滤器工厂- 方式1:
    • 继承和参考示例: 在这里插入图片描述
    • 配置形式: 在这里插入图片描述
  • 自定义过滤器工厂-方式2: 在这里插入图片描述 在这里插入图片描述
  • 自定义过滤器工厂-核心API 在这里插入图片描述

    这些过滤器工厂的核心Api比较简单,从名称就可以看出其含义;

  • 编写一个过滤器工程:
    1. 创建一个类: PreLogGatewayFilterFactory: 在这里插入图片描述

      最后在过滤器工厂上面加上 @Component 注解

    2. 在配置中新增内容,并修改工厂类,打印配置中新增的数据: 在这里插入图片描述

      在这里插入图片描述

      配置文件中,传入了ab两个配置值,在我们工厂类中可以通过config.getName,config.getValue获取到;当有请求访问经过此过滤器工厂时,日志就会打印出来了;

10.10 全局过滤器

  • 会作用在所有的路由,有执行顺序的概念,order越小越靠前执行;
  • 手记笔记

10.11 悬念:如何为Spring Cloud Gateway 整合Sentinel?

sentinel要在1.6 版本以后才支持gateway

10.12 监控SpringCloud gateway

10.13 排错、调试技巧总结

10.14 进阶:再谈过滤器执行顺序

  • 结论:
    1. order越小越靠前执行
    2. 过滤器工厂的Order按配置顺序从1开始递增
    3. 如果配置了默认过滤器,则线执行相同Order的默认过滤器 在这里插入图片描述

      相同顺序的,以default-filter中的优先

    4. 如需自行控制Order,可返回OrderedGatewayFilter 在这里插入图片描述
  • 源码: 在这里插入图片描述

10.15 Spring Cloud Gateway限流

10.16 本章总结

  • 路由、路由谓词工厂、过滤器工厂、全局过滤器
  • 网关集大成:
    • 注册到Nacos
    • 集成Ribbon
    • 容错(默认Hystrix,也可用Sentinel)

十一. 微服务的用户认证与授权

11.1 认证授权-必然会面临的话题

  • 每个应用基本上都需要进行登录,校验用户权限

11.2 有状态vs 无状态

  • 有状态:
    • 图示: 在这里插入图片描述
    • 优点:服务端控制力强
    • 缺点:存在中心点,鸡蛋放在一个篮子里,迁移麻烦,服务器端存储数据,加大了服务器端压力
  • 无状态:
    • 图示: 在这里插入图片描述
    • 优点:去中心话,无存储,简单,任意扩容、缩容
    • 缺点:服务器端控制力相对弱(不能随时强制让人下线,修改登录时长等)

11.3 微服务认证方案 01 “处处安全”

11.4 微服务认证方案 02 - 外部无状态,内部有状态方案

  • 图示: 在这里插入图片描述
  • 它能够与老架构项目相兼容。就是老项目可能没有Token,但是可以从Session中获取信息。 在这里插入图片描述

它安全性和性能都不占优势,但它的优点是能够与老项目服务相兼容

11.5 微服务认证方案 03 - 网关认证授权、内部裸奔方案

  • 图示: 在这里插入图片描述

安全性低,性能高

11.6 微服务认证方案 04 内部裸奔改进方案

  • 图示: 在这里插入图片描述
  • 每个服务都能够对Token进行解析,每个服务就不会裸奔了,但是每个服务都知道Token解密方式,容易暴露;

11.7 微服务认证方案 05 方案对比

  • 对比图示: 在这里插入图片描述

11.8 访问控制模型

  • 模型如图: 在这里插入图片描述
  • RBAC: 在这里插入图片描述

11.9 JWT是什么?【是什么、组成】

  • JWT全称Json web token,是一个开放标准(RFC 7519),用来在各方之间安全地传输信息。JWT可被验证和信任,因为它是数字签名的。
  • JWT组成图示: 在这里插入图片描述
  • 公式: 在这里插入图片描述
  • JWT的手记

11.10 AOP实现登录状态检查

  • 实现登录状态检查的方式: 在这里插入图片描述

建议使用SpringAop 来实现,这样解耦且灵活

  • 手动实现切面:
    • 定义注解: 在这里插入图片描述
    • 定义切面: 在这里插入图片描述 在这里插入图片描述
    • 定义异常捕获类: 在这里插入图片描述

11.11 Feign实现Token传递

  • Controller层可以接收Token: 在这里插入图片描述

  • Feign中可以携带Token: 在这里插入图片描述

  • 上面的这种方式携带Token,需要每个都进行配置,比较麻烦。当我们Feign调用的接口比较多的时候,我们可以使用拦截器统一携带Token: 在这里插入图片描述

  • 使用全局配置的时候,需要在配置中添加如图配置: 在这里插入图片描述

11.12 RestTemplate实现Token传递

  • 两种方式,分别是exchange()ClientHttpRequestInterceptor
  • exchange()代码示例: 在这里插入图片描述
  • 使用RestTemplate拦截器示例:
    • 拦截器配置: 在这里插入图片描述
    • RestTemplate配置: 在这里插入图片描述

11.13 Java 自定义注解

11.15 本章总结

在这里插入图片描述

十二. 配置管理

12.1 为什么要实现配置管理?

  • 不同环境存在不同的配置
  • 配置属性要求动态刷新,不重启

在这里插入图片描述

使用Nacos就可以作为一个配置服务器,实现上面两个功能;

12.2 使用Nacos管理配置

  1. 添加依赖:

    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    复制代码
  2. 写配置:- 配置内的内容与Nacos中的配置必须保持一致,一定要记住这张图: 在这里插入图片描述

  3. 建立bootstrap.yml: 在这里插入图片描述

    spirngconfig与Nacos的配置是分开来的。config的配置建议放在bootstrap.yml中,否则可能不生效,应用无法读取配置;

  4. 代码中写入配置: 在这里插入图片描述

  5. 在Nacos中建立配置: 在这里插入图片描述 在这里插入图片描述

    配置好内容后点击发布即可。

  6. 重启应用,调用接口,发现参数能获取到,完成!

12.3 配置属性动态刷新与回滚

  • 在需要属性动态刷新的类上写上注解 @RefreshScope ,即可动态刷新配置,如图所示: 在这里插入图片描述

  • 当我们将itmuch改为itmuch.com,调用接口时,会自动刷新: 在这里插入图片描述 在这里插入图片描述

  • 回滚: 在这里插入图片描述 在这里插入图片描述

12.4 应用的配置共享

  • 配置共享:

  • shared-dataids: 在这里插入图片描述

  • 方式2: ext-config: 在这里插入图片描述

  • 方式3: 自动的方式: 在这里插入图片描述

    这个自动方式就是里面的内容是所有环境的公共配置数据,profiles.active指向的环境可以放置其存在变化的配置;

  • 优先级:在这里插入图片描述

12.5 引导上下文

在这里插入图片描述

  • 默认远程配置优先级更高,我们可以使用下方代码进行配置优先级: 在这里插入图片描述
  • 远程配置优先级必须要在Nacos下配置才生效,如图所示: 在这里插入图片描述

12.6 数据持久化

  • 在这里插入图片描述

服务发现组件是放在文件夹内。配置数据是放在嵌入式数据库中(生产环境建议更换为mysql);

12.7 搭建生产可用的Nacos集群

12.8 配置最佳实践总结

  • 能放本地的情况下,就不要放在远程
  • 尽量规避优先级,简化配置
  • 定规范,例如所有配置属性都要加上注释
  • 配置管理人员尽量少(Nacos的安全权限功能还未齐全,为了安全高效管理着想,人员尽量少)

十三. 调用链监控-Sleuth

13.1 调用链监控

  • 使用调用链监控,我们能够清晰的看出来这个接口调用了哪些方法,哪些方法消耗了多少时间,同时如果出现了问题,是哪个方法出现了问题,我们也能够快速定位
  • 业界主流的调用链监控工具
    • Spring Cloud Sleuth+Zipkin
    • Skywalking、Pinpoint

13.2 整合Sleuth

  • 什么是Sleuth?
    • Sleuth是一个Spring Cloud的分布式跟踪解决方案
  • Sleuth术语?
    • Span(跨度): Sleuth的基本工作单元,它用一个64位的id唯一标识。除ID外,span还包含其他数据,例如描述、时间戳事件、键值对的注解(标签)、span ID、span 父ID等 在这里插入图片描述

      里面每一行数据,可以理解为一个span

    • trace(跟踪): 一组span组成的树状结构成为trace
    • Annotation(标注):
      • CS(Client Sent 客户端发送):客户端发起一个请求,该annotation描述了span的开始
      • SR(Serverr Received 服务器端的接收): 服务器端获得请求并准备处理它
      • SS(Server Sent服务器端发送): 该annotation表明完成请求处理(当响应发回客户端时)
      • CR(Client Received客户端接收):span结束的标识。客户端成功接收到服务器端的响应
  • 为用户中心整合Sleuth:
    1. 加依赖

      	<dependency>
      		<groupId>org.springframework.cloud</groupId>
      		<artifactId>spring-cloud-starter-sleuth</artifactId>
      	</dependency>
      复制代码
    2. 修改日志级别(可打印更多的日志,可选项) 在这里插入图片描述

13.3 Zipkin搭建与整合

  • Zipkin是什么?
    • Zipkin是Twitter开源的分布式跟踪系统,主要用来收集系统的时序数据,从而追踪系统的调用问题
    • Zipkin通俗来讲,它就是将sleuth收集来的数据进行存储、展示的,它的可视化界面能够更友好的,更清晰的为我们提供决策;
  • 搭建Zipkin Server (本文章版本为:2.12.9)
    • 方式一:使用Zipkin官方的Shell下载,如下命令可下载最新版本:
      curl -sSL https://zipkin.io/quickstart.sh | bash -s
      复制代码
    • 方式二: 到Maven中央仓库下载,访问如下地址即可:
      https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=1
      复制代码

      下载下来的文件名为: zipkin-server-2.12.9-exec.jar

    • 方式三:使用百度盘地址下载,提供2.12.9版本:
      https://pan.baidu.com/s/1HXjzNDpzin6fXGrZPyQeWQ
      复制代码

      密码:aon2

  • 启动Zipkin,执行如图所示命令: java -jar zipkin-server-2.12.9-exec.jar 在这里插入图片描述
  • 为用户中心整合Sleuth+Zipkin:
    1. 加依赖:去掉Sleuth,加上zipkin依赖(去掉sleuth是因为zipkin中有sleuth的依赖)
      • Gradle:
        	compile group: 'org.springframework.cloud', name: 'spring-cloud-sleuth-zipkin', version: '2.2.3.RELEASE'
        复制代码
      • Maven:
        	<dependency>
                   <groupId>org.springframework.cloud</groupId>
         	       <artifactId>spring-cloud-sleuth-zipkin</artifactId>
            	   <version>2.2.3.RELEASE</version>
        	</dependency>
        复制代码
    2. 加配置:设置zipkin服务器地址以及抽样率,如图所示: 在这里插入图片描述

      抽样率不是越高越好,也不是越低越好。抽样率高的话,分析的更加准确,但是它的性能消耗会更严重;

13.4 整合Zipkin之后Nacos报错的解决

13.5 为所有微服务整合Zipkin

  • 参照13.5的引入方式;

13.6 Zipkin数据持久化

  • 持久化方式:

  • 下载ElasticSearch:( 建议使用5,6,7版本)

    • 点击地址进行下载:(官网地址)[elastic.co/cn/downloads/past-releases#elasticsearch] 在这里插入图片描述
    • 解压并进入目录: 在这里插入图片描述
    • 切换到bin目录,并执行: ./elasticsearch 或后台执行 ./elasticsearch -d
    • 查看Zipkin的环境变量,配置STORAGE_TYPEES_HOSTS,然后执行zipkin server服务: 在这里插入图片描述 在这里插入图片描述

    Zipkin其他环境变量:github.com/openzipkin/…

13.7 依赖关系图

  • 使用ElasticSearch的话,需要使用 spark job才能分析出依赖关系图,使用方式如下: 在这里插入图片描述

    它是zipkin的子项目,第一步下载,第二步启动

  • Zipkin Dependencies使用ElasticSearch的环境变量: 在这里插入图片描述
  • 启动Zipkin Dependencies: 在这里插入图片描述
  • Zipkin Denpendencies其他的环境变量:(github.com/openzipkin/…
  • Zipkin Dependencies指定分析日期: 在这里插入图片描述

    可以编写脚本每日执行;

十四. 既有代码优化与改善

14.1 简单指标: Statistic

  • 注释原则:
    • 每一步主要业务流程
    • 核心方法
    • 条件、分支、判断前
  • 使用Statistic插件: 在这里插入图片描述 在这里插入图片描述

    建议服务上线,注释率要求达到35%

14.3 Alibaba Java代码规约(P3c)

  • github
  • IDEA插件支持,搜索 Alibaba Java Coding Guidelines

14.4 SonarQube

  • 教程
  • 下载:jdk8只支持6.x~7.8.x 的版本
  • 安装:在这里插入图片描述
  • 查看日志命令:
    tail -f ../../logs/sonar.log
    复制代码
  • 访问首页:localhost:9000/about
  • 账号密码都是admin
  • 根据手记我们与项目融合,建议使用Token,命令行的方式去融合。融合后我们可以很方便的看到程序有多少个bug,哪里的代码不够优雅等信息: 在这里插入图片描述
  • 它还有很多插件,比如汉化插件、其他监控插件等: 在这里插入图片描述

内嵌数据库不方便伸缩,所以不适用于生产环境,所以建议更换为MySql之类的数据库

十五. 进阶:多维度微服务监控

1.51 本章概要

  • Spring Boot Actutator: 监控微服务实例的情况
  • Sentinel Dashboard: 监控实例的QPS、限流等
  • Spring Cloud Sleuth+Zipkin: 监控服务的调用情况

15.2 Spring Boot Actuator监控数据库

  • SpringBoot Admin:

  • 搭建SpringBoot admin 步骤:

    • 加依赖:
      • 整合版本,如图所示: 在这里插入图片描述
      • 加入SpringBootAdmin以及Nacos,将Admin注册到Nacos上,如图所示: 在这里插入图片描述
    • 写注解:
      • 在启动类上添加 @EnableAdminServer 注解,如图所示: 在这里插入图片描述
    • 加配置:
      • 在application.yml中进行配置: 在这里插入图片描述
  • 被监控的服务的步骤:

    • 加依赖:
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-actuator</artifactId>
      	</dependency>
      复制代码
    • 加配置: 在这里插入图片描述

15.3 JVM监控

  • Spring Boot Actuator: metrics、heapdump、threaddump
  • Java自带的JVM监控工具: jconsole、jvisualvm
  • 自带工具打开方式:
    • jconsole: 在IDEA或者CMD中输入 jconsole,如图所示: 在这里插入图片描述 在这里插入图片描述
    • jvisualvm: 与jconsole类似,输入jvisualvm 即可,如图所示: 在这里插入图片描述

      jvisualvm与jconsole类似,但是它的功能更强大一点,但是它们都是客户端形式,希望能出一款强大的web浏览形式的监控工具;

15.4 GC日志、线程Dump日志、堆Dump可视化分析

  1. 第一步,启动参数中设置打印GC详情日志: 在这里插入图片描述
  2. 第二步,选择项目,右击选择Synchronize 'xxxx',生成出gc.log,如图所示: 在这里插入图片描述 在这里插入图片描述
  3. 找到输出的日志文件,右键后选择 Reveal in Finder,将文件导出: 在这里插入图片描述
  4. 将生成的文件在gceasy.io中,点击选择文件打开,然后会生成统计图表 在这里插入图片描述
  5. 生成统计图表如图: 在这里插入图片描述
  6. 虽然这款工具很强大,但是它不是开源产品,我们可以使用如图产品替代,但是可能相比来说要功能缺失一些: 在这里插入图片描述

15.5 日志监控

  • ELK架构如图所示: 在这里插入图片描述

对日志监控的工具可以不做强制要求,只要合适就行,不一定得必须要ELK

15.6 其他监控

  • 监控的时候,应该要全面一点,比如用到了docker,我们应该就要监控docker。用到了Linux服务器,我们就应该要监控服务器的运行情况。用到了RabbitMQ,我们也应该去监控rabbitmq。
  • 只有当监控完善的时候,我们分析问题就能更加的全面。

十六. 进阶:完美融合异构微服务

17.1 如何完美整合异构微服务

  • 非SpringCloud的服务,就叫做异构微服务
  • 完美整合:
    • SpringCloud 微服务完美调用异构微服务
    • 异构微服务完美嗲用SpringCloud微服务
  • 完美调用:互相之间需要满足如下:
    • 服务发现
    • 负载均衡
    • 容错处理

17.2 Spring Cloud Wii实现完美整合

它未来是SpringCloudAlibaba的一个子项目

十八.课程总结:

  1. SpringCloud是一系列的工具集,SpringCloudAlibaba是一站式解决方案
  2. 知其然而不知其所以然是不可取的,我们更要知道去知道核心原理,这样就算是Eureka、Nacos、或者别的服务发现或者其他组件,我们都能很快的上手;
文章分类
后端
文章标签