上海安全建设协会网站,freenom申请域名,百度分析工具,wordpress 函数api文件路径SpringCloud(一)、这个阶段该如何学习?1.微服务介绍2.面试常见问题(二)、微服务概述1.什么是微服务?2. 微服务与微服务架构(1).微服务(2).微服务架构⭐(3). 微服务优缺点(4). 微服务技术栈有那些#xff1f;(5). 为什么选择SpringCloud作为微服务架构(三)、SpringCloud入门概…
SpringCloud(一)、这个阶段该如何学习?1.微服务介绍2.面试常见问题(二)、微服务概述1.什么是微服务?2. 微服务与微服务架构(1).微服务(2).微服务架构⭐(3). 微服务优缺点(4). 微服务技术栈有那些(5). 为什么选择SpringCloud作为微服务架构(三)、SpringCloud入门概述1.SpringCloud是什么?2. SpringCloud和SpringBoot的关系⭐3. Dubbo 和 SpringCloud技术选型(1). 分布式服务治理Dubbo(2). Dubbo 和 SpringCloud对比(3). SpringCloud能干嘛(4).SpringCloud下载(四)、SpringCloud Rest学习环境搭建服务提供者1.介绍2. SpringCloud版本选择3.创建父工程(1).添加父类Maven依赖4.创建子工程 SpringCloud-api (普通Maven)5.创建子工程SpringCloud-provider-dept-8001 (普通Maven项目)6.创建子工程SpringCloud-consumer-dept-80 (普通Maven)(五)、Eureka服务注册中心1.什么是Eureka2.原理理解(1).Eureka架构和Dubbo架构的对比(2).Eureka的两个组件(3).Eureka的三大角色3.构建步骤(1).第一步: 导入依赖(2).第二步: 配置yaml(3).第三步: 开启服务4.项目构建四大步骤⭐5.服务注册-信息配置-自我保护机制(1).Eureka-client (服务注册-服务端)(2).Eureka (信息配置)(3).Eureka (自我保护机制: 好死不如赖活着)(4). 注册进来的微服务获取一些消息团队开发会用到服务端80816. Eureka: 集群环境配置(1).搭建多个模块 (模拟多台电脑)(2). 集群成员相互关联7.对比和Zookeeper区别(1). 回顾CAP原则(2).ACID是什么(3). CAP是什么?(4). CAP理论的核心(5). 作为分布式服务注册中心Eureka比Zookeeper好在哪里(六)、Ribbon: 负载均衡(基于客户端)1.负载均衡以及Ribbon2.集成Ribbon 在客户端 80端口3.使用Ribbon实现负载均衡4.自定义负载均衡算法(1).切换系统已有均衡算法(2).自定义负载均衡算法(七)、Feign负载均衡 基于客户端1.Feign简介(1).Feign能干什么(2).Feign的使用步骤2. Ribbon与Feign如何选择?(八)、Hystrix:服务熔断1.服务雪崩2.什么是Hystrix3.Hystrix能干嘛4.服务熔断 (提供者下用)(1).什么是服务熔断?(2).入门案列5.服务降级 服务调用者下用(1).什么是服务降级(2).服务降级需要考虑的问题(3).自动降级分类(4).入门案列6. 服务熔断和降级的区别7.Dashboard 流监控(1).详细步骤(2).介绍(九)、 Zull路由网关1.概述2.开始运用Zuul路由网关(十)、SpringCloud Config1.概述2.Git环境搭建3.服务端链接Git配置(1).链接操作(2)三种读取方式4.客户端链接服务端访问远程5.远程配置实战测试(1).启用eureka-7001(2).启用config-8081(十)、汇总(一)、这个阶段该如何学习?
回顾之前的知识
JavaSE数据库前端ServletHttpMybatisSpringSpringmvcSpringBootDubbo Zookeeper 分布式基础Maven、GitAjax、GitMaven、JSON
1.微服务介绍
Ctrl Shift Esc : 查看自己电脑的内存一定要使用11G以上的我这里是15.8G
三层架构 MVC (dao service servlet)框架:(1).Spring mybatis springMvc (SSM)(2).SpringBoot 新一代的JavaEE开发标准自动装配(3).SpringCloud : 活字印刷进行业务拆分
微服务架构的四个核心问题(1).服务很多客户端怎么访问?(2).这么多服务服务之间怎么通信?(3).这么多服务? 如何治理?(4).服务挂了怎么办?
解决方案:(1).SpringCloud NetFlix ! (一站式服务)api网关zuul组件Feign -- HttpClient --http通信方式同步 阻塞服务治理服务注册与发现Eureka服务意外停止熔断机制Hystrix(2).Dubbo Zookeeper! 半自动需要整合别人的访问API : 没有! 要么找第三方组件 要么自己实现通信Dubbo是一个高性能的基于Java实现的RPC通信框架! 使用起来就是一个jar包服务治理服务注册与发现zookeeper: 动物园管理者(Hadoop , Hive)服务注册中心服务意外停止熔断机制没有借助了Hystrix(3).Spring Cloud Alibaba ! 最新的一站式服务API网关Zuul 和 Gateway组件通信Dubbo服务注册和发现Nacos。熔断机制Sentinel
万变不离其宗1.API 网关2.HTTP RPC (通信)3.注册和发现 (服务治理)4.熔断机制 (服务泵机)2.面试常见问题
什么是微服务 答:微服务是一种架构思想它提倡将一个单独的应用拆分多个小的服务微服务之间是如何独立通讯的 答: 用过RPC 或则SpringCloud的RestSpringCloud 和 Dubbo有那些区别 答: 最大的区别就在于SpringCloud使用RPC的方式进行调用Dubbo使用Http的RestSpringBoot 和 SpringCloud请谈谈你对他们的理解 答: SpringBoot用于开发单个小模块SpringCloud对开发的小模块进行集结。什么是服务熔断什么是服务降级微服务的优缺点分别是什么说下你在项目开发中遇到的坑你所知道的微服务技术栈有哪些列举一二Eureka和Zookeeper都可以提供服务注册与发现的功能请说说两者的区别
(二)、微服务概述
1.什么是微服务?
什么是微服务 微服务(Microservice Architecture) 是近几年流行的一种架构思想关于它的概念很难一言以蔽之。
究竟什么是微服务呢我们在此引用ThoughtWorks 公司的首席科学家 Martin Fowler 于2014年提出的一段话 原文https://martinfowler.com/articles/microservices.html
汉化https://www.cnblogs.com/liuning8023/p/4493156.html
就目前而言对于微服务业界并没有一个统一的标准的定义。但通常而言微服务架构是一种架构模式或者说是一种架构风格它提倡将单一的应用程序划分成一组小的服务每个服务运行在其独立的自己的进程内服务之间互相协调互相配置为用户提供最终价值服务之间采用轻量级的通信机制(HTTP)互相沟通每个服务都围绕着具体的业务进行构建并且能够被独立的部署到生产环境中另外应尽量避免统一的集中式的服务管理机制对具体的一个服务而言应该根据业务上下文选择合适的语言工具(Maven)对其进行构建可以有一个非常轻量级的集中式管理来协调这些服务可以使用不同的语言来编写服务也可以使用不同的数据存储。
再来从技术维度角度理解下
微服务化的核心就是将传统的一站式应用根据业务拆分成一个一个的服务彻底地去耦合每一个微服务提供单个业务功能的服务一个服务做一件事情从技术角度看就是一种小而独立的处理过程类似进程的概念能够自行单独启动或销毁拥有自己独立的数据库。
2. 微服务与微服务架构
(1).微服务
强调的是服务的大小它关注的是某一个点是具体解决某一个问题/提供落地对应服务的一个服务应用狭义的看可以看作是IDEA中的一个个微服务工程或者Moudel。
IDEA 工具里面使用Maven开发的一个个独立的小Moudel它具体是使用SpringBoot开发的一个小模块专业的事情交给专业的模块来做一个模块就做着一件事情。
强调的是一个个的个体每个个体完成一个具体的任务或者功能。(2).微服务架构⭐
一种新的架构形式Martin Fowler 于2014年提出。
微服务架构是一种架构模式它提倡将单一应用程序划分成一组小的服务服务之间相互协调互相配合为用户提供最终价值。每个服务运行在其独立的进程中服务与服务之间采用轻量级的通信机制(如HTTP)互相协作每个服务都围绕着具体的业务进行构建并且能够被独立的部署到生产环境中另外应尽量避免统一的集中式的服务管理机制对具体的一个服务而言应根据业务上下文选择合适的语言、工具(如Maven)对其进行构建。
(3). 微服务优缺点
优点
单一职责原则每个服务足够内聚足够小代码容易理解这样能聚焦一个指定的业务功能或业务需求开发简单开发效率高一个服务可能就是专一的只干一件事微服务能够被小团队单独开发这个团队只需2-5个开发人员组成微服务是松耦合的是有功能意义的服务无论是在开发阶段或部署阶段都是独立的微服务能使用不同的语言开发易于和第三方集成微服务允许容易且灵活的方式集成自动部署通过持续集成工具如jenkinsHudsonbamboo微服务易于被一个开发人员理解修改和维护这样小团队能够更关注自己的工作成果无需通过合作才能体现价值微服务允许利用和融合最新技术微服务只是业务逻辑的代码不会和HTMLCSS或其他的界面混合;每个微服务都有自己的存储能力可以有自己的数据库也可以有统一的数据库
缺点
开发人员要处理分布式系统的复杂性多服务运维难度随着服务的增加运维的压力也在增大系统部署依赖问题服务间通信成本问题数据一致性问题系统集成测试问题性能和监控问题
(4). 微服务技术栈有那些
微服务技术条目落地技术服务开发SpringBoot、Spring、SpringMVC等服务配置与管理Netfix公司的Archaius、阿里的Diamond等服务注册与发现Eureka、Consul、Zookeeper等服务调用Rest、PRC、gRPC服务熔断器Hystrix、Envoy等负载均衡Ribbon、Nginx等服务接口调用(客户端调用服务的简化工具)Fegin等消息队列Kafka、RabbitMQ、ActiveMQ等服务配置中心管理SpringCloudConfig、Chef等服务路由(API网关)Zuul等服务监控Zabbix、Nagios、Metrics、Specatator等全链路追踪Zipkin、Brave、Dapper等数据流操作开发包SpringCloud Stream(封装与RedisRabbitKafka等发送接收消息)时间消息总栈SpringCloud Bus服务部署Docker、OpenStack、Kubernetes等
(5). 为什么选择SpringCloud作为微服务架构
选型依据
整体解决方案和框架成熟度
社区热度
可维护性
学习曲线 开发用起来很简单就几个注解但是要理解其思想
当前各大IT公司用的微服务架构有那些
阿里dubboHFS
京东JFS
新浪Motan
当当网DubboX
…
各微服务框架对比
功能点/服务框架Netflix/SpringCloudMotangRPCThriftDubbo/DubboX功能定位完整的微服务框架RPC框架但整合了ZK或Consul实现集群环境的基本服务注册发现RPC框架RPC框架服务框架支持Rest是Ribbon支持多种可拔插的序列号选择否否否否支持RPC否是否否否支持多语言是否是是否负载均衡是(服务端zuul客户端Ribbon)zuul-服务动态路由云端负载均衡Eureka针对中间层服务器是(客户端)否否是客户端配置服务Netfix ArchaiusSpring Cloud Config Server 集中配置是(Zookeeper提供)否否否服务调用链监控是(zuul)zuul提供边缘服务API网关否否否否高可用/容错是(服务端Hystrix客户端Ribbon)是(客户端)否否是(客户端)典型应用案例NetflixSinaGoogleFacebook社区活跃程度高一般高一般2017年后重新开始维护之前中断了5年学习难度中等低高高低文档丰富程度高一般一般一般高其他Spring Cloud Bus为我们的应用程序带来了更多管理端点支持降级Netflix内部在开发集成gRPCIDL定义实践的公司比较多
(三)、SpringCloud入门概述
1.SpringCloud是什么? SpringCloud基于SpringBoot提供了一套微服务解决方案包括服务注册与发现配置中心全链路监控服务网关负载均衡熔断器等组件,除了基于NetFlix的开源组件做高度抽象封装之外还有一些选型中立的开源组件。
SpringCloud利用SpringBoot的开发便利性巧妙地简化了分布式系统基础设施的开发SpringCloud为开发人员提供了快速构建分布式系统的一些工具包括配置管理服务发现断路器路由微代理事件总线全局锁决策竞选分布式会话等等他们都可以用SpringBoot的开发风格做到一键启动和部署。
SpringBoot并没有重复造轮子它只是将目前各家公司开发的比较成熟经得起实际考研的服务框架组合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理最终给开发者留出了一套简单易懂易部署和易维护的分布式系统开发工具包。
SpringCloud是分布式微服务架构下的一站式解决方案是各个微服务架构落地技术的集合体俗称微服务全家桶。
2. SpringCloud和SpringBoot的关系⭐
SpringBoot专注于开发方便的开发单个个体微服务SpringCloud是关注全局的微服务协调整理治理框架它将SpringBoot开发的一个个单体微服务整合并管理起来为各个微服务之间提供配置管理、服务发现、断路器、路由、为代理、事件总栈、全局锁、决策竞选、分布式会话等等集成服务SpringBoot可以离开SpringCloud独立使用开发项目但SpringCloud离不开SpringBoot属于依赖关系SpringBoot专注于快速、方便的开发单个个体微服务SpringCloud关注全局的服务治理框架
3. Dubbo 和 SpringCloud技术选型
(1). 分布式服务治理Dubbo
目前成熟的互联网架构应用服务化拆分消息中间件
传统的较大型网站架构图:
(2). Dubbo 和 SpringCloud对比
可以看一下社区活跃度 https://github.com/dubbo
https://github.com/spring-cloud
对比结果
DubboSpringCloud服务注册中心ZookeeperSpring Cloud Netfilx Eureka服务调用方式RPCREST API服务监控Dubbo-monitorSpring Boot Admin断路器不完善Spring Cloud Netfilx Hystrix服务网关无Spring Cloud Netfilx Zuul分布式配置无Spring Cloud Config服务跟踪无Spring Cloud Sleuth消息总栈无Spring Cloud Bus数据流无Spring Cloud Stream批量任务无Spring Cloud Task
最大区别Spring Cloud 抛弃了Dubbo的RPC通信采用的是基于HTTP的REST方式
严格来说这两种方式各有优劣。虽然从一定程度上来说后者牺牲了服务调用的性能但也避免了上面提到的原生RPC带来的问题。而且REST相比RPC更为灵活服务提供方和调用方的依赖只依靠一纸契约不存在代码级别的强依赖这个优点在当下强调快速演化的微服务环境下显得更加合适。
品牌机和组装机的区别
很明显Spring Cloud的功能比DUBBO更加强大涵盖面更广而且作为Spring的拳头项目它也能够与SpringFramework. Spring Boot. Spring Data. Spring Batch等其他Spring项目完美融合,这些对于微服务而言是至关重要的。使用Dubbo构建的微服务架构就像组装电脑各环节我们的选择自由度很高但是最终结果很有可能因为一条内存质量不行就点不亮了总是让人不怎么放心但是如果你是一名高手 那这些都不是问题而SpringCloud就像品牌机在Spring Source的整合下做了大量的兼容性测试保证了机器拥有更高的稳定性,但是如果要在使用非原装组件外的东西就需要对其基础有足够的了解。
社区支持与更新力度的区别
最为重要的是DUBBO停止了5年左右的更新虽然2017.7重启了。对于技术发展的新需求,需要由开发者自行拓展升级(比如当当网弄出了DubboX)这对于很多想要采用微服务架构的中小软件组织显然是不太合适的中小公司没有这么强大的技术能力去修改Dubbo源码周边的一整套解决方案并不是每一个公司都有阿里的大牛真实的线上生产环境测试过。
总结
曾风靡国内的开源RPC服务框架Dubbo在重启维护后,令许多用户为之雀跃但同时也迎来了一-些质疑的声 音。互联网技术发展迅速Dubbo 是否还能跟上时代?Dubbo 与Spring Cloud相比又有何优势和差异是否会有相关举措保证Dubbo的后续更新频率
人物: Dubbo重启维护开发的刘军,主要负责人之一
刘军阿里巴巴中间件高级研发工程师主导了Dubbo重启维护以后的几个发版计划专注于高性能RPC框架 和微服务相关领域。曾负责网易考拉RPC框架的研发及指导在内部使用参与了服务治理平台、分布式跟踪系 统、分布式一致性框架等从无到有的设计与开发过程。
二者解决的问题域不一样Dubbo的定位是一款RPC框架而SpringCloud的目标是微服务架构下的一站式解决方案。
(3). SpringCloud能干嘛
Distributed/versioned configuration 分布式/版本控制配置Service registration and discovery 服务注册与发现Routing 路由Service-to-service calls 服务到服务的 调用Load balancing 负载均衡配置Circuit Breakers 断路器Distributed messaging 分布式消息管理 …
(4).SpringCloud下载
官网http://projects.spring.io/spring-cloud/
版本号有点特别
SpringCloud没有采用数字编号的方式命名版本号而是采用了伦敦地铁站的名称同时根据字母表的顺序来对应版本时间顺序比如最早的Realse版本Angel第二个Realse版本Brixton然后是Camden、Dalston、Edgware目前最新的是Hoxton SR4 CURRENT GA通用稳定版。看官网啊嘻嘻嘻
自学参考书
SpringCloud Netflix 中文文档https://springcloud.cc/spring-cloud-netflix.htmlSpringCloud 中文API文档(官方文档翻译版)https://springcloud.cc/spring-cloud-dalston.htmlSpringCloud中国社区http://springcloud.cn/SpringCloud中文网https://springcloud.cc
(四)、SpringCloud Rest学习环境搭建服务提供者
1.介绍
我们会使用一个Dept部门模块做一个微服务通用案例 Consumer消费者 (Client) 通过REST调用 Provider提供者(Server) 提供的服务。回顾SpringSpringMVCMybatis等以往学习的知识。Maven的分包分模块架构复习。
一个简单的Maven模块结构是这样的-- app-parent: 一个父项目(app-parent)聚合了很多子项目(app-util\app-dao\app-web...)|-- pom.xml||-- app-core||---- pom.xml||-- app-web||---- pom.xml......
1234567891011
一个父工程带着多个Moudule子模块
MicroServiceCloud父工程(Project)下初次带着3个子模块(Module)
microservicecloud-api 【封装的整体entity/接口/公共配置等】microservicecloud-consumer-dept-80 【服务提供者】microservicecloud-provider-dept-8001 【服务消费者】
2. SpringCloud版本选择
大版本说明
SpringBootSpringCloud关系1.2.xAngel版本(天使)兼容SpringBoot1.2x1.3.xBrixton版本(布里克斯顿)兼容SpringBoot1.3x也兼容SpringBoot1.4x1.4.xamden版本(卡姆登)兼容SpringBoot1.4x也兼容SpringBoot1.5x1.5.xDalston版本(多尔斯顿)兼容SpringBoot1.5x不兼容SpringBoot2.0x1.5.xEdgware版本(埃奇韦尔)兼容SpringBoot1.5x不兼容SpringBoot2.0x2.0.xFinchley版本(芬奇利)兼容SpringBoot2.0x不兼容SpringBoot1.5x
实际开发版本关系
spring-boot-starter-parentspring-cloud-dependencles版本号发布日期版本号发布日期1.5.2.RELEASE2017-03Dalston.RC12017-x1.5.9.RELEASE2017-11Edgware.RELEASE2017-111.5.16.RELEASE2018-04Edgware.SR52018-101.5.20.RELEASE2018-09Edgware.SR52018-102.0.2.RELEASE2018-05Fomchiey.BULD-SNAPSHOT2018-x2.0.6.RELEASE2018-10Fomchiey-SR22018-102.1.4.RELEASE2019-04Greenwich.SR12019-03
3.创建父工程
新建父工程项目springcloud切记 Packageing是pom模式主要是定义POM文件将后续各个子模块公用的jar包等统一提取出来类似一个抽象父类 (1).添加父类Maven依赖
这里使用了dependecyManger,目的是为了让子项目如果引用的时候会有一个父类指定的版本(目的是为了达到所有的子项目版本一致)
?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.xsdmodelVersion4.0.0/modelVersiongroupIdorg.jsxs/groupIdartifactIdSpringCloud/artifactIdversion1.0-SNAPSHOT/versionmodulesmoduleSpringCloud-api/modulemoduleSpringCloud-provider-dept-8001/module/modulespropertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingmaven.compiler.source1.8/maven.compiler.sourcemaven.compiler.target1.8/maven.compiler.targetjunit.version4.12/junit.versionlog4j.version1.2.17/log4j.versionlombok.version1.16.18/lombok.version/properties
!-- 更改打包方式--packagingpom/packaging!-- 使用依赖管理--dependencyManagement
!-- 创建依赖项--dependencies
!-- SpringCloud 的依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversionHoxton.SR8/versiontypepom/typescopeimport/scope/dependency
!-- SpringBoot 的依赖--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-dependencies/artifactIdversion2.3.3.RELEASE/versiontypepom/typescopeimport/scope/dependency
!-- MySql 数据库--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.6/version/dependency
!-- 导入德鲁伊数据源 --dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.1.10/version/dependency!--SpringBoot 启动器--dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion1.3.2/version/dependency!--日志测试~--dependencygroupIdch.qos.logback/groupIdartifactIdlogback-core/artifactIdversion1.2.3/version/dependency!--junit--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion${junit.version}/version/dependency!-- log4j--dependencygroupIdlog4j/groupIdartifactIdlog4j/artifactIdversion${log4j.version}/version/dependency!-- lombok --dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion${lombok.version}/version/dependency/dependencies/dependencyManagement
/project4.创建子工程 SpringCloud-api (普通Maven)
客户端的资源 80 1.编写一个数据库: 数据库语句如下
CREATE DATABASE db01;
USE db01;
CREATE TABLE dept(deptno BIGINT(20) Not Null PRIMARY KEY AUTO_INCREMENT,dname VARCHAR(60) DEFAULT NULL,db_source VARCHAR(60) DEFAULT NULL
);
INSERT INTO dept(deptno,dname,db_source) VALUES(0,开发部,DATABASE());
INSERT INTO dept(deptno,dname,db_source) VALUES(1,人事部,DATABASE());
INSERT INTO dept(deptno,dname,db_source) VALUES(2,财务部,DATABASE());
INSERT INTO dept(deptno,dname,db_source) VALUES(3,售后部,DATABASE());2.所需要的依赖
?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/artifactIdgroupIdorg.jsxs/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersiongroupIdcom.jsxs/groupIdartifactIdSpringCloud-api/artifactIdpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.target/propertiesdependenciesdependencygroupIdlog4j/groupIdartifactIdlog4j/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependency/dependencies
/project3.创建一个实体类Dept 注意这里开启了链式编程注解并且实现了序列化的操作
package com.jsxs.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;import java.io.Serializable;Data
NoArgsConstructor
AllArgsConstructor
Accessors(chain true) //目的是为了打开链式写法
public class Dept implements Serializable { // 实体类在网络通信的时候一定要进行序列化否则会报错 ORM关系private Long deptno; // 主键private String dname; //部门的名字// 这里的数据存在哪个数据库里面。微服务: 一个服务对应一个数据库同一个信息可能存在不同的数据库中。private String db_source;
}
4.链式编程注解的介绍
⭐非链式写法:Dept deptnew Dept();dept.getDeptno();dept.getDname();⭐链式写法:Dept deptnew Dept();dept.getDeptno().getDname();
***** 上面的写法与下面的写法等同 **** 5.创建子工程SpringCloud-provider-dept-8001 (普通Maven项目)
1.需要的依赖需要添加一些SpringBoot的启动器
?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/artifactIdgroupIdorg.jsxs/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdSpringCloud-provider-dept-8001/artifactIdpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.target/propertiesdependencies
!-- 我们需要拿到实体类所以我们要获取刚才设置的Model -SpringCloud-api --dependencygroupIdcom.jsxs/groupIdartifactIdSpringCloud-api/artifactIdversion1.0-SNAPSHOT/version/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdscopetest/scope/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactId/dependencydependencygroupIdch.qos.logback/groupIdartifactIdlogback-core/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactId/dependency
!-- test--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-test/artifactId/dependency
!-- jetty--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jetty/artifactId/dependency
!-- 热部署工具--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency/dependencies
/project2.在Classpath:目录下编写application.yaml 主要任务就是端口号 Mybatis绑定 和 数据源
server:port: 8081
# Mybatis的配置
mybatis:type-aliases-package: com.jsxs.pojomapper-locations: classpath:mybatis/mapper/*.xml# Spring的配置
spring:application:name: SpringCloud-provider-deptdatasource:url: jdbc:mysql://localhost:3306/db01?useUnicodetruecharacterEncodingutf-8username: rootpassword: 121788driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource3.编写dao层接口以及Mapper.xml dao层的接口
package com.jsxs.dao;import com.jsxs.pojo.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;import java.util.List;Mapper
Repository
public interface DeptDao {public boolean addDept(Dept dept);public Dept queryById(Long id);public ListDept all();
}mybatis/DeptMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttps://mybatis.org/dtd/mybatis-3-mapper.dtd
!-- 1. 我们首先要绑定工作空间--
mapper namespacecom.jsxs.dao.DeptDao!-- 2. 我们编写SQL语句 --insert idaddDept parameterTypecom.jsxs.pojo.Deptinsert into dept(deptno,dname,db_source)values(#{deptno},#{dname},DATABASE())/insertselect idqueryById resultTypecom.jsxs.pojo.Dept parameterTypeLongselect *from dept where deptno#{id}/selectselect idall resultTypecom.jsxs.pojo.Deptselect *from dept/select
/mapper4.编写Service层的接口以及实现类 DeptService
package com.jsxs.service;import com.jsxs.pojo.Dept;import java.util.List;public interface DeptService {public boolean addDept(Dept dept);public Dept queryById(Long id);public ListDept all();
}
DeptServiceImpl
package com.jsxs.service;import com.jsxs.dao.DeptDao;
import com.jsxs.pojo.Dept;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.List;Service
public class DeptServiceImpl implements DeptService{Resourceprivate DeptDao deptDao;Overridepublic boolean addDept(Dept dept) {return deptDao.addDept(dept);}Overridepublic Dept queryById(Long id) {return deptDao.queryById(id);}Overridepublic ListDept all() {return deptDao.all();}}5.编写Cotroller层业务
package com.jsxs.controller;import com.jsxs.pojo.Dept;
import com.jsxs.service.DeptService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.List;// 提供Restful服务
RestController
public class DeptController {Resourceprivate DeptService deptService;PostMapping(/dept/add)public Boolean addDept(Dept dept){boolean flag deptService.addDept(dept);return flag;}GetMapping(/dept/queryById/{id})public Dept queryById(PathVariable(id) Long id){Dept dept deptService.queryById(id);return dept;}GetMapping(/dept/all)public ListDept all(){ListDept all deptService.all();return all;}
}6.创建子工程SpringCloud-consumer-dept-80 (普通Maven)
1.Maven依赖 边导入依赖 边看依赖的加载情况
?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/artifactIdgroupIdorg.jsxs/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdSpringCloud-consumer-dept-80/artifactIdpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.target/propertiesdependenciesdependencygroupIdcom.jsxs/groupIdartifactIdSpringCloud-api/artifactIdversion1.0-SNAPSHOT/version/dependency!-- 热部署工具--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency/dependencies
/project2.application.yaml 80 端口不会在web网址上显示 会自动隐藏。通常客户端的端口就是 80
server:port: 803.注入RestTemplate到Spring容器中去 config/configBean.java ⭐新思路: 就是利用Bean注入现成的类
package com.jsxs.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;Configuration // 相当于application.xml文件
public class ConfigBean {// 把RestTemplate注入到Spring中去Beanpublic RestTemplate getRestTemplate(){return new RestTemplate();}
}4.编写Controller层 controller/DeptCustomerController.java 注意: 这里我们只是引入了实体类的数据并没有引入service接口 思考: 消费者界面不应该存在Dao层也不应该存在Service层,该如何使用服务呢 RestTemplate … 我们直接调用就行但需要注入到Spring中 用户层的这个访问路径可以随意写没有必要和服务层的路径完全一致 getForObject(服务层URL返回类型.class) postForObject(服务层URL参数返回类型.class)
package com.jsxs.controller;import com.jsxs.pojo.Dept;
import org.springframework.stereotype.Controller;
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 javax.annotation.Resource;
import java.util.List;RestController
public class DeptConsumerController {//注意: 这里我们只是引入了实体类的数据并没有引入service接口//思考: 消费者界面不应该存在Dao层也不应该存在Service层,该如何使用服务呢//RestTemplate ... 我们直接调用就行但需要注入到Spring中Resource// (URI url, 实体 map,ClassT responseType) 地址---- 实体 ----返回类型.classprivate RestTemplate restTemplate; // 提供多种便捷访问远程 访问http服务的方法简单的Rest// 设置服务层的前缀为常量private static final String REST_URL_PREFIXhttp://localhost:8081;// 根据id进行数据的查找// 用户层的这个访问路径可以随意写没有必要和服务层的路径完全一致RequestMapping(/consumer/dept/get/{id})public Dept get(PathVariable(id) Long deptno){// 这里返回的是: 服务层的路径return restTemplate.getForObject(REST_URL_PREFIX/dept/queryById/deptno,Dept.class);}// 添加数据RequestMapping(/consumer/dept/add)public boolean add(Dept dept){return restTemplate.postForObject(REST_URL_PREFIX/dept/add,dept,Boolean.class);}// 查找全部数据RequestMapping(/consumer/dept/all)public ListDept all(){return restTemplate.getForObject(REST_URL_PREFIX/dept/all,List.class);}
}5.编写启动类
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplication
public class DeptConsumer_80 {public static void main(String[] args) {SpringApplication.run(DeptConsumer_80.class,args);}
}6.启动测试 先启动服务层的然后再启动用户层的 添加的时候会报错: 吉士先生认为可能是请求状态的错误Get 和 Post
(五)、Eureka服务注册中心
1.什么是Eureka
Netflix在涉及Eureka时遵循的就是AP原则。Eureka是Netflix的一个子模块也是核心模块之一。Eureka是基于REST的服务用于定位服务以实现云端中间件层服务发现和故障转移服务注册与发现对于微服务来说是非常重要的有了服务注册与发现只需要使用服务的标识符就可以访问到服务而不需要修改服务调用的配置文件了功能类似于Dubbo的注册中心比如Zookeeper。
2.原理理解
(1).Eureka架构和Dubbo架构的对比
Eureka基本的架构
Springcloud 封装了Netflix公司开发的Eureka模块来实现服务注册与发现 (对比Zookeeper).Eureka采用了C-S的架构设计EurekaServer作为服务注册功能的服务器他是服务注册中心.而系统中的其他微服务使用Eureka的客户端连接到EurekaServer并维持心跳(每隔三十秒请求链接一次)连接。这样系统的维护人员就可以通过EurekaServer来监控系统中各个微服务是否正常运行Springcloud 的一些其他模块 (比如Zuul) 就可以通过EurekaServer来发现系统中的其他微服务并执行相关的逻辑. 和Dubbo架构对比.
(2).Eureka的两个组件
Eureka 包含两个组件Eureka Server 和 Eureka Client.Eureka Server 提供服务注册各个节点启动后回在EurekaServer中进行注册这样Eureka Server中的服务注册表中将会储存所有课用服务节点的信息服务节点的信息可以在界面中直观的看到。Eureka Client 是一个Java客户端用于简化EurekaServer的交互客户端同时也具备一个内置的使用轮询负载算法的负载均衡器。在应用启动后将会向EurekaServer发送心跳 (默认周期为30秒) 。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳Eureka Server将会从服务注册表中把这个服务节点移除掉 (默认周期为90s)。
(3).Eureka的三大角色
Eureka Server提供服务的注册与发现Service Provider服务生产方将自身服务注册到Eureka中从而使服务消费方能狗找到Service Consumer服务消费方从Eureka中获取注册服务列表从而找到消费服务
3.构建步骤
1.建立SpringCloud-Eureka-7001普通Maven模块
(1).第一步: 导入依赖
2.配置pom.xml依赖 !-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server --
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka-server/artifactIdversion1.4.6.RELEASE/version
/dependency
!-- 热部署工具 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactId/dependency(2).第二步: 配置yaml
3.applocation.yaml 这里的配置主要是: 服务主机设置、设置注册中心、端口号、以及动态设置监控页面
# 配置服务端口号
server:port: 7001
#Eureka 尤瑞卡
eureka:instance:hostname: localhost #Eureka服务端的实列名称client:register-with-eureka: false #表示是否向Eureka注册中心注册自己fetch-registry: false #如果为false,则表示自己为注册中心service-url: # 监控页面defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #动态编写 http://localhost:7001/eureka/4.源码中的端口默认值为8761所以我们要重写这个方法 this.serviceUrl.put(defaultZone, http://localhost:8761/eureka/);(3).第三步: 开启服务
5.开启服务
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;SpringBootApplicationEnableEurekaServer // 步骤三: 开启服务
public class EurekaServer_7001 {public static void main(String[] args) {SpringApplication.run(EurekaServer_7001.class,args);}
}4.项目构建四大步骤⭐
6.构建项目的思路
1.导入相关依赖2.编写配置文件 (配置文件的时候,里面的内容 约定大于配置)3.开启这个功能 (EnableXXX)4.配置类
5.服务注册-信息配置-自我保护机制
(1).Eureka-client (服务注册-服务端)
调整之前创建的springlouc-provider-dept-800 1.导入Eureka的依赖 这里是普通的Eureka依赖
!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka --
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka/artifactIdversion1.4.6.RELEASE/version
/dependency
2.application中新增Eureca配置 主要解决的问题是: 服务端注册到哪一个注册中心去? # Eureka 服务注册到哪里?
eureka:client:service-url:defaultZone: http://localhost:7001/eureka/3.开启服务 EnableEurekaClient 和注册中心的开启服务注解不一样
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;//启动类
SpringBootApplication
// 开启服务
EnableEurekaClient
public class DeptProvider_8001 {public static void main(String[] args) {SpringApplication.run(DeptProvider_8001.class,args);}
}
4.先启动7001服务端后启动8081客户端进行测试然后访问监控页http://localhost:7001/ 产看结果如图成功 首次启动7001端口—》注册中心 然后启动8081端口–服务端 刷新注册中心 7001 8081服务端的 application.yaml 修改两个配置信息配置⭐ (2).Eureka (信息配置)
1.导入监控配置在服务端8081 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency2.进行配置数据
server:port: 8081
# Mybatis的配置
mybatis:type-aliases-package: com.jsxs.pojomapper-locations: classpath:mybatis/mapper/*.xml# Spring的配置
spring:application:name: SpringCloud-provider-deptdatasource:url: jdbc:mysql://localhost:3306/db01?useUnicodetruecharacterEncodingutf-8username: rootpassword: 121788driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource# Eureka 服务注册到哪里?
eureka:client:service-url:defaultZone: http://localhost:7001/eureka/instance:instance-id: jsxs-01# info配置
info:app.name: jsxs-springcloudcompany.name: pdd3.进行启动测试: 先7001(注册中心),然后8081(服务端)
4.出现下面这个问题的一般是下载了VM ware等类似软件的出现了多张网卡。
微服务向eureka注册中心注册时显示的IP地址不正常全部是localhost或者主机名称。正常情况下应该显示的为微服务所在服务器的IP地址
由于服务器配备了多网卡的原因导致eureka在发现微服务时无法确定微服务所注册的是哪张网卡所以会默认显示为localhost或者主机名称。
需要在配置文件中忽略网卡对注册中心的影响 正常情况下是访问不了这个网址的: 但是如果添加了以下的配置(注册中心7001)那么就可以访问了
#Npcap Loopback Adapter为忽略的网卡名称
spring:cloud:inetutils:ignored-interfaces[0]: Npcap Loopback Adapterhttp://laptop-a930e2o7:8081/actuator/info
(3).Eureka (自我保护机制: 好死不如赖活着)
这里我们关闭服务端-》也就是服务注册的过程(8081)。并不是注册中心(7001) 一句话总结就是某时刻某一个微服务不可用eureka不会立即清理依旧会对该微服务的信息进行保存
默认情况下当eureka server在一定时间内没有收到某个微服务实例的心跳eureka server便会把该实例从注册表中删除默认是90秒但是如果短时间内丢失大量的实例心跳便会触发eureka server的自我保护机制比如在开发测试时需要频繁地重启微服务实例但是我们很少会把eureka server一起重启因为在开发过程中不会修改eureka注册中心当一分钟内收到的心跳数大量减少时会触发该保护机制。可以在eureka管理界面看到Renews threshold和Renews(last min)当后者最后一分钟收到的心跳数小于前者心跳阈值的时候触发保护机制会出现红色的警告EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEYRE NOT.RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEGING EXPIRED JUST TO BE SAFE.从警告中可以看到eureka认为虽然收不到实例的心跳但它认为实例还是健康的eureka会保护这些实例不会把它们从注册表中删掉。【默认情况下如果EurekaServer在一 定时间内没有接收到某 个微服务实例的心跳EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生时微服务与Eureka之间无法正常通行以上行为可能变得非常危险了-因为微服务本身其实是健康的此时本不应该注销这个服务。Eureka通过 自我保护机制来解决这个问题–当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障)么这个节点就会进入自我保护模式。- .旦进入该模式 EurekaServer就会保护服务注册表中的信息不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后该EurekaServer节 点会自动退出自我保护模式。】该保护机制的目的是避免网络连接故障在发生网络故障时微服务和注册中心之间无法正常通信但服务本身是健康的不应该注销该服务如果eureka因网络故障而把微服务误删了那即使网络恢复了该微服务也不会重新注册到eureka server了因为只有在微服务启动的时候才会发起注册请求后面只会发送心跳和服务列表请求这样的话该实例虽然是运行着但永远不会被其它服务所感知。所以eureka server在短时间内丢失过多的客户端心跳时会进入自我保护模式该模式下eureka会保护注册表中的信息不在注销任何微服务当网络故障恢复后eureka会自动退出保护模式。自我保护模式可以让集群更加健壮。在自我保护模式中EurekaServer会保护服务注册表中的信息 不再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时该EurekaServer节点就会自动退出自我保护模式。它的设计哲学就是宁可保留错误的服务注册信息也不盲目注销任何可能健康的服务实例。一句话: 好死不如赖活着。综上自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留) 也不盲目注销任何健康的微服务。使用自我保护模式可以让Eureka集群更加的健壮和稳定但是我们在开发测试阶段需要频繁地重启发布如果触发了保护机制则旧的服务实例没有被删除这时请求有可能跑到旧的实例中而该实例已经关闭了这就导致请求错误影响开发测试。所以在开发测试阶段我们可以把自我保护模式关闭只需在eureka server配置文件中加上如下配置即可eureka.server.enable-self-preservationfalse【不推荐关闭自我保护机制】
(4). 注册进来的微服务获取一些消息团队开发会用到服务端8081
源码DiscoverClient.java 添加配置
package com.jsxs.controller;import com.jsxs.pojo.Dept;
import com.jsxs.service.DeptService;import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.List;// 提供Restful服务
RestController
public class DeptController {Resourceprivate DeptService deptService;// 获取一些配置信息:Resourceprivate DiscoveryClient discoveryClient;//注册进来的微服务~ ,获取一些消息。GetMapping(/dept/discovery)public Object Discover(){//获取微服务列表的清单ListString string_list discoveryClient.getServices();System.out.println(Discoverstring_list);//得到一个具体的微服务ListServiceInstance instances discoveryClient.getInstances(SPRINGCLOUD-PROVIDER-DEPT);for (ServiceInstance instance : instances) {System.out.println(主机: 端口号: 路径: 实列名字分别是》instance.getHost()\tinstance.getPort()\tinstance.getUri()\tinstance.getServiceId());}return this.discoveryClient;}
}开启注解支持
package com.jsxs;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;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;//启动类
SpringBootApplication
// 开启服务
EnableEurekaClient
// 开启服务发现
EnableDiscoveryClient
public class DeptProvider_8001 {public static void main(String[] args) {SpringApplication.run(DeptProvider_8001.class,args);}
}6. Eureka: 集群环境配置
集群7001需要绑定7002与70037002需要绑定7001与7003以此类推
新建springcloud-eureka-7002、springcloud-eureka-7003 模块
(1).搭建多个模块 (模拟多台电脑)
1.为pom.xml添加依赖 (与springcloud-eureka-7001相同) dependencies!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka-server/artifactIdversion1.4.6.RELEASE/version/dependency!-- 热部署工具 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactId/dependency/dependencies2.application.yml配置(与springcloud-eureka-7001相同)
server:port: 7003# Eureka配置
eureka:instance:hostname: localhost # Eureka服务端的实例名字client:register-with-eureka: false # 表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要)fetch-registry: false # fetch-registry如果为false,则表示自己为注册中心service-url: # 监控页面~# 重写Eureka的默认端口以及访问路径 ---http://localhost:7001/eureka/defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/3.主启动类(与springcloud-eureka-7001相同)
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;SpringBootApplicationEnableEurekaServer // 步骤三: 开启服务
public class EurekaServer_7003 {public static void main(String[] args) {SpringApplication.run(EurekaServer_7003.class,args);}
}(2). 集群成员相互关联
配置一些自定义本机名字找到本机hosts文件并打开
C:\Windows\System32\drivers\etc127.0.0.1 eureka7001.com127.0.0.1 eureka7002.com127.0.0.1 eureka7003.com修改application.yml的配置如图为springcloud-eureka-7001配置springcloud-eureka-7002/springcloud-eureka-7003同样分别修改为其对应的名称即可.开始互相绑定 服务端注册路径: 要同时注册三个的。不能有空格冒号要中文
http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/全部启动测试 7003 7001 7002 7.对比和Zookeeper区别
(1). 回顾CAP原则
关系型数据库 RDBMS (MySQL 、Oracle 、sqlServer) ACID
非关系型数据库 NoSQL (Redis 、MongoDB) CAP
(2).ACID是什么
A (Atomicity) 原子性C (Consistency) 一致性I (Isolation) 隔离性D (Durability) 持久性
(3). CAP是什么?
C (Consistency) 强一致性A (Availability) 可用性P (Partition tolerance) 分区容错性
CAP的三进二CA、AP、CP
(4). CAP理论的核心
一个分布式系统不可能同时很好的满足一致性可用性和分区容错性这三个需求根据CAP原理将NoSQL数据库分成了满足CA原则满足CP原则和满足AP原则三大类 CA单点集群满足一致性可用性的系统通常可扩展性较差 CP满足一致性分区容错的系统通常性能不是特别高 AP满足可用性分区容错的系统通常可能对一致性要求低一些 (5). 作为分布式服务注册中心Eureka比Zookeeper好在哪里
著名的CAP理论指出一个分布式系统不可能同时满足C (一致性) 、A (可用性) 、P (容错性)
由于分区容错性P在分布式系统中是必须要保证的因此我们只能再A和C之间进行权衡。
Zookeeper 保证的是 CP — 满足一致性分区容错的系统通常性能不是特别高Eureka 保证的是 AP — 满足可用性分区容错的系统通常可能对一致性要求低一些
Zookeeper保证的是CP 当向注册中心查询服务列表时我们可以容忍注册中心返回的是几分钟以前的注册信息可用性可以低一些但不能接收服务直接down掉不可用。也就是说服务注册功能对可用性的要求要高于一致性。
但zookeeper会出现这样一种情况当master节点因为网络故障与其他节点失去联系时剩余节点会重新进行leader选举。问题在于选举leader的时间太长30-120s且选举期间整个zookeeper集群是不可用的这就导致在选举期间注册服务瘫痪不可用了。在云部署的环境下因为网络问题使得zookeeper集群失去master节点是较大概率发生的事件虽然服务最终能够恢复但是漫长的选举时间导致注册长期不可用是不可容忍的。
Eureka保证的是AP
Eureka看明白了这一点因此在设计时就优先保证可用性。Eureka各个节点都是平等的几个节点挂掉不会影响正常节点的工作剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时如果发现连接失败则会自动切换至其他节点只要有一台Eureka还在就能保住注册服务的可用性只不过查到的信息可能不是最新的除此之外Eureka还有之中自我保护机制如果在15分钟内超过85%的节点都没有正常的心跳那么Eureka就认为客户端与注册中心出现了网络故障此时会出现以下几种情况
Eureka不在从注册列表中移除因为长时间没收到心跳而应该过期的服务Eureka仍然能够接受新服务的注册和查询请求但是不会被同步到其他节点上 (即保证当前节点依然可用)当网络稳定时当前实例新的注册信息会被同步到其他节点中
因此Eureka可以很好的应对因网络故障导致部分节点失去联系的情况而不会像zookeeper那样使整个注册服务瘫痪
(六)、Ribbon: 负载均衡(基于客户端)
1.负载均衡以及Ribbon Ribbon是什么 Spring Cloud Ribbon 是基于Netflix Ribbon 实现的一套 客户端负载均衡的工具。简单的说Ribbon 是 Netflix 发布的开源项目主要功能是提供客户端的软件负载均衡算法将 Netflix 的中间层服务连接在一起。Ribbon 的客户端组件提供一系列完整的配置项如连接超时、重试等。简单的说就是在配置文件中列出 LoadBalancer (简称LB负载均衡) 后面所有的机器Ribbon 会自动的帮助你基于某种规则 (如简单轮询随机连接等等) 去连接这些机器。我们也容易使用 Ribbon 实现自定义的负载均衡算法 Ribbon能干嘛 这里的服务1 2 3 4 5 对应的是提供者的服务1 2 3 4 5不是Eureka集群
LB即负载均衡 (LoadBalancer) 在微服务或分布式集群中经常用的一种应用。负载均衡简单的说就是将用户的请求平摊的分配到多个服务上从而达到系统的HA (高用)。常见的负载均衡软件有 Nginx、Lvs 等等。 Lvs 前 后 Dubbo、SpringCloud 中均给我们提供了负载均衡SpringCloud 的负载均衡算法可以自定义。负载均衡简单分类
集中式LB
即在服务的提供方和消费方之间使用独立的LB设施如Nginx(反向代理服务器)由该设施负责把访问请求通过某种策略转发至服务的提供方
进程式 LB
将LB逻辑集成到消费方消费方从服务注册中心获知有哪些地址可用然后自己再从这些地址中选出一个合适的服务器。Ribbon 就属于进程内LB它只是一个类库集成于消费方进程消费方通过它来获取到服务提供方的地址
2.集成Ribbon 在客户端 80端口
导入依赖Ribbon和Eureka 提供者和消费者的Eureka是一样的 !-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-ribbon/artifactIdversion1.4.6.RELEASE/version/dependency!-- Eureka --!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka/artifactIdversion1.4.6.RELEASE/version/dependency在application.yml文件中配置Eureka
# Eureka
eureka:client:register-with-eureka: false # 我们不向Eureka中注册自己因为我们是消费者,默认是注册service-url: #到哪里找服务?defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/开启注解服务
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;SpringBootApplication
EnableEurekaClient
public class DeptConsumer_80 {public static void main(String[] args) {SpringApplication.run(DeptConsumer_80.class,args);}
}
配置类 (配置负载均衡) config/config.java
package com.jsxs.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;Configuration // 相当于application.xml文件
public class ConfigBean {LoadBalanced // 配置负载均衡只需要添加一个注解就可以Bean // 把RestTemplate注入到Spring中去public RestTemplate getRestTemplate(){return new RestTemplate();}
}修改控制层对服务层的访问路径
使用Ribbon负载均衡我们这里不应该写死。而应该通过id名(服务提供者)进行获取 SpringCloud-provider-dept // 设置服务层的前缀为常量//private static final String REST_URL_PREFIXhttp://localhost:8081;// 使用Ribbon负载均衡我们这里不应该写死。而应该通过id名(服务提供者)进行获取 SpringCloud-provider-deptprivate static final String REST_URL_PREFIXhttp://SpringCloud-provider-dept;package com.jsxs.controller;import com.jsxs.pojo.Dept;
import org.springframework.stereotype.Controller;
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 javax.annotation.Resource;
import java.util.List;RestController
public class DeptConsumerController {//注意: 这里我们只是引入了实体类的数据并没有引入service接口//思考: 消费者界面不应该存在Dao层也不应该存在Service层,该如何使用服务呢//RestTemplate ... 我们直接调用就行但需要注入到Spring中Resource// (URI url, 实体 map,ClassT responseType) 地址---- 实体 ----返回类型.classprivate RestTemplate restTemplate; // 提供多种便捷访问远程 访问http服务的方法简单的Rest// 设置服务层的前缀为常量//private static final String REST_URL_PREFIXhttp://localhost:8081;// 使用Ribbon负载均衡我们这里不应该写死。而应该通过id名(服务提供者)进行获取 SpringCloud-provider-deptprivate static final String REST_URL_PREFIXhttp://SpringCloud-provider-dept;// 根据id进行数据的查找RequestMapping(/consumer/dept/get/{id})public Dept get(PathVariable(id) Long deptno){return restTemplate.getForObject(REST_URL_PREFIX/dept/queryById/deptno,Dept.class);}// 添加数据RequestMapping(/consumer/dept/add)public boolean add(Dept dept){return restTemplate.postForObject(REST_URL_PREFIX/dept/add,dept,Boolean.class);}// 查找全部数据RequestMapping(/consumer/dept/all)public ListDept all(){return restTemplate.getForObject(REST_URL_PREFIX/dept/all,List.class);}
}
结论: Eureka和Ribbon整合之后客户端可以直接调用不再用关心我们的IP地址和端口号。 为什么? ①因为我们实现了负载均衡所以客户端像跳哪个服务器负载均衡会帮助我们寻找。②我们在controller做了手脚通过注册服务的id进行跳转。
3.使用Ribbon实现负载均衡
流程图:
Ribbon有两个步骤1.去Eureka集群中查找可用的服务列表2.通过负载均衡的算法从服务提供者中选择一个看起来比较OK的
1.新建两个服务提供者Moudlespringcloud-provider-dept-8003、springcloud-provider-dept-8002
CREATE DATABASE db03;
USE db03;
CREATE TABLE dept(deptno BIGINT(20) Not Null PRIMARY KEY AUTO_INCREMENT,dname VARCHAR(60) DEFAULT NULL,db_source VARCHAR(60) DEFAULT NULL
);
INSERT INTO dept(dname,db_source) VALUES(开发部,DATABASE());
INSERT INTO dept(dname,db_source) VALUES(人事部,DATABASE());
INSERT INTO dept(dname,db_source) VALUES(财务部,DATABASE());
INSERT INTO dept(dname,db_source) VALUES(售后部,DATABASE());2.参照springcloud-provider-dept-8001 依次为另外两个Moudle添加pom.xml依赖 、resourece下的mybatis和application.yml配置Java代码
3.启动所有服务测试(根据自身电脑配置决定启动服务的个数)访问http://eureka7001.com:7001/查看结果
4.进行用户访问 第一次刷新 第二次刷新 Eureka 内存 以上这种每次访问http://localhost/consumer/dept/list随机访问集群中某个服务提供者这种情况叫做轮询轮询算法在SpringCloud中可以自定义。
4.自定义负载均衡算法
如何切换或者自定义规则呢
(1).切换系统已有均衡算法
默认的是轮询如果我们需要切换。那么我们就自己配置一个类 Beanpublic IRule myIRule(){return new RandomRule();}1.在springcloud-provider-dept-80模块下的ConfigBean中进行配置切换使用不同的规则
package com.jsxs.config;import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;Configuration // 相当于application.xml文件
public class ConfigBean {// IRule :/*** 1.AvailabilityFilteringRule 先过滤掉奔溃(跳匝)的服务对剩下的服务进行轮询* 2.RoundRobinRule 轮询 《默认》* 3 .RoundRobinRule 随机* 4. RetryRule 会先按照轮询获取服务~,如果服务获取失败,则会在指定的时间内运行。**/LoadBalanced // 配置负载均衡只需要添加一个注解就可以Bean // 把RestTemplate注入到Spring中去public RestTemplate getRestTemplate(){return new RestTemplate();}// 启用随机作为Ribbon的算法Beanpublic IRule myIRule(){return new RandomRule();}
}2.启动测试: 发现真的变成随机负载了。
(2).自定义负载均衡算法
1.切记我们自定义的负载均衡算法不能被Spring扫描到。所以我们自定义的算法需要放在启动类的上一级
自定义的算法会覆盖默认的算法均衡
FooConfiguration必须是Configuration但请注意它不在主应用程序上下文的ComponentScan
中否则将由所有RibbonClients共享。如果您使用ComponentScan或SpringBootApplication
则需要采取措施避免包含例如将其放在一个单独的不重叠的包中或者指定要在ComponentScan。2.自定义配置的java文件 murule/JsxsRandomRule.java
package com.myrule;import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;import java.util.List;
import java.util.concurrent.ThreadLocalRandom;public class JsxsRandomRule extends AbstractLoadBalancerRule {public JsxsRandomRule() {}SuppressWarnings({RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE})public Server choose(ILoadBalancer lb, Object key) {if (lb null) {return null;} else {Server server null;while(server null) {if (Thread.interrupted()) {return null;}ListServer upList lb.getReachableServers(); // 获得活着的服务ListServer allList lb.getAllServers(); // 获得全部的服务int serverCount allList.size(); //if (serverCount 0) {return null;}int index this.chooseRandomInt(serverCount); //生成随机数server (Server)upList.get(index); //从活着的服务中随机获取一个if (server null) {Thread.yield();} else {if (server.isAlive()) {return server;}server null;Thread.yield();}}return server;}}protected int chooseRandomInt(int serverCount) {return ThreadLocalRandom.current().nextInt(serverCount);}public Server choose(Object key) {return this.choose(this.getLoadBalancer(), key);}public void initWithNiwsConfig(IClientConfig clientConfig) {}
}3.在启动类上声明注解
package com.jsxs;import com.myrule.JsxsRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;SpringBootApplication
EnableEurekaClient
// 在微服务启动的时候就会加载我们自定义的均衡算法。
RibbonClient(name SpringCloud-provider-dept,configuration JsxsRule.class) // 服务端的ID名 自定义配置的类
public class DeptConsumer_80 {public static void main(String[] args) {SpringApplication.run(DeptConsumer_80.class,args);}
}切换成我们自定义的负载均衡 myrule/JsxsRule.java
package com.myrule;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 JsxsRule {// 启用随机作为Ribbon的算法Beanpublic IRule myIRule(){return new JsxsRandomRule();}
}
5.测试无误。
(七)、Feign负载均衡 基于客户端
1.Feign简介
Ribbon基于客户端。
Feign是声明式Web Service客户端它让微服务之间的调用变得更简单类似controller调用service。
SpringCloud集成了Ribbon和Eureka也可以使用Feigin提供负载均衡的http客户端。
Feign就是在Ribbon的基础上加了一层将**使用方式转变为面向接口变成的方式**
只需要创建一个接口然后添加注解即可~
Feign主要是社区版大家都习惯面向接口编程。这个是很多开发人员的规范。调用微服务访问两种方法
微服务名字 【ribbon 是通过微服务名字去访问】接口和注解 【feign】
(1).Feign能干什么
Feign旨在使编写Java Http客户端变得更容易前面在使用Ribbon RestTemplate时利用RestTemplate对Http请求的封装处理形成了一套模板化的调用方法。但是在实际开发中由于对服务依赖的调用可能不止一处往往一个接口会被多处调用所以通常都会针对每个微服务自行封装一个客户端类来包装这些依赖服务的调用。所以Feign在此基础上做了进一步的封装由他来帮助我们定义和实现依赖服务接口的定义在Feign的实现下我们只需要创建一个接口并使用注解的方式来配置它 (类似以前Dao接口上标注Mapper注解现在是一个微服务接口上面标注一个Feign注解)即可完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon 时自动封装服务调用客户端的开发量
Feign默认集成了Ribbon
利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息并且通过轮询实现了客户端的负载均衡而与Ribbon不同的是通过Feign只需要定义服务绑定接口且以声明式的方法优雅而简单的实现了服务调用。
(2).Feign的使用步骤 创建springcloud-consumer-fdept-feign模块 拷贝springcloud-consumer-dept-80模块下的pom.xmlresource以及java代码到springcloud-consumer-feign模块并添加feign依赖分别在SpringCloud-api模块和SpringCloud-consumer-dept-feign (80)模块。
!--Feign的依赖--
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-feign/artifactIdversion1.4.6.RELEASE/version
/dependency进行配置在SpringCloud-api模块下创建 service/DeptClientServer.java并添加注解 接口
package com.jsxs.service;import com.jsxs.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;import java.util.List;
FeignClient(value SpringCloud-provider-dept) //feign接口里面的值是微服务的服务提供者ID名
public interface DeptClientServer { //接口GetMapping(/dept/add)public boolean addDept(Dept dept);GetMapping(/dept/get/{id})public Dept queryById(PathVariable(id) Long deptno);GetMapping(/dept/all)public ListDept all();
}
通过Ribbon实现原来的controllerDeptConsumerController.java (80)
package com.jsxs.controller;import com.jsxs.pojo.Dept;
import org.springframework.stereotype.Controller;
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 javax.annotation.Resource;
import java.util.List;RestController
public class DeptConsumerController {//注意: 这里我们只是引入了实体类的数据并没有引入service接口//思考: 消费者界面不应该存在Dao层也不应该存在Service层,该如何使用服务呢//RestTemplate ... 我们直接调用就行但需要注入到Spring中Resource// (URI url, 实体 map,ClassT responseType) 地址---- 实体 ----返回类型.classprivate RestTemplate restTemplate; // 提供多种便捷访问远程 访问http服务的方法简单的Rest// 设置服务层的前缀为常量//private static final String REST_URL_PREFIXhttp://localhost:8081;// 使用Ribbon负载均衡我们这里不应该写死。而应该通过id名(服务提供者)进行获取 SpringCloud-provider-deptprivate static final String REST_URL_PREFIXhttp://SpringCloud-provider-dept;// 根据id进行数据的查找RequestMapping(/consumer/dept/get/{id})public Dept get(PathVariable(id) Long deptno){return restTemplate.getForObject(REST_URL_PREFIX/dept/queryById/deptno,Dept.class);}// 添加数据RequestMapping(/consumer/dept/add)public boolean add(Dept dept){return restTemplate.postForObject(REST_URL_PREFIX/dept/add,dept,Boolean.class);}// 查找全部数据RequestMapping(/consumer/dept/all)public ListDept all(){return restTemplate.getForObject(REST_URL_PREFIX/dept/all,List.class);}
}
5 . 通过Feign实现 改造后controllerDeptConsumerController.java 80
这里的this 是 DeptConsumerController
package com.jsxs.controller;import com.jsxs.pojo.Dept;
import com.jsxs.service.DeptClientServer;
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 javax.annotation.Resource;
import java.util.List;RestController
public class DeptConsumerController {Resourceprivate DeptClientServer deptClientServernull;RequestMapping(/consumer/dept/get/{id})public Dept get(PathVariable(id) Long deptno){return this.deptClientServer.queryById(deptno);}// 添加数据RequestMapping(/consumer/dept/add)public boolean add(Dept dept){System.out.println(this-------------);return this.deptClientServer.addDept(dept);}// 查找全部数据RequestMapping(/consumer/dept/all)public ListDept all(){System.out.println(this-------------);return this.deptClientServer.all();}
}Feign和Ribbon二者对比前者显现出面向接口编程特点代码看起来更清爽而且Feign调用方式更符合我们之前在做SSM或者SprngBoot项目时Controller层调用Service层的编程习惯
6.启动类设置开启
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;SpringBootApplication
EnableEurekaClient
EnableFeignClients(basePackages {com.jsxs})
// 在微服务启动的时候就会加载我们自定义的均衡算法。
public class FeignDeptConsumer_80 {public static void main(String[] args) {SpringApplication.run(FeignDeptConsumer_80.class,args);}
}成功 2. Ribbon与Feign如何选择?
根据个人习惯而定如果喜欢REST风格使用Ribbon如果喜欢社区版的面向接口风格使用Feign.
Feign 本质上也是实现了 Ribbon只不过后者是在调用方式上为了满足一些开发者习惯的接口调用习惯Feign 的作用就是替代原先Ribbon在Controller层中RestTemplate使代码的可读性变高但是性能变低了。
(八)、Hystrix:服务熔断 分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系每个依赖关系在某些时候将不可避免失败
1.服务雪崩
多个微服务之间调用的时候假设微服务A调用微服务B和微服务C微服务B和微服务C又调用其他的微服务这就是所谓的“扇出”如果扇出的链路上某个微服务的调用响应时间过长或者不可用对微服务A的调用就会占用越来越多的系统资源进而引起系统崩溃所谓的“雪崩效应”。
对于高流量的应用来说单一的后端依赖可能会导致所有服务器上的所有资源都在几十秒内饱和。比失败更糟糕的是这些应用程序还可能导致服务之间的延迟增加备份队列线程和其他系统资源紧张导致整个系统发生更多的级联故障这些都表示需要对故障和延迟进行隔离和管理以达到单个依赖关系的失败而不影响整个应用程序或系统运行。
我们需要弃车保帅
2.什么是Hystrix
Hystrix是一个应用于处理分布式系统的延迟和容错的开源库在分布式系统里许多依赖不可避免的会调用失败比如超时异常等Hystrix 能够保证在一个依赖出问题的情况下不会导致整个体系服务失败避免级联故障以提高分布式系统的弹性。
“断路器”本身是一种开关装置当某个服务单元发生故障之后通过断路器的故障监控 (类似熔断保险丝) 向调用方返回一个服务预期的可处理的备选响应 (FallBack) 而不是长时间的等待或者抛出调用方法无法处理的异常这样就可以保证了服务调用方的线程不会被长时间不必要的占用从而避免了故障在分布式系统中的蔓延乃至雪崩。
3.Hystrix能干嘛
服务降级服务熔断服务限流接近实时的监控 …
当一切正常时请求流可以如下所示 当许多后端系统中有一个潜在阻塞服务时它可以阻止整个用户请求 随着大容量通信量的增加单个后端依赖项的潜在性会导致所有服务器上的所有资源在几秒钟内饱和。
应用程序中通过网络或客户端库可能导致网络请求的每个点都是潜在故障的来源。比失败更糟糕的是这些应用程序还可能导致服务之间的延迟增加从而备份队列、线程和其他系统资源从而导致更多跨系统的级联故障。 当使用Hystrix包装每个基础依赖项时上面的图表中所示的体系结构会发生类似于以下关系图的变化。每个依赖项是相互隔离的限制在延迟发生时它可以填充的资源中并包含在回退逻辑中该逻辑决定在依赖项中发生任何类型的故障时要做出什么样的响应 官网资料https://github.com/Netflix/Hystrix/wiki
4.服务熔断 (提供者下用)
(1).什么是服务熔断?
熔断机制是赌对应雪崩效应的一种微服务链路保护机制。 当扇出链路的某个微服务不可用或者响应时间太长时会进行服务的降级进而熔断该节点微服务的调用快速返回错误的响应信息。检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况当失败的调用到一定阀值缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是HystrixCommand。
服务熔断解决如下问题
当所依赖的对象不稳定时能够起到快速失败的目的快速失败后能够根据一定的算法动态试探所依赖对象是否恢复。
(2).入门案列
新建springcloud-provider-dept-hystrix-8001模块并拷贝springcloud-provider-dept–8001内的pom.xml、resource和Java代码进行初始化并调整。导入hystrix依赖 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-hystrix/artifactIdversion1.4.6.RELEASE/version/dependency调整yml配置文件(hystrix-8001)
server:port: 8081
# Mybatis的配置
mybatis:type-aliases-package: com.jsxs.pojomapper-locations: classpath:mybatis/mapper/*.xml# Spring的配置
spring:application:name: SpringCloud-provider-deptdatasource:url: jdbc:mysql://localhost:3306/db01?useUnicodetruecharacterEncodingutf-8username: rootpassword: 121788driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource# Eureka 服务注册到哪里?
eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: jsxs-01prefer-ip-address: true
# info配置
info:app.name: jsxs-springcloudcompany.name: pddprefer-ip-address: false:
prefer-ip-address: true
修改controller (hystrix-8001)
HystrixCommand
package com.jsxs.controller;import com.jsxs.pojo.Dept;
import com.jsxs.service.DeptService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
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.RestController;import javax.annotation.Resource;
import java.util.List;// 提供Restful服务
RestController
public class DeptController {Resourceprivate DeptService deptService;GetMapping(/dept/queryById/{id})HystrixCommand(fallbackMethod hystrixQueryById) //假如出现错误就选择备选方案的方法public Dept queryById(PathVariable(id) Long id){Dept dept deptService.queryById(id);// 抛出异常if(deptnull){throw new RuntimeException(这个idid不存在该用户! 或者信息不存在);}return dept;}// 备选方案GetMapping(/dept/queryById/{id})public Dept hystrixQueryById(PathVariable(id) Long id){// 这里我们采用了链式编程因为在API中我们设置了链式编程的注解所以这个实体类可以进行链式编程return new Dept().setDeptno(id).setDname(这个idid不存在该用户! 或者信息不存在).setDb_source(无数据库);}
}
为主启动类添加对熔断的支持注解EnableCircuitBreaker
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;//启动类
SpringBootApplication
// 开启服务
EnableEurekaClient
// 开启服务发现
EnableDiscoveryClient
// 添加熔断的支持
EnableCircuitBreaker
public class DeptProvider_Hystrix_8001 {public static void main(String[] args) {SpringApplication.run(DeptProvider_Hystrix_8001.class,args);}
}为主启动类添加对熔断的支持注解EnableCircuitBreaker
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;//启动类
SpringBootApplication
// 开启服务
EnableEurekaClient
// 开启服务发现
EnableDiscoveryClient
// 添加熔断的支持
EnableCircuitBreaker
public class DeptProvider_Hystrix_8001 {public static void main(String[] args) {SpringApplication.run(DeptProvider_Hystrix_8001.class,args);}
}测试 使用了服务熔断 查看已有的编号 查看未有的编号: 会选择备用方案。 而不使用熔断的springcloud-provider-dept–8001模块访问相同地址会出现下面状况:
5.服务降级 服务调用者下用
(1).什么是服务降级
服务降级是指当服务器压力剧增的情况下根据实际业务情况及流量对一些服务和页面有策略的不处理或换种简单的方式处理从而释放服务器资源以保证核心业务正常运作或高效运作。说白了就是尽可能的把系统资源让给优先级高的服务。
资源有限而请求是无限的。如果在并发高峰期不做服务降级处理一方面肯定会影响整体服务的性能严重的话可能会导致宕机某些重要的服务不可用。所以一般在高峰期为了保证核心功能服务的可用性都要对某些服务降级处理。比如当双11活动时把交易无关的服务统统降级如查看蚂蚁深林查看历史订单等等以及退货。
服务降级主要用于什么场景呢当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时为了保证重要或基本的服务能正常运行可以将一些 不重要 或 不紧急 的服务或任务进行服务的 延迟使用 或 暂停使用。
降级的方式可以根据业务来可以延迟服务比如延迟给用户增加积分只是放到一个缓存中等服务平稳之后再执行 或者在粒度范围内关闭服务比如关闭相关文章的推荐。
由上图可得当某一时间内服务A的访问量暴增而B和C的访问量较少为了缓解A服务的压力这时候需要B和C暂时关闭一些服务功能去承担A的部分服务从而为A分担压力叫做服务降级。
(2).服务降级需要考虑的问题
1那些服务是核心服务哪些服务是非核心服务2那些服务可以支持降级那些服务不能支持降级降级策略是什么3除服务降级之外是否存在更复杂的业务放通场景策略是什么
(3).自动降级分类
1超时降级主要配置好超时时间和超时重试次数和机制并使用异步机制探测回复情况2失败次数降级主要是一些不稳定的api当失败调用次数达到一定阀值自动降级同样要使用异步机制探测恢复情况3故障降级比如要调用的远程服务挂掉了网络故障、DNS故障、http服务返回错误的状态码、rpc服务抛出异常则可以直接降级。降级后的处理方案有默认值比如库存服务挂了返回默认现货、兜底数据比如广告挂了返回提前准备好的一些静态页面、缓存之前暂存的一些缓存数据4限流降级秒杀或者抢购一些限购商品时此时可能会因为访问量太大而导致系统崩溃此时会使用限流来进行限制访问量当达到限流阀值后续请求会被降级降级后的处理方案可以是排队页面将用户导流到排队页面等一会重试、无货直接告知用户没货了、错误页如活动太火爆了稍后重试。
当服务器关闭之后用户依然能够访问这个服务器。但是没有数据只有提示。
(4).入门案列
这里的API包相当于客户端的资源包。因为每一个Model都有三层可以显示 也 可以隐藏
在springcloud-api模块下的service包中新建降级配置DeptClientServiceFallBackFactory.java
package com.jsxs.service;import com.jsxs.pojo.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Service;import java.util.List;/**** 服务降级的操作*/
Servicepublic class DeptClientServerFallback implements FallbackFactory {Overridepublic DeptClientServer create(Throwable throwable) {return new DeptClientServer() { // 因为不能new一个接口,所以我们应该new接口的实现类Overridepublic boolean addDept(Dept dept) {return false;}Overridepublic Dept queryById(Long deptno) {return new Dept().setDeptno(deptno).setDb_source(无数据库).setDname(iddeptno没有用户的信息客户端提供了降级的服务,这个服务已关闭);}Overridepublic ListDept all() {return null;}};}
}在DeptClientService中指定降级配置类DeptClientServiceFallBackFactory
FeignClient(value SpringCloud-provider-dept,fallbackFactory DeptClientServerFallback.class) //feign接口里面的值是微服务的服务提供者ID名 ,绑定服务降级package com.jsxs.service;import com.jsxs.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;import java.util.List;
FeignClient(value SpringCloud-provider-dept,fallbackFactory DeptClientServerFallback.class) //feign接口里面的值是微服务的服务提供者ID名 ,绑定服务降级
public interface DeptClientServer { //接口GetMapping(/dept/add)public boolean addDept(Dept dept);GetMapping(/dept/get/{id})public Dept queryById(PathVariable(id) Long deptno);GetMapping(/dept/all)public ListDept all();
}
在springcloud-consumer-dept-feign-80模块(Feign客户端)中开启降级
server:port: 80# Eureka
eureka:client:register-with-eureka: false # 我们不向Eureka中注册自己因为我们是消费者,默认是注册service-url: #defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/# 开启服务降级 feign.hystrix
feign:hystrix:enabled: true测试:(服务端客户端feign注册中心) 这里我们可能会出现一直访问服务降级的操作并无大碍。可以通过测试all和get 开启服务端 关闭提供者(服务端) 访问/dept/get/? 总结:
6. 服务熔断和降级的区别
服务熔断—服务端某个服务超时或异常引起熔断~类似于保险丝(自我熔断)服务降级—客户端从整体网站请求负载考虑当某个服务熔断或者关闭之后服务将不再被调用此时在客户端我们可以准备一个 FallBackFactory 返回一个默认的值(缺省值)。会导致整体的服务下降但是好歹能用比直接挂掉强。触发原因不太一样服务熔断一般是某个服务下游服务故障引起而服务降级一般是整体负荷考虑管理目标的层次不太一样熔断其实是一个框架级的处理每个微服务都需要无层级之分而降级一般需要对业务有层级之分比如降级一般是从最外围服务开始实现方式不太一样服务降级具有代码侵入性(由控制器完成/或自动降级)熔断一般称为自我熔断。
熔断降级限流
限流限制并发的请求访问量超过阈值则拒绝
降级服务分优先级牺牲非核心服务不可用保证核心服务稳定从整体负荷考虑
熔断依赖的下游服务故障触发熔断避免引发本系统崩溃系统自动执行和恢复
7.Dashboard 流监控
(1).详细步骤
1.新建springcloud-consumer-hystrix-dashboard-9001模块 2.添加依赖 dependenciesdependencygroupIdcom.jsxs/groupIdartifactIdSpringCloud-api/artifactIdversion1.0-SNAPSHOT/version/dependency!-- hystrix-dashboard --!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix-dashboard --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-hystrix-dashboard/artifactIdversion2.2.5.RELEASE/version/dependency!-- hystrix 依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-hystrix/artifactIdversion2.2.5.RELEASE/version/dependency!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-ribbon/artifactIdversion1.4.6.RELEASE/version/dependency!-- Eureka --!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka/artifactIdversion1.4.6.RELEASE/version/dependency!-- 热部署工具--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency/dependencies3.配置文件
server: port: 90014.服务端(提供者必须要有这个依赖)-hystrix-8001这个模块 !-- 监控信息--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency!-- hystrix 依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-hystrix/artifactIdversion2.2.5.RELEASE/version/dependency5.访问http://localhost:9001/hystrix 启动 7001 hystrix-8001 9001 http://localhost:8081/dept/queryById/1 -》先get http://localhost:8081/actuator/hystrix.stream -》查看ping 进入监控页面 监控它 http://localhost:8081/actuator/hystrix.stream 如果出现上面的情况我们需要在9001配置这样的 hystrix:dashboard:proxy-stream-allow-list: *然后再次重新启动发现,如果我们不刷新那么他就会慢慢变小
(2).介绍
一圈
实心圆 公有两种含义,他通过颜色的变化代表了实例的健康程度它的健康程度从绿色黄色橙色红色递减该实心圆除了颜色的变化之外它的大小也会根据实例的请求流量发生变化流量越大,该实心圆就越大所以通过该实心圆的展示就可以在大量的实例中快速发现故障实例和高压力实例。
一线
曲线用来记录2分钟内流量的相对变化可以通过它来观察到流量的上升和下降趋势!
(九)、 Zull路由网关
1.概述 什么是zuul? Zull包含了对请求的路由(用来跳转的)和过滤两个最主要功能
其中路由功能负责将外部请求转发到具体的微服务实例上是实现外部访问统一入口的基础之前我们在测试过程中地址都是http://localhost:8001/dept/get/1 当然端口号还有8002、8003但是实际我们应该把localhost:8001 这一部分隐藏起来真实服务的地址不应该暴露出去例如我们可以设置为http://www.jsxs.com/dept/get/1做一个统一的访问地址。
而过滤器功能则负责对请求的处理过程进行干预是实现请求校验服务聚合等功能的基础。
Zuul和Eureka进行整合将Zuul自身注册为Eureka服务治理下的应用同时从Eureka中获得其他服务的消息也即以后的访问微服务都是通过Zuul跳转后获得。zull管理这些服务然后zull注册到Eureka中 注意Zuul 服务最终还是会注册进 Eureka
提供代理 路由 过滤 三大功能 Zuul 能干嘛 路由过滤官方文档https://github.com/Netflix/zuul/
2.开始运用Zuul路由网关
这里的微服务名字一定要全部小写!!!!!! 新建springcloud-zuul-9527模块并导入依赖 dependenciesdependencygroupIdcom.jsxs/groupIdartifactIdSpringCloud-api/artifactIdversion1.0-SNAPSHOT/version/dependency!-- zuul 依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-zuul/artifactIdversion2.2.5.RELEASE/version/dependency!-- hystrix-dashboard --!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix-dashboard --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-hystrix-dashboard/artifactIdversion2.2.5.RELEASE/version/dependency!-- hystrix 依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-hystrix/artifactIdversion2.2.5.RELEASE/version/dependency!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-ribbon/artifactIdversion1.4.6.RELEASE/version/dependency!-- Eureka --!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka/artifactIdversion1.4.6.RELEASE/version/dependency!-- 热部署工具--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency/dependenciesapplication.yml
server:port: 9527
# 给这个微服务起个名字
spring:application:name: SpringCloud-zuul
# Eureka# 服务注册到哪里
eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: zuul9527.com # 更改描述信息prefer-ip-address: true # 显示IP地址
# 展示信息
info:app.name: Jsxscompany.name: PDD主启动类
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;SpringBootApplication
EnableZuulProxy // zuul服务代理
public class SpringCloudZuul9527 {public static void main(String[] args) {SpringApplication.run(SpringCloudZuul9527.class,args);}
}开始测试 (7001 hystrix-8001 9527) 1.增加127.0.1的端口
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost127.0.0.1 eureka7001.com127.0.0.1 eureka7002.com127.0.0.1 eureka7003.com127.0.0.1 www.jsxs.com2.查看Eureka 3.利用配置的9527启动hystric-8001的查询项目结果能够查询
http://www.jsxs.com:9527/springcloud-provider-dept/dept/queryById/14.hystrix-8001进行启动测试
http://localhost:8081/dept/queryById/1注意: http://www.jsxs.com:9527/SpringCloud-provider-dept/dept/queryById/15.对其设置别名的操作
server:port: 9527
# 给这个微服务起个名字
spring:application:name: SpringCloud-zuul
# Eureka# 服务注册到哪里
eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: zuul9527.com # 更改描述信息prefer-ip-address: true # 显示IP地址
# 展示信息
info:app.name: Jsxscompany.name: PDD
zuul:routes:mydept.serviceId: SpringCloud-provider-dept # 以前是通过这个微服务名进行访问的mydept.path: /mydept/** # 现在我们对其进行配置,使用这个路径来访问我们的网址http://www.jsxs.com:9527/mydept/dept/queryById/1http://www.jsxs.com:9527/springcloud-provider-dept/dept/queryById/16.对其设置为忽略别名
server:port: 9527
# 给这个微服务起个名字
spring:application:name: SpringCloud-zuul
# Eureka# 服务注册到哪里
eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: zuul9527.com # 更改描述信息prefer-ip-address: true # 显示IP地址
# 展示信息
info:app.name: Jsxscompany.name: PDD
zuul:routes:mydept.serviceId: springcloud-provider-dept # 以前是通过这个微服务名进行访问的mydept.path: /mydept/** # 现在我们对其进行配置,使用这个路径来访问我们的网址ignored-services: springcloud-provider-dept # 不能再使用这个网址访问了http://www.jsxs.com:9527/springcloud-provider-dept/dept/queryById/1http://www.jsxs.com:9527/mydept/dept/queryById/17.添加公共前缀 /jsxs
server:port: 9527
# 给这个微服务起个名字
spring:application:name: SpringCloud-zuul
# Eureka# 服务注册到哪里
eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: zuul9527.com # 更改描述信息prefer-ip-address: true # 显示IP地址
# 展示信息
info:app.name: Jsxscompany.name: PDD
zuul:routes:mydept.serviceId: springcloud-provider-dept # 以前是通过这个微服务名进行访问的mydept.path: /mydept/** # 现在我们对其进行配置,使用这个路径来访问我们的网址ignored-services: springcloud-provider-dept # 不能再使用这个网址访问了
# ignored-services: *prefix: /jsxs #设置公共的前缀http://www.jsxs.com:9527/mydept/dept/queryById/1http://www.jsxs.com:9527/jsxs/mydept/dept/queryById/1我们看到微服务名称被替换并隐藏换成了我们自定义的微服务名称mydept同时加上了前缀jsxs这样就做到了对路由访问的加密处理
详情参考springcloud中文社区zuul组件 :https://www.springcloud.cc/spring-cloud-greenwich.html#_router_and_filter_zuul
(十)、SpringCloud Config
GIT: https://gitee.com/lwt121788/spring-cloud/blob/master/config-dept.yaml Dalston.RELEASE Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server您可以在所有环境中管理应用程序的外部属性。客户端和服务器上的概念映射与Spring Environment和PropertySource抽象相同因此它们与Spring应用程序非常契合但可以与任何以任何语言运行的应用程序一起使用。随着应用程序通过从开发人员到测试和生产的部署流程您可以管理这些环境之间的配置并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git因此它轻松支持标签版本的配置环境以及可以访问用于管理内容的各种工具。很容易添加替代实现并使用Spring配置将其插入。
1.概述
布式系统面临的–配置文件问题
微服务意味着要将单体应用中的业务拆分成一个个子服务每个服务的粒度相对较小因此系统中会出现大量的服务由于每个服务都需要必要的配置信息才能运行所以一套集中式的动态的配置管理设施是必不可少的。spring cloud提供了configServer来解决这个问题我们每一个微服务自己带着一个application.yml那上百个的配置文件修改起来令人头疼 什么是SpringCloud config分布式配置中心 spring cloud config 为微服务架构中的微服务提供集中化的外部支持配置服务器为各个不同微服务应用的所有环节提供了一个中心化的外部配置。
spring cloud config 分为服务端和客户端两部分。
服务端也称为 分布式配置中心它是一个独立的微服务应用用来连接配置服务器并为客户端提供获取配置信息加密解密信息等访问接口。
客户端则是通过指定的配置中心来管理应用资源以及与业务相关的配置内容并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息这样就有助于对环境配置进行版本管理。并且可用通过git客户端工具来方便的管理和访问配置内容。
spring cloud config 分布式配置中心能干嘛
集中式管理配置文件不同环境不同配置动态化的配置更新分环境部署比如 /dev /test /prod /beta /release yaml的多文档快- - -运行期间动态调整配置不再需要在每个服务部署的机器上编写配置文件服务会向配置中心统一拉取配置自己的信息当配置发生变动时服务不需要重启即可感知到配置的变化并应用新的配置将配置信息以REST接口的形式暴露
spring cloud config 分布式配置中心与GitHub整合 由于spring cloud config 默认使用git来存储配置文件 (也有其他方式比如自持SVN 和本地文件)但是最推荐的还是git 而且使用的是 http / https 访问的形式。
2.Git环境搭建
1.码云上创建仓库 2.打开Git命令 在指定的文件夹上克隆仓库,先配置仓库信息 git config --list # 查看git config --global user.name jsxs # 用户名git config --global user.email 226120396111.com #邮箱 开始克隆
git clone gitgitee.com:lwt121788/spring-cloud.git # 克隆命令复制的是SSH手动创建application.yaml 在application.yaml中编写如下的配置
spring:profiles:active: dev
---
spring:profiles: devapplication:name: springcloud-config-dev
---
spring:profiles: testapplication:name: springcloud-config-test按照步骤进行提交到码云上
cd spring-cloud # 进入响应的文件夹git add . # 把所有新改动的文件全部添加上去git status # 查看添加的状态git commit -m first commit #进行提交以及备注git push origin master #进行推送到码云3.服务端链接Git配置
我们需要在远程建立一个仓库springcloud来存放我们的配置先在本地写好然后push到远程仓库。
(1).链接操作
1.新建springcloud-config-server-3344模块导入pom.xml依赖 dependencies!--web--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--config--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-config-server/artifactIdversion2.1.1.RELEASE/version/dependency!-- 监控信息 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency/dependencies2.resource下创建application.yml配置文件Spring Cloud Config服务器从git存储库必须提供为远程客户端提供配置
server:port: 3344
#告诉微服务我是谁
spring:application:name: SpringCloud-config-server#链接远程的仓库cloud:config:server:git:uri: https://gitee.com/lwt121788/spring-cloud.git # 这个链接是HTTPS的不是SSH的
# 不加这个配置会报Cannot execute request on any known server 这个错连接Eureka服务端地址不对
# 或者直接注释掉eureka依赖 这里暂时用不到eureka
#eureka:
# client:
# register-with-eureka: false # 表示不想注册中心中注册自己
# fetch-registry: false #表示是注册中心 3.编写启动类
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;SpringBootApplication
EnableConfigServer
public class configServer3344 {public static void main(String[] args) {SpringApplication.run(configServer3344.class,args);}
}4.如果启动后出现下面的信息我们需要让仓库开源 4.开源之后成功访问到3344,但是因为我们在application.yaml中设置文档块(---)的形式所以我们只有访问它的applicati.name才有效
(2)三种读取方式
1.http://localhost:3344/application-test.yaml 2.http://localhost:3344/application/test/master 3.http://localhost:3344/master/application-test.yaml
4.客户端链接服务端访问远程
在建立客户端之前我们还需要新建一个config-client.ymlpush到远程仓库 config-client.yml文件
spring:profiles:active: dev
---
server:port: 8201
#开发环境
spring:profiles: devapplication:name: SpringCloud-provider-dept# Eureka 服务注册到哪里?
eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
---
server:port: 8202
# 测试环境
spring:profiles: testapplication:name: SpringCloud-provider-dept# Eureka 服务注册到哪里?
eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/新建一个springcloud-config-client-3355模块并导入依赖 dependencies!--config--!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-start --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-config/artifactIdversion2.1.1.RELEASE/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency/dependenciesresources下创建application.yml和bootstrap.yml配置文件 bootstrap.yml 是系统级别的配置
# 系统级别的配置
spring:cloud:config:name: config-client #想要读取Git远程资源的名称 config-client.yamluri: http://localhost:3344 #客户端链接服务端服务端链接Gitprofile: dev #到config-client.yaml哪个生参环境? devlabel: master# 实际上是对访问链接的拆分 http://localhost:3344/application/test/master
application.yml 是用户级别的配置
# 用户级别的配置
spring:application:name: SpringCloud-config-client创建controller包下的ConfigClientController.java 用于测试
package com.jsxs.controller;import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
/*** 假如说我们调用到远程的话下面的信息都能输出成功否则的话我们就会输出失败*/
public class configClientController {// 获取远程的服务名字Value(${spring.application.name})private String applicationName;// 获取远程的注册中心Value(${eureka.client.service-url.defaultZone})private String eurekaServer;// 获取远程的端口Value(${server.port})private String port;RequestMapping(/config)public String getConfig(){return this.applicationName\tthis.eurekaServer\tthis.port;}
}主启动类
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplication
public class configClient3355 {public static void main(String[] args) {SpringApplication.run(configClient3355.class,args);}
}测试
启动服务端Config_server_3344 再启动客户端ConfigClient
http://localhost:3344/config-client-dev.yamlhttp://localhost:8201/config5.远程配置实战测试
本地新建config-dept.yml和config-eureka.yml并提交到码云仓库 config-eureka.yml
# 激活dev
spring:profiles:active: dev
---
# 配置服务端口号
server:port: 7001
# 配置这个块为开发环境
spring:profiles: devapplication:name: SpringCloud-config-eureka
#Eureka 尤瑞卡
eureka:instance:hostname: eureka7001.com #Eureka服务端的实列名称prefer-ip-address: true #以IP地址的方式向eureka进行注册域名变iclient:register-with-eureka: false #表示是否向Eureka注册中心注册自己fetch-registry: false #如果为false,则表示自己为注册中心service-url: # 监控页面# 单机: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #动态编写 http://localhost:7001/eureka/# 集群:(关联)defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
---
# 配置服务端口号
server:port: 7001
# 配置这个块为测试环境
spring:profiles: testapplication:name: SpringCloud-config-eureka
#Eureka 尤瑞卡
eureka:instance:hostname: eureka7001.com #Eureka服务端的实列名称prefer-ip-address: true #以IP地址的方式向eureka进行注册域名变iclient:register-with-eureka: false #表示是否向Eureka注册中心注册自己fetch-registry: false #如果为false,则表示自己为注册中心service-url: # 监控页面# 单机: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #动态编写 http://localhost:7001/eureka/# 集群:(关联)defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/config-dept.yml
spring:profiles:active: dev
---
server:port: 8081
# Mybatis的配置
mybatis:type-aliases-package: com.jsxs.pojomapper-locations: classpath:mybatis/mapper/*.xml# Spring的配置
spring:profiles: dev #开发环境设置为devapplication:name: SpringCloud-config-deptdatasource:url: jdbc:mysql://localhost:3306/db01?useUnicodetruecharacterEncodingutf-8username: rootpassword: 121788driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource# Eureka 服务注册到哪里?
eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: jsxs-01prefer-ip-address: true
# info配置
info:app.name: jsxs-springcloudcompany.name: pdd
---
server:port: 8081
# Mybatis的配置
mybatis:type-aliases-package: com.jsxs.pojomapper-locations: classpath:mybatis/mapper/*.xml# Spring的配置
spring:profiles: test #开发环境设置为testapplication:name: SpringCloud-config-deptdatasource:url: jdbc:mysql://localhost:3306/db02?useUnicodetruecharacterEncodingutf-8username: rootpassword: 121788driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource# Eureka 服务注册到哪里?
eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/instance:instance-id: jsxs-02prefer-ip-address: true
# info配置
info:app.name: jsxs-springcloudcompany.name: pdd(1).启用eureka-7001
新建springcloud-config-eureka-7001模块并将原来的springcloud-eureka-7001模块下的内容拷贝的该模块。 1.导入依赖 dependencies!--config--!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-start --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-config/artifactIdversion2.1.1.RELEASE/version/dependency!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka-server/artifactIdversion1.4.6.RELEASE/version/dependency!-- 热部署工具 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactId/dependency/dependencies2.清空该模块的application.yml配置并新建bootstrap.yml连接远程配置 bootstrap.yaml
# 链接远程
# 系统级别的配置
spring:cloud:config:name: config-eureka #想要读取Git远程资源的名称 config-client.yamluri: http://localhost:3344 #客户端链接服务端服务端链接Gitprofile: dev #到config-client.yaml哪个生参环境? devlabel: master# 实际上是对访问链接的拆分 http://localhost:3344/application/test/master
application.yaml
spring:application:name: EurekaServer_config3.主启动类
package com.jsxs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;SpringBootApplicationEnableEurekaServer // 步骤三: 开启服务
public class EurekaServer_config_7001 {public static void main(String[] args) {SpringApplication.run(EurekaServer_config_7001.class,args);}
}
4.启动 config-7001 3344查看是否能启动Eureka
http://localhost:3344/config-eureka-dev.yamlhttp://localhost:7001/(2).启用config-8081
新建springcloud-config-dept-8001模块并拷贝springcloud-provider-dept-8001的内容 同理导入spring cloud config依赖、清空application.yml 、新建bootstrap.yml配置文件并配置 dependencies!--config--!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-start --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-config/artifactIdversion2.1.1.RELEASE/version/dependency!-- hystrix 依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-hystrix/artifactIdversion2.2.5.RELEASE/version/dependency!-- 监控信息--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency!-- Eureka --!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka/artifactIdversion1.4.6.RELEASE/version/dependency!-- 我们需要拿到实体类所以我们要获取刚才设置的Model -SpringCloud-api --dependencygroupIdcom.jsxs/groupIdartifactIdSpringCloud-api/artifactIdversion1.0-SNAPSHOT/version/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdscopetest/scope/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactId/dependencydependencygroupIdch.qos.logback/groupIdartifactIdlogback-core/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactId/dependency!-- test--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-test/artifactId/dependency!-- jetty--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jetty/artifactId/dependency!-- 热部署工具--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency/dependenciesbootstrap.yml
# 系统级别的配置
spring:cloud:config:name: config-dept #想要读取Git远程资源的名称 config-client.yamluri: http://localhost:3344 #客户端链接服务端服务端链接Gitprofile: dev #到config-client.yaml哪个生参环境? devlabel: master# 实际上是对访问链接的拆分 http://localhost:3344/application/test/master
application.yaml
spring:application:name: SpringCloud-config-dept-8001主启动类
package com.jsxs;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;//启动类
SpringBootApplication
// 开启服务
EnableEurekaClient
// 开启服务发现
EnableDiscoveryClient
public class DeptProviderConfig_8001 {public static void main(String[] args) {SpringApplication.run(DeptProviderConfig_8001.class,args);}}
启动 Config_Server_3344、启动ConfigEurekaServer_7001、启动DeptProvider_8001、 总结通过这个小案例改动eureka与dept发现就是把配置文件改成远程读取的方式其他例如pom文件、controller、启动类什么都没有变化
(十)、汇总