介绍:课程介绍 1、前置 javaSE,javaEE,SSM,Boot
为什么:一线城市,上了规模大厂、中厂,都需要cloud。
cloud,薪资高
2、特点 各大机构视频教程、网络文章、spring官网以及本人8年的java开发经验。
跟着本课程,写就可以了。
入门课程,会用cloud。
3、如何学习 保姆级教程。
代码和课程图片粘贴md格式的文档上面。
倍速播放。关闭弹幕。
学完一个知识点,有任何问题,弹幕、评论、粉丝群大家讨论。
4、面向人员 大学生朋友:大学当中,科班非科班,毕业找一份java工作,没问题。
工作1-3年朋友:自己行业又累薪资又低。4-6个月,坚持下来,转行找到java开发职位没问题。
5、心态 太简单了、太难。 我不是RMB,做不到14亿人都喜欢。 右上角有个X,点击一下退出可以了。
不要吃饱了骂厨子、念完经打和尚、过河拆桥。
Talk is cheap ,show me the code 。 坚持。30小结。都看完,知识就是你的了。
欢迎大家,一键三连。
6、获取资料 www.ydlclass.comopen in new window 文档区,免费下载即可。
我itlils 和楠哥itnanls java学习整套路径,列出来。 教程都由我和楠哥亲自录制 。 免费自学java成功。
案例:免费自学,java工作,应届生,一线,10k。
随时一对一解决问题,规划,简历修改。加入我们会员。
第一章 SpringCloud简介 一、 软件架构演进 单体架构
image-20220328172416767 垂直架构
image-20220328172721883 分布式架构
image-20220328173112642 SOA架构
image-20220328174118241 微服务架构
image-20220328174633493 二、微服务架构 1、 微服务理念 ①"微服务”一词源 于 Martin Fowler的名为 Microservices的博文,可以在他的官方博客上找到http://martinfowler.com/articles/microservices.htmlopen in new window
②微服务是系统架构上的一种设计风格,它的主旨是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务之间一般通过 HTTP 的 RESTfuL API 进行通信协作。
restfull 风格 :数据的增删改查,使用http的不同方式。数据传输用json。
From: 元动力 1 2 3 4 5 6 7 查询 GET ip:port/user/1 新增 POST ip:port/user json{username:itlils,age:18} 修改 PUT ip:port/user/1 json{username:itlils,age:19} 删除 DELETE ip:port/user/1
③由于有了轻量级的通信协作基础,所以这些微服务可以使用不同的语言来编写。大厂,各种语言混用。
cloud官网: https://spring.io/open in new window
image-20220329154419410 image-20220329152020956 2、 现在大型互联网公司,都在使用微服务架构: 京东的促销节架构:618
image-20220329152531517 阿里的架构:
image-20220329152552588 京东物流的架构:
image-20220329152611053 3、 springcloud组件: image-20220329152758773 image-20220329153147800 第二章 走进springcloud 一、了解springcloud ①Spring Cloud 是一系列框架 的有序集合。
②Spring Cloud 并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来。
netflix eureka 1.1,alibaba 2.2
③通过 Spring Boot 风格进行再封装,屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
④它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、 断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
⑤Spring Cloud项目官方网址:https://spring.io/projects/spring-cloudopen in new window
⑥Spring Cloud 版本命名方式采用了伦敦地铁站的名称 ,同时根据字母表的顺序来对应版本时间顺序,比如:最早的Release版本:Angel,第二个Release版本:Brixton,然后是Camden、Dalston、Edgware,Finchley,Greenwich,Hoxton。
目前最新的是2021.0.1版本。
image-20220329161144299 二、 cloud与boot版本对应关系 image-20220329164540295 三、 dubbo对比 image-20220329161102849 相同点 :Spring Cloud 与 Dubbo 都是实现微服务有效的工具。
不同点 :
1Dubbo 只是实现了服务治理,而 Spring Cloud 子项目分别覆盖了微服务架构下的众多部件。
2Dubbo 使用 RPC 通讯协议,Spring Cloud 使用 RESTful 完成通信,Dubbo 效率略高于 Spring Cloud。
小结
• 微服务就是将项目的各个模块拆分为可独立运行、部署、测试的架构设计风格。
• Spring 公司将其他公司中微服务架构常用的组件整合起来,并使用 SpringBoot 简化其开发、配置。称为 Spring Cloud。
• Spring Cloud 与 Dubbo都是实现微服务有效的工具。Dubbo 性能更好,而 Spring Cloud 功能更全面。Dubbo 已经融入到spingcloudAlibaba这一套
本课程技术特点 : 两套springcloud.
1. 5年前的项目。springcloud netflix(eureka config hystrix) hoxton。会讲到。
2. 新项目 springcloud alibaba(nacos sentinel)。也会讲到。
第三章 停更/升级/替换 红色不维护。
绿色是alibaba一套,推荐使用。
image-20220329171255668 第四章 微服务架构编码构建 image-20220404103923982 一、 搭建 Provider 和 Consumer 服务 1、父工程 spring-cloud-parent image-20220404103149867 使用utf-8编码
image-20220404103334670 maven设置
image-20220404103417399 pom.xml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 < ?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < modelVersion> 4.0.0< /modelVersion> < groupId> com.ydlclass< /groupId> < artifactId> spring-cloud-parent< /artifactId> < version> 1.0.0< /version> < !--spring boot 环境 --> < parent> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-parent< /artifactId> < version> 2.2.11.RELEASE< /version> < relativePath/> < /parent> < properties> < maven.compiler.source> 8< /maven.compiler.source> < maven.compiler.target> 8< /maven.compiler.target> < project.build.sourceEncoding> UTF-8< /project.build.sourceEncoding> < project.reporting.outputEncoding> UTF-8< /project.reporting.outputEncoding> < /properties> < /project>
2、提供者 eureka-provider image-20220330164728077 搭建springboot工程:步骤把大象装冰箱有几步? 工作中别问同事
pom.xml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 < ?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < parent> < artifactId> spring-cloud-parent< /artifactId> < groupId> com.ydlclass< /groupId> < version> 1.0.0< /version> < /parent> < modelVersion> 4.0.0< /modelVersion> < artifactId> eureka-provider< /artifactId> < properties> < maven.compiler.source> 8< /maven.compiler.source> < maven.compiler.target> 8< /maven.compiler.target> < /properties> < dependencies> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-web< /artifactId> < /dependency> < /dependencies> < /project>
application.yml
主启动类 ProviderApp
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.ydlclass.provider;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class ProviderApplication { public static void main (String[] args) { SpringApplication.run(ProviderApplication.class,args); } }
Goods
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 package com.ydlclass.provider.domain;import java.io.Serializable;public class Goods implements Serializable { private int id; private String title; private double price; private int count; public Goods (int id, String title, double price, int count) { this .id = id; this .title = title; this .price = price; this .count = count; } @Override public String toString () { return "Goods{" + "id=" + id + ", title='" + title + '\'' + ", price=" + price + ", count=" + count + '}' ; } public int getId () { return id; } public void setId (int id) { this .id = id; } public String getTitle () { return title; } public void setTitle (String title) { this .title = title; } public double getPrice () { return price; } public void setPrice (double price) { this .price = price; } public int getCount () { return count; } public void setCount (int count) { this .count = count; } }
GoodsController
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.ydlclass.provider.controller;import com.ydlclass.provider.domain.Goods;import com.ydlclass.provider.service.GoodsService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/goods") public class GoodsController { @Autowired GoodsService goodsService; @GetMapping("findById/{id}") public Goods findById (@PathVariable("id") int id) { Goods goods = goodsService.findById(id); return goods; } }
GoodsService
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.ydlclass.provider.service;import com.ydlclass.provider.dao.GoodsDao;import com.ydlclass.provider.domain.Goods;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Service public class GoodsService { @Autowired GoodsDao goodsDao; public Goods findById (int id) { Goods goods = goodsDao.findById(id); return goods; } }
GoodsDao
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.ydlclass.provider.dao;import com.ydlclass.provider.domain.Goods;import org.springframework.stereotype.Repository;@Repository public class GoodsDao { public Goods findById (int id) { return new Goods (id,"手机" ,2000 ,100 ); } }
测试:
访问:http://localhost:8000/goods/findById/1open in new window
image-20220330170647529 3、消费者 eureka-consumer image-20220404111105516 pom.xml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 < ?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < parent> < artifactId> spring-cloud-parent< /artifactId> < groupId> com.ydlclass< /groupId> < version> 1.0-SNAPSHOT< /version> < /parent> < modelVersion> 4.0.0< /modelVersion> < artifactId> eureka-consumer< /artifactId> < dependencies> < !--spring boot web--> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-web< /artifactId> < /dependency> < /dependencies> < /project>
Goods
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package com.ydlclass.consumer.domain;public class Goods { private int id; private String title; private double price; private int count; public Goods () { } public Goods (int id, String title, double price, int count) { this .id = id; this .title = title; this .price = price; this .count = count; } public int getId () { return id; } public void setId (int id) { this .id = id; } public String getTitle () { return title; } public void setTitle (String title) { this .title = title; } public double getPrice () { return price; } public void setPrice (double price) { this .price = price; } public int getCount () { return count; } public void setCount (int count) { this .count = count; } }
OrderController
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.ydlclass.consumer.controller;import com.ydlclass.consumer.domain.Goods;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/order") public class OrderController { @GetMapping("/add/{id}") public Goods add (@PathVariable("id") Integer id) { return new Goods (); } }
application.yml
测试:
http://localhost:9000/order/add/2open in new window
image-20220404112103333 二、使用 RestTemplate 完成远程调用 Spring提供的一种简单便捷的模板类,用于在 java 代码里访问 restful 服务。 其功能与 HttpClient 类似,但是 RestTemplate 实现更优雅,使用更方便。 consumer工程中
RestTemplateConfig
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.ydlclass.consumer.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate () { return new RestTemplate (); } }
OrderController
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 package com.ydlclass.consumer.controller;import com.ydlclass.consumer.domain.Goods;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;@RestController @RequestMapping("/order") public class OrderController { @Autowired private RestTemplate restTemplate; @GetMapping("/goods/{id}") public Goods findGoodsById (@PathVariable("id") int id) { System.out.println("findGoodsById..." +id); String url = "http://localhost:8000/goods/findOne/" +id; Goods goods = restTemplate.getForObject(url, Goods.class); return goods; } }
测试:
第五章 Eureka服务注册与发现 一、Eureka 概念:
• Eureka 是 Netflix 公司开源的一个服务注册与发现的组件 。
• Eureka 和其他 Netflix 公司的服务组件(例如负载均衡、熔断器、网关等) 一起,被 Spring Cloud 社区整合为Spring-Cloud-Netflix 模块。
• Eureka 包含两个组件:Eureka Server (注册中心) 和 Eureka Client (服务提供者、服务消费者)。
操作:
image-20200606113829765 二、 搭建 Eureka Server 服务 (1)创建 eureka-server 模块
(2) 引入 SpringCloud 和 euraka-server 相关依赖
(3)完成 Eureka Server 相关配置
(4)启动该模块
父工程 pom
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 < ?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < modelVersion> 4.0.0< /modelVersion> < groupId> com.ydlclass< /groupId> < artifactId> spring-cloud-parent< /artifactId> < packaging> pom< /packaging> < version> 1.0-SNAPSHOT< /version> < modules> < module> eureka-provider< /module> < module> eureka-consumer< /module> < module> eureka-server< /module> < /modules> < !--spring boot 环境 --> < parent> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-parent< /artifactId> < version> 2.1.0.RELEASE< /version> < relativePath/> < /parent> < properties> < project.build.sourceEncoding> UTF-8< /project.build.sourceEncoding> < project.reporting.outputEncoding> UTF-8< /project.reporting.outputEncoding> < java.version> 1.8< /java.version> < !--spring cloud 版本--> < spring-cloud.version> Greenwich.RELEASE< /spring-cloud.version> < /properties> < !--引入Spring Cloud 依赖--> < dependencyManagement> < dependencies> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-dependencies< /artifactId> < version> ${spring-cloud.version}< /version> < type> pom< /type> < scope> import< /scope> < /dependency> < /dependencies> < /dependencyManagement> < /project>
eureka-server工程
pom
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 < ?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < parent> < artifactId> spring-cloud-parent< /artifactId> < groupId> com.ydlclass< /groupId> < version> 1.0-SNAPSHOT< /version> < /parent> < modelVersion> 4.0.0< /modelVersion> < artifactId> eureka-server< /artifactId> < dependencies> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-web< /artifactId> < /dependency> < !-- eureka-server --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-netflix-eureka-server< /artifactId> < /dependency> < /dependencies> < /project>
EurekaApp
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.ydlclass.eureka;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication @EnableEurekaServer public class EurekaApp { public static void main (String[] args) { SpringApplication.run(EurekaApp.class,args); } }
application.yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 server: port: 8761 eureka: instance: hostname: localhost client: service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka register-with-eureka: false fetch-registry: false
**测试: ** 访问 localhost:8761
image-20200611013357920 三、 改造 Provider 和 Consumer 称为 Eureka Client ① 引 eureka-client 相关依赖
② 完成 eureka client 相关配置
③ 启动 测试
Provider工程
pom
From: 元动力 1 2 3 4 5 < !-- eureka-client --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-netflix-eureka-client< /artifactId> < /dependency>
ProviderApp
application.yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 server: port: 8001 eureka: instance: hostname: localhost client: service-url: defaultZone: http://localhost:8761/eureka spring: application: name: eureka-provider
Consumer
pom
From: 元动力 1 2 3 4 5 < !-- eureka-client --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-netflix-eureka-client< /artifactId> < /dependency>
ConsumerApp
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.ydlclass.consumer;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@EnableDiscoveryClient @EnableEurekaClient @SpringBootApplication public class ConsumerApp { public static void main (String[] args) { SpringApplication.run(ConsumerApp.class,args); } }
application.yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 server: port: 9000 eureka: instance: hostname: localhost client: service-url: defaultZone: http://localhost:8761/eureka spring: application: name: eureka-consumer
四、 Consumer 服务 通过从 Eureka Server 中抓取 Provider 地址,完成远程调用 Consumer
OrderController
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package com.ydlclass.consumer.controller;import com.ydlclass.consumer.domain.Goods;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.discovery.DiscoveryClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import java.util.List;@RestController @RequestMapping("/order") public class OrderController { @Autowired RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; @GetMapping("/add/{id}") public Goods add (@PathVariable("id") Integer id) { List<ServiceInstance> instances = discoveryClient.getInstances("EUREKA-PROVIDER" ); if (instances==null ||instances.size()<=0 ){ return null ; } ServiceInstance serviceInstance = instances.get(0 ); String host = serviceInstance.getHost(); int port = serviceInstance.getPort(); System.out.println(host); System.out.println(port); String url="http://" +host+":" +port+"/goods/findById/" +id; Goods goods = restTemplate.getForObject(url, Goods.class); return goods; } }
五、 Euraka配置详解 Eureka包含四个部分的配置
instance:当前Eureka Instance实例信息配置 client:Eureka Client客户端特性配置 server:Eureka Server注册中心特性配置 dashboard:Eureka Server注册中心仪表盘配置 1、实例信息配置
From: 元动力 1 2 3 4 5 6 7 8 eureka: instance: hostname: localhost prefer-ip-address: ip-address: instance-id: lease-renewal-interval-in-seconds: 30 lease-expiration-duration-in-seconds: 90
Eureka Instance的配置信息全部保存在org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean配置类里,实际上它是com.netflix.appinfo.EurekaInstanceConfig的实现类,替代了netflix的com.netflix.appinfo.CloudInstanceConfig的默认实现。
Eureka Instance的配置信息全部以eureka.instance.xxx的格式配置。
配置列表
应用名,首先获取spring.application.name的值,如果取值为空,则取默认unknown。
应用组名
instanceEnabledOnit = false 实例注册到Eureka上是,是否立刻开启通讯。有时候应用在准备好服务之前需要一些预处理。
非安全的端口
安全端口
nonSecurePortEnabled = true 是否开启非安全端口通讯
securePortEnabled = false 是否开启安全端口通讯
leaseRenewalIntervalInSeconds = 30 实例续约间隔时间
leaseExpirationDurationInSeconds = 90 实例超时时间,表示最大leaseExpirationDurationInSeconds秒后没有续约,Server就认为他不可用了,随之就会将其剔除。
virtualHostName = unknown 虚拟主机名,首先获取spring.application.name的值,如果取值为空,则取默认unknown。
注册到eureka上的唯一实例ID,不能与相同appname的其他实例重复。
secureVirtualHostName = unknown 安全虚拟主机名,首先获取spring.application.name的值,如果取值为空,则取默认unknown。
metadataMap = new HashMap(); 实例元数据,可以供其他实例使用。比如spring-boot-admin在监控时,获取实例的上下文和端口。
dataCenterInfo = new MyDataCenterInfo(DataCenterInfo.Name.MyOwn); 实例部署的数据中心。如AWS、MyOwn。
实例的IP地址
statusPageUrlPath = "/actuator/info" 实例状态页相对url
实例状态页绝对URL
实例主页相对URL
实例主页绝对URL
healthCheckUrlUrlPath = "/actuator/health" 实例健康检查相对URL
实例健康检查绝对URL
secureHealthCheckUrl = null 实例安全的健康检查绝对URL
配置属性的命名空间(Spring Cloud中被忽略)
主机名,不配置的时候讲根据操作系统的主机名来获取
是否优先使用IP地址作为主机名的标识
2、客户端特性配置
From: 元动力 1 2 3 4 5 6 7 eureka: client: service-url: defaultZone: register-with-eureka: fetch-registry:
Eureka Client客户端特性配置是对作为Eureka客户端的特性配置,包括Eureka注册中心,本身也是一个Eureka Client。
Eureka Client特性配置全部在org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中,实际上它是com.netflix.discovery.EurekaClientConfig的实现类,替代了netxflix的默认实现。
Eureka Client客户端特性配置全部以eureka.client.xxx的格式配置。
配置列表
是否启用Eureka client。
registryFetchIntervalSeconds=30 定时从Eureka Server拉取服务注册信息的间隔时间
instanceInfoReplicationIntervalSeconds=30 定时将实例信息(如果变化了)复制到Eureka Server的间隔时间。(InstanceInfoReplicator线程)
initialInstanceInfoReplicationIntervalSeconds=40 首次将实例信息复制到Eureka Server的延迟时间。(InstanceInfoReplicator线程)
eurekaServiceUrlPollIntervalSeconds=300 拉取Eureka Server地址的间隔时间(Eureka Server有可能增减)
Eureka Server的代理端口
Eureka Server的代理主机名
Eureka Server的代理用户名
Eureka Server的代理密码
eurekaServerReadTimeoutSeconds=8 从Eureka Server读取信息的超时时间
eurekaServerConnectTimeoutSeconds=5 连接Eureka Server的超时时间
Eureka Client第一次启动时获取服务注册信息的调用的回溯实现。Eureka Client启动时首次会检查有没有BackupRegistry的实现类,如果有实现类,则优先从这个实现类里获取服务注册信息。
eurekaServerTotalConnections=200 Eureka client连接Eureka Server的链接总数
eurekaServerTotalConnectionsPerHost=50 Eureka client连接单台Eureka Server的链接总数
eurekaServerURLContext=null 当Eureka server的列表在DNS中时,Eureka Server的上下文路径。如http://xxxx/eureka。open in new window
当Eureka server的列表在DNS中时,Eureka Server的端口。
当Eureka server的列表在DNS中时,且要通过DNSName获取Eureka Server列表时,DNS名字。
实例所属区域。
eurekaConnectionIdleTimeoutSeconds = 30 Eureka Client和Eureka Server之间的Http连接的空闲超时时间。
heartbeatExecutorThreadPoolSize=2 心跳(续约)执行器线程池大小。
heartbeatExecutorExponentialBackOffBound=10 心跳执行器在续约过程中超时后的再次执行续约的最大延迟倍数。默认最大延迟时间=10 * eureka.instance.leaseRenewalIntervalInSeconds
cacheRefreshExecutorThreadPoolSize=2 cacheRefreshExecutord的线程池大小(获取注册信息)
cacheRefreshExecutorExponentialBackOffBound=10 cacheRefreshExecutord的再次执行的最大延迟倍数。默认最大延迟时间=10 *eureka.client.registryFetchIntervalSeconds
serviceUrl= new HashMap();serviceUrl.put(DEFAULT_ZONE, DEFAULT_URL); Eureka Server的分区地址。默认添加了一个defualtZone。也就是最常用的配置eureka.client.service-url.defaultZone=xxx
是否注册到Eureka Server。
preferSameZoneEureka=true 是否使用相同Zone下的Eureka server。
是否记录Eureka Server和Eureka Client之间注册信息的差异
是否开启增量同步注册信息。
fetchRemoteRegionsRegistry=null 获取注册服务的远程地区,以逗号隔开。
availabilityZones=new HashMap() 可用分区列表。用逗号隔开。
filterOnlyUpInstances = true 是否只拉取UP状态的实例。
是否拉取注册信息。
shouldUnregisterOnShutdown = true 是否在停止服务的时候向Eureka Server发起Cancel指令。
shouldEnforceRegistrationAtInit = false 是否在初始化过程中注册服务。
3、注册中心端配置
From: 元动力 1 2 3 4 5 6 7 eureka: server: enable-self-preservation: eviction-interval-timer-in-ms: 120 2 月#清理间隔(单位毫秒,默认是60*1000) instance: lease-renewal-interval-in-seconds: 30 lease-expiration-duration-in-seconds: 90
Eureka Server注册中心端的配置是对注册中心的特性配置。Eureka Server的配置全部在org.springframework.cloud.netflix.eureka.server.EurekaServerConfigBean里,实际上它是com.netflix.eureka.EurekaServerConfig的实现类,替代了netflix的默认实现。
Eureka Server的配置全部以eureka.server.xxx的格式进行配置。
配置列表
enableSelfPreservation=true 是否开启自我保护
renewalPercentThreshold = 0.85 自我保护续约百分比阀值因子。如果实际续约数小于续约数阀值,则开启自我保护
renewalThresholdUpdateIntervalMs = 15 * 60 * 1000 续约数阀值更新频率。
peerEurekaNodesUpdateIntervalMs = 10 * 60 * 1000 Eureka Server节点更新频率。
enableReplicatedRequestCompression = false 是否启用复制请求压缩。
waitTimeInMsWhenSyncEmpty=5 * 60 * 1000 当从其他节点同步实例信息为空时等待的时间。
peerNodeConnectTimeoutMs=200 节点间连接的超时时间。
peerNodeReadTimeoutMs=200 节点间读取信息的超时时间。
peerNodeTotalConnections=1000 节点间连接总数。
peerNodeTotalConnectionsPerHost = 500; 单个节点间连接总数。
peerNodeConnectionIdleTimeoutSeconds = 30; 节点间连接空闲超时时间。
retentionTimeInMSInDeltaQueue = 3 * MINUTES; 增量队列的缓存时间。
deltaRetentionTimerIntervalInMs = 30 * 1000; 清理增量队列中过期的频率。
evictionIntervalTimerInMs = 60 * 1000; 剔除任务频率。
responseCacheAutoExpirationInSeconds = 180; 注册列表缓存超时时间(当注册列表没有变化时)
responseCacheUpdateIntervalMs = 30 * 1000; 注册列表缓存更新频率。
useReadOnlyResponseCache = true; 是否开启注册列表的二级缓存。
是否为client提供增量信息。
maxThreadsForStatusReplication = 1; 状态同步的最大线程数。
maxElementsInStatusReplicationPool = 10000; 状态同步队列的最大容量。
syncWhenTimestampDiffers = true; 当时间差异时是否同步。
注册信息同步重试次数。
registrySyncRetryWaitMs = 30 * 1000; 注册信息同步重试期间的时间间隔。
maxElementsInPeerReplicationPool = 10000; 节点间同步事件的最大容量。
minThreadsForPeerReplication = 5; 节点间同步的最小线程数。
maxThreadsForPeerReplication = 20; 节点间同步的最大线程数。
maxTimeForReplication = 30000; 节点间同步的最大时间,单位为毫秒。
disableDeltaForRemoteRegions = false; 是否启用远程区域增量。
remoteRegionConnectTimeoutMs = 1000; 远程区域连接超时时间。
remoteRegionReadTimeoutMs = 1000; 远程区域读取超时时间。
remoteRegionTotalConnections = 1000; 远程区域最大连接数
remoteRegionTotalConnectionsPerHost = 500; 远程区域单机连接数
remoteRegionConnectionIdleTimeoutSeconds = 30; 远程区域连接空闲超时时间。
remoteRegionRegistryFetchInterval = 30; 远程区域注册信息拉取频率。
remoteRegionFetchThreadPoolSize = 20; 远程区域注册信息线程数。
4、仪表盘配置
From: 元动力 1 2 3 4 eureka: dashboard: enabled: true path: /
注册中心仪表盘的配置主要是控制注册中心的可视化展示。以eureka.dashboard.xxx的格式配置。
仪表盘访问路径
是否启用仪表盘
改造 provider
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 server: port: 8001 eureka: instance: hostname: localhost prefer-ip-address: true ip-address: 127.0 .0 .1 instance-id: ${eureka.instance.ip-address}:${spring.application.name}:${server.port} lease-renewal-interval-in-seconds: 3 lease-expiration-duration-in-seconds: 9 client: service-url: defaultZone: http://localhost:8761/eureka spring: application: name: eureka-provider
consumer
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 server: port: 9000 eureka: instance: hostname: localhost client: service-url: defaultZone: http://localhost:8761/eureka spring: application: name: eureka-consumer
server
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 server: port: 8761 eureka: instance: hostname: localhost client: service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka register-with-eureka: false fetch-registry: false server: enable-self-preservation: false eviction-interval-timer-in-ms: 3000
六、高可用 image-20220406114821846 准备两个Eureka Server
分别进行配置,相互注册
Eureka Client 分别注册到这两个 Eureka Server中
创建eureka-server1
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 server: port: 8761 eureka: instance: hostname: eureka-server1 client: service-url: defaultZone: http://eureka-server2:8762/eureka register-with-eureka: true fetch-registry: true spring: application: name: eureka-server-ha
创建eureka-server2
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 server: port: 8762 eureka: instance: hostname: eureka-server2 client: service-url: defaultZone: http://eureka-server1:8761/eureka register-with-eureka: true fetch-registry: true spring: application: name: eureka-server-ha
修改 :C:\Windows\System32\drivers\etc\hosts
127.0.0.1 eureka-server1 127.0.0.1 eureka-server2
image-20220406144138369 测试:
provider
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 server: port: 8001 eureka: instance: hostname: localhost prefer-ip-address: true ip-address: 127.0 .0 .1 instance-id: ${eureka.instance.ip-address}:${spring.application.name}:${server.port} lease-renewal-interval-in-seconds: 3 lease-expiration-duration-in-seconds: 9 client: service-url: defaultZone: http://eureka-server1:8761/eureka,http://eureka-server2:8762/eureka spring: application: name: eureka-provider
consumer
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 server: port: 9000 eureka: instance: hostname: localhost client: service-url: defaultZone: http://eureka-server1:8761/eureka,http://eureka-server2:8762/eureka spring: application: name: eureka-consumer
访问:http://localhost:9000/order/add/4open in new window
image-20220406144153992 高可用测试:停掉一个eureka,依然可以访问consumer。
eureka不更新了,所以淘汰了。
第六章 Zookeeper服务注册与发现 image-20220406194741473 有的老项目以前是dubbo,升级到微服务,使用zookeeper做注册中心。
zookeeper是一个分布式协调工具,可以实现注册中心功能。dubbo,大数据组件hadoop,hive,kafka。
实质 :注册中心换成zk
1下载:https://zookeeper.apache.org/open in new window
image-20220406152809933 zoo.cfg
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 # The number of milliseconds of each tick tickTime=2000 # The number of ticks that the initial # synchronization phase can take initLimit=10 # The number of ticks that can pass between # sending a request and getting an acknowledgement syncLimit=5 # the directory where the snapshot is stored. # do not use /tmp for storage, /tmp here is just # example sakes. dataDir=F:/apache-zookeeper-3.5.6-bin/data # the port at which the clients will connect clientPort=2181 # the maximum number of client connections. # increase this if you need to handle more clients #maxClientCnxns=60 # # Be sure to read the maintenance section of the # administrator guide before turning on autopurge. # # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance # # The number of snapshots to retain in dataDir #autopurge.snapRetainCount=3 # Purge task interval in hours # Set to "0" to disable auto purge feature #autopurge.purgeInterval=1
启动 bin目录下
image-20220406153622431 2zookeeper-provider
pom
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <artifactId>zookeeper-provider</artifactId> <dependencies> <!--springcloud 整合 zookeeper 组件--> <dependency> <groupId>org.springframework.cloud</groupId> <!--zk发现--> <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.9</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
yml
From: 元动力 1 2 3 4 5 6 7 8 9 server: port: 8004 spring: application: name: zookeeper-provider cloud: zookeeper: connect-string: 127.0.0.1:2181 # zk地址
主启动类
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.ydlclass.zk; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /** * @Created by IT李老师 * 公主号 “元动力课堂” * 个人微 itlils */ @SpringBootApplication @EnableDiscoveryClient //开启发现客户端 public class ProviderApp { public static void main(String[] args) { SpringApplication.run(ProviderApp.class,args); } }
业务逻辑代码直接复制粘贴过来
image-20220406172259585 3zookeeper-consumer
pom
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <artifactId>zookeeper-consumer</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <!--springcloud 整合 zookeeper 组件--> <dependency> <groupId>org.springframework.cloud</groupId> <!--zk发现--> <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.5.6</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
yml
From: 元动力 1 2 3 4 5 6 7 8 9 server: port: 8005 spring: application: name: zookeeper-consumer cloud: zookeeper: connect-string: 127.0.0.1:2181 # zk地址
启动类
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.ydlclass.zk; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /** * @Created by IT李老师 * 公主号 “元动力课堂” * 个人微 itlils */ @SpringBootApplication @EnableDiscoveryClient public class ConsumerApp { public static void main(String[] args) { SpringApplication.run(ConsumerApp.class,args); } }
业务逻辑代码直接复制粘贴过来
image-20220406185656845 controller只改一个
From: 元动力 1 List<ServiceInstance> instances = discoveryClient.getInstances("zookeeper-provider");
测试:http://localhost:8005/order/add/5open in new window
image-20220407144912417 第七章 Consul服务注册与发现 image-20220407161804433 一、 是什么: 二、 怎么用: 1、 准备 image-20220407161630689 image-20220407161746354 2、 搭建 consul-provider pom
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 server: port: 8006 spring: application: name: consul-provider cloud: consul: host: 127.0.0.1 port: 8500 discovery: service-name: ${spring.application.name}
启动类
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.ydlclass.consul; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /** * @Created by IT李老师 * 公主号 “元动力课堂” * 个人微 itlils */ @SpringBootApplication @EnableDiscoveryClient public class ProviderApp { public static void main(String[] args) { SpringApplication.run(ProviderApp.class,args); } }
业务逻辑复制
image-20220407163424691 启动
image-20220407162423209 3、搭建 consul-consumer pom
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 < dependencies> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-consul-discovery< /artifactId> < /dependency> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-web< /artifactId> < /dependency> < /dependencies>
yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 server: port: 8007 spring: application: name: consul-consumer cloud: consul: host: 127.0 .0 .1 port: 8500 discovery: service-name: ${spring.application.name}
启动类
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.ydlclass.consul;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication @EnableDiscoveryClient public class ConsumerApp { public static void main (String[] args) { SpringApplication.run(ConsumerApp.class,args); } }
业务逻辑复制
image-20220407164001822 controller只改一句话
From: 元动力 1 List<ServiceInstance> instances = discoveryClient.getInstances("consul-provider" );
启动
image-20220407164133404 最终测试调用成功即可:http://localhost:8007/order/add/9open in new window
image-20220407164211124 三、 三个注册中心的异同 组件 语言 cap 健康检查 暴露接口 cloud集成 eureka java ap 支持 http 已经集成 zookeeper java cp 支持 tcp 已经集成 consul go cp 支持 http 已经集成
cap
第八章 Ribbon负载均衡服务调用 一、是什么 Netflix公司推出的http和TCP的客户端负载均衡工具。
ribbon:
1、服务端负载均衡 负载均衡算法在服务端,服务端维护服务列表。
image-20220407173053676 2、客户端负载均衡 image-20220407173409352 二、如何使用 1.新版的eureka依赖以及集成了Ribbon依赖,所以可以不引用
From: 元动力 1 2 3 4 5 <!--Ribbon的依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>
image-20220408112040713 2.声明restTemplate时@LoadBalanced
3.restTemplate请求远程服务时,ip端口替换为服务名
From: 元动力 1 2 String url="http://EUREKA-PROVIDER/goods/findById/" +id;Goods goods = restTemplate.getForObject(url, Goods.class);
测试:
1.启动2个provider
controller
From: 元动力 1 goods.setTitle(goods.getTitle()+"|端口号:"+port);
idea设置 能启动两份 provider
image-20220408112658153 image-20220408112814966 2.多次访问consumer
image-20220408113212684 image-20220408113134662 多次刷新,发现:ribbon客户端,默认使用轮询算法,经行负载均衡调用。
三、ribbon 负载均衡策略 内置负载均衡规则类 规则描述 RoundRobinRule 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。 AvailabilityFilteringRule 对以下两种服务器进行忽略:(1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。注意:可以通过修改配置loadbalancer.<clientName>.connectionFailureCountThreshold来修改连接失败多少次之后被设置为短路状态。默认是3次。(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上线,可以由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。 WeightedResponseTimeRule 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 ZoneAvoidanceRule 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。 BestAvailableRule 忽略哪些短路的服务器,并选择并发数较低的服务器。 RandomRule 随机选择一个可用的服务器。 Retry 重试机制的选择逻辑
四、 设置ribbon 负载均衡策略 1、代码 consumer工程
1.MyRule 返回想要的规则即可
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.ydlclass.consumer.config;import com.netflix.loadbalancer.IRule;import com.netflix.loadbalancer.RandomRule;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configuration public class MyRule { @Bean public IRule rule () { return new RandomRule (); } }
2.启动类
From: 元动力 1 @RibbonClient(name ="EUREKA-PROVIDER",configuration = MyRule.class)
总结:
1.irule的具体实现类,看到他带的几个策略的写法。
2.仿照策略的写法,自己写策略。
3.调用不同的其他微服务时,可以采用不同的策略。
2、配置 consumer工程
application.yml
From: 元动力 1 2 3 EUREKA-PROVIDER: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
作用:方便运维修改,重启。随时切换策略。
第九章、OpenFeign服务接口调用 一、概述 二、快速入门 a.在消费端引入 open-feign 依赖:
From: 元动力 1 2 3 4 < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-openfeign< /artifactId> < /dependency>
b.编写Feign调用接口。复制粘贴被调方的conreoller方法,加上类路径。
GoodsFeignClient:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.ydlclass.consumer.feign;import com.ydlclass.consumer.domain.Goods;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;@FeignClient("EUREKA-PROVIDER") public interface GoodsFeign { @GetMapping("/goods/findById/{id}") public Goods findById (@PathVariable("id") Integer id) ; }
c.在启动类 添加 @EnableFeignClients 注解,开启Feign功能
d.测试调用
OrderController
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 package com.ydlclass.consumer.controller;import com.ydlclass.consumer.domain.Goods;import com.ydlclass.consumer.feign.GoodsFeign;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.discovery.DiscoveryClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import java.util.List;@RestController @RequestMapping("/order") public class OrderController { @Autowired RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; @Autowired GoodsFeign goodsFeign; @GetMapping("/add/{id}") public Goods add (@PathVariable("id") Integer id) { Goods goods = goodsFeign.findById(id); return goods; } }
三、其他设置 1、超时设置 • Feign 底层依赖于 Ribbon 实现负载均衡和远程调用
image-20220408171431530 • Ribbon默认1秒超时。
• 超时配置: yml中
From: 元动力 1 2 3 4 # 设置Ribbon的超时时间 ribbon: ConnectTimeout: 1000 # 连接超时时间 默认1s ReadTimeout: 3000 # 逻辑处理的超时时间 默认1s
测试:
1.连接超时,provider都停掉
image-20220408172036937 2.逻辑处理的超时时间
provider
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 @GetMapping("/findById/{id}") public Goods findById(@PathVariable("id") Integer id){ Goods goods = goodsService.findById(id); goods.setTitle(goods.getTitle()+"|端口号:"+port); //模拟业务逻辑比较繁忙 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } return goods; }
image-20220408172302166 2、日志记录 1.Feign 只能记录 debug 级别的日志信息。
From: 元动力 1 2 3 4 # 设置当前的日志级别 debug,feign只支持记录debug级别的日志 logging: level: com.ydlclass: debug
• 定义Feign日志级别Bean
FeignLogConfig
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.ydlclass.consumer.config;import feign.Logger;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configuration public class FeignLogConfig { @Bean public Logger.Level level () { return Logger.Level.FULL; } }
启用该Bean: GoodsFeignClient
From: 元动力 1 @FeignClient(value = "FEIGN-PROVIDER",configuration = FeignLogConfig.class)
设置为headers
image-20220408182713438 第十章 Hystrix断路器 (豪猪)-保险丝 一、概述 重点:能让服务的调用方,够快的知道被调方挂了!不至于说让用户在等待。
Hystix 是 Netflix 开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败(雪崩)。
雪崩:一个服务失败,导致整条链路的服务都失败的情形。
image-20220411101214886 image-20220411104119551 image-20220411101248131 image-20220411101310179 Hystix 主要功能
image-20220411101741096 隔离
线程池隔离
没有hystrix,a重试100次,才知道c挂了!
image-20220411102317061 使用了hystrix,更细分线程池,只需要重试40次,让a更快的知道c挂了
image-20220411102720425 信号量隔离
没有hystrix,a一个带着认证信息的线程,重试100次,才知道c挂了!
image-20220411103036778 使用了hystrix,更细分线程池,一个带着认证信息的线程,只需要重试40次,让a更快的知道c挂了
image-20220411103152275 降级 :
服务提供方降级(异常,超时)
image-20220411104951728 消费方降级
image-20220411112946547 熔断
限流
是有限流,但是,项目一般不用。nginx或者网关限流。
二、服务降级 服务提供方
a、在服务提供方,引入 hystrix 依赖
From: 元动力 1 2 3 4 5 < !-- hystrix --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-netflix-hystrix< /artifactId> < /dependency>
b、方法
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 public Goods findById_fallback (Integer id) { Goods goods=new Goods (); goods.setGoodId(-1 ); goods.setTitle("provider提供方降级!" ); goods.setPrice(-9.9 ); goods.setStock(-10 ); return goods; }
c、使用 @HystrixCommand 注解配置降级方法
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @GetMapping("/findById/{id}") @HystrixCommand(fallbackMethod = "findById_fallback",commandProperties = { //设置Hystrix的超时时间,默认1s @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000") }) public Goods findById (@PathVariable("id") Integer id) { Goods goods = goodsService.findById(id); goods.setTitle(goods.getTitle()+"|端口号:" +port); try { Thread.sleep(5000 ); } catch (InterruptedException e) { e.printStackTrace(); } return goods; }
d、在启动类上开启Hystrix功能:@EnableCircuitBreaker
测试:http://localhost:9000/order/add/10open in new window
1.出错,服务方降级了
image-20220411110206538 2.3000超时,服务方降级了
image-20220411111020806 服务消费方
a、feign 组件已经集成了 hystrix 组件。
b、
image-20220411113035040 c、定义feign 调用接口实现类,复写方法,即 降级方法
GoodsFeignClientFallback
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.ydlclass.consumer.feign;import com.ydlclass.consumer.domain.Goods;import org.springframework.stereotype.Component;@Component public class GoodsFeignCallback implements GoodsFeign { @Override public Goods findById (Integer id) { Goods goods=new Goods (); goods.setGoodId(-2 ); goods.setTitle("调用方降级了!" ); goods.setPrice(-5.5 ); goods.setStock(-5 ); return goods; } }
d、在 @FeignClient 注解中使用 fallback 属性设置降级处理类。
GoodsFeignClient
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.ydlclass.consumer.feign;import com.ydlclass.consumer.config.FeignLogConfig;import com.ydlclass.consumer.domain.Goods;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;@FeignClient(value = "EUREKA-PROVIDER",configuration = FeignLogConfig.class,fallback = GoodsFeignCallback.class) public interface GoodsFeign { @GetMapping("/goods/findById/{id}") public Goods findById (@PathVariable("id") Integer id) ; }
e、配置开启
From: 元动力 1 2 3 4 # 开启feign对hystrix的支持 feign: hystrix: enabled: true
测试:停掉provider
http://localhost:9000/order/add/10open in new window
image-20220411113635280 三、熔断 image-20220411114750082 测试:
provider
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 package com.ydlclass.proviver.controller;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;import com.ydlclass.proviver.domain.Goods;import com.ydlclass.proviver.service.GoodsService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/goods") public class GoodsController { @Autowired GoodsService goodsService; @Value("${server.port}") int port; @GetMapping("/findById/{id}") @HystrixCommand(fallbackMethod = "findById_fallback",commandProperties = { //设置Hystrix的超时时间,默认1s @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000") }) public Goods findById (@PathVariable("id") Integer id) { Goods goods = goodsService.findById(id); goods.setTitle(goods.getTitle()+"|端口号:" +port); if (id==1 ){ int a=1 /0 ; } return goods; } public Goods findById_fallback (Integer id) { Goods goods=new Goods (); goods.setGoodId(-1 ); goods.setTitle("provider提供方降级!" ); goods.setPrice(-9.9 ); goods.setStock(-10 ); return goods; } }
访问两个接口
http://localhost:9000/order/add/10open in new window image-20220411115310796 多次访问 http://localhost:9000/order/add/1open in new window image-20220411115332277 3.导致10也不能访问了
image-20220411115128870 4.再过一会儿,半开状态
http://localhost:9000/order/add/10open in new window
image-20220411115423173 Hyst rix 熔断机制,用于监控微服务调用情况,当失败的情况达到预定的阈值(5秒失败20次),会打开断路器,拒绝所有请求,直到服务恢复正常为止。
From: 元动力 1 2 3 circuitBreaker.sleepWindowInMilliseconds:监控时间 circuitBreaker.requestVolumeThreshold:失败次数 circuitBreaker.errorThresholdPercentage:失败率
提供者controller中
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = { //设置Hystrix的超时时间,默认1s @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000"), //监控时间 默认5000 毫秒 @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "5000"), //失败次数。默认20次 @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "20"), //失败率 默认50% @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "50") })
四、熔断监控**-运维 image-20200612072519498 Hystrix 提供了 Hystrix-dashboard 功能,用于实时监控微服务运行状态。
但是Hystrix-dashboard只能监控一个微服务。
Netflix 还提供了 Turbine ,进行聚合监控。
image-20200612072621556 Turbine聚合监控
1、搭建监控模块 a、 创建监控模块
创建hystrix-monitor模块,使用Turbine聚合监控多个Hystrix dashboard功能,
b、引入Turbine聚合监控起步依赖
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 < ?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < parent> < artifactId> spring-cloud-parent< /artifactId> < groupId> com.ydlclass< /groupId> < version> 1.0.0< /version> < /parent> < modelVersion> 4.0.0< /modelVersion> < artifactId> hystrix-monitor< /artifactId> < properties> < maven.compiler.source> 8< /maven.compiler.source> < maven.compiler.target> 8< /maven.compiler.target> < /properties> < dependencies> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-netflix-hystrix-dashboard< /artifactId> < /dependency> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-netflix-turbine< /artifactId> < /dependency> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-actuator< /artifactId> < /dependency> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-netflix-eureka-client< /artifactId> < /dependency> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-test< /artifactId> < scope> test< /scope> < /dependency> < /dependencies> < build> < plugins> < plugin> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-maven-plugin< /artifactId> < /plugin> < /plugins> < /build> < /project>
d、修改application.yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 spring: application: name: hystrix-monitor server: port: 8769 turbine: combine-host-port: true app-config: EUREKA-PROVIDER,EUREKA-CONSUMER cluster-name-expression: "'default'" aggregator: cluster-config: default eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ hystrix: dashboard: proxy-stream-allow-list: "*"
e、创建启动类
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.ydlclass.monitor;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;import org.springframework.cloud.netflix.turbine.EnableTurbine;@SpringBootApplication @EnableEurekaClient @EnableTurbine @EnableHystrixDashboard public class HystrixMonitorApp { public static void main (String[] args) { SpringApplication.run(HystrixMonitorApp.class,args); } }
2、修改被监控模块 需要分别修改 hystrix-provider 和 hystrix-consumer 模块:
a、导入依赖:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 < 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>
b、配置Bean
此处为了方便,将其配置在启动类中。
From: 元动力 1 2 3 4 5 6 7 8 9 @Bean public ServletRegistrationBean getServlet () { HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet (); ServletRegistrationBean registrationBean = new ServletRegistrationBean (streamServlet); registrationBean.setLoadOnStartup(1 ); registrationBean.addUrlMappings("/actuator/hystrix.stream" ); registrationBean.setName("HystrixMetricsStreamServlet" ); return registrationBean; }
c、启动类上添加注解@EnableHystrixDashboard
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @EnableDiscoveryClient @EnableEurekaClient @SpringBootApplication @EnableFeignClients @EnableHystrixDashboard public class ConsumerApp { public static void main (String[] args) { SpringApplication.run(ConsumerApp.class,args); } @Bean public ServletRegistrationBean getServlet () { HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet (); ServletRegistrationBean registrationBean = new ServletRegistrationBean (streamServlet); registrationBean.setLoadOnStartup(1 ); registrationBean.addUrlMappings("/actuator/hystrix.stream" ); registrationBean.setName("HystrixMetricsStreamServlet" ); return registrationBean; } }
3、启动测试 a、启动服务:
eureka-server
hystrix-provider
hystrix-consumer
hystrix-monitor
b、访问:
在浏览器访问http://localhost:8769/hystrix/open in new window 进入Hystrix Dashboard界面
1585421193757 界面中输入监控的Url地址 http://localhost:8769/turbine.stream,监控时间间隔2000毫秒和title,如下图open in new window
image-20220411154048113 实心圆:它有颜色和大小之分,分别代表实例的监控程度和流量大小。如上图所示,它的健康度从绿色、黄色、橙色、红色递减。通过该实心圆的展示,我们就可以在大量的实例中快速的发现故障实例和高压力实例。 曲线:用来记录 2 分钟内流量的相对变化,我们可以通过它来观察到流量的上升和下降趋势。 1-
第十一章、zuul路由网关 zuul核心人员走了两个,zuul2的研发过久,spring公司等不及,自己研发的Gateway网关。
https://github.com/Netflix/zuul/wikiopen in new window
第十二章 Gateway新一代网关 功能:路由+过滤
一、 概述 https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/open in new window
不使用
存在的问题:
From: 元动力 1 2 3 4 解决缺点:1客户端需要记录不同微服务地址,增加客户端的复杂性 2每个后台微服务都需要认证 3http 发请求,涉及到跨域 4后台新增微服务,不能动态知道地址
image-20220411172117753 使用了网关的话:
• 网关旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。
• 在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用N个微服务的接口完成一个用户请求。
• 网关就是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、缓存、负载均衡、流量管控、路由转发等
• 在目前的网关解决方案里,有Nginx+ Lua、Netflix Zuul/zuul2 、Spring Cloud Gateway等等
image-20220411172632761 二、 快速入门 (1)搭建网关模块 api-gateway-server
(2)引入依赖:starter-gateway
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 < ?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < parent> < artifactId> gateway-parent< /artifactId> < groupId> com.ydlclass< /groupId> < version> 1.0-SNAPSHOT< /version> < /parent> < modelVersion> 4.0.0< /modelVersion> < artifactId> api-gateway-server< /artifactId> < dependencies> < !--引入gateway 网关--> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-gateway< /artifactId> < /dependency> < !-- eureka-client --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-netflix-eureka-client< /artifactId> < /dependency> < /dependencies> < /project>
(3)编写启动类
ApiGatewayApp
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.ydlclass.gateway;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplication @EnableEurekaClient public class ApiGatewayApp { public static void main (String[] args) { SpringApplication.run(ApiGatewayApp.class,args); } }
(4)编写配置文件
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 server: port: 80 spring: application: name: api-gateway-server cloud: # 网关配置 gateway: # 路由配置:转发规则 routes: #集合。 # id: 唯一标识。默认是一个UUID # uri: 转发路径 # predicates: 条件,用于请求网关路径的匹配规则 # filters:配置局部过滤器的 - id: eureka-provider # 静态路由 # uri: http://localhost:8001/ # 动态路由 uri: lb://GATEWAY-PROVIDER predicates: - Path=/goods/** filters: - AddRequestParameter=username,zhangsan - id: eureka-consumer # uri: http://localhost:9000 uri: lb://GATEWAY-CONSUMER predicates: - Path=/order/** # 微服务名称配置 discovery: locator: enabled: true # 设置为true 请求路径前可以添加微服务名称 lower-case-service-id: true # 允许为小写 eureka: client: service-url: defaultZone: http://localhost:8761/eureka
(5)启动测试
http://localhost/goods/findById/2open in new window
image-20220411174704253 image-20220411174649892 三、 静态路由
From: 元动力 1 uri: http://localhost:8000/
四、动态路由 image-20220411180512597 1、引入eureka-client配置 pom
From: 元动力 1 2 3 4 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
yml
From: 元动力 1 2 3 4 eureka: client: service-url: defaultZone: http://localhost:8761/eureka
2、修改uri属性:uri: lb://服务名称
From: 元动力 1 uri: lb://eureka-provider
测试:
http://localhost/goods/findById/2open in new window
image-20220411180644761 五、微服务名称配置**
From: 元动力 1 2 3 4 5 6 7 8 9 spring: cloud: # 网关配置 gateway: # 微服务名称配置 discovery: locator: enabled: true # 设置为true 请求路径前可以添加微服务名称 lower-case-service-id: true # 允许为小写
测试:http://localhost/eureka-provider/goods/findById/2open in new window
image-20220411180853933 六、过滤器 (1)两个维度:
内置过滤器 自定义过滤器
局部过滤器 全局过滤器
(2)过滤器种类:
内置局部过滤器
内置全局过滤器
自定义局部过滤器
自定义全局过滤器
image-20200612075159655 内置过滤器 局部过滤器:
From: 元动力 1 2 3 4 5 6 7 - id: gateway-provider uri: lb://GATEWAY-PROVIDER predicates: - Path=/goods/** filters: - AddResponseHeader=foo, bar
image-20220411182635931 内置过滤器 全局过滤器: route同级
From: 元动力 1 2 default-filters: - AddResponseHeader=yld,itlils
image-20220411182831552 image-20220411182910608 拓展:
内置的过滤器工厂
这里简单将Spring Cloud Gateway内置的所有过滤器工厂整理成了一张表格。如下:
过滤器工厂 作用 参数 AddRequestHeader 为原始请求添加Header Header的名称及值 AddRequestParameter 为原始请求添加请求参数 参数名称及值 AddResponseHeader 为原始响应添加Header Header的名称及值 DedupeResponseHeader 剔除响应头中重复的值 需要去重的Header名称及去重策略 Hystrix 为路由引入Hystrix的断路器保护 HystrixCommand
的名称FallbackHeaders 为fallbackUri的请求头中添加具体的异常信息 Header的名称 PrefixPath 为原始请求路径添加前缀 前缀路径 PreserveHostHeader 为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host 无 RequestRateLimiter 用于对请求限流,限流算法为令牌桶 keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus RedirectTo 将原始请求重定向到指定的URL http状态码及重定向的url RemoveHopByHopHeadersFilter 为原始请求删除IETF组织规定的一系列Header 默认就会启用,可以通过配置指定仅删除哪些Header RemoveRequestHeader 为原始请求删除某个Header Header名称 RemoveResponseHeader 为原始响应删除某个Header Header名称 RewritePath 重写原始的请求路径 原始路径正则表达式以及重写后路径的正则表达式 RewriteResponseHeader 重写原始响应中的某个Header Header名称,值的正则表达式,重写后的值 SaveSession 在转发请求之前,强制执行WebSession::save
操作 无 secureHeaders 为原始响应添加一系列起安全作用的响应头 无,支持修改这些安全响应头的值 SetPath 修改原始的请求路径 修改后的路径 SetResponseHeader 修改原始响应中某个Header的值 Header名称,修改后的值 SetStatus 修改原始响应的状态码 HTTP 状态码,可以是数字,也可以是字符串 StripPrefix 用于截断原始请求的路径 使用数字表示要截断的路径的数量 Retry 针对不同的响应进行重试 retries、statuses、methods、series RequestSize 设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返回 413 Payload Too Large
请求包大小,单位为字节,默认值为5M ModifyRequestBody 在转发请求之前修改原始请求体内容 修改后的请求体内容 ModifyResponseBody 修改原始响应体的内容 修改后的响应体内容 Default 为所有路由添加过滤器 过滤器工厂名称及值
**Tips:**每个过滤器工厂都对应一个实现类,并且这些类的名称必须以GatewayFilterFactory
结尾,这是Spring Cloud Gateway的一个约定,例如AddRequestHeader
对应的实现类为AddRequestHeaderGatewayFilterFactory
。
1、AddRequestHeader GatewayFilter Factory
为原始请求添加Header,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 spring: cloud: gateway: routes: - id: add_request_header_route uri: https://example.org filters: - AddRequestHeader=X-Request-Foo, Bar
为原始请求添加名为 X-Request-Foo
,值为 Bar
的请求头
2、AddRequestParameter GatewayFilter Factory
为原始请求添加请求参数及值,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 spring: cloud: gateway: routes: - id: add_request_parameter_route uri: https://example.org filters: - AddRequestParameter=foo, bar
为原始请求添加名为foo,值为bar的参数,即:foo=bar
3、AddResponseHeader GatewayFilter Factory
为原始响应添加Header,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 spring: cloud: gateway: routes: - id: add_response_header_route uri: https://example.org filters: - AddResponseHeader=X-Response-Foo, Bar
为原始响应添加名为 X-Request-Foo
,值为 Bar
的响应头
4、DedupeResponseHeader GatewayFilter Factory
DedupeResponseHeader可以根据配置的Header名称及去重策略剔除响应头中重复的值,这是Spring Cloud Greenwich SR2提供的新特性,低于这个版本无法使用。
我们在Gateway以及微服务上都设置了CORS(解决跨域)Header的话,如果不做任何配置,那么请求 -> 网关 -> 微服务,获得的CORS Header的值,就将会是这样的:
From: 元动力 1 2 Access-Control-Allow-Credentials: true , true Access-Control-Allow-Origin: https://musk.mars, https://musk.mars
可以看到这两个Header的值都重复了,若想把这两个Header的值去重的话,就需要使用到DedupeResponseHeader,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 spring: cloud: gateway: routes: - id: dedupe_response_header_route uri: https://example.org filters: - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
去重策略:
RETAIN_FIRST:默认值,保留第一个值 RETAIN_LAST:保留最后一个值 RETAIN_UNIQUE:保留所有唯一值,以它们第一次出现的顺序保留 若想对该过滤器工厂有个比较全面的了解的话,建议阅读该过滤器工厂的源码,因为源码里有详细的注释及示例,比官方文档写得还好:org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory
5、Hystrix GatewayFilter Factory
为路由引入Hystrix的断路器保护,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 spring: cloud: gateway: routes: - id: hystrix_route uri: https://example.org filters: - Hystrix=myCommandName
Hystrix是Spring Cloud第一代容错组件,不过已经进入维护模式,未来Hystrix会被Spring Cloud移除掉,取而代之的是Alibaba Sentinel/Resilience4J。所以本文不做详细介绍了,感兴趣的话可以参考官方文档:
6、FallbackHeaders GatewayFilter Factory
同样是对Hystrix的支持,上一小节所介绍的过滤器工厂支持一个配置参数:fallbackUri
,该配置用于当发生异常时将请求转发到一个特定的uri上。而FallbackHeaders
这个过滤工厂可以在转发请求到该uri时添加一个Header,这个Header的值为具体的异常信息。配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 spring: cloud: gateway: routes: - id: ingredients uri: lb://ingredients predicates: - Path=//ingredients/** filters: - name: Hystrix args: name: fetchIngredients fallbackUri: forward:/fallback - id: ingredients-fallback uri: http://localhost:9994 predicates: - Path=/fallback filters: - name: FallbackHeaders args: executionExceptionTypeHeaderName: Test-Header
这里也不做详细介绍了,感兴趣可以参考官方文档:
7、PrefixPath GatewayFilter Factory
为原始的请求路径添加一个前缀路径,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 spring: cloud: gateway: routes: - id: prefixpath_route uri: https://example.org filters: - PrefixPath=/mypath
该配置使访问${GATEWAY_URL}/hello
会转发到https://example.org/mypath/hello
8、PreserveHostHeader GatewayFilter Factory
为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host Header。配置示例:
From: 元动力 1 2 3 4 5 6 7 8 spring: cloud: gateway: routes: - id: preserve_host_route uri: https://example.org filters: - PreserveHostHeader
如果不设置,那么名为 Host
的Header将由Http Client控制
9、RequestRateLimiter GatewayFilter Factory
用于对请求进行限流,限流算法为令牌桶。配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 spring: cloud: gateway: routes: - id: requestratelimiter_route uri: https://example.org filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20
由于另一篇文章中已经介绍过如何使用该过滤器工厂实现网关限流,所以这里就不再赘述了:
或者参考官方文档:
10、RedirectTo GatewayFilter Factory
将原始请求重定向到指定的Url,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 spring: cloud: gateway: routes: - id: redirect_route uri: https://example.org filters: - RedirectTo=302, https://acme.org
该配置使访问 ${GATEWAY_URL}/hello
会被重定向到 https://acme.org/hello
,并且携带一个 Location:http://acme.org
的Header,而返回客户端的HTTP状态码为302
注意事项:
HTTP状态码应为3xx,例如301 URL必须是合法的URL,该URL会作为Location
Header的值 11、RemoveHopByHopHeadersFilter GatewayFilter Factory
为原始请求删除IETFopen in new window 组织规定的一系列Header,默认删除的Header如下:
Connection Keep-Alive Proxy-Authenticate Proxy-Authorization TE Trailer Transfer-Encoding Upgrade 可以通过配置去指定仅删除哪些Header,配置示例:
From: 元动力 1 2 3 4 5 6 7 spring: cloud: gateway: filter: remove-hop-by-hop: headers: Connection,Keep-Alive
12、RemoveRequestHeader GatewayFilter Factory
为原始请求删除某个Header,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 spring: cloud: gateway: routes: - id: removerequestheader_route uri: https://example.org filters: - RemoveRequestHeader=X-Request-Foo
删除原始请求中名为 X-Request-Foo
的请求头
13、RemoveResponseHeader GatewayFilter Factory
为原始响应删除某个Header,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 spring: cloud: gateway: routes: - id: removeresponseheader_route uri: https://example.org filters: - RemoveResponseHeader=X-Response-Foo
删除原始响应中名为 X-Request-Foo
的响应头
14、RewritePath GatewayFilter Factory
通过正则表达式重写原始的请求路径,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 spring: cloud: gateway: routes: - id: rewritepath_route uri: https://example.org predicates: - Path=/foo/** filters: - RewritePath=/foo/(?<segment>.*), /$\{segment}
该配置使得访问 /foo/bar
时,会将路径重写为/bar
再进行转发,也就是会转发到 https://example.org/bar
。需要注意的是:由于YAML语法,需用$\
替换 $
15、RewriteResponseHeader GatewayFilter Factory
重写原始响应中的某个Header,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 spring: cloud: gateway: routes: - id: rewriteresponseheader_route uri: https://example.org filters: - RewriteResponseHeader=X-Response-Foo, password=[^&]+, password=***
该配置的意义在于:如果响应头中 X-Response-Foo
的值为/42?user=ford&password=omg!what&flag=true
,那么就会被按照配置的值重写成/42?user=ford&password=***&flag=true
,也就是把其中的password=omg!what
重写成了password=***
16、SaveSession GatewayFilter Factory
在转发请求之前,强制执行WebSession::save
操作,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 spring: cloud: gateway: routes: - id: save_session uri: https://example.org predicates: - Path=/foo/** filters: - SaveSession
主要用在那种像 Spring Session 延迟数据存储(数据不是立刻持久化)的,并希望在请求转发前确保session状态保存情况。如果你将Spring Secutiry于Spring Session集成使用,并想确保安全信息都传到下游机器,你就需要配置这个filter。
17、secureHeaders GatewayFilter Factory
secureHeaders过滤器工厂主要是参考了这篇博客open in new window 中的建议,为原始响应添加了一系列起安全作用的响应头。默认会添加如下Headers(包括值):
X-Xss-Protection:1; mode=block
Strict-Transport-Security:max-age=631138519
X-Frame-Options:DENY
X-Content-Type-Options:nosniff
Referrer-Policy:no-referrer
Content-Security-Policy:default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'
X-Download-Options:noopen
X-Permitted-Cross-Domain-Policies:none
如果你想修改这些Header的值,那么就需要使用这些Headers对应的后缀,如下:
xss-protection-header
strict-transport-security
frame-options
content-type-options
referrer-policy
content-security-policy
download-options
permitted-cross-domain-policies
配置示例:
From: 元动力 1 2 3 4 5 6 7 spring: cloud: gateway: filter: secure-headers: xss-protection-header: 2 ; mode=unblock
如果想禁用某些Header,可使用如下配置:
From: 元动力 1 2 3 4 5 6 7 8 spring: cloud: gateway: filter: secure-headers: disable: frame-options,download-options
18、SetPath GatewayFilter Factory
修改原始的请求路径,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 spring: cloud: gateway: routes: - id: setpath_route uri: https://example.org predicates: - Path=/foo/{segment} filters: - SetPath=/{segment}
该配置使访问 ${GATEWAY_URL}/foo/bar
时会转发到 https://example.org/bar
,也就是原本的/foo/bar
被修改为了/bar
19、SetResponseHeader GatewayFilter Factory
修改原始响应中某个Header的值,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 spring: cloud: gateway: routes: - id: setresponseheader_route uri: https://example.org filters: - SetResponseHeader=X-Response-Foo, Bar
将原始响应中 X-Response-Foo
的值修改为 Bar
20、SetStatus GatewayFilter Factory
修改原始响应的状态码,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 spring: cloud: gateway: routes: - id: setstatusstring_route uri: https://example.org filters: - SetStatus=BAD_REQUEST - id: setstatusint_route uri: https://example.org filters: - SetStatus=401
SetStatusd的值可以是数字,也可以是字符串。但一定要是Spring HttpStatus
枚举类中的值。上面这两种配置都可以返回401这个HTTP状态码。
21、StripPrefix GatewayFilter Factory
用于截断原始请求的路径,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 spring: cloud: gateway: routes: - id: nameRoot uri: http://nameservice predicates: - Path=/name/** filters: - StripPrefix=2
如上配置,如果请求的路径为 /name/bar/foo
,那么则会截断成/foo
后进行转发 ,也就是会截断2个路径。
22、Retry GatewayFilter Factory
针对不同的响应进行重试,例如可以针对HTTP状态码进行重试,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 spring: cloud: gateway: routes: - id: retry_test uri: http://localhost:8080/flakey predicates: - Host=*.retry.com filters: - name: Retry args: retries: 3 statuses: BAD_GATEWAY
可配置如下参数:
retries
:重试次数statuses
:需要重试的状态码,取值在 org.springframework.http.HttpStatus
中methods
:需要重试的请求方法,取值在 org.springframework.http.HttpMethod
中series
:HTTP状态码序列,取值在 org.springframework.http.HttpStatus.Series
中23、RequestSize GatewayFilter Factory
设置允许接收最大请求包的大小,配置示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 spring: cloud: gateway: routes: - id: request_size_route uri: http://localhost:8080/upload predicates: - Path=/upload filters: - name: RequestSize args: maxSize: 5000000
如果请求包大小超过设置的值,则会返回 413 Payload Too Large
以及一个errorMessage
24、Modify Request Body GatewayFilter Factory
在转发请求之前修改原始请求体内容,该过滤器工厂只能通过代码配置,不支持在配置文件中配置。代码示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Bean public RouteLocator routes (RouteLocatorBuilder builder) { return builder.routes() .route("rewrite_request_obj" , r -> r.host("*.rewriterequestobj.org" ) .filters(f -> f.prefixPath("/httpbin" ) .modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE, (exchange, s) -> return Mono.just(new Hello (s.toUpperCase())))).uri(uri)) .build(); }static class Hello { String message; public Hello () { } public Hello (String message) { this .message = message; } public String getMessage () { return message; } public void setMessage (String message) { this .message = message; } }
Tips:该过滤器工厂处于 BETA 状态,未来API可能会变化,生产环境请慎用
25、Modify Response Body GatewayFilter Factory
可用于修改原始响应体的内容,该过滤器工厂同样只能通过代码配置,不支持在配置文件中配置。代码示例:
From: 元动力 1 2 3 4 5 6 7 8 9 10 @Bean public RouteLocator routes (RouteLocatorBuilder builder) { return builder.routes() .route("rewrite_response_upper" , r -> r.host("*.rewriteresponseupper.org" ) .filters(f -> f.prefixPath("/httpbin" ) .modifyResponseBody(String.class, String.class, (exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri) .build(); }
Tips:该过滤器工厂处于 BETA 状态,未来API可能会变化,生产环境请慎用
26、Default Filters
Default Filters用于为所有路由添加过滤器工厂,也就是说通过Default Filter所配置的过滤器工厂会作用到所有的路由上。配置示例:
From: 元动力 1 2 3 4 5 6 spring: cloud: gateway: default-filters: - AddResponseHeader=X-Response-Default-Foo, Default-Bar - PrefixPath=/httpbin
官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.0.RELEASE/single/spring-cloud-gateway.html#_gatewayfilter_factoriesopen in new window
自定义过滤器 1、自定义 局部过滤器
麻烦,很少。
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 // // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package org.springframework.cloud.gateway.filter.factory; import java.util.Arrays; import java.util.List; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.support.GatewayToStringStyler; import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; public class StripPrefixGatewayFilterFactory extends AbstractGatewayFilterFactory<StripPrefixGatewayFilterFactory.Config> { public static final String PARTS_KEY = "parts"; public StripPrefixGatewayFilterFactory() { super(StripPrefixGatewayFilterFactory.Config.class); } public List<String> shortcutFieldOrder() { return Arrays.asList("parts"); } public GatewayFilter apply(StripPrefixGatewayFilterFactory.Config config) { return new GatewayFilter() { public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); ServerWebExchangeUtils.addOriginalRequestUrl(exchange, request.getURI()); String path = request.getURI().getRawPath(); String[] originalParts = StringUtils.tokenizeToStringArray(path, "/"); StringBuilder newPath = new StringBuilder("/"); for(int i = 0; i < originalParts.length; ++i) { if (i >= config.getParts()) { if (newPath.length() > 1) { newPath.append('/'); } newPath.append(originalParts[i]); } } if (newPath.length() > 1 && path.endsWith("/")) { newPath.append('/'); } ServerHttpRequest newRequest = request.mutate().path(newPath.toString()).build(); exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, newRequest.getURI()); return chain.filter(exchange.mutate().request(newRequest).build()); } public String toString() { return GatewayToStringStyler.filterToStringCreator(StripPrefixGatewayFilterFactory.this).append("parts", config.getParts()).toString(); } }; } public static class Config { private int parts; public Config() { } public int getParts() { return this.parts; } public void setParts(int parts) { this.parts = parts; } } }
2、自定义 全局过滤器
需求:1黑客ip,直接给你拒接掉。
2某些请求路径 如“goods/findById”,危险操作,记录日志。
自定义全局过滤器步骤:
From: 元动力 1 2 3 1. 定义类实现 GlobalFilter 和 Ordered接口 2. 复写方法 3. 完成逻辑处理
IpFilter
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package com.ydlclass.gateway.filter;import org.springframework.cloud.gateway.filter.GatewayFilterChain;import org.springframework.cloud.gateway.filter.GlobalFilter;import org.springframework.core.Ordered;import org.springframework.http.HttpStatus;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.stereotype.Component;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;import java.net.InetAddress;import java.net.InetSocketAddress;@Component public class IpFilter implements GlobalFilter , Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); InetSocketAddress remoteAddress = request.getRemoteAddress(); String hostName = remoteAddress.getHostName(); System.out.println(hostName); InetAddress address = remoteAddress.getAddress(); String hostAddress = address.getHostAddress(); System.out.println(hostAddress); String hostName1 = address.getHostName(); System.out.println(hostName1); if (hostAddress.equals("192.168.31.11" )) { response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } return chain.filter(exchange); } @Override public int getOrder () { return 0 ; } }
UrlFilter
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package com.ydlclass.gateway.filter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.net.URI; /** * @Created by IT李老师 * 公主号 “元动力课堂” * 个人微 itlils */ @Component public class UrlFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //某些请求路径 如“goods/findById”,危险操作,记录日志。 //拿到请求和响应,为所欲为 ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); URI uri = request.getURI(); String path = uri.getPath(); System.out.println(path); if(path.contains("goods/findById")){ //打日志 System.out.println("path很危险!"); } return chain.filter(exchange); } @Override public int getOrder() { return 1; } }
测试:
1、ipfilter
image-20220411191527069 把自己的ip设置为拒绝访问的话
image-20220411191641610 2、
image-20220411192132436 第十三章 分布式配置中心 13-16组件,超大型公司才会用到
国内BATJ,或者国外FLAG:facebook linkedin amazon google
处理大规模微服务的技术。
一、Config 概述 image-20220418081959807 Spring Cloud Config 解决了在分布式场景下多环境配置文件的管理和维护。
好处:
• 集中管理配置文件
• 不同环境不同配置,动态化的配置更新
• 配置信息改变时,不需要重启即可更新配置信息到服务
二、Config 快速入门 image-20220418082533367 config-server:
使用gitee创建远程仓库,上传配置文件
config-dev.yml
搭建 config-server 模块
ConfigServerApp
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.ydlclass.config;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.config.server.EnableConfigServer;@SpringBootApplication @EnableConfigServer public class ConfigServerApp { public static void main (String[] args) { SpringApplication.run(ConfigServerApp.class,args); } }
导入 config-server 依赖
pom
From: 元动力 1 2 3 4 5 < !-- config-server --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-config-server< /artifactId> < /dependency>
编写配置,设置 gitee 远程仓库地址
application.yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 server: port: 9527 spring: application: name: config-server cloud: config: server: git: uri: https://gitee.com/ydlclass_cch/ydlclass-configs.git label: master
测试访问远程配置文件
http://localhost:9527/master/provider-dev.ymlopen in new window
image-20220418083733698 config-client: provider
导入 starter-config 依赖
From: 元动力 1 2 3 4 5 < !--config client --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-config< /artifactId> < /dependency>
配置config server 地址,读取配置文件名称等信息
bootstrap.yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 spring: cloud: config: uri: http://localhost:9527 name: provider profile: dev label: master
获取配置值
GoodsController
From: 元动力 1 2 3 4 @Value("${ydlclass}") private String ydlclass; goods.setTitle(goods.getTitle()+"|端口号:" +port+"|ydlclass" +ydlclass);
启动测试
http://localhost:8000/goods/findById/9open in new window
image-20220418084608302 Config 客户端刷新
image-20220418085057098 在 config 客户端引入 actuator 依赖
From: 元动力 1 2 3 4 < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-actuator< /artifactId> < /dependency>
获取配置信息类上,添加 @RefreshScope 注解
GoodsController
添加配置
bootstrap.yml
From: 元动力 1 2 3 4 5 management: endpoints: web: exposure: include: '*'
使用curl工具发送post请求
curl -X POST http://localhost:8000/actuator/refreshopen in new window
image-20220418085907801 测试: 值已经变了
image-20220418085930400 三、Config 集成Eureka image-20220418090254336 config-client配置:
pom
From: 元动力 1 2 3 4 5 < !-- eureka-client --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-netflix-eureka-client< /artifactId> < /dependency>
ProviderApp
bootstrap.yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 spring: cloud: config: name: config profile: dev label: master discovery: enabled: true service-id: CONFIG-SERVER management: endpoints: web: exposure: include: '*'
config-server配置:
pom
From: 元动力 1 2 3 4 5 < !-- eureka-client --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-netflix-eureka-client< /artifactId> < /dependency>
ConfigServerApp
application.yml
From: 元动力 1 2 3 4 eureka: client: service-url: defaultZone: http://localhost:8761/eureka
测试:
image-20220418093808497 第十四章 SpringCloud Bus消息总线 远程的配置文件更新了,运维只需要发一个请求,所有用到这个配置文件的几百个应用更新了。
一、Bus 概述 image-20220418094548555 Spring Cloud Bus 是用轻量的消息中间件将分布式的节点连接起来,可以用于广播配置文件的更改或者服务的监控管理。关键的思想就是,消息总线可以为微服务做监控,也可以实现应用程序之间相通信。
Spring Cloud Bus 可选的消息中间件包括 RabbitMQ 和 Kafka 。
二、RabbitMQ 回顾 message queue
异步、解耦、削峰填谷
image-20200613074044506 image-20200613074052830 RabbitMQ 提供了 6 种工作模式:简单模式、work queues、Publish/Subscribe 发布与订阅模式、Routing
路由模式、Topics 主题模式、RPC 远程调用模式(远程调用,不太算 MQ;暂不作介绍)。
image-20200613074109383 三、Bus 快速入门-运维 image-20220418094548555 1、分别在 config-server 和 config-client中引入 bus依赖:bus-amqp
From: 元动力 1 2 3 4 5 6 7 8 9 < !-- bus --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-bus-amqp< /artifactId> < /dependency> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-actuator< /artifactId> < /dependency>
2、分别在 config-server 和 config-client中配置 RabbitMQ
server 的配置文件:
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 server: port: 9527 spring: application: name: config-server cloud: config: server: git: uri: https://gitee.com/ydlclass_cch/ydlclass-configs.git label: master rabbitmq: host: localhost port: 5672 username: guest password: guest virtual-host: / eureka: client: service-url: defaultZone: http://localhost:8761/eureka management: endpoints: web: exposure: include: 'bus-refresh'
client的配置文件 bootstrap.yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 spring: cloud: config: name: config profile: dev label: master discovery: enabled: true service-id: CONFIG-SERVER rabbitmq: host: localhost port: 5672 username: guest password: guest virtual-host: / management: endpoints: web: exposure: include: '*'
在config-server中设置暴露监控断点:bus-refresh
From: 元动力 1 2 3 4 5 6 management: endpoints: web: exposure: include: 'bus-refresh'
bus自动在mq中建立交换机
image-20220418095857082 只要微服务起起来,自动在mq中,建立队列,和交换机绑定
image-20220418100013437 启动测试
1.git配置改变
image-20220418104835631 2.往配置中心发请求
curl -X POST http://localhost:9527/actuator/bus-refreshopen in new window
image-20220418104622908 3.微服务自动重启
image-20220418104702500 4.访问微服务,发现配置已经改变
image-20220418104819862 第十五章 SpringCloud Stream消息驱动 一、Stream 概述 image-20220418111329857 1.Spring Cloud Stream 是一个构建消息驱动微服务应用的框架。
2.Stream 解决了开发人员无感知 的使用消息中间件的问题,因为Stream对消息中间件的进一步封装,可以做到代码层面对中间件的无感知,甚至于动态的切换中间件 ,使得微服务开发的高度解耦,服务可以关注更多自己的业务流程。
3.Spring Cloud Stream目前支持两种消息中间件RabbitMQ和Kafka
就像jdbc一样
image-20220418111643163 Stream 组件
image-20200613074759833 Spring Cloud Stream 构建的应用程序与消息中间件之间是通过绑定器 Binder 相关联的。绑定器对于应用程序而言起到了隔离作用, 它使得不同消息中间件的实现细节对应用程序来说是透明的。
binding 是我们通过配置把应用和spring cloud stream 的 binder 绑定在一起
output:发送消息 Channel,内置 Source接口
input:接收消息 Channel,内置 Sink接口
二、Stream 消息生产者 pom
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 < ?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < parent> < artifactId> stream-parent< /artifactId> < groupId> com.ydlclass< /groupId> < version> 1.0-SNAPSHOT< /version> < /parent> < modelVersion> 4.0.0< /modelVersion> < artifactId> stream-producer< /artifactId> < dependencies> < !--spring boot web--> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-web< /artifactId> < /dependency> < !-- stream --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-stream-rabbit< /artifactId> < /dependency> < /dependencies> < /project>
ProducerApp
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 package com.ydlclass.stream;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class ProducerApp { public static void main (String[] args) { SpringApplication.run(ProducerApp.class,args); } }
application.yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 server: port: 8000 spring: cloud: stream: binders: ydlclass_binder: type: rabbit environment: spring: rabbitmq: host: localhost port: 5672 username: guest password: guest virtual-host: / bindings: output: binder: ydlclass_binder destination: ydlclass_exchange
消息发送类 MessageProducer
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.ydlclass.stream.producer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.stream.annotation.EnableBinding;import org.springframework.cloud.stream.messaging.Source;import org.springframework.messaging.MessageChannel;import org.springframework.messaging.support.MessageBuilder;import org.springframework.stereotype.Component;import java.nio.charset.StandardCharsets;@Component @EnableBinding(Source.class) public class MessageProducer { @Autowired MessageChannel output; public void send (String msg) { output.send(MessageBuilder.withPayload(msg).build()); System.out.println("MessageProducer 确实发了消息了!" ); } }
调用的controller ProducerController
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.ydlclass.stream.controller;import com.ydlclass.stream.producer.MessageProducer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("test") public class ProducerController { @Autowired MessageProducer messageProducer; @GetMapping("/send") public String send () { String msg="使用stream来发消息了!" ; messageProducer.send(msg); return "success!" ; } }
image-20220418114016165 三、Stream 消息消费者 pom
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 < ?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < parent> < artifactId> stream-parent< /artifactId> < groupId> com.ydlclass< /groupId> < version> 1.0-SNAPSHOT< /version> < /parent> < modelVersion> 4.0.0< /modelVersion> < artifactId> stream-consumer< /artifactId> < dependencies> < !--spring boot web--> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-web< /artifactId> < /dependency> < !-- stream --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-stream-rabbit< /artifactId> < /dependency> < /dependencies> < /project>
ConsumerApp
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 package com.ydlclass.stream;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class ConsumerApp { public static void main (String[] args) { SpringApplication.run(ConsumerApp.class,args); } }
application.yml
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 server: port: 9000 spring: cloud: stream: binders: ydlclass_binder: type: rabbit environment: spring: rabbitmq: host: localhost port: 5672 username: guest password: guest virtual-host: / bindings: input: binder: ydlclass_binder destination: ydlclass_exchange
消息接收类 MessageListener
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.ydlclass.stream.consumer;import org.springframework.cloud.stream.annotation.EnableBinding;import org.springframework.cloud.stream.annotation.StreamListener;import org.springframework.cloud.stream.messaging.Sink;import org.springframework.messaging.Message;import org.springframework.stereotype.Component;@EnableBinding({Sink.class}) @Component public class MessageListener { @StreamListener(Sink.INPUT) public void receive (Message message) { System.out.println(message); System.out.println(message.getPayload()); } }
测试
image-20220418154602979 第十六章 SpringCloud Sleuth分布式请求链路追踪 一、概述 image-20220418155007573 Spring Cloud Sleuth 其实是一个工具,它在整个分布式系统中能跟踪一个用户请求的过程,捕获这些跟踪数据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。
Zipkin 是 Twitter 的一个开源项目,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。
二、快速入门 安装启动zipkin。 java –jar zipkin.jar
image-20220418185033323 访问zipkin web界面。 http://localhost:9411/open in new window
image-20200613080015686 在服务提供方和消费方分别引入 sleuth 和 zipkin 依赖
From: 元动力 1 2 3 4 5 6 7 8 9 10 < !-- sleuth-zipkin --> < !--< dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-sleuth< /artifactId> < /dependency> --> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-zipkin< /artifactId> < /dependency>
分别配置服务提供方和消费方。
provider
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 server: port: 8001 eureka: client: service-url: defaultZone: http://localhost:8761/eureka spring: application: name: feign-provider zipkin: base-url: http://localhost:9411/ sleuth: sampler: probability: 1
consumer
From: 元动力 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 server: port: 9000 eureka: instance: hostname: localhost client: service-url: defaultZone: http://localhost:8761/eureka spring: application: name: feign-consumer zipkin: base-url: http://localhost:9411/ sleuth: sampler: probability: 1 logging: level: com.ydlclass: debug
启动,测试
image-20220418160537372 调用关系图也能展现
image-20220418160602065