目录
1.3. 单体应用架构和微服务架构的区别1.3.1.单体应用架构的优点
12.2.3.Zuul 1.0(慢 servlet 2.0 ) zuul2.0 没出来
13.4.1.创建一个gateway微服务模块--此步骤省略
14.2.3.创建一个配置文件--名字是bootstrap.properties
14.2.5.将application配置文件的内容复制到配置中心
14.3.2.将public里面的配置克隆到dev(开发环境下)
14.4.2.将product和order的数据源剪切到新建的配置中
14.4.3.修改bootstrap.properties文件
1.系统架构演变
随着互联网的发展,网站应用的规模也在不断的扩大,进而导致系统架构也在不断的进行变化。 从互联网早起到现在,系统架构大体经历了下面几个过程: 单体应用架构--->垂直应用架构--->分布式架构--->SOA架构--->微服务架构,当然还有悄然兴起的Service Mesh(服务网格化)。
1.1.单体应用架构
互联网早期,一般的网站应用流量较小,只需一个应用,将所有功能代码都部署在一起就可以,这样可以减少开发、部署和维护的成本。比如说一个电商系统,里面会包含很多用户管理,商品管理,订单管理,物流管理等等很多模块, 我们会把它们做成一个web项目,然后部署到一台tomcat服务器上。
1.2.微服务架构
把一个项目拆分成若干个工程,而每一个工程是可以独立运行和部署的,物理进行了拆分,逻辑上还是一个整体---->必须要springboot(独立的系统) 必须依赖于springboot技术。Springcloud如果没有springboot 那么springcloud也无法使用。 springboot可以独立使用。因为springboot里面内置了tomcat
1.3. 单体应用架构和微服务架构的区别
1.3.1.单体应用架构的优点
(1)项目架构简单,小型项目的话,开发成本低。
(2)项目部署在一个节点上,维护方便
1.3.2.单体应用架构的缺点
(1)全部功能集成在一个工程中,对于大型项目来讲不易开发和维护[修改代码]。
(2)项目模块之间紧密耦合,单点容错率低。
(3)无法针对不同模块进行针对性优化和水平扩展
1.3.3.微服务架构的优点
(1)服务原子化拆分,独立打包、部署和升级,保证每个微服务清晰的任务划分,利于扩展
(2)微服务之间采用Restful等轻量级http协议相互调用
1.3.4.微服务架构的缺点
(1)小型项目----微服务架构不合适。仓库系统---微服务。
(2)微服务系统开发的技术成本高《高》(容错、分布式事务等)
2.什么是springCloud
Spring Cloud就是微服务系统架构的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶,在平时我们构建微服务的过程中需要做如服务发现注册、配置中心、负载均衡、断路器、数据监控等操作,而Spring Cloud 为我们提供了一套简易的编程模型,使我们能在 Spring Boot 的基础上轻松地实现微服务项目的构建
3.微服务出现的问题
3.1.这么多小服务,如何管理他们? --概念:服务治理
3.2.这么多小服务,他们之间如何通讯?调用 --概念:服务调用
3.3.这么多小服务,客户端怎么访问他们?前端 --概念:服务网关
3.4.这么多小服务,一旦出现问题了,应该如何自处理? --概念:服务容错
3.5.这么多小服务,一旦出现问题了,应该如何排错? --概念:链路追踪
4.微服务架构的常见概念
4.1.服务治理
服务治理就是进行服务的自动化管理,其核心是服务的自动注册与发现
4.1.1.服务注册
服务实例将自身服务信息注册到注册中心。
4.1.2.服务发现
服务实例通过注册中心,获取到注册到其中的服务实例的信息,通过这些信息去请求它们提供的服务。
4.1.3.服务剔除
服务注册中心将出问题的服务自动剔除到可用列表之外,使其不会被调用到。
4.2.服务调用
在微服务架构中,通常存在多个服务之间的远程调用的需求。目前主流的远程调用技术有基于HTTP的RESTful接口以及基于TCP的RPC协议。
4.2.1.RESTful接口
这是一种HTTP调用的格式,更标准,更通用,无论哪种语言都支持http协
4.2.2.RPC协议
@Autowire Bservice bservice.方法()
一种进程间通信方式。允许像调用本地服务一样调用远程服务。RPC框架的主要目标就是让远程服务调用更简单、透明。RPC框架负责屏蔽底层的传输方式、序列化方式和通信细节。开发人员在使用的时候只需要了解谁在什么位置提供了什么样的远程服务接口即可,并不需要关心底层通信细节和调用过程。
4.2.3.RESTful接口和RPC协议的区别
4.3.服务网关
随着微服务的不断增多,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信可能出现:
1.客户端需要调用不同的url地址,增加难度
2.在一定的场景下,存在跨域请求的问题
3.每个微服务都需要进行单独的身份认证
针对这些问题,API网关顺势而生。API网关直面意思是将所有API调用统一接入到API网关层,由网关层统一接入和输出。一个网关的基本功能有:统一接入、安全防护、协议适配、流量管控、长短链接支持、容错能力。有了网关之后,各个API服务提供团队可以专注于自己的的业务逻辑处理,而API网关更专注于安全、流量、路由等问题。
4.4. 服务容错
在微服务当中,一个请求经常会涉及到调用几个服务,如果其中某个服务不可用,没有做服务容错的话,极有可能会造成一连串的服务不可用,这就是雪崩效应。 我们没法预防雪崩效应的发生,只能尽可能去做好容错。服务容错的三个核心思想是:
1.不被外界环境影响
2.不被上游请求压垮
3.不被下游响应拖垮
4.5.链路追踪
随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。因此,就需要对一次请求涉及的多个服务链路进行日志记录,性能监控即链路追踪
5.微服务架构的解决方案
5.1.SpringCloud-Netflix
springcloud 很多组件都是拿的是Netflix公司,这家公司这些组件停止维护和更新)
Eureka组件解决服务治理
Feign组件解决服务调用的问题
zuul组件解决客户端调用微服务的问题
hystrix组件解决容错
sleuth组件链路追踪
Spring Cloud是一系列框架的集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署.Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。已经停更了。Euruka(注册中),feign远程调用,hystrix 容错,zuul网关
5.2. SpringCloud Alibaba
引入springcloud很多组件都更新了-springcloud alibaba
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
nacos组件解决服务治理
openfeign组件解决服务调用
gateway[spring公司]主件解决api网关
sentinel主件解决服务容错
sleuth组件链路追踪--Netflix
6.搭建微服务
本次是使用的电商项目中的商品微服务、订单微服务为案例
6.1.准备条件
6.1.1.技术选型
maven:3.5.0+
数据库:MySQL 5.7 以上
持久层: Mybatis-plus /《Mybatis Mapper Mybatis-plus》
其他: SpringCloud Alibaba /技术栈 / druid
6.1.2.模块设计
创建父工程 ----jar的版本管理 公共jar的引入
创建公共模块【实体类】 《实体类,公共依赖,工具类。》
创建商品微服务 【端口: 8080~8089 搭建集群】
创建订单微服务 【端口: 8090~8099 搭建集群】
6.2.创建父工程
6.2.3.依赖
将自动生成的依赖删除一下,还有他们的版本号要对应,下面地址是其他博客的写的版本对应
springboot,springCloud,springCloudAlibaba各版本之间的对应关系_lwdbcy的博客-CSDN博客
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>springcloud-comment</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.guan</groupId>
<artifactId>springboot-springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-springcloud</name>
<description>Demo project for Spring Boot</description>
<!--如果你的工程为父工程那么它的打包方式为pom-->
<packaging>pom</packaging>
<!--定义版本号-->
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF- 8</project.reporting.outputEncoding>
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version>
</properties>
<!--dependencyManagement:它只负责jar的版本号管理,不负责jar的下载,交于子模块,子模块在使用时无需指定版本号
:springboot springcloud springcloudalibaba之间版本一定要匹配
-->
<dependencyManagement>
<dependencies>
<!--springcloud的版本管理-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springcloudalibaba的版本管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
6.2.4.隐藏java中的文件--在另一篇博客中
可以将父工程的src给删除,我们不在父工程写代码,其他的不要删除要不然可能会报错
6.3.公共模块代码
6.3.1.创建公共模块
6.3.2.添加依赖
<!--引入lombok依赖-->
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
</dependencies>
6.3.3.添加实体类
@Data
@TableName(value="shop_product")
public class Product {
@TableId(type= IdType.AUTO)
private Integer pid;
private String pname;//商品名称
private Double pprice;//商品价格
private Integer stock;//库存
}
@Data
@TableName("shop_order")
public class Order {
@TableId(type = IdType.AUTO)
private Long oid; //订单id
private Integer uid;//用户id
private String username;//用户名
private Integer pid;//商品id
private String pname;//商品名称
private Double pprice;//商品价格
private Integer number;//购买数量
}
6.4.商品微服务--对商品的各种操作
如果其他微服务也要用到商品的操作,让其他服务调用商品微服务,不要再其他服务在写对商品的操作
6.4.1.创建商品微服务--省略
6.4.2.添加依赖
<dependencies>
<!--引入公共模块-->
<dependency>
<groupId>com.guan</groupId>
<artifactId>springcloud-comment</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--引入mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--引入web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
6.4.3.创建配置并在配置文件中写入数据源
#为了后期扩展方便微服务的端口号设置为8080-8090之间
server.port=8081
#数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=****
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?serverTimezone=Asia/Shanghai
#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
6.4.4.添加主启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringcloudApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudApplication.class, args);
}
}
6.4.5.controller
@RestController
@RequestMapping("product")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/getById/{pid}")
public Product product(@PathVariable Integer pid){
return productService.findById(pid);
}
}
6.4.6.dao
@Mapper
public interface ProductMapper extends BaseMapper<Product> {
}
6.4.7. ProductService
public interface ProductService {
Product findById(Integer pid);
}
6.4.8.service
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductMapper productMapper;
@Override
public Product findById(Integer pid) {
return productMapper.selectById(pid);
}
}
6.5.订单微服务
6.5.1.创建订单微服务--省略
6.5.2.添加依赖
<!--引入公共模块-->
<dependency>
<groupId>com.guan</groupId>
<artifactId>springcloud-comment</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--引入价格模块-->
<dependency>
<groupId>com.guan</groupId>
<artifactId>springcloud-product</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
6.5.3.创建配置文件,并且写入数据源
#为了后期扩展方便订单微服务的端口号设置为8090-8099之间
server.port=8091
#数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=****
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?serverTimezone=Asia/Shanghai
#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
6.5.4.创建主启动类
@SpringBootApplication
public class SpringcloudOrderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudOrderApplication.class, args);
}
//将RestTemplate交于容器管理
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
6.5.5.controller
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired
private OrderServiceImpl orderService;
//注入工具类 --这个工具类没有交于容器管理,需要自己手动交于容器
@Autowired
private RestTemplate restTemplate;
@GetMapping("buy/{pid}/{num}")
public String buy(@PathVariable Integer pid,@PathVariable Integer num){
System.out.println("=======购买开始===========");
Order order=new Order();
//设置购买的数量
order.setNumber(num);
//设置购买人的名字
order.setUsername("东方青苍");
//设置id
order.setUid(1);
//设置订单中商品的信息
//由于商品的信息在商品微服务中,如果想要用,得调用
//远程调用有两种方法1.http协议的restful风格的调用--适合微服务2.基于TCp协议的RPC--适合SOA分布式
//所以我们用http协议--1.自己写代码完成http的调用
// 2springboot提供一个工具类RestTemplate--属于http协议完成的调用
Product forObject = restTemplate.getForObject("http://localhost:8081/product/getById/" + pid, Product.class);
//获取商品的id
order.setPid(pid);
order.setPprice(forObject.getPprice());
order.setPname(forObject.getPname());
orderService.saveOrder(order);
System.out.println("==========购买结束=========");
return "下单成功";
}
}
6.5.6.service
public interface OrderService {
public int saveOrder(Order order);
}
6.5.7.serviceImpl
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Override
public int saveOrder(Order order) {
//添加,将订单的信息添加到order中
return orderMapper.insert(order);
}
}
6.5.8.dao
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}
6.5.9.运行
7.服务治理
7.1.为什使用服务治理
上面的代码,因为我们生产者的ip和端口号都写死了,会出现一下的问题
1.如果商品微服务部署的地址发生改变,订单微服务也要跟着修改
2.没有办法使用负载均衡
3.一旦服务变得越来越多,人工维护调用关系困难
解决的方法:使用服务治理主件--所有的微服务都会自动的把自己的信息注册到该主件
7.2.什么是服务治理
服务治理是微服务架构中最核心最基本的模块。用于实现各个微服务的自动化注册与发现。
7.2.1.服务注册
在服务治理框架中,都会构建一个注册中心,每个服务单元向注册中心登记自己提供服务的详细信息。并在注册中心形成一张服务的清单,服务注册中心需要以心跳30s 90s的方式去监测清单中 的服务是否可用,如果不可用,需要在服务清单中剔除不可用的服务
7.2.2.服务发现
服务调用方向服务注册中心咨询服务,并获取所有服务的实例清单,实现对具体服务实例的访问。
通过上面的调用图会发现,除了微服务,还有一个组件是服务注册中心,它是微服务架构非常重要
的一个组件,在微服务架构里主要起到了协调者的一个作用。注册中心一般包含如下几个功能:
1. 服务发现:
服务注册:保存服务提供者和服务调用者的信息
服务订阅:服务调用者订阅服务提供者的信息,注册中心向订阅者推送提供者的信息
2. 服务配置:
配置订阅:服务提供者和服务调用者订阅微服务相关的配置
配置下发:主动将配置推送给服务提供者和服务调用者
3. 服务健康检测
检测服务提供者的健康情况,如果发现异常,执行服务剔除
7.3.常见的注册中心
7.3.1.Zookeeper
zookeeper是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决分布式 应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。
7.3.2.Eureka
Eureka是Springcloud Netflix中的重要组件,主要作用就是做服务注册和发现。但是现在已经闭源 ,停更不停用。
7.3.3.Consul
Consul是基于GO语言开发的开源工具,主要面向分布式,服务化的系统提供服务注册、服务发现和配置管理的功能。Consul的功能都很实用,其中包括:服务注册/发现、健康检查、Key/Value存储、多数据中心和分布式一致性保证等特性。Consul本身只是一个二进制的可执行文件,所以安装和部署都非常简单,只需要从官网下载后,在执行对应的启动脚本即可。
7.3.4.Nacos (服务治理 配置中心)
Nacos是一个更易于构建云原生应用的动态服务发现,配置管理和服务管理平台是 SpringCloud Alibaba 组件之一,负责服务注册发现和服务配置,可以这样认为nacos=eureka+config。
8.nacos
8.1.什么是nacos
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理,从上面的介绍就可以看出,nacos的作用就是一个注册中心,用来管理注册上来的各个微服务。
8.2.搭建Nacos 的环境
8.2.1.下载Nacos
Releases · alibaba/nacos · GitHub
8.2.2.安装Nacos --解压就可以
8.2.3.启动Nacos
进入Nacos 中bin文件
输入命令 startup.cmd -m standalone 默认启动集群模式 加上-m standalone是单例模式
Nacos 1.3.0之前都是单击模式 1.3.0之后是集群模式
8.2.4.访问Nacos
localhost:8848/nacos
8.3. 将商品微服务注册到nacos
8.3.1.添加依赖
<!--引入ali的nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
8.3.2.在配置文件中指定路径和微服务的名称
#指定nacos注册中心的ip和端口号
spring.cloud.nacos.discovery.server-addr=localhost:8848
#指定微服务的名称
spring.application.name=product
8.3.3.启动服务
8.4.订单微服务拉取商品微服务
8.4.1.添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
8.4.2.在配置文件中指定那个服务和拉取微服务的名称
#指定那个注册中心
spring.cloud.nacos.discovery.server-addr=localhost:8848
#是否把该服务注册到注册中心
spring.cloud.nacos.discovery.register-enabled=false
#指定拉取那一个微服务
spring.application.name=product
8.4.3.修改controller层里面的代码
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired
private OrderServiceImpl orderService;
//注入工具类 --这个工具类没有交于容器管理,需要自己手动交于容器
@Autowired
private RestTemplate restTemplate;
//spring 中提供一个工具类,该类可以从注册中心来取微服务的信息
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("buy/{pid}/{num}")
public String buy(@PathVariable Integer pid,@PathVariable Integer num){
System.out.println("=======购买开始===========");
Order order=new Order();
//设置购买的数量
order.setNumber(num);
//设置购买人的名字
order.setUsername("东方青苍");
//设置id
order.setUid(1);
//拉取商品的信息
//1.拉取服务名称对应的所有实例对象
List<ServiceInstance> instances = discoveryClient.getInstances("product");
//获取第一个实例对象
ServiceInstance serviceInstance = instances.get(0);
//获取实例对象中的端口号和ip
//获取端口号
// serviceInstance.getPort();
//获取ip地址
// serviceInstance.getHost();
//获取端口号和ip
String s = serviceInstance.getUri().toString();
Product forObject = restTemplate.getForObject(s+"/product/getById/" + pid, Product.class);
//获取商品的id
order.setPid(pid);
order.setPprice(forObject.getPprice());
order.setPname(forObject.getPname());
orderService.saveOrder(order);
System.out.println("==========购买结束=========");
return "下单成功";
}
}
9.负载均衡
通过上面我们使用注册中心解决了ip和端口的写死的问题,但是还没有实现负载均衡
9.1.什么是负载均衡
通俗的讲, 负载均衡就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。根据负载均衡发生位置的不同,一般分为服务端负载均衡和客户端负载均衡。 服务端负载均衡指的是发生在服务提供者一方,比如常见的nginx负载均衡而客户端负载均衡指的是发生在服务请求的一方,也就是在发送请求之前已经选好了由哪个实例处理请求
我们在微服务调用关系中一般会选择客户端负载均衡,也就是在服务调用的一方来决定服务由哪个提供者执行.
9.2.自定义负载均衡
9.2.1.启动多个商品微服务
9.2.2.controller层代码
//1.拉取服务名称对应的所有实例对象
List<ServiceInstance> instances = discoveryClient.getInstances("product");
//获取第一个实例对象 new Random().nextInt(instances.size())随机生成一个int的整数
ServiceInstance serviceInstance = instances.get(new Random().nextInt(instances.size()));
9.2.3.访问
9.3.基于Ribbon实现负载均衡 ---组件
9.3.1.什么是Ribbon
是 Netflix 发布的一个负载均衡器,有助于控制 HTTP 和 TCP客户端行为。在 SpringCloud 中, nacos一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从nacos中读 取到的服务信息,在调用服务节点提供的服务时,会合理(策略)的进行负载。 在SpringCloud中可以将注册中心和Ribbon配合使用,Ribbon自动的从注册中心中获取服务提供者的 列表信息,并基于内置的负载均衡算法,请求服务。
9.3.2.Ribbon的主要作用
1.服务调用
基于Ribbon实现服务调用, 是通过拉取到的所有服务列表组成(服务名-请求路径的)映射关系。借助 RestTemplate 最终进行调用
2.负载均衡
当有多个服务提供者时,Ribbon可以根据负载均衡的算法自动的选择需要调用的服务地址 Ribbon是Spring Cloud的一个组件, 它可以让我们使用一个注解就能轻松的搞定负载均衡
9.3.3.使用Ribbon完成负载均衡
1.添加注解
//将RestTemplate交于容器管理
@Bean
@LoadBalanced //ribbon借助restTemplate完成负载均衡的调用
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
2.controller
@RequestMapping("order")
public class OrderController {
@Autowired
private OrderServiceImpl orderService;
//注入工具类 --这个工具类没有交于容器管理,需要自己手动交于容器
@Autowired
private RestTemplate restTemplate;
@GetMapping("buy/{pid}/{num}")
public String buy(@PathVariable Integer pid,@PathVariable Integer num){
System.out.println("=======购买开始===========");
Order order=new Order();
//设置购买的数量
order.setNumber(num);
//设置购买人的名字
order.setUsername("东方青苍");
//设置id
order.setUid(1);
//拉取商品的信息
//restTemplate调用必须是 http://服务提供者的名字/服务提供者的资源路径
Product forObject = restTemplate.getForObject("http://product/product/getById/" + pid, Product.class);
//获取商品的id
order.setPid(pid);
order.setPprice(forObject.getPprice());
order.setPname(forObject.getPname());
orderService.saveOrder(order);
System.out.println("==========购买结束=========");
return "下单成功";
}
}
3.访问--默认使用的是轮询
9.3.4.Ribbon支持的负载均衡策略
Ribbon内置了多种负载均衡策略,内部负载均衡的顶级接口为com.netflix.loadbalancer.IRule , 具体的负载策略如下图所示:
9.3.5.通过修改配置来调整Ribbon的负载均衡策略
#指定ribbon负载均衡的策略
product.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
微服务名称.ribbon.NFLoadBalancerRuleClassName=负载均衡策略
10.基于OpenFeign实现服务调用
10.1.什么使用openFeign
上面使用的RestTemplate远程调用的语法跟我们平时调用的语法不一样
10.2.什么是openFeign
OpenFeign是Spring Cloud提供的一个声明式的伪Http客户端,它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可.Nacos很好的兼容了oppenFeign,openFeign负载均衡默认集成了 Ribbon,所以在Nacos下使用Fegin默认就实现了负载均衡的效果。
10.3.使用openFeign
10.3.1.添加openFeign的依赖
<!--添加openFeign的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
10.3.2.创建openFeign的接口
//调用微服务 (value="被调用的微服务的名称")
@FeignClient(value = "product")
public interface FeignProduct {
//调用的微服务的那个接口:必须和调用的微服务的方法参数一样
@GetMapping("/product/getById/{pid}")
public Product product(@PathVariable Integer pid);
}
10.3.3.在主类上开启openFeign注解
@SpringBootApplication
@EnableFeignClients
public class SpringcloudOrderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudOrderApplication.class, args);
}
//将RestTemplate交于容器管理
@Bean
@LoadBalanced //ribbon借助restTemplate完成负载均衡的调用
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
10.3.4.修改controller层的代码
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired
private OrderServiceImpl orderService;
//注入工具类 --这个工具类没有交于容器管理,需要自己手动交于容器
@Autowired
private RestTemplate restTemplate;
//注入我们刚刚写的接口--会自动生成代理类
@Autowired
private FeignProduct feignProduct;
@GetMapping("buy/{pid}/{num}")
public String buy(@PathVariable Integer pid,@PathVariable Integer num){
System.out.println("=======购买开始===========");
Order order=new Order();
//设置购买的数量
order.setNumber(num);
//设置购买人的名字
order.setUsername("东方青苍");
//设置id
order.setUid(1);
//拉取商品的信息
//调用商品的方法
Product product = feignProduct.product(pid);
//获取商品的id
order.setPid(pid);
order.setPprice(product.getPprice());
order.setPname(product.getPname());
orderService.saveOrder(order);
System.out.println("==========购买结束=========");
return "下单成功";
}
}
10.3.5.访问
11.nacos集群
在实际开发过程中,如果使用Nacos的话,为了确保高可用,我们一般都会对其进行集群的部署。Nacos规定集群中Nacos节点的数量需要大于等于3个;同时,单机模式下Nacos的数据默认保存在其内嵌数据库中deby,不方便观察数据存储的基本情况。而且如果集群中启动多个默认配置下的Nacos节点,数据存储是存在一致性问题的。为了解决这个问题,Nacos采用了集中式存储的方式来支持集群化部署,目前只支持MySQL的存储;此外,我们还需要借助Nginx实现负载均衡。这一过程的部署架构图如下所示:
11.1.如何使用nacos集群
11.1.1创建一个数据库
11.1.3.指定使用mysql作为数据存储
因为nacos数据默认保存在其内嵌数据库中deby,所有我们想要使用自己数据库就得指定,找到自己nacos然后进入conf
11.1.4.配置集群文件
nacos/conf下
nacos并复制三份
11.1.6.修改每一份的端口号
11.1.7.启动三个nacos
11.1.8.访问nacos
11.2.搭建nginx代理上面三个nacos
11.2.1.启动nginx
11.2.2.访问
11.3.将微服务注册到nacos集群上
12.gateway网关
12.1.什么是网关
大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用
这样的架构,会存在着诸多的问题:
客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性
认证复杂,每个服务都需要独立认证。
存在跨域请求,在一定场景下处理相对复杂
如何解决:
上面的这些问题可以借助API网关来解决。所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服 务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控(黑白名单)、路由转发等等。 添加上API网关之后,系统的架构图变成了如下所示:
12.2.常见的网关
12.2.1.Ngnix+lua
使用nginx的反向代理和负载均衡可实现对api服务器的负载均衡及高可用lua是一种脚本语言,可以来编写一些简单的逻辑, nginx支持lua脚本
12.2.2.kong
基于Nginx+Lua开发,性能高,稳定,有多个可用的插件(限流、鉴权等等)可以开箱即用。 问题:
只支持Http协议;二次开发,自由扩展困难;提供管理API,缺乏更易用的管控、配置方式。
12.2.3.Zuul 1.0(慢 servlet 2.0 ) zuul2.0 没出来
Netflix开源的网关,功能丰富,使用JAVA开发,易于二次开发 问题:缺乏管控,无法动态配
置;依赖组件较多;处理Http请求依赖的是Web容器,性能不如Nginx
12.2.4.Spring Cloud Gateway
Spring公司为了替换Zuul而开发的网关服务,将在下面具体介绍。
注意:SpringCloud alibaba技术栈中并没有提供自己的网关,我们可以采用Spring Cloud Gateway来做网关
12.3.什么是Gateway网关
Spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0 和 Project Reactor 等术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。它的目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控和限流。
12.3.1.Gateway网关优点
1.性能强劲:是第一代网关Zuul的1.6倍
2.功能强大:内置了很多实用的功能,例如转发、监控、限流等
3.设计优雅,容易扩展.
12.3.2.Gateway网关缺点
1.其实现依赖Netty与WebFlux,不是传统的Servlet编程模型,学习成本高
2.不能将其部署在Tomcat、Jetty等Servlet容器里,只能打成jar包执行 web.Jar
3.需要Spring Boot 2.0及以上的版本,才支持
注意:gateway内置了服务器 netty服务器。
13.4.如何使用gateway网关
13.4.1.创建一个gateway微服务模块--此步骤省略
13.4.2.加入相关的依赖
<dependencies>
<!--只需要添加该依赖,不要使用spring-boot-starter- web依赖。
因为gateway内置了服务器netty.而web的jar内置 tomcat-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
13.4.3.配置文件
#配置端口号
server:
port: 7000
#
spring:
application:
name: springCloud-gateway
#路由的转发 routes需要的是一个对象--List<RouteDefinition> routes
cloud:
gateway:
routes:
- id: springcloud-product
#路由转发的真是地址
uri: http://localhost:8081
#predicates断言--当满足断言时,才会转发到真实的地址
predicates:
- Path=/product/**
- id: springcloud-order
uri: http://localhost:8091
predicates:
- Path=/order/**
List<RouteDefinition> routes
id,路由标识符,区别于其他 Route。默认生成一个
uri,路由指向的目的地 uri,即客户端请求最终被转发到的微服务。
order,用于多个 Route 之间的排序,数值越小排序越靠前,匹配优先级越高。
predicate,断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由。
filter,过滤器用于修改请求和响应信息。
13.4.4.创建主启动类
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class,args);
}
}
13.4.5.访问
13.5.优化--让gateway网关从注册中心拉取服务
发现: 路由配置时uri的地址还是一个固定的网络地址,如果后期微服务地址发送改变,也需要修改网关的配置。 不能完成负载均衡。
解决: 我们知道,gateway他也是可一个微服务,它可以从注册中心拉取服务信息
13.5.1.加入依赖
<!--nacos的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
13.5.2.配置文件中指定注册中心的地址
13.6.gateway自动路由
发现: 有一个微服务需要配置一个路由,如果这时增加一个新的微服务,则需要在配置文件中增加一个新的路由配置。
能不能自动路由转发微服务呢!====能
13.6.1.修改配置文件
13.6.2.访问
13.7.Gateway断言
在gateway中内置很多断言器, SpringCloud Gateway包括许多内置的断言工厂,所有这些断言都与 HTTP请求的不同属性匹配体如下:
13.7.1.基于Datetime类型的断言工厂
此类型的断言根据时间做判断,主要有三个:
AfterRoutePredicateFactory:接收一个日期参数,判断请求日期是 否晚于指定日期
BeforeRoutePredicateFactory:接收一个日期参数,判断请求日期是否早于指定日期BetweenRoutePredicateFactory:接收两个日期参数,判断请求日 期是否在指定时间段内
-After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]
3.7.2.基于远程地址的断言工厂
RemoteAddrRoutePredicateFactory:接收一个IP地址段,判断请求主机地址是否在地址段中 -RemoteAddr=192.168.1.1/24
13.7.3.基于Cookie的断言工厂
CookieRoutePredicateFactory:接收两个参数,cookie 名字和一个正则表达式。 判断请求
cookie是否具有给定名称且值与正则表达式匹配。
-Cookie=chocolate,ch.
13.7.4.基于Header的断言工厂
HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。 判断请求Header是否 具有给定名称且值与正则表达式匹配。 key value
-Header=X-Request-Id, \d+
13.7.5.基于Host的断言工厂
HostRoutePredicateFactory:接收一个参数,主机名模式。判断请求的Host是否满足匹配规则。
-Host=**.testhost.org
13.7.6.基于Method请求方法的断言工厂
MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。
-Method=GET
13.7.7.基于Path请求路径的断言工厂
PathRoutePredicateFactory:接收一个参数,判断请求的URI部分是否满足路径规则。
-Path=/foo/{segment}基于Query请求参数的断言工厂
QueryRoutePredicateFactory :接收两个参数,请求param和正则表达式, 判断请求参数是否具 有给定名称且值与正则表达式匹配。
-Query=baz, ba.
17.7.8.基于路由权重的断言工厂
WeightRoutePredicateFactory:接收一个[组名,权重], 然后对于同一个组内的路由按照权重转发
routes:
-id: weight_route1 uri: host1 predicates:
-Path=/product/**
-Weight=group3, 1
-id: weight_route2 uri: host2 predicates:
-Path=/product/**
-Weight= group3, 9
如果上面内置的断言不能满足你的需求:可以自定义断言。
注意: 名称必须为XXXRoutePredicateFactory并且继承AbstractRoutePredicateFactory
使用时: xxx=
13.8.过滤器
13.8.1.过滤器的作用
过滤器就是在请求的传递过程中,对请求和响应做一些手脚
13.8.2.过滤器的生命周期
Pre:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
Post :这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
13.8.3.过滤器的分类
Gateway 的Filter从作用范围可分为两种: GatewayFilter与GlobalFilter
局部过滤器(作用在某一个路由上)
全局过滤器(作用全部路由上)
GatewayFilter:应用到单个路由或者一个分组的路由上。
GlobalFilter:应用到所有的路由上。
13.8.4.自定义全局过滤器
内置的过滤器已经可以完成大部分的功能,但是对于企业开发的一些业务功能处理,还是需要我们自己编写过滤器来实现的,那么我们一起通过代码的形式自定义一个过滤器,去完成统一的权限校验。
开发中的鉴权逻辑:
当客户端第一次请求服务时,服务端对用户进行信息认证(登录)
认证通过,将用户信息进行加密形成token,返回给客户端aaaa,作为登录凭证
以后每次请求,客户端都携带认证的token
服务端对token进行解密,判断是否有效。
如上图,对于验证用户是否已经登录鉴权的过程可以在网关统一检验.检验的标准就是请求中是否携带token凭证以及token的正确性.下面的我们自定义一个GlobalFilter,去校验所有请求的请求参数中是否包含“token”,如何不包含请求参数“token”则不转发路由,否则执行正常的逻辑
自定义全局过滤器 要求:必须实现GlobalFilter,Ordered接口
1.定义一个类作为过滤器实现GlobalFilter,Ordered接口
public class LoginFilter implements GlobalFilter, Ordered {
@Autowired
private Anon anon;
//过滤业务
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//获取到request response
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
//1.获取去请求路径
String path = request.getPath().toString();
if (anon.getUrl().contains(path)){
//放行
return chain.filter(exchange);
}
//2.判断是否携带token
String token = request.getHeaders().getFirst("token");
if (StringUtils.hasText(token)&&"admin".equals(token)){
//放行
return chain.filter(exchange);
}
//3.返回一个json数据
//设置状态码
response.setStatusCode(HttpStatus.UNAUTHORIZED);
//返回json的数据
Map<String,Object> map=new HashMap<>();
map.put("msg","请先登录");
map.put("code",4000);
//作为json转换
byte[] bytes = JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8);
//调用bufferFactory生产DATa Buffer对象
DataBuffer wrap = response.bufferFactory().wrap(bytes);
//调用Mono中的just方法,返回写给前端的JSON数据
return response.writeWith(Mono.just(wrap));
}
@Override
public int getOrder() {
return 0;
}
}
2.定义实体类
@Component
@ConfigurationProperties(prefix = "anon")
public class Anon {
private List<String> url;
public List<String> getUrl() {
return url;
}
public void setUrl(List<String> url) {
this.url = url;
}
}
3.修改配置文件
anon.url[0]=/sso/login
anon.url[1]=/product/getMsg
4.定义一个方法
@GetMapping("getMsg")
public String getmsg(){
return "登录============";
}
14.配置文件
14.1.为什么使用配置文件
1.商品微服务搭建一个集群,如果配置文件发生改变的话,每一台的商品微服务也要跟着一起改变
2.商品微服务和订单微服务这些可能会存在相同的配置,如果这些相同的配置发生变化,需要对配一个微服务进行修改
解决办法:
提供一个随微服务配置文件进行统一的管理的主件
nacos可以作为配置中心
springcloud-config:这个是基于git完成
apollo配置中心
14.2.如何使用配置文件
14.2.1.在配置中心创建一个配置文件
14.2.2.添加配置文件依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
14.2.3.创建一个配置文件--名字是bootstrap.properties
#这个文件的优先级要高于application.properties--该文件是引用配置中心的配置内容
#如果application.properties和bootstrap有相同的内容,以properties和bootstrap有相同的为主
#起名字--跟我们的配置中心的名称一样
spring.application.name=springCloud-order
#指定nacos的配置中心的地址
spring.cloud.nacos.config.server-addr=localhost:81
#指定nacos中心文件的后缀--默认是properties
spring.cloud.nacos.config.file-extension=properties
#如果配置中的的名字不是我们微服务的名称必须指定引用那个配置内容
#spring.cloud.nacos.config.name=配置中心的名字
14.2.4.写一个方法进行测试
14.2.5.将application配置文件的内容复制到配置中心
14.2.6.配置文件实时刷新
1.修改配置中心的文件
2.添加注解
3.访问
14.3.命名空间
14.3.1.创建命名空间
14.3.2.将public里面的配置克隆到dev(开发环境下)
14.3.3.运行项目
14.4.配置公共的配置文件
配置文件与配置文件之间有共同的配置,如果那个共同的配置需要改动,那么可能需要改动很多配置文件
14.4.1.新建配置
14.4.2.将product和order的数据源剪切到新建的配置中
14.4.3.修改bootstrap.properties文件
14.5.4.访问--测试
15.Sleuth--链路追踪
15.1.什么是链路追踪
在大型系统的微服务化构建中,一个系统被拆分成了许多微服务。这些模块负责不同的功能,组合成系统,最终可以提供丰富的功能。在这种架构中,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心【区域】,也就意味着这种架构形式也会存在一些问题:
如何快速发现问题?
如何判断故障影响范围?
如何梳理服务依赖以及依赖的合理性?
如何分析链路性能问题以及实时容量规划?
分布式链路追踪(Distributed Tracing),就是将一次分布式请求还原成调用链路,进行日志记录,性能监控并将一次分布式请求的调用情况集中展示。比如各个服务节点上的耗时、请求具体到达哪台机器上IP、每个服务节点的请求状态200 500等等。
15.2.常见的链路追踪
15.2.1.cat
由大众点评开源,基于Java开发的实时应用监控平台,包括实时应用监控,业务监控 。 集成
方案是通过代码埋点的方式来实现监控,比如: 拦截器,过滤器等。 对代码的侵入性很大,集成成本较高。风险较大。
15.2.2.zipkin
由Twitter公司开源,开放源代码分布式的跟踪系统,用于收集服务的定时数据,以解决微
服务架构中的延迟问题,包括:数据的收集、存储、查找和展现《图形化》。该产品结合spring-cloud-sleuth 使用较为简单, 集成很方便, 但是功能较简单。
15.2.3.pinpoint
Pinpoint是韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点
是支持多种插件,UI功能强大,接入端无代码侵入。
15.2.4.skywalking 【未来企业会使用的多】
SkyWalking是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多 种插件,UI功能较强,接入端无代码侵入。目前已加入Apache孵化器。
15.2.5.Sleuth
Sleuth 日志记录每一条链路上的所有节点,以及这些节点所在的机器,和耗时log4j,SpringCloud 提供的分布式系统中链路追踪解决方案。
注意:SpringCloud alibaba技术栈中并没有提供自己的链路追踪技术的,我们可以采用Sleuth +
Zipkin来做链路追踪解决方案
Sleuth--为每个微服务生成日志--侵入性[修改xml配置文件]
Zipkin--对每个微服务的日志进行搜索并以图形化展示--侵入性[修改配置文件]
15.3.什么是Sleuth
SpringCloud Sleuth主要功能就是在分布式系统中提供追踪解决方案它大量借用了Google Dapper的设计, 先来了解一下Sleuth中的术语和相关概念。
Trace (一条完整链路--包含很多span(微服务接口))
由一组Trace Id(贯穿整个链路)相同的Span串联形成一个树状结构.为了实现请求跟踪,当请求到达分布式系统的入口端点时,只需要服务跟踪框架为该请求创建一个唯一的标识(即TraceId),同时在分布式系统内部流转的时候,框架始终保持传递该唯一值,直到整个请求的返回。那么我们就可以使用该唯一标识将所有的请求串联起来,形成一条完整的请求链路。
Span 代表了一组基本的工作单元。为了统计各处理单元的延迟,当请求到达各个服务组件的时候,也通过一个唯一标识(SpanId)来标记它的开始、具体过程和结束。通过SpanId的开始和结束时间戳,就能统计该span的调用时间,除此之外,我们还可以获取如事件的名称。请求信息等元数据。
15.4.如何使用Sleuth
15.4.1.在父工程添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
</dependencies>
查看日志文件并不是一个很好的方法,当微服务越来越多日志文件也会越来越多,通过Zipkin可以将日志聚合,并进行可视化展示和全文检索。
15.5.Zipkin
15.5.1.什么是Zipkin
Zipkin 是 Twitter 的一个开源项目,它基于Google Dapper实现,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储展现、查找和我们可以使用它来收集各个服务器上请求链路的跟踪数据,并通过它提供的REST API接口来辅助我们查询跟踪数据以实现对分布式系统的监控程序,从而及时地发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源除了面向开发的 API 接口之外,它也提供了方便的UI组件来帮助我们直观的搜索跟踪信息和分析请求链路明细,比如:可以查询某段时间内各用户请求的处理时间等。
Zipkin 提供了可插拔数据存储方式:In-Memory、MySql、Cassandra 以及 Elasticsearch
上图展示了 Zipkin 的基础架构,它主要由 4 个核心组件构成:
Collector:收集器组件,它主要用于处理从外部系统发送过来的跟踪信息,将这些信息转换为Zipkin 内部处理的 Span 格式,以支持后续的存储、分析、展示等功能。
Storage:存储组件,它主要对处理收集器接收到的跟踪信息,默认会将这些信息存储在内存中,我们也可以修改此存储策略,通过使用其他存储组件将跟踪信息存储到数据库中。
RESTful API:API 组件,它主要用来提供外部访问接口。比如给客户端展示跟踪信息,或是外接系统访问以实现监控等。
Web UI:UI 组件,基于 API 组件实现的上层应用。通过 UI 组件用户可以方便而有直观地查询和分析跟踪信息。
Zipkin 分为两端,一个是 Zipkin 服务端,一个是 Zipkin 客户端,客户端也就是微服务的应用。客户端会配置服务端的 URL 地址,一旦发生服务间的调用的时候,会被配置在微服务里面的 Sleuth 的监听器监听,并生成相应的 Trace 和 Span 信息发送给服务端。
15.6. ZipKin安装
15.6.1.下载成功--输入命令就可以用
15.6.2.启动ZipKin--找到自己下载的位置
15.6.3.访问zipken
15.7.如何使用zipkin
15.7.1.在父类中添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
15.7.2.修改配置文件
#指定zipkin服务端所在的地址
spring.zipkin.base-url=http://localhost:9411
#不要让nacos也把zipkin注册到注册中心
spring.zipkin.discovery-client-enabled=false
#设置zipkin对sleuth链路日志的采样比列,在企业中是3% 我现在是1.0=100%
spring.sleuth.sampler.probability=1.0
复制到每一个微服务的配置文件上--除了共同的微服务
15.7.3.重启项目并且访问