郑州汉狮做网站网络公司网站seo多少钱
郑州汉狮做网站网络公司,网站seo多少钱,网站文字变白色代码怎么做,一流的龙岗网站制作Java微服务篇2——SpringCloud
1、微服务架构
1.1、单体应用架构
的⽤户量、数据量规模都⽐较⼩#xff0c;项目所有的功能模块都放在一个工程中编码、 编译、打包并且部署在一个Tomcat容器中的架构模式就是单体应用架构#xff0c;这样的架构既简单实 ⽤、便于维护#…Java微服务篇2——SpringCloud
1、微服务架构
1.1、单体应用架构
的⽤户量、数据量规模都⽐较⼩项目所有的功能模块都放在一个工程中编码、 编译、打包并且部署在一个Tomcat容器中的架构模式就是单体应用架构这样的架构既简单实 ⽤、便于维护成本⼜低成为了那个时代的主流架构⽅式。 优点
高效开发项⽬前期开发节奏快团队成员少的时候能够快速迭代架构简单MVC架构只需要借助IDE开发、调试即可易于测试只需要通过单元测试或者浏览器完成易于部署打包成单⼀可执⾏的jar或者打成war包放到容器内启动
缺点
可靠性差 某个应用Bug例如死循环、内存溢出等 可能会导致整个应用的崩溃复杂性高 以一个百万行级别的单体应用为例整个项目包含的模块多、模块的边界模糊、 依赖 关系不清晰、 代码质量参差不齐、 混乱地堆砌在一起。使得整个项目非常复杂扩展能力受限 单体应用只能作为一个整体进行扩展无法根据业务模块的需要进行伸缩。例如 应用中有的模块是计算密集型的它需要强劲的CPU 有的模块则是IO密集型的需要更大的内 存。 由于这些模块部署在一起不得不在硬件的选择上做出妥协
业务量上涨之后单体应用架构进一步丰富变化比如应用集群部署、使用Nginx进行负载均衡、增加 缓存服务器、增加文件服务器、数据库集群并做读写分离等通过以上措施增强应对高并发的能力、应 对一定的复杂业务场景但依然属于单体应用架构 1.2、垂直应用架构
为了避免上⾯提到的那些问题开始做模块的垂直划分做垂直划分的原则是基于拉勾现有的业务 特性来做核心目标标第⼀个是为了业务之间互不影响第⼆个是在研发团队的壮⼤后为了提⾼效率 减少组件之间的依赖 优点
系统拆分实现了流量分担解决了并发问题可以针对不同模块进⾏优化⽅便⽔平扩展负载均衡容错率提⾼系统间相互独⽴互不影响新的业务迭代时更加⾼效
缺点
服务之间相互调⽤如果某个服务的端⼝或者ip地址发⽣改变调⽤的系统得⼿动改变搭建集群之后实现负载均衡⽐较复杂如内⽹负载在迁移机器时会影响调⽤⽅的路 由导致 线上故障服务之间调⽤⽅式不统⼀基于 httpclient 、 webservice 接⼝协议不统⼀服务监控不到位除了依靠端⼝、进程的监控调⽤的成功率、失败率、总耗时等等这些监 控指标 是没有的
1.3、SOA应用架构
在做了垂直划分以后模块随之增多维护的成本在也变⾼⼀些通⽤的业务和模块重复的越来越 多为了解决上⾯提到的接⼝协议不统⼀、服务⽆法监控、服务的负载均衡引⼊了阿⾥巴巴开源的 Dubbo ⼀款⾼性能、轻量级的开源Java RPC框架可以和Spring框架无缝集成。它提供了三⼤核⼼能 ⼒⾯向接⼝的远程⽅法调⽤智能容错和负载均衡以及服务⾃动注册和发现
SOA (Service-Oriented Architecture)即面向服务的架构。根据实际业务把系统拆分成合适 的、独立部署的模块模块之间相互独立通过Webservice/Dubbo等技术进行通信 优点
分布式松耦合扩展灵活可重用
缺点
服务抽取粒度较大服务调用方和提供方耦合度较高接口耦合度
1.4、微服务应用架构
微服务架构可以说是SOA架构的一种拓展这种架构模式下它拆分粒度更小、服务更独立。把应用 拆分成为一个个微小的服务不同的服务可以使用不同的开发语言和存储服务之间往往通过Restful等 轻量级通信。微服务架构关键在于微小、独立、轻量级通信
微服务是在 SOA 上做的升华粒度更加细致微服务架构强调的⼀个重点是业务需要彻底的组件化和服务化 微服务架构和SOA架构很明显的一个区别就是服务拆分粒度的不同但是对于拉勾的架构发展来 说我们所看到的SOA阶段其实服务拆分粒度相对来说已经比较细了超前哦所以上述拉勾SOA 到拉勾微服务从服务拆分上来说变化并不大只是引入了相对完整的新一代Spring Cloud微服务技 术。自然上述我们看到的都是拉勾架构演变的阶段结果每一个阶段其实都经历了很多变化服务拆分其实也是走过了从粗到细并非绝对的一步到位
2、微服务架构的核心概念
2.1、API网关
API请求调用统一接入API网关层由网关转发请求API网关更专注在安全、路由、流量等问题的处理上微服务团队专注于处理业务逻辑即可
统一接入路由安全防护统一鉴权负责网关访问身份认证验证与“访问认证中心”通信实际认证业务逻辑 交移“访问认证中心”处理黑白名单实现通过IP地址控制禁止访问网关功能控制访问协议适配实现通信协议校验、适配转换的功能流量管控限流长短链接支持容错能力负载均衡
2.2、服务注册与发现
服务提供者将所提供服务的信息服务器IP和端口、服务访问协议等注册/登记到注册中心
服务消费者能够从注册中心获取到较为实时的服务列表然后根究一定的策略选择一个服务访问 2.3、通信
服务间通信采用的方式例如httprpc
2.4、熔断
熔断即断路保护微服务架构中如果下游服务因访问压力过大而响应变慢或失败上游服务为了 保护系统整体可用性可以暂时切断对下游服务的调用。这种牺牲局部保全整体的措施就叫做熔断
2.5、链路追踪
微服务架构越发流行一个项目往往拆分成很多个服务那么一次请求就需要涉及到很多个服务。不同 的微服务可能是由不同的团队开发、可能使用不同的编程语言实现、整个项目也有可能部署在了很多服 务器上甚至百台、千台横跨多个不同的数据中心。所谓链路追踪就是对一次请求涉及的很多个服 务链路进行日志记录、性能监控
3、SpringCloud
3.1、SpringCloud是什么
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分 布式系统基础设施的开发如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等 都可以用 Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子它只是将 目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来通过Spring Boot风格进行再封 装屏蔽掉了复杂的配置和实现原理最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统 开发工具包
3.2、SpringCloud可以做什么
Distributed/versioned configuration 分布式/版本化配置Service registration and discovery 服务注册和发现Routing 智能路由 Service-to-service calls 服务调用Load balancing 负载均衡Circuit Breakers 熔断器Global locks 全局锁Leadership election and cluster state选举与集群状态管理Distributed messaging 分布式消息传递平台
3.3、Spring Cloud 架构 4、微服务过程存在的问题
4.1、商品案例
数据库准备
CREATE DATABASE springcloud;
USE springcloud;
CREATE TABLE commodity(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(50), #商品名称price DOUBLE, #商品价格DESC VARCHAR(100), #商品描述images VARCHAR(400), #商品图片stock INT, #商品库存TYPE VARCHAR(20), #商品类型deteled TINYINT(1) #逻辑删除
);4.2、目录结构 4.3、父项目
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionmodulesmoduleproduct/modulemoduleconsume/module/modulesparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.5.3/versionrelativePath/ !-- lookup parent from repository --/parentgroupIdcn.winkto/groupIdartifactIdspringcloud/artifactIdversion0.0.1-SNAPSHOT/versionnamespringcloud/namedescriptionDemo project for Spring Cloud/descriptionpropertiesjava.version1.8/java.version/properties!--指定打包方式为pom--packagingpom/packagingdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--微服务的监控与管理--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-logging/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependenciesbuildpluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactIdconfigurationsource8/sourcetarget8/targetencodingUTF-8/encoding/configuration/pluginplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdexecutionsexecutiongoalsgoalrepackage/goal/goals/execution/executions/plugin/plugins/build/project4.4、生产者product
pom文件
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdspringcloud/artifactIdgroupIdcn.winkto/groupIdversion0.0.1-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdproduct/artifactIddependenciesdependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.2.0/version/dependency/dependencies
/projectapplication.yaml
mybatis:type-aliases-package: cn.winkto.beanmapper-locations: classpath:mapper/*.xml
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: blingbling123.url: jdbc:mysql://localhost:3306/springcloud?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghaiapplication:name: eureka-product
server:port: 9000实体类
public class Commodity {private int id;private String name;private double price;private String desc;private String images;private int stock;private String type;private boolean deteled;
}mapper
Repository
public interface CommodityMapper {public Commodity selectCommodityById(int id);
}service
public interface CommodityService {public Commodity selectCommodityById(int id);
}Service
public class CommodityServiceImpl implements CommodityService {AutowiredCommodityMapper commodityMapper;Overridepublic Commodity selectCommodityById(int id) {return commodityMapper.selectCommodityById(id);}
}controller
RestController
public class CommodityController {AutowiredCommodityService commodityService;RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){System.out.println(生产者被调用);return commodityService.selectCommodityById(id);}
}
启动类
SpringBootApplication
MapperScan(cn.winkto.mapper)
public class ProductApplication {public static void main(String[] args) {SpringApplication.run(ProductApplication.class, args);}
}
4.5、消费者consume
pom文件
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdspringcloud/artifactIdgroupIdcn.winkto/groupIdversion0.0.1-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdconsume/artifactId/project
application.yaml
server:port: 9100
spring:application:name: consume
bean
public class Commodity {private int id;private String name;private double price;private String desc;private String images;private int stock;private String type;private boolean deteled;
}
配置类
Configuration
public class WinktoConfig {Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}
controller
RestController
public class CommodityController {AutowiredRestTemplate restTemplate;RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){System.out.println(消费者被调用);return restTemplate.getForObject(http://localhost:9000/selectCommodityById/1, Commodity.class);}
}
启动类
SpringBootApplication
public class ConsumeApplication {public static void main(String[] args) {SpringApplication.run(ConsumeApplication.class, args);}
}
4.6、测试
http://localhost:9000/selectCommodityById/1http://localhost:9100/selectCommodityById/1
4.7、问题分析
在服务消费者中我们把url地址硬编码到代码中不方便后期维护服务提供者只有一个服务即便服务提供者形成集群服务消费者还需要自己实现负载均衡在服务消费者中不清楚服务提供者的状态服务消费者调用服务提供者时候如果出现故障能否及时发现不向用户抛出异常页面RestTemplate这种请求调用方式是否还有优化空间能不能类似于Dubbo那样玩这么多的微服务统一认证如何实现配置文件每次都修改好多个很麻烦
解决方案
服务管理自动注册与发现、状态监管服务负载均衡熔断远程过程调用网关拦截、路由转发统一认证集中式配置管理配置信息实时自动更新
5、SpringCloud一代组件学习
版本号问题
springcloud使用的版本号是英文方式而不是传统的数字版本因为springcloud是微服务的解决方案他会有很多子项目每个子项目都维护这自己的版本号为了避免冲突就使用了伦敦地铁站的名字作为版本号。以首字母作为顺序a,b,c,d…排列
现有版本号Angel、Brixton、Camden、Daston、Edgware、Finchley、GreenWich、Hoxton
Base设计阶段。只有相应的设计没有具体的功能实现Alpha软件的初级版本。基本功能已经实现但存在较多的bugBate相对于Alpha已经有了很大的进步消除了严重的BUG但还存在一些潜在的BUG还需要不断测试RELEASE最终版本没有太大的问题
后缀名
BUILD-XXX开发版开发团队内部使用不是很稳定GA稳定版相比于开发版基本上可以使用了PREM1、M2里程碑版主要是修复了一些BUG的版本一个GA后通常有多个里程碑版RC候选发布版该阶段的软件类似于最终版的一个发行观察期基本只修复比较严重的BUGSR正式发布版
一定要注意版本对应
5.1、Eureka服务注册中心
Eureka 工作模式 Eureka 基础架构 Eureka 交互流程及原理
图中Application Service作为服务提供者向Eureka Server中注册服务Eureka Server接受到注 册事件会在集群和分区中进行数据同步Application Client作为消费端服务消费者可以从Eureka Server中获取到服务注册信息进行服务调用微服务启动后会周期性地向Eureka Server发送心跳默认周期为30秒默认Eureka Server 90S会将还没有续约的给剔除以续约自己的信息Eureka Server在一定时间内没有接收到某个微服务节点的心跳Eureka Server将会注销该微服务节点默认90秒每个Eureka Server同时也是Eureka Client多个Eureka Server之间通过复制的方式完成服务注册列表的同步Eureka Client会缓存Eureka Server中的信息。即使所有的Eureka Server节点都宕掉服务消费者依然可以使用缓存中的信息找到服务提供者
Eureka通过心跳检测、健康检查和客户端缓存等机制提高系统的灵活性、可伸缩性和高可用性
5.1.1、搭建eureka-server
目录结构
![]](https://img-blog.csdnimg.cn/f9f6bc4de18d47ee843e72d457885cda.png?x-oss-processimage/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d5ZmdoaA,size_16,color_FFFFFF,t_70) 父依赖中导入springcloud
!--Hoxton.SR12--
dependencyManagementdependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversionHoxton.SR12/versiontypepom/typescopeimport/scope/dependency/dependencies
/dependencyManagement
模块依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdspringcloud/artifactIdgroupIdcn.winkto/groupIdversion0.0.1-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdeureka/artifactIddependencies!--Eureka server依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-server/artifactId/dependency/dependencies
/project
application.yaml
server:port: 8099
spring:application:name: eureka-server
eureka:client:service-url:# 客户端与EurekaServer交互的地址,是一个mapdefaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/# 是否向eureka注册自己自己就是服务端所以不用注册register-with-eureka: false# 是否需要从Eureka Server获取服务信息己就是服务端所以不用拉取fetch-registry: falseinstance:hostname: localhost
启动器
SpringBootApplication
//开启euraka服务
EnableEurekaServer
public class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class, args);}
}
最终效果
http://localhost:8099/ 可以将自己注册进eureka里测试一下效果
server:port: 8099
spring:application:name: eureka-server
eureka:client:service-url:# 客户端与EurekaServer交互的地址,是一个mapdefaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/# 是否向eureka注册自己自己就是服务端所以不用注册register-with-eureka: true# 是否需要从Eureka Server获取服务信息己就是服务端所以不用拉取fetch-registry: trueinstance:hostname: localhost#使用ip注册否则会使用主机名注册prefer-ip-address: true#自定义实例显示格式instance-id: ${spring.cloud.client.ipaddress}:${spring.application.name}:${server.port}:project.version 5.1.2、将微服务注册进eureka
生产者依赖修改
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdspringcloud/artifactIdgroupIdcn.winkto/groupIdversion0.0.1-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdproduct/artifactIddependenciesdependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.2.0/version/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency/dependencies
/project
生产者application.yaml
mybatis:type-aliases-package: cn.winkto.beanmapper-locations: classpath:mapper/*.xml
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: blingbling123.url: jdbc:mysql://localhost:3306/springcloud?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghaiapplication:name: product
server:port: 9000
eureka:client:service-url:# 客户端与EurekaServer交互的地址,是一个mapdefaultZone: http://localhost:8099/eureka/instance:#使用ip注册否则会使用主机名注册prefer-ip-address: true#自定义实例显示格式instance-id: ${spring.cloud.client.ipaddress}:${spring.application.name}:${server.port}:project.version
消费者依赖修改
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdspringcloud/artifactIdgroupIdcn.winkto/groupIdversion0.0.1-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdconsume/artifactIddependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency/dependencies
/project
消费者application.yaml
server:port: 9100
spring:application:name: consume
eureka:client:service-url:# 客户端与EurekaServer交互的地址,是一个mapdefaultZone: http://localhost:8099/eureka/instance:#使用ip注册否则会使用主机名注册prefer-ip-address: true#自定义实例显示格式instance-id: ${spring.cloud.client.ipaddress}:${spring.application.name}:${server.port}:project.version
生产者和消费者启动器都添加/EnableDiscoveryClient注解
EnableEurekaClient仅用于EurekaEnableDiscoveryClient可以用为所有注册中心
最终效果
5.1.3、eureka-server集群
拷贝Eureka模块修改端口互相注册启动服务 最终效果
5.1.4、通过eureka-server解除硬编码
消费者修改启动类
SpringBootApplication
EnableDiscoveryClient
public class ConsumeApplication {public static void main(String[] args) {SpringApplication.run(ConsumeApplication.class, args);}
}
消费者消费过程修改
RestController
public class CommodityController {AutowiredRestTemplate restTemplate;AutowiredDiscoveryClient discoveryClient;RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){System.out.println(消费者被调用);// return restTemplate.getForObject(http://localhost:9000/selectCommodityById/id, Commodity.class);// 通过服务id服务名获取服务列表ListServiceInstance product discoveryClient.getInstances(product);// http://192.168.1.16:9000System.out.println(product.get(0).getUri());return restTemplate.getForObject(product.get(0).getUri()/selectCommodityById/id, Commodity.class);}
}
5.1.5、eureka元数据
标准元数据主机名、IP地址、端口号等信息这些信息都会被发布在服务注册表中用于服务之间的调用自定义元数据可以使用eureka.instance.metadata-map配置符合KEY/VALUE的存储格式。这 些元数据可以在远程客户端中访问
添加元数据
mybatis:type-aliases-package: cn.winkto.beanmapper-locations: classpath:mapper/*.xml
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: blingbling123.url: jdbc:mysql://localhost:3306/springcloud?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghaiapplication:name: pruduct
server:port: 9000
eureka:client:service-url:# 客户端与EurekaServer交互的地址,是一个mapdefaultZone: http://127.0.0.1:8099/eureka/,http://127.0.0.1:8199/eureka/instance:#使用ip注册否则会使用主机名注册prefer-ip-address: true#自定义实例显示格式instance-id: ${spring.cloud.client.ipaddress}:${spring.application.name}:${server.port}:project.versionmetadata-map:name: winktopassword: blingbling
消费者获取元数据
RestController
public class CommodityController {AutowiredRestTemplate restTemplate;AutowiredDiscoveryClient discoveryClient;RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){System.out.println(消费者被调用);// return restTemplate.getForObject(http://localhost:9000/selectCommodityById/id, Commodity.class);// 通过服务id服务名获取服务列表ListServiceInstance product discoveryClient.getInstances(pruduct);// http://192.168.1.16:9000System.out.println(product.get(0).getMetadata());return restTemplate.getForObject(product.get(0).getUri()/selectCommodityById/id, Commodity.class);}
}
最终效果
5.1.6、服务续约心跳检测
服务每隔30秒会向注册中心续约(心跳)一次也称为报活如果没有续约租约在90秒后到期 然后服务会被失效。每隔30秒的续约操作我们称之为心跳检测
Eureka Client 30S续约一次在Eureka Server更新自己的状态 (Client端进行配置)Eureka Server90S还没有进行续约将该微服务实例从服务注册表Map剔除 (Client端进行 配置)Eureka Client 30S拉取服务最新的注册表并缓存到本地 (Client端进行配置)
当需要修改时需要修改下配置即可
server:port: 8099
spring:application:name: eureka-server
eureka:client:service-url:# 客户端与EurekaServer交互的地址,是一个map(互相注册)defaultZone: http://127.0.0.1:8199/eureka/# 是否向eureka注册自己自己就是服务端所以不用注册register-with-eureka: false# 是否需要从Eureka Server获取服务信息己就是服务端所以不用拉取fetch-registry: falseinstance:#使用ip注册否则会使用主机名注册prefer-ip-address: true#自定义实例显示格式instance-id: ${spring.cloud.client.ipaddress}:${spring.application.name}:${server.port}:project.version# 续约间隔时间默认30秒lease-renewal-interval-in-seconds: 30# 租约到期服务时效时间默认值90秒,服务超过90秒没有发生心跳EurekaServer会将服务从列表移除lease-expiration-duration-in-seconds: 90
5.1.7、eureka服务下线
服务下线 当服务正常关闭操作时会发送服务下线的REST请求给EurekaServer服务中心接受到请求后将该服务置为下线状态 失效剔除 Eureka Server会定时间隔值是eureka.server.eviction-interval-timer-in-ms默认60s进行检 查如果发现实例在在一定时间此值由客户端设置的eureka.instance.lease-expiration-duration-inseconds定义默认值为90s内没有收到心跳则会注销此实例
5.1.8、eureka自我保护机制
自我保护模式正是一种针对网络异常波动的安全保护措施使用自我保护模式能使Eureka集群更加的 健壮、稳定的运行
如果在15分钟内超过85%的客户端节点都没有正常的心跳那么 Eureka就认为客户端与注册中心出现了网络故障Eureka Server自动进入自我保护机制 Eureka Server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务 Eureka Server仍然能够接受新服务的注册和查询请求但是不会被同步到其它节点上保证当前节点依然可用 当网络稳定时当前Eureka Server新的注册信息会被同步到其它节点中
Eureka Server可以很好的应对因网络故障导致部分节点失联的情况而不会像ZK那样如果有一半不可用的情况会导致整个集群不可用而变成瘫痪
5.2、Ribbon负载均衡
负载均衡一般分为服务器端负载均衡和客户端负载均衡 服务器端负载均衡比如Nginx、F5这些请求到达服务器之后由这些负载均衡器根据一定的 算法将请求路由到目标服务器处理 客户端负载均衡比如我们要说的Ribbon服务消费者客户端会有一个服务器地址列表调用 方在请求前通过一定的负载均衡算法选择一个服务器进行访问负载均衡算法的执行是在请求客户端进行
5.2.1、Ribbon快速入门
无需额外依赖
复制一份product为product-duplicatet端口号为9001启动eureka-server
修改生产者controller打印一下端口号
RestController
public class CommodityController {Value(${server.port})int port;AutowiredCommodityService commodityService;RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){System.out.println(port生产者被调用);return commodityService.selectCommodityById(id);}
}
修改消费者添加LoadBalanced表负载均衡
Configuration
public class WinktoConfig {// 旧版注册// Bean// LoadBalanced// public RestTemplate restTemplate(){// return new RestTemplate();// }// 新版注册BeanLoadBalancedpublic RestOperations restTemplate(RestTemplateBuilder builder) {return builder.build();}
}
RestController
public class CommodityController {AutowiredRestOperations restTemplate;AutowiredDiscoveryClient discoveryClient;RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){System.out.println(消费者被调用);// return restTemplate.getForObject(http://localhost:9000/selectCommodityById/id, Commodity.class);// 通过服务id服务名获取服务列表// ListServiceInstance product discoveryClient.getInstances(product);// http://192.168.1.16:9000// System.out.println(product.get(0).getMetadata());// 无需ip与端口号直接填写服务名称即可return restTemplate.getForObject(http://product/selectCommodityById/id, Commodity.class);}
}
启动生产者消费者
http://localhost:9100/selectCommodityById/1 5.2.2、Ribbon负载均衡策略
Ribbon内置了多种负载均衡策略负载均衡的顶级接口为 com.netflix.loadbalancer.IRule其结构图为 负载均衡策略描述RoundRobinRule轮询策略默认超过10次获取到的server都不可用会返回一个空的serverRandomRule随机策略如果随机到的server为null或者不可用的话会while不停的循环选取RetryRule重试策略 一定时限内循环重试。默认继承RoundRobinRule也支持自定 注入RetryRule会在每次选取之后对选举的server进行判断是 否为null是否alive并且在500ms内会不停的选取判断。而 RoundRobinRule失效的策略是超过10次RandomRule是没有失效时间的概念只要serverList没都挂BestAvailableRule最小 连接数策略 遍历serverList选取出可用的且连接数最小的一个server。该算法里面有一个LoadBalancerStats的成员变量会存储所有server的 运行状况和连接数。如果选取到的server为null那么会调用 RoundRobinRule重新选取AvailabilityFilteringRule可用过滤策略 扩展了轮询策略会先通过默认的轮询选取一个server再去判断该server是否超时可用当前连接数是否超限都成功再返回ZoneAvoidanceRule区域权衡策略默认策略 扩展了轮询策略继承了2个过滤器ZoneAvoidancePredicate和 AvailabilityPredicate除了过滤超时和链接数过多的server还会过滤掉不符合要求的zone区域里面的所有节点 在一个区域/机房 内的服务实例中轮询。先过滤再轮询
轮询策略的修改
# 服务名称
product:ribbon:# 负载均衡策略NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule 5.3、Hystrix
5.3.1、雪崩
服务雪崩效应是一种因“服务提供者的不可用”原因导致“服务调用者不可用”结果并将不可用逐渐放大的现象
扇入代表着该微服务被调用的次数扇入大说明该模块复用性好扇出该微服务调用其他微服务的个数扇出大说明业务逻辑复杂
服务雪崩原因
服务提供者不可用 硬件故障程序bug缓存击穿请求量过大 重试加大请求流量 用户重试代码逻辑重试 服务调用者不可用 同步资源耗尽
雪崩的解决方案
服务熔断在微服务架构中当扇出链路的某个微服务不可用或者响应时间太长时将熔断该节点微服务的调用进行服务的降级快速返回错误的响应信息当检测到该节点微服务调用响应正常后恢复调用链路服务降级就是当某个服务熔断之后服务器将不再被调用此刻客户端可以自 己准备一个本地的fallback回调返回一个缺省值这样做虽然服务水平下降但好歹可用比直接挂掉要强服务限流服务降级是当服务出问题或者影响到核心流程的性能时暂时将服务屏蔽掉待高峰或者问题解决后再打开
5.3.2、Hystrix核心内容
包裹请求使用HystrixCommand包裹对依赖的调用逻辑。 页面静态化微服务方法 HystrixCommand 添加Hystrix控制跳闸机制当某服务的错误率超过一定的阈值时Hystrix可以跳闸停止请求该服务一段时间资源隔离Hystrix为每个依赖都维护了一个小型的线程池(舱壁模式)。如果该线程池已满 发往该依赖的请求就被立即拒绝而不是排队等待从而加速失败判定监控Hystrix可以近乎实时地监控运行指标和配置的变化例如成功、失败、超时、以及被拒绝的请求等回退机制当请求失败、超时、被拒绝或当断路器打开时执行回退逻辑。回退逻辑由开发人员自行提供例如返回一个缺省值自我修复断路器打开一段时间后会自动进入“半开”状态探测服务是否可用如还是不可用 再次退回打开状态
5.3.3、Hystrix快速入门
生产者改造添加延迟
RestController
public class CommodityController {Value(${server.port})int port;AutowiredCommodityService commodityService;RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){System.out.println(port生产者被调用);try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}return commodityService.selectCommodityById(id);}
}
消费者改造对controller中熔断策略进行配置在启动类上开启熔断
RestController
public class CommodityController {AutowiredRestOperations restTemplate;AutowiredDiscoveryClient discoveryClient;// RequestMapping(/selectCommodityById/{id})// public Commodity selectCommodityById(PathVariable int id){// System.out.println(消费者被调用);// // return restTemplate.getForObject(http://localhost:9000/selectCommodityById/id, Commodity.class);//// // 通过服务id服务名获取服务列表// // ListServiceInstance product discoveryClient.getInstances(product);// // http://192.168.1.16:9000// // System.out.println(product.get(0).getMetadata());// // 无需ip与端口号直接填写服务名称即可// return restTemplate.getForObject(http://product/selectCommodityById/id, Commodity.class);// }HystrixCommand(// 线程池标识要保持唯一不唯一的话就共用了threadPoolKey selectCommodityById,// 线程池细节属性配置threadPoolProperties {// 线程数HystrixProperty(namecoreSize,value 1),// 等待队列长度HystrixProperty(namemaxQueueSize,value20)},commandProperties {// 每一个属性都是一个HystrixPropertyHystrixProperty(nameexecution.isolation.thread.timeoutInMilliseconds,value 5000)})RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){System.out.println(消费者被调用);return restTemplate.getForObject(http://product/selectCommodityById/id, Commodity.class);}
}
SpringBootApplication
EnableDiscoveryClient
//开启熔断服务
EnableCircuitBreaker
public class ConsumeApplication {public static void main(String[] args) {SpringApplication.run(ConsumeApplication.class, args);}
}
效果
5.3.4、服务降级
修改一下消费者controller添加失败回调
RestController
public class CommodityController {AutowiredRestOperations restTemplate;AutowiredDiscoveryClient discoveryClient;// RequestMapping(/selectCommodityById/{id})// public Commodity selectCommodityById(PathVariable int id){// System.out.println(消费者被调用);// // return restTemplate.getForObject(http://localhost:9000/selectCommodityById/id, Commodity.class);//// // 通过服务id服务名获取服务列表// // ListServiceInstance product discoveryClient.getInstances(product);// // http://192.168.1.16:9000// // System.out.println(product.get(0).getMetadata());// // 无需ip与端口号直接填写服务名称即可// return restTemplate.getForObject(http://product/selectCommodityById/id, Commodity.class);// }HystrixCommand(// 线程池标识要保持唯一不唯一的话就共用了threadPoolKey selectCommodityById,// 线程池细节属性配置threadPoolProperties {// 线程数HystrixProperty(namecoreSize,value 1),// 等待队列长度HystrixProperty(namemaxQueueSize,value20)},commandProperties {// 每一个属性都是一个HystrixPropertyHystrixProperty(nameexecution.isolation.thread.timeoutInMilliseconds,value 5000)},fallbackMethod selectCommodityByIdFallBack)RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){System.out.println(消费者被调用);return restTemplate.getForObject(http://product/selectCommodityById/id, Commodity.class);}public Commodity selectCommodityByIdFallBack(int id){return new Commodity();}
}
最终效果
5.3.5、Hystrix舱壁模式
其实就是线程池隔离策略
如果不进行任何设置所有熔断方法使用一个Hystrix线程池10个线程那么这样的话会导致问题 这个问题并不是扇出链路微服务不可用导致的而是我们的线程机制导致的如果方法A的请求把10个 线程都用了方法2请求处理的时候压根都没法去访问B因为没有线程可用并不是B服务不可用
threadPoolKey参数即表明开启舱壁模式
5.3.6、Hystrix熔断机制 当调用出现问题时开启一个时间窗10s在这个时间窗内统计调用次数是否达到最小请求数 如果没有达到则重置统计信息回到第1步如果达到了则统计失败的请求数占所有请求数的百分比是否达到阈值 如 果达到则跳闸不再请求对应服务如果没有达到则重置统计信息回到第1步 如果跳闸则会开启一个活动窗口默认5s每隔5sHystrix会让一个请求通过,到达那个问题服 务看是否调用成功如果成功重置断路器回到第1步如果失败回到第3步
修改HystrixCommand的commandProperties属性
RestController
public class CommodityController {AutowiredRestOperations restTemplate;AutowiredDiscoveryClient discoveryClient;// RequestMapping(/selectCommodityById/{id})// public Commodity selectCommodityById(PathVariable int id){// System.out.println(消费者被调用);// // return restTemplate.getForObject(http://localhost:9000/selectCommodityById/id, Commodity.class);//// // 通过服务id服务名获取服务列表// // ListServiceInstance product discoveryClient.getInstances(product);// // http://192.168.1.16:9000// // System.out.println(product.get(0).getMetadata());// // 无需ip与端口号直接填写服务名称即可// return restTemplate.getForObject(http://product/selectCommodityById/id, Commodity.class);// }HystrixCommand(// 线程池标识要保持唯一不唯一的话就共用了threadPoolKey selectCommodityById,// 线程池细节属性配置threadPoolProperties {// 线程数HystrixProperty(namecoreSize,value 1),// 等待队列长度HystrixProperty(namemaxQueueSize,value20)},commandProperties {// 每一个属性都是一个HystrixPropertyHystrixProperty(nameexecution.isolation.thread.timeoutInMilliseconds,value 5000),// 统计窗口时间的设置HystrixProperty(name metrics.rollingStats.timeInMilliseconds,value 8000),// 统计窗口内的最小请求数HystrixProperty(name circuitBreaker.requestVolumeThreshold,value 2),// 统计窗口内错误请求阈值的设置 50%HystrixProperty(name circuitBreaker.errorThresholdPercentage,value 50),// 自我修复的活动窗口时间HystrixProperty(name circuitBreaker.sleepWindowInMilliseconds,value 3000)},fallbackMethod selectCommodityByIdFallBack)RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){System.out.println(消费者被调用);return restTemplate.getForObject(http://product/selectCommodityById/id, Commodity.class);}public Commodity selectCommodityByIdFallBack(int id){return new Commodity();}
}
application.yaml开放健康检查接口
# springboot中暴露健康检查等断点接口
management:endpoints:web:exposure:include: *# 暴露健康接口的细节endpoint:health:show-details: always HystrixCommand的commandProperties属性也可以使用yaml方式书写
# 配置熔断策略
hystrix:command:default:circuitBreaker:# 强制打开熔断器如果该属性设置为true强制断路器进入打开状态将会拒绝所有的请求。默认false关闭的forceOpen: false# 触发熔断错误比例阈值默认值50%errorThresholdPercentage: 50# 熔断后休眠时长默认值5秒sleepWindowInMilliseconds: 3000# 熔断触发最小请求次数默认值是20requestVolumeThreshold: 2execution:isolation:thread:# 熔断超时设置默认为1秒timeoutInMilliseconds: 2000
5.3.7、Hystrix扩展
当我们来调整maxQueueSize属性也需要调整queueSizeRejectionThreshold队列最大阈值超出的请求将会被拒绝两个属性必须同时配置
5.4、 Feign
Feign是Netflix开发的一个轻量级RESTful的HTTP服务客户端用它来发起请求远程调用的 是以Java接口注解的方式调用Http请求
SpringCloud对Feign进行了增强使Feign支持了SpringMVC注解OpenFeign
5.4.1、Feign快速入门
导入依赖
dependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-hystrix/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependency
/dependencies
启动类修改启用feign功能
SpringBootApplication
EnableDiscoveryClient
//开启熔断服务
// EnableCircuitBreaker
//开启Feign远程调用自带熔断
EnableFeignClients
public class ConsumeApplication {public static void main(String[] args) {SpringApplication.run(ConsumeApplication.class, args);}
}
FeignClient接口尽量与controller保持一致
FeignClient(name product)
public interface CommondityFeign {RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id);
}
修改controller
RestController
public class CommodityController {// Autowired// RestOperations restTemplate;// Autowired// DiscoveryClient discoveryClient;Autowiredprivate CommondityFeign commondityFeign;// RequestMapping(/selectCommodityById/{id})// public Commodity selectCommodityById(PathVariable int id){// System.out.println(消费者被调用);// // return restTemplate.getForObject(http://localhost:9000/selectCommodityById/id, Commodity.class);//// // 通过服务id服务名获取服务列表// // ListServiceInstance product discoveryClient.getInstances(product);// // http://192.168.1.16:9000// // System.out.println(product.get(0).getMetadata());// // 无需ip与端口号直接填写服务名称即可// return restTemplate.getForObject(http://product/selectCommodityById/id, Commodity.class);// }// HystrixCommand(// // 线程池标识要保持唯一不唯一的话就共用了// threadPoolKey selectCommodityById,// // 线程池细节属性配置// threadPoolProperties {// // 线程数// HystrixProperty(namecoreSize,value 1),// // 等待队列长度// HystrixProperty(namemaxQueueSize,value20)// },// commandProperties {// // 每一个属性都是一个HystrixProperty// HystrixProperty(nameexecution.isolation.thread.timeoutInMilliseconds,value 5000),//// // 统计窗口时间的设置// HystrixProperty(name metrics.rollingStats.timeInMilliseconds,value 8000),// // 统计窗口内的最小请求数// HystrixProperty(name circuitBreaker.requestVolumeThreshold,value 2),// // 统计窗口内错误请求阈值的设置 50%// HystrixProperty(name circuitBreaker.errorThresholdPercentage,value 50),// // 自我修复的活动窗口时间// HystrixProperty(name circuitBreaker.sleepWindowInMilliseconds,value 3000)// },// fallbackMethod selectCommodityByIdFallBack// )// RequestMapping(/selectCommodityById/{id})// public Commodity selectCommodityById(PathVariable int id){// System.out.println(消费者被调用);// return restTemplate.getForObject(http://product/selectCommodityById/id, Commodity.class);// }// public Commodity selectCommodityByIdFallBack(int id){// return new Commodity();// }HystrixCommand(// 线程池标识要保持唯一不唯一的话就共用了threadPoolKey selectCommodityById,// 线程池细节属性配置threadPoolProperties {// 线程数HystrixProperty(namecoreSize,value 1),// 等待队列长度HystrixProperty(namemaxQueueSize,value20)},commandProperties {// 每一个属性都是一个HystrixPropertyHystrixProperty(nameexecution.isolation.thread.timeoutInMilliseconds,value 5000),// 统计窗口时间的设置HystrixProperty(name metrics.rollingStats.timeInMilliseconds,value 8000),// 统计窗口内的最小请求数HystrixProperty(name circuitBreaker.requestVolumeThreshold,value 2),// 统计窗口内错误请求阈值的设置 50%HystrixProperty(name circuitBreaker.errorThresholdPercentage,value 50),// 自我修复的活动窗口时间HystrixProperty(name circuitBreaker.sleepWindowInMilliseconds,value 3000)},fallbackMethod selectCommodityByIdFallBack)RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){return commondityFeign.selectCommodityById(id);}public Commodity selectCommodityByIdFallBack(int id){return new Commodity();}
}
application.yaml添加ribbon.eureka.enabledtrue要不然集群的时候会爆服务找不到
ribbon:eureka:enabled: true
5.4.2、Feign对负载均衡的支持
Feign 本身已经集成了Ribbon依赖和自动配置因此我们不需要额外引入依赖可以通过 ribbon.xx 来进 行全局配置,也可以通过服务名.ribbon.xx 来对指定服务进行细节配置配置
Feign默认的请求处理超时时长1s有时候我们的业务确实执行的需要一定时间那么这个时候我们就 需要调整请求处理超时时长Feign自己有超时设置如果配置Ribbon的超时则会以Ribbon的为准
product:ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule#对所有操作都进行重试OkToRetryOnAllOperations: true#对当前选中实例重试次数不包括第一次调用MaxAutoRetries: 0#切换实例的重试次数MaxAutoRetriesNextServer: 0
5.4.3、Feign对熔断器的支持
默认Feign关闭熔断器
当有两个超时时间设置Feign/hystrix熔断的时候是根据这两个时间的最小值来进行的即处理时长超过最短的那个超时时间了就熔断进入回退降级逻辑
feign:hystrix:enabled: true
此时注意之前的服务降级已经失效需要重新配置
新建服务降级类实现CommondityFeign书写默认方法
Component(commindityFallback)
public class CommindityFallback implements CommondityFeign {Overridepublic Commodity selectCommodityById(int id) {return new Commodity();}
}
在CommondityFeign设置回调class
FeignClient(name product,fallback CommindityFallback.class)
public interface CommondityFeign {RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id);
} 5.4.4、Feign对请求压缩和响应压缩的支持
Feign 支持对请求和响应进行GZIP压缩以减少通信过程中的性能损耗。通过下面的参数 即可开启请求与响应的压缩功能
feign:hystrix:enabled: truecompression:request:enabled: true #默认不开启mime-types: text/html,application/xml,application/json # 设置压缩的数据类型此处也是默认值min-request-size: 2048 # 设置触发压缩的大小下限此处也是默认值response:enabled: true #默认不开启
5.5、GateWay
Spring Cloud GateWay不仅提供统一的路由方式反向代理并且基于 Filter(定义过滤器对请求过滤完成一些功能) 链的方式提供了网关基本的功能例如鉴权、流量控制、熔断、路径重写、日志监控等
5.5.1、GateWay工作流程
客户端向Spring Cloud GateWay发出请求然后在GateWay Handler Mapping中找到与请求相匹配 的路由将其发送到GateWay Web HandlerHandler再通过指定的过滤器链来将请求发送到我们实际 的服务执行业务逻辑然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前 pre或者之后post执行业务逻辑。 Filter在“pre”类型过滤器中可以做参数校验、权限校验、流量监控、日志输出、协议转换等在“post” 类型的过滤器中可以做响应内容、响应头的修改、日志的输出、流量监控等。
5.5.2、GateWay快速入门
导入依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdspringcloud/artifactIdgroupIdcn.winkto/groupIdversion0.0.1-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdgateway/artifactIddependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-commons/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!--GateWay 网关--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependency!--引入webflux--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-webflux/artifactId/dependency/dependencies
/project
application.yaml
server:port: 9300
spring:application:name: gatewaycloud:gateway:routes:- id: commondity# 匹配的路径uri: http://127.0.0.1:9100# 匹配规则predicates:- Path/commondity/**# 去除uri第一个参数如/commondity/selectCommodityById/1 --- /selectCommodityById/1filters:- StripPrefix1main:web-application-type: reactive
eureka:client:service-url:# 客户端与EurekaServer交互的地址,是一个mapdefaultZone: http://127.0.0.1:8099/eureka/,http://127.0.0.1:8199/eureka/instance:#使用ip注册否则会使用主机名注册prefer-ip-address: true#自定义实例显示格式instance-id: ${spring.cloud.client.ipaddress}:${spring.application.name}:${server.port}:project.version
启动类
SpringBootApplication
public class GateWayApplication {public static void main(String[] args) {SpringApplication.run(GateWayApplication.class, args);}
}
5.5.3、路由规则详解 时间前
spring:cloud:gateway:routes:- id: commondity# 匹配的路径uri: http://127.0.0.1:9100# 匹配规则predicates:- Path/commondity/**filters:- After2017-01-20T17:42:47.789-07:00[America/Denver]
时间后
spring:cloud:gateway:routes:- id: commondity# 匹配的路径uri: http://127.0.0.1:9100# 匹配规则predicates:- Path/commondity/**filters:- Before2017-01-20T17:42:47.789-07:00[America/Denver]
时间间
spring:cloud:gateway:routes:- id: commondity# 匹配的路径uri: http://127.0.0.1:9100# 匹配规则predicates:- Path/commondity/**filters:- Between2017-01-20T17:42:47.789-07:00[America/Denver]
cookie
spring:cloud:gateway:routes:- id: commondity# 匹配的路径uri: http://127.0.0.1:9100# 匹配规则predicates:- Path/commondity/**filters:- Cookiechocolate, ch.p
header
spring:cloud:gateway:routes:- id: commondity# 匹配的路径uri: http://127.0.0.1:9100# 匹配规则predicates:- Path/commondity/**filters:- HeaderX-Request-Id, \d
host
spring:cloud:gateway:routes:- id: commondity# 匹配的路径uri: http://127.0.0.1:9100# 匹配规则predicates:- Path/commondity/**filters:- Host**.somehost.org,**.anotherhost.org
method
spring:cloud:gateway:routes:- id: commondity# 匹配的路径uri: http://127.0.0.1:9100# 匹配规则predicates:- Path/commondity/**filters:- MethodGET,POST
请求路径正则匹配
上面的案例就是
请求参数
spring:cloud:gateway:routes:- id: commondity# 匹配的路径uri: http://127.0.0.1:9100# 匹配规则predicates:- Path/commondity/**filters:- Querygreen
请求参数且值符合正则表达式
spring:cloud:gateway:routes:- id: commondity# 匹配的路径uri: http://127.0.0.1:9100# 匹配规则predicates:- Path/commondity/**filters:- Queryred, gree.
远程地址匹配
spring:cloud:gateway:routes:- id: commondity# 匹配的路径uri: http://127.0.0.1:9100# 匹配规则predicates:- Path/commondity/**filters:- RemoteAddr192.168.1.1/24
5.5.4、动态路由
spring:cloud:gateway:routes:- id: commondity# 匹配的路径动态路由lb://服务名称uri: lb://product# 匹配规则predicates:- Path/commondity/**filters:- StripPrefix1
5.5.5、过滤器
过滤器生命周期来分类
pre器在请求被路由之前调用可利用这种过滤器实现身份验证、在集群中选 择 请求的微服务、记录调试信息等post在路由到微服务以后执行可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等
过滤器范围来分类
GateWayFilter应用到单个路由路由上GlobalFilter应用到所有的路由上常用
书写WinktoFilter实现GlobalFilter完成过滤器功能OrderedFilter过滤器排序
Component
public class WinktoFilter implements GlobalFilter, OrderedFilter {private static ListString blackList new ArrayList();static {blackList.add(127.0.0.1);blackList.add(0:0:0:0:0:0:0:1);}Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request exchange.getRequest();ServerHttpResponse response exchange.getResponse();String ip Objects.requireNonNull(request.getRemoteAddress()).getHostString();for (int i 0; i blackList.size(); i) {if (ip.equals(blackList.get(i))){return response.writeWith(Mono.just(response.bufferFactory().wrap(Black household.getBytes())));}}// 放行return chain.filter(exchange);}Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {}// 返回值表示当前过滤器的顺序(优先级)数值越小优先级越高Overridepublic int getOrder() {return 0;}
} 5.6、Config 分布式配置中心
分布式集群环境中可能有很多个微服务我们不可能一个一个去修改配置 然后重启生效在一定场景下我们还需要在运行期间动态调整配置信息比如根据各个微服务的负载 情况动态调整数据源连接池大小我们希望配置内容发生变化的时候微服务可以自动更新。
Server 端提供配置文件的存储、以接口的形式将配置文件的内容提供出去通过使用 EnableConfigServer注解在 Spring boot 应用中非常简单的嵌入Client 端通过接口获取配置数据并初始化自己的应用
5.6.1、github上不去解决方案
进入https://github.com.ipaddress.com/获取ip
进入https://fastly.net.ipaddress.com/github.global.ssl.fastly.net获取ip
打开C:\Windows\System32\drivers\etc新建文件github
140.82.114.4 github.com
199.232.5.194 github.global.ssl.fastly.net
打开cmd输入ipconfig /flushdns更新DNS缓存
5.6.2、SpringCloud Config快速入门 新建config模块
导入依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdspringcloud/artifactIdgroupIdcn.winkto/groupIdversion0.0.1-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdconfig/artifactIddependencies!--eureka client 客户端依赖引入--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!--config配置中心服务端--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-config-server/artifactId/dependency/dependencies
/project
application.yaml
server:port: 9400
eureka:client:service-url:# 客户端与EurekaServer交互的地址,是一个mapdefaultZone: http://127.0.0.1:8099/eureka/,http://127.0.0.1:8199/eureka/instance:#使用ip注册否则会使用主机名注册prefer-ip-address: true#自定义实例显示格式instance-id: ${spring.cloud.client.ipaddress}:${spring.application.name}:${server.port}:project.version
spring:application:name: configcloud:config:server:git:# 项目地址https://github.com/winkto/winkto.gituri: https://github.com/winkto/winkto.gitusername: winktopassword: ******search-paths: winkto# 分支label: main
启动类
SpringBootApplication
EnableDiscoveryClient
// 开启配置服务器功能
EnableConfigServer
public class ConfigApplication {public static void main(String[] args) {SpringApplication.run(ConfigApplication.class, args);}
}
测试
http://localhost:9400/main/application-dev.yaml 5.6.3、SpringClou Config改造消费者
消费者导入依赖
dependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-hystrix/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-config-client/artifactId/dependency
/dependencies
修改application.yaml为bootstrap.yaml并添加分布式配置中心的地址bootstrap.yml是系统级别的优先级比application.yml高应用启动时会检查这个配置文件 在这个配置文件中指定配置中心的服务地址会自动拉取所有应用配置并且启用
spring:application:name: consumecloud:#config客户端配置,和ConfigServer通信并告知ConfigServer希望获取的配置信息在哪个文件中config:# ConfigServer配置中心地址uri: http://localhost:9400name: applicationprofile: devlabel: main
contrller
RestController
public class CommodityController {Autowiredprivate CommondityFeign commondityFeign;Value(${person.name})private String name;Value(${person.age})private int age;HystrixCommand(// 线程池标识要保持唯一不唯一的话就共用了threadPoolKey selectCommodityById,// 线程池细节属性配置threadPoolProperties {// 线程数HystrixProperty(namecoreSize,value 1),// 等待队列长度HystrixProperty(namemaxQueueSize,value20)},commandProperties {// 每一个属性都是一个HystrixPropertyHystrixProperty(nameexecution.isolation.thread.timeoutInMilliseconds,value 5000),// 统计窗口时间的设置HystrixProperty(name metrics.rollingStats.timeInMilliseconds,value 8000),// 统计窗口内的最小请求数HystrixProperty(name circuitBreaker.requestVolumeThreshold,value 2),// 统计窗口内错误请求阈值的设置 50%HystrixProperty(name circuitBreaker.errorThresholdPercentage,value 50),// 自我修复的活动窗口时间HystrixProperty(name circuitBreaker.sleepWindowInMilliseconds,value 3000)},fallbackMethod selectCommodityByIdFallBack)RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){return commondityFeign.selectCommodityById(id);}RequestMapping(/person)public String person(){return nameage;}
} 5.6.4、Config配置手动刷新
当我们修改GitHub上面的值时服务端Config Server能 实时获取最新的值但客户端Config Client读的是缓存无法实时获取最新值
修改github上的配置文件
访问config查看文件
访问客户端查看配置数据
发现数据并没有更新
开启手动刷新
消费者bootstrap.yml中添加配置
management:endpoints:web:exposure:# include: refreshinclude: *
消费者controller上加上手动刷新的标识
RestController
RefreshScope
public class CommodityController {Autowiredprivate CommondityFeign commondityFeign;Value(${person.name})private String name;Value(${person.age})private int age;HystrixCommand(// 线程池标识要保持唯一不唯一的话就共用了threadPoolKey selectCommodityById,// 线程池细节属性配置threadPoolProperties {// 线程数HystrixProperty(namecoreSize,value 1),// 等待队列长度HystrixProperty(namemaxQueueSize,value20)},commandProperties {// 每一个属性都是一个HystrixPropertyHystrixProperty(nameexecution.isolation.thread.timeoutInMilliseconds,value 5000),// 统计窗口时间的设置HystrixProperty(name metrics.rollingStats.timeInMilliseconds,value 8000),// 统计窗口内的最小请求数HystrixProperty(name circuitBreaker.requestVolumeThreshold,value 2),// 统计窗口内错误请求阈值的设置 50%HystrixProperty(name circuitBreaker.errorThresholdPercentage,value 50),// 自我修复的活动窗口时间HystrixProperty(name circuitBreaker.sleepWindowInMilliseconds,value 3000)},fallbackMethod selectCommodityByIdFallBack)RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){return commondityFeign.selectCommodityById(id);}RequestMapping(/person)public String person(){return nameage;}
}
由于上github经常卡程序拉不到最新的文件于是我换了gitee和之前的操作一样当前gitee上的配置文件
config和comsume拿到的配置文件如下
修改gitee文件
刷新config文件秒到有没有,唯一体验不好的就是广告太多了
此时consume仍是之前的缓存
我们手动让它刷新一下在线发送一个post请求注意不能是get
http://localhost:9100/actuator/refresh 回到consume刷新发现配置已经更新
5.6.5、Config配置自动刷新
在微服务架构中可以结合消息总线Bus实现分布式配置的自动更新Spring Cloud Config Spring Cloud Bus
消息总线Bus即使用MQ消息代理构建一个共用的Topic通过这个Topic连接各个 微服务实例MQ广播的消息会被所有在注册中心的微服务实例监听和消费。
Spring Cloud Bus基于MQ的支持RabbitMq/Kafka 是Spring Cloud中的消息总线方案 Spring Cloud Config Spring Cloud Bus 结合可以实现配置信息的自动更新
首先要保证有一个可以正常使用的MQ服务器
config和consume导入依赖
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-bus-amqp/artifactId
/dependency
config和consume配置rabbitmq信息
spring:rabbitmq:host: 106.54.85.216port: 5672username: winktopassword: blingbling
config配置暴露bus-refresh端口
management:endpoints:web:exposure:# include: bus-refreshinclude: *
修改gitee上的配置文件
config中心已经刷新
访问config通知消息队列配置文件已经更新
http://127.0.0.1:9400/actuator/bus-refresh consume更新成功
6、SpringCloud二代组件学习
Spring Cloud Alibaba 也是一套微服务解决方案包含开发分布式应用微服 务的必需组件方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。依托 Spring Cloud Alibaba您只需要添加一些注解和少量配置就可以将 Spring Cloud 应用接入阿里微服 务解决方案通过阿里中间件来迅速搭建分布式应用系统
6.1、Nacos
6.1.1、Nacos安装使用
Nacos就是注册中心配置中心的组合NacosEureka Config Bus
Nacos 官方https://github.com/alibaba/nacos/releases
Nacos 百度云https://pan.baidu.com/s/1LLC30x5k6lxh865oxkQu1Q提取码6i9j
安装方式直接解压即可
启动方式
linux
sh startup.sh -m standalone
windows
cmd startup.cmd -m standalone
管理端
http://106.54.85.216:8848/nacos/index.html#/login
默认账号密码为nacosnacos
6.1.2、微服务注册到Nacos
我们将项目回退到4.7的代码
父项目
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionpackagingpom/packagingmodulesmoduleproduct/modulemoduleproduct-duplicate/module/modulesparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.3.12.RELEASE/versionrelativePath/ !-- lookup parent from repository --/parentgroupIdcn.winkto/groupIdartifactIdspringcloudali/artifactIdversion0.0.1-SNAPSHOT/versionnamespringcloudali/namedescriptionDemo project for Spring Boot/descriptionpropertiesjava.version1.8/java.version/properties!--Hoxton.SR12--dependencyManagementdependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversionHoxton.SR12/versiontypepom/typescopeimport/scope/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion2.2.4.RELEASE/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagementdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--微服务的监控与管理--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-logging/artifactId/dependency/dependenciesbuildpluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactIdconfigurationsource8/sourcetarget8/targetencodingUTF-8/encoding/configuration/pluginplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdexecutionsexecutiongoalsgoalrepackage/goal/goals/execution/executions/plugin/plugins/build/project
生产者
导入依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdspringcloudali/artifactIdgroupIdcn.winkto/groupIdversion0.0.1-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdproduct/artifactIddependenciesdependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.2.0/version/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency/dependencies/project
实体类
public class Commodity {private int id;private String name;private double price;private String desc;private String images;private int stock;private String type;private boolean deteled;
}
mapper
Repository
public interface CommodityMapper {public Commodity selectCommodityById(int id);
}
mapper映射文件
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecn.winkto.mapper.CommodityMapperselect idselectCommodityById parameterTypeint resultTypeCommodityselect * from commodity where id#{id}/select
/mapper
service
public interface CommodityService {public Commodity selectCommodityById(int id);
}
Service
public class CommodityServiceImpl implements CommodityService {AutowiredCommodityMapper commodityMapper;Overridepublic Commodity selectCommodityById(int id) {return commodityMapper.selectCommodityById(id);}
}
controller
RestController
public class CommodityController {Value(${server.port})int port;AutowiredCommodityService commodityService;RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){System.out.println(port生产者被调用);return commodityService.selectCommodityById(id);}
}
启动类
SpringBootApplication
MapperScan(cn.winkto.mapper)
public class ProductduplicateApplication {public static void main(String[] args) {SpringApplication.run(ProductduplicateApplication.class, args);}
}
application.yaml
mybatis:type-aliases-package: cn.winkto.beanmapper-locations: classpath:mapper/*.xml
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: blingbling123.url: jdbc:mysql://localhost:3306/springcloud?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghaiapplication:name: productcloud:nacos:discovery:server-addr: 106.54.85.216:8848
server:port: 9001
将生产者拷贝一份为product-duplicate
消费者
导入依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdspringcloudali/artifactIdgroupIdcn.winkto/groupIdversion0.0.1-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdconsume/artifactIddependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency/dependencies
/project
public class Commodity {private int id;private String name;private double price;private String desc;private String images;private int stock;private String type;private boolean deteled;
}
config
Configuration
public class WinktoConfig {// 旧版注册// Bean// LoadBalanced// public RestTemplate restTemplate(){// return new RestTemplate();// }// 新版注册BeanLoadBalancedpublic RestOperations restTemplate(RestTemplateBuilder builder) {return builder.build();}
}
feign
FeignClient(name product,fallback CommindityFallback.class)
public interface CommondityFeign {RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id);
}
Component(commindityFallback)
public class CommindityFallback implements CommondityFeign {Overridepublic Commodity selectCommodityById(int id) {return new Commodity();}
}
controller
RestController
public class CommodityController {// Autowired// RestOperations restTemplate;// Autowired// DiscoveryClient discoveryClient;Autowiredprivate CommondityFeign commondityFeign;RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){return commondityFeign.selectCommodityById(id);}
}
启动类
SpringBootApplication
EnableDiscoveryClient
//开启熔断服务
// EnableCircuitBreaker
//开启Feign远程调用自带熔断
EnableFeignClients
public class ConsumeApplication {public static void main(String[] args) {SpringApplication.run(ConsumeApplication.class, args);}
}
application.yaml
server:port: 9100
spring:application:name: consumecloud:nacos:discovery:server-addr: 106.54.85.216:8848
# springboot中暴露健康检查等断点接口
management:endpoints:web:exposure:# include: refreshinclude: *# 暴露健康接口的细节endpoint:health:show-details: always
效果
6.1.3、保护阈值
保护阈值可以设置为0-1之间的浮点数它其实是一个比例值当前服务健康实例数/当前服务总实例数
nacos是服务注册中心服务消费者要从nacos获取某一个服务的可用实例信息对于 服务实例有健康/不健康状态之分nacos在返回给消费者实例信息的时候会返回健康实例。这个时候在一些高并发、大流量场景下会存在一定的问题
如果服务A有100个实例98个实例都不健康了只有2个实例是健康的如果nacos只返回这两个 健康实例的信息的话那么后续消费者的请求将全部被分配到这两个实例流量洪峰到来2个健康的实例也扛不住了整个服务A就扛不住上游的微服务也会导致崩溃产生雪崩效应
保护阈值的意义在于 当服务A健康实例数/总实例数 保护阈值 的时候说明健康实例真的不多了这个时候保护阈值会被触发状态true
nacos将会把该服务所有的实例信息健康的不健康的全部提供给消费者消费者可能访问到不健康的实例请求失败但这样也比造成雪崩要好牺牲了一些请求保证了整个系统的一个可用。
6.1.4、负载均衡
Nacos客户端引入的时候会关联引入Ribbon的依赖包我们使用OpenFiegn的时候也会引入Ribbon的依赖Ribbon包括Hystrix都按原来方式进行配置即可
消费者application.yaml
server:port: 9100
spring:application:name: consumecloud:nacos:discovery:server-addr: 106.54.85.216:8848
# springboot中暴露健康检查等断点接口
management:endpoints:web:exposure:# include: refreshinclude: *# 暴露健康接口的细节endpoint:health:show-details: always
# 配置熔断策略
hystrix:command:default:circuitBreaker:# 强制打开熔断器如果该属性设置为true强制断路器进入打开状态将会拒绝所有的请求。默认false关闭的forceOpen: false# 触发熔断错误比例阈值默认值50%errorThresholdPercentage: 50# 熔断后休眠时长默认值5秒sleepWindowInMilliseconds: 3000# 熔断触发最小请求次数默认值是20requestVolumeThreshold: 2execution:isolation:thread:# 熔断超时设置默认为1秒timeoutInMilliseconds: 2000
product:ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule#对所有操作都进行重试OkToRetryOnAllOperations: true#对当前选中实例重试次数不包括第一次调用MaxAutoRetries: 0#切换实例的重试次数MaxAutoRetriesNextServer: 0
6.1.5、数据模型 Namespace命名空间对不同的环境进行隔离比如隔离开发环境、测试环境和生产环境
Group分组将若干个服务或者若干个配置集归为一组通常习惯一个系统归为一个组
Service某一个服务比如商品微服务
DataId配置集或者可以认为是一个配置文件
概念描述Namespace代表不同的环境如开发dev、测试test、生产环境prodGroup代表某项目Service某个项目中具体xxx服务DataId某个项目中具体的xxx配置文件6.1.6、配置中心
使用Nacos之后分布式配置就简单很多Github不需要了配置信息直接配置在Nacos server中Bus也不需要了(依然可以完成动态刷新)
dataid完整格式
${prefix}-${spring.profile.active}.${file-extension}
prefix 默认为spring.application.namespring.profile.active即为当前环境对应的 profilefile-extension为配置内容的数据格式可以通过配置项
添加配置文件
导入依赖
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-config/artifactId
/dependency
application.yaml更名为bootstrap.yaml并添加nacos地址
spring:cloud:nacos:discovery:server-addr: 106.54.85.216:8848config:server-addr: 106.54.85.216:8848# 命名空间不指定默认为publicnamespace: 03f3f10e-9154-41df-8bbb-5a79e743bf40# 分组不指定默认为DEFAULT_GROUPgroup: DEFAULT_GROUPfile-extension: yaml
controller添加接口
RestController
RefreshScope
public class CommodityController {// Autowired// RestOperations restTemplate;// Autowired// DiscoveryClient discoveryClient;Autowiredprivate CommondityFeign commondityFeign;Value(${message})private String message;RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id){return commondityFeign.selectCommodityById(id);}RequestMapping(/hello)public String hello(){return message;}
} 编辑配置文件 刷新接口页面
6.1.7、多配置文件
若一个微服务希望从配置中心Nacos server中获取多个dataId的配置信息则只需扩展多个 dataId即可
添加配置文件
修改bootstrap.yaml
spring:cloud:nacos:discovery:server-addr: 106.54.85.216:8848config:server-addr: 106.54.85.216:8848# 命名空间不指定默认为publicnamespace: 03f3f10e-9154-41df-8bbb-5a79e743bf40# 分组不指定默认为DEFAULT_GROUPgroup: DEFAULT_GROUPfile-extension: yamlextension-configs:- data-id: m1refresh: true- data-id: m2refresh: true
访问接口 修改m1 刷新页面
6.2、Sentinel
Sentinel是一个面向云原生微服务的流量控制、熔断降级组件
替代Hystrix针对问题服务雪崩、服务降级、服务熔断、服务限流
丰富的应用场景Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景例如秒杀即 突发流量控制在系统容量可以承受的范围、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等完备的实时监控Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器 秒级数据甚至 500 台以下规模的集群的汇总运行情况。 # 锁定server端的配置文件读取它的配置项 namespace: 07137f0a-bf66-424b-b910-20ece612395a # 命名空间id group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP如果使用默认分组可以不配置 file-extension: yaml #默认properties # 根据规则拼接出来的dataId效果lagou-service-page.yaml ext-config[0]: data-id: abc.yaml group: DEFAULT_GROUP refresh: true #开启扩展dataId的动态刷新 ext-config[1]: data-id: def.yaml group: DEFAULT_GROUP refresh: true #开启扩展dataId的动态刷新广泛的开源生态Sentinel 提供开箱即用的与其它开源框架/库的整合模块例如与 Spring Cloud、Dubbo的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel完善的 SPI 扩展点Sentinel 提供简单易用、完善的 SPI 扩展接口可以通过实现扩展接口来快 速地定制逻辑例如定制规则管理、适配动态数据源等。
6.2.1、Sentinel-dashboard
Sentinel-dashboard1.8.2 官方https://github.com/alibaba/Sentinel/releases
Sentinel-dashboard1.8.2 百度云https://pan.baidu.com/s/1j6Lht2cZRxrgkQjiHezakA提取码r9pf
端口8080
访问地址http://localhost:8080/
账号密码sentinel/sentinel
6.2.2、Sentinel快速入门
消费者导入依赖
!--sentinel 核心环境 依赖--
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId
/dependency
bootstrap.yaml修改配置sentinel dashboard删除原有hystrix配置删除 原有OpenFeign的降级配置
server:port: 9100
spring:application:name: consumecloud:nacos:discovery:server-addr: 106.54.85.216:8848config:server-addr: 106.54.85.216:8848# 命名空间不指定默认为publicnamespace: 03f3f10e-9154-41df-8bbb-5a79e743bf40# 分组不指定默认为DEFAULT_GROUPgroup: DEFAULT_GROUPfile-extension: yamlextension-configs:- data-id: m1refresh: true- data-id: m2refresh: truesentinel:transport:dashboard: 127.0.0.1:8080port: 8719
# springboot中暴露健康检查等断点接口
management:endpoints:web:exposure:include: *# 暴露健康接口的细节endpoint:health:show-details: always
启动静态化微服务使用 Sentinel 监控静态化微服务发现控制台没有任何变化因为懒加载我们只需要发起一次请求触发即可
6.2.3、流控规则快速体验 6.2.4、通过线程数限流
修改消费者controller
RestController
RefreshScope
public class CommodityController {// Autowired// RestOperations restTemplate;// Autowired// DiscoveryClient discoveryClient;Autowiredprivate CommondityFeign commondityFeign;Value(${message})private String message;Value(${message1})private String message1;Value(${message2})private String message2;RequestMapping(/selectCommodityById/{id})public Commodity selectCommodityById(PathVariable int id) throws InterruptedException {Thread.sleep(10000);return commondityFeign.selectCommodityById(id);}RequestMapping(/hello)public String hello(){return messagemessage1message2;}
}
新增线程规则
使用并发软件测试即可
6.2.5、流控关联规则
当其他服务达到阈值当前服务失败
6.2.6、降级
Sentinel 降级会在调用链路中某个资源出现不稳定状态时例如调用超时或异常比例升高对这 个资源的调用进行限制让请求快速失败避免影响到其它的资源而导致级联错误。当资源被降级后 在接下来的降级时间窗口之内对该资源的调用都自动熔断这里的降级其实是Hystrix中的熔断
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/92691.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!