导图社区 SpringCloud终极详解
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。本思维导图全面全方位的对SpringCloud进行终极详解,是学习入门的最好资料!
编辑于2019-11-28 08:31:08SpringCloud
从面试题开始
什么是微服务?
微服务之间是如何独立通讯的
springCloud和Dubbo有哪些区别?
SpringBoot和SpringCloud,请你谈谈对他们的理解
什么是服务熔断?什么是服务降级
微服务的优缺点分别是什么?说下你在项目开发中碰到的坑
你所知道的微服务技术栈有哪些?请列举一二
eureka和zookeeper都可以提供服务注册与发现的功能,请说说两个的区别?
......
微服务概述
是什么
业界大牛马丁.福勒(Martin Fowler) 这样描述微服务: 论文网址: https://martinfowler.com/articles/microservices.html  就目前而言,对于微服务业界并没有一个统一的、标准的定义(While there is no precise definition of this architectural style) 但通常而言, 微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分成一组小的服务,每个服务运行在其独立的自己的进程中,服务之间互相协调、互相配合,为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通(通常是基于HTTP的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储。
技术维度理解
微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底 地去耦合,每一个微服务提供单个业务功能的服务,一个服务做一件事, 从技术角度看就是一种小而独立的处理过程,类似进程概念,能够自行单独启动 或销毁,拥有自己独立的数据库。
课堂作业
微服务架构提出者马丁福勒论文阅读
微服务与微服务架构
微服务 强调的是服务的大小,它关注的是某一个点,是具体解决某一个问题/提供落地对应服务的一个服务应用, 狭意的看,可以看作Eclipse里面的一个个微服务工程/或者Module 微服务架构  微服务架构是⼀种架构模式,它提倡将单⼀应⽤程序划分成⼀组⼩的服务,服务之间互相协调、互相配合,为⽤户提供最终价值。每个服务运⾏在其独⽴的进程中,服务与服务间采⽤轻量级的通信机制互相协作(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进⾏构建,并且能够被独⽴的部署到⽣产环境、类⽣产环境等。另外,应当尽量避免统⼀的、集中式的服务管理机制,对具体的⼀个服务⽽⾔,应根据业务上下⽂,选择合适的语⾔、⼯具对其进⾏构建。
微服务优缺点
优点 每个服务足够内聚,足够小,代码容易理解这样能聚焦一个指定的业务功能或业务需求 开发简单、开发效率提高,一个服务可能就是专一的只干一件事。 微服务能够被小团队单独开发,这个小团队是2到5人的开发人员组成。 微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的。 微服务能使用不同的语言开发。 易于和第三方集成,微服务允许容易且灵活的方式集成自动部署,通过持续集成工具,如Jenkins, Hudson, bamboo 。 微服务易于被一个开发人员理解,修改和维护,这样小团队能够更关注自己的工作成果。无需通过合作才能体现价值。 微服务允许你利用融合最新技术。 微服务只是业务逻辑的代码,不会和HTML,CSS 或其他界面组件混合。 每个微服务都有自己的存储能力,可以有自己的数据库。也可以有统一数据库。 缺点 开发人员要处理分布式系统的复杂性 多服务运维难度,随着服务的增加,运维的压力也在增大 系统部署依赖 服务间通信成本 数据一致性 系统集成测试 性能监控……
微服务技术栈有哪些
微服务条目 落地技术 备注 服务开发 Springboot、Spring、SpringMVC 服务配置与管理 Netflix公司的Archaius、阿里的Diamond等 服务注册与发现 Eureka、Consul、Zookeeper等 服务调用 Rest、RPC、gRPC 服务熔断器 Hystrix、Envoy等 负载均衡 Ribbon、Nginx等 服务接口调用(客户端调用服务的简化工具) Feign等 消息队列 Kafka、RabbitMQ、ActiveMQ等 服务配置中心管理 SpringCloudConfig、Chef等 服务路由(API网关) Zuul等 服务监控 Zabbix、Nagios、Metrics、Spectator等 全链路追踪 Zipkin,Brave、Dapper等 服务部署 Docker、OpenStack、Kubernetes等 数据流操作开发包 SpringCloud Stream(封装与Redis,Rabbit、Kafka等发送接收消息) 事件消息总线 Spring Cloud Bus ......
为什么选择SpringCloud作为微服务架构
选型依据
整体解决方案和框架成熟度
社区热度
可维护性
学习曲线
当前各大IT公司用的微服务架构有哪些?
阿里Dubbo/HSF
京东JSF
新浪微博Motan
当当网DubboX
......
各微服务框架对比

SpringCloud入门概述
是什么
官网说明
 SpringCloud,基于SpringBoot提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件,除了基于NetFlix的开源组件做高度抽象封装之外,还有一些选型中立的开源组件。 SpringCloud利用SpringBoot的开发便利性巧妙地简化了分布式系统基础设施的开发,SpringCloud为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等,它们都可以用SpringBoot的开发风格做到一键启动和部署。 SpringBoot并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包
SpringCloud=分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶
SpringCloud和SpringBoot是什么关系
SpringBoot专注于快速方便的开发单个个体微服务。 SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来, 为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务 SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖的关系. SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。
Dubbo是怎么到SpringCloud的? 哪些优缺点让你去技术选型
目前成熟的互联网架构(分布式+服务治理Dubbo)

我们把SpringCloud VS DUBBO进行一番对比
活跃度
https://github.com/dubbo
https://github.com/spring-cloud
对比结果
 最大区别:SpringCloud抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式。 严格来说,这两种方式各有优劣。虽然从一定程度上来说,后者牺牲了服务调用的性能,但也避免了上面提到的原生RPC带来的问题。而且REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更加合适。 品牌机与组装机的区别 很明显,Spring Cloud的功能比DUBBO更加强大,涵盖面更广,而且作为Spring的拳头项目,它也能够与Spring Framework、Spring Boot、Spring Data、Spring Batch等其他Spring项目完美融合,这些对于微服务而言是至关重要的。使用Dubbo构建的微服务架构就像组装电脑,各环节我们的选择自由度很高,但是最终结果很有可能因为一条内存质量不行就点不亮了,总是让人不怎么放心,但是如果你是一名高手,那这些都不是问题;而Spring Cloud就像品牌机,在Spring Source的整合下,做了大量的兼容性测试,保证了机器拥有更高的稳定性,但是如果要在使用非原装组件外的东西,就需要对其基础有足够的了解。 社区支持与更新力度 最为重要的是,DUBBO停止了5年左右的更新,虽然2017.7重启了。对于技术发展的新需求,需要由开发者自行拓展升级(比如当当网弄出了DubboX),这对于很多想要采用微服务架构的中小软件组织,显然是不太合适的,中小公司没有这么强大的技术能力去修改Dubbo源码+周边的一整套解决方案,并不是每一个公司都有阿里的大牛+真实的线上生产环境测试过。
总结Cloud与Dubbo
问题: 曾风靡国内的开源 RPC 服务框架 Dubbo 在重启维护后,令许多用户为之雀跃,但同时,也迎来了一些质疑的声音。互联网技术发展迅速,Dubbo 是否还能跟上时代?Dubbo 与 Spring Cloud 相比又有何优势和差异?是否会有相关举措保证 Dubbo 的后续更新频率? 人物:Dubbo重启维护开发的刘军,主要负责人之一 刘军,阿里巴巴中间件高级研发工程师,主导了 Dubbo 重启维护以后的几个发版计划,专注于高性能 RPC 框架和微服务相关领域。曾负责网易考拉 RPC 框架的研发及指导在内部使用,参与了服务治理平台、分布式跟踪系统、分布式一致性框架等从无到有的设计与开发过程。  
能干嘛
Distributed/versioned configuration(分布式/版本控制配置)
Service registration and discovery(服务注册与发现)
Routing(路由)
Service-to-service calls(服务到服务的调用)
Load balancing(负载均衡配置)
Circuit Breakers(断路器)
Distributed messaging(分布式消息管理)
。。。。。。
去哪下
官网
http://projects.spring.io/spring-cloud/
参考书
https://springcloud.cc/spring-cloud-netflix.html
本次开发API说明
http://cloud.spring.io/spring-cloud-static/Dalston.SR1/
https://springcloud.cc/spring-cloud-dalston.html
springcloud中国社区
http://springcloud.cn/
springcloud中文网
https://springcloud.cc/
怎么玩
服务的注册与发现(Eureka)
服务消费者(rest+Ribbon)
服务消费者(Feign)
断路器(Hystrix)
断路器监控(Hystrix Dashboard)
路由网关(Zuul)
分布式配置中心(Spring Cloud Config)
消息总线(Spring Cloud Bus)
服务链路追踪(Spring Cloud Sleuth)
。。。。。。
All

SpringCloud国内使用情况
国内公司
阿里云
Rest微服务构建 案例工程模块
总体介绍
承接着我们的springmvc+mybatis+mysql初级高级课程,以Dept部门模块做一个微服务通用案例 Consumer消费者(Client)通过REST调用Provider提供者(Server)提供的服务
已经学习过的知识springmvc

已经学习过的知识mybatis

Maven的分包分模块架构复习
一个简单的Maven模块结构是这样的: ---- app-parent 一个父项目(app-parent)聚合很多子项目(app-util,app-dao,app-service,app-web) |---- pom.xml (pom) | |-------- app-util | |-------- pom.xml (jar) | |-------- app-dao | |-------- pom.xml (jar) | |-------- app-service | |-------- pom.xml (jar) | |-------- app-web |-------- pom.xml (war)
一个Project带着多个Module子模块
MicroServiceCloud父工程(Project)下初次带着3个子模块(Module)
microservicecloud-api
封装的整体entity/接口/公共配置等
microservicecloud-provider-dept-8001
微服务落地的服务提供者
microservicecloud-consumer-dept-80
微服务调用的客户端使用
80端口
80端口是为HTTP(HyperText Transport Protocol)即超文本传输协议开放的 此为上网冲浪使用次数最多的协议,主要用于WWW(World Wide Web)即万维网传输信息的协议。 可以通过HTTP地址(即常说的"网址")加":80"来访问网站, 因为浏览网页服务默认的端口号都是80,因此只需输入网址即可,不用输入":80"了。
直接动手干
本次springCloud版本

构建步骤
microservicecloud 整体父工程Project
新建父工程microservicecloud,切记是Packageing是pom模式

主要是定义POM文件,将后续各个子模块公用的jar包等统一提出来,类似一个抽象父类
POM
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> packaging>pompackaging> properties> project.build.sourceEncoding>UTF-8project.build.sourceEncoding> maven.compiler.source>1.8maven.compiler.source> maven.compiler.target>1.8maven.compiler.target> junit.version>4.12junit.version> log4j.version>1.2.17log4j.version> lombok.version>1.16.18lombok.version> properties> dependencyManagement> dependencies> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-dependenciesartifactId> version>Dalston.SR1version> type>pomtype> scope>importscope> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-dependenciesartifactId> version>1.5.9.RELEASEversion> type>pomtype> scope>importscope> dependency> dependency> groupId>mysqlgroupId> artifactId>mysql-connector-javaartifactId> version>5.0.4version> dependency> dependency> groupId>com.alibabagroupId> artifactId>druidartifactId> version>1.0.31version> dependency> dependency> groupId>org.mybatis.spring.bootgroupId> artifactId>mybatis-spring-boot-starterartifactId> version>1.3.0version> dependency> dependency> groupId>ch.qos.logbackgroupId> artifactId>logback-coreartifactId> version>1.2.3version> dependency> dependency> groupId>junitgroupId> artifactId>junitartifactId> version>${junit.version}version> scope>testscope> dependency> dependency> groupId>log4jgroupId> artifactId>log4jartifactId> version>${log4j.version}version> dependency> dependencies> dependencyManagement> project>
microservicecloud-api 公共子模块Module
新建microservicecloud-api

创建完成后请回到父工程查看pom文件变化
修改POM
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-apiartifactId> dependencies> dependency> groupId>org.projectlombokgroupId> artifactId>lombokartifactId> dependency> dependencies> project>
新建部门Entity且配合lombok使用
package com.atguigu.springcloud.entities; import java.io.Serializable; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; @SuppressWarnings("serial") @NoArgsConstructor @Data @Accessors(chain=true) public class Dept implements Serializablepublicclass Dept implements Serializable //必须序列化 { private Long deptno; //主键 private String dname; //部门名称 private String db_source;//来自那个数据库,因为微服务架构可以一个服务对应一个数据库,同一个信息被存储到不同数据库 public Dept(String dname) { super(); this.dname = dname; } }
mvn clean install后给其它模块引用,达到通用目的。 也即需要用到部门实体的话,不用每个工程都定义一份,直接引用本模块即可。
microservicecloud-provider-dept-8001 部门微服务提供者Module
新建microservicecloud-provider-dept-8001
 
创建完成后请回到父工程查看pom文件变化
POM
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-provider-dept-8001artifactId> dependencies> dependency> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloud-apiartifactId> version>${project.version}version> dependency> dependency> groupId>junitgroupId> artifactId>junitartifactId> dependency> dependency> groupId>mysqlgroupId> artifactId>mysql-connector-javaartifactId> dependency> dependency> groupId>com.alibabagroupId> artifactId>druidartifactId> dependency> dependency> groupId>ch.qos.logbackgroupId> artifactId>logback-coreartifactId> dependency> dependency> groupId>org.mybatis.spring.bootgroupId> artifactId>mybatis-spring-boot-starterartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-jettyartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-webartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-testartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependencies> project>
YML
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径 type-aliases-package: com.atguigu.springcloud.entities # 所有Entity别名类所在包 mapper-locations: - classpath:mybatis/mapper/**/*.xml # mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型 driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动包 url: jdbc:mysql://localhost:3306/cloudDB01 # 数据库名称 username: root password: 123456 dbcp2: min-idle: 5 # 数据库连接池的最小维持连接数 initial-size: 5 # 初始化连接数 max-total: 5 # 最大连接数 max-wait-millis: 200 # 等待连接获取的最大超时时间
工程src/main/resources目录下新建mybatis文件夹后新建mybatis.cfg.xml文件
xml version="1.0" encoding="UTF-8" ?> DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> configuration> settings> setting name="cacheEnabled" value="true"/> settings> configuration>
MySQL创建部门数据库脚本
DROP DATABASE IF EXISTS cloudDB01; CREATE DATABASE cloudDB01 CHARACTER SET UTF8; USE cloudDB01; CREATE TABLE dept ( deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, dname VARCHAR(60), db_source VARCHAR(60) ); 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()); INSERT INTO dept(dname,db_source) VALUES('运维部',DATABASE()); SELECT * FROM dept;
DeptDao部门接口
package com.atguigu.springcloud.dao; import java.util.List; import org.apache.ibatis.annotations.Mapper; import com.atguigu.springcloud.entities.Dept; @Mapper public interface DeptDao { public boolean addDept(Dept dept); public Dept findById(Long id); public List findAll(); }
工程src/main/resources/mybatis目录下新建mapper文件夹后再建DeptMapper.xml
xml version="1.0" encoding="UTF-8" ?> DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> mapper namespace="com.atguigu.springcloud.dao.DeptDao"> select id="findById" resultType="Dept" parameterType="Long"> select deptno,dname,db_source from dept where deptno=#{deptno}; select> select id="findAll" resultType="Dept"> select deptno,dname,db_source from dept; select> insert id="addDept" parameterType="Dept"> INSERT INTO dept(dname,db_source) VALUES(#{dname},DATABASE()); insert> mapper>
DeptService部门服务接口
package com.atguigu.springcloud.service; import java.util.List; import com.atguigu.springcloud.entities.Dept; public interface DeptService { public boolean add(Dept dept); public Dept get(Long id); public List list(); }
DeptServiceImpl部门服务接口实现类
package com.atguigu.springcloud.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.atguigu.springcloud.dao.DeptDao; import com.atguigu.springcloud.entities.Dept; import com.atguigu.springcloud.service.DeptService; @Service public class DeptServiceImpl implements DeptService { @Autowired private DeptDao dao ; @Override public boolean add(Dept dept) { return dao.addDept(dept); } @Override public Dept get(Long id) { return dao.findById(id); } @Override public List list() { return dao.findAll(); } }
DeptController部门微服务提供者REST
package com.atguigu.springcloud.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.atguigu.springcloud.entities.Dept; import com.atguigu.springcloud.service.DeptService; @RestController public class DeptController { @Autowired private DeptService service; @RequestMapping(value="/dept/add",method=RequestMethod.POST) public boolean add(@RequestBody Dept dept) { return service.add(dept); } @RequestMapping(value="/dept/get/{id}",method=RequestMethod.GET) public Dept get(@PathVariable("id") Long id) { return service.get(id); } @RequestMapping(value="/dept/list",method=RequestMethod.GET) public List list() { return service.list(); } }
DeptProvider8001_App主启动类
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DeptProvider8001_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_App.class, args); } }
测试
http://localhost:8001/dept/get/2
http://localhost:8001/dept/list
最终工程展现

microservicecloud-consumer-dept-80 部门微服务消费者Module
新建microservicecloud-consumer-dept-80
POM
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-consumer-dept-80artifactId> description>部门微服务消费者description> dependencies> dependency> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloud-apiartifactId> version>${project.version}version> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-webartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependencies> project>
YML
server: port: 80
com.atguigu.springcloud.cfgbeans包下ConfigBean的编写(类似spring里面的applicationContext.xml写入的注入Bean)
package com.atguigu.springcloud.cfgbeans; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class ConfigBean { @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); } }
com.atguigu.springcloud.controller包下新建DeptController_Consumer部门微服务消费者REST
RestTemplate
是什么
RestTemplate提供了多种便捷访问远程Http服务的方法, 是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集
官网及使用
官网地址 https://docs.spring.io/spring-framework/docs/4.3.7.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html 使用 使用restTemplate访问restful接口非常的简单粗暴无脑。 (url, requestMap, ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。
代码
package com.atguigu.springcloud.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; 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 com.atguigu.springcloud.entities.Dept; @RestController public class DeptController_Consumer { private static final String REST_URL_PREFIX = "http://localhost:8001"; @Autowired private RestTemplate restTemplate; @RequestMapping(value="/consumer/dept/add") public boolean add(Dept dept) { return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add", dept, Boolean.class); } @RequestMapping(value="/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id, Dept.class); } @SuppressWarnings("unchecked") @RequestMapping(value="/consumer/dept/list") public List list() { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list", List.class); } }
DeptConsumer80_App主启动类
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DeptConsumer80_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_App.class, args); } }
测试
http://localhost/consumer/dept/get/2
http://localhost/consumer/dept/list
http://localhost/consumer/dept/add?dname=AI
Eureka服务注册与发现
是什么
 Eureka是什么 Eureka是Netflix的一个子模块,也是核心模块之一。Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务架构来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了。功能类似于dubbo的注册中心,比如Zookeeper。
Netflix在设计Eureka时遵守的就是AP原则
CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得
原理讲解
Eureka的基本架构
Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务注册和发现(请对比Zookeeper)。 Eureka 采用了 C-S 的设计架构。Eureka Server 作为服务注册功能的服务器,它是服务注册中心。 而系统中的其他微服务,使用 Eureka 的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。SpringCloud 的一些其他模块(比如Zuul)就可以通过 Eureka Server 来发现系统中的其他微服务,并执行相关的逻辑。 请注意和Dubbo的架构对比   Eureka包含两个组件:Eureka Server和Eureka Client Eureka Server提供服务注册服务 各个节点启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到 EurekaClient是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)
三大角色
Eureka Server 提供服务注册和发现
Service Provider服务提供方将自身服务注册到Eureka,从而使服务消费方能够找到
Service Consumer服务消费方从Eureka获取注册服务列表,从而能够消费服务
盘点下目前我们的工程情况
总父工程
通用模块api
服务提供者Provider
服务消费者Consumer
构建步骤
microservicecloud-eureka-7001 eureka服务注册中心Module
新建microservicecloud-eureka-7001
POM
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-eureka-7001artifactId> dependencies> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-eureka-serverartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependencies> project>
YML
server: port: 7001 eureka: instance: hostname: localhost #eureka服务端的实例名称 client: register-with-eureka: false #false表示不向注册中心注册自己。 fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务 service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
EurekaServer7001_App主启动类
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer//EurekaServer服务器端启动类,接受其它微服务注册进来 public class EurekaServer7001_App { public static void main(String[] args) { SpringApplication.run(EurekaServer7001_App.class, args); } }
@EnableEurekaServer
测试
http://localhost:7001/
结果页面

No application available 没有服务被发现 O(∩_∩)O 因为没有注册服务进来当然不可能有服务被发现
microservicecloud-provider-dept-8001 将已有的部门微服务注册进eureka服务中心
修改microservicecloud-provider-dept-8001
POM
修改部分
dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-eurekaartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-configartifactId> dependency>
完整内容
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-provider-dept-8001artifactId> dependencies> dependency> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloud-apiartifactId> version>${project.version}version> dependency> org.springframework.cloud spring-cloud-starter-eureka org.springframework.cloud spring-cloud-starter-config dependency> groupId>junitgroupId> artifactId>junitartifactId> dependency> dependency> groupId>mysqlgroupId> artifactId>mysql-connector-javaartifactId> dependency> dependency> groupId>com.alibabagroupId> artifactId>druidartifactId> dependency> dependency> groupId>ch.qos.logbackgroupId> artifactId>logback-coreartifactId> dependency> dependency> groupId>org.mybatis.spring.bootgroupId> artifactId>mybatis-spring-boot-starterartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-jettyartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-webartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-testartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependencies> project>
YML
修改部分
eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://localhost:7001/eureka
完整内容
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路径 type-aliases-package: com.atguigu.springcloud.entities #entity别名类 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://localhost:7001/eureka
DeptProvider8001_App主启动类
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient //本服务启动后会自动注册进eureka服务中 public class DeptProvider8001_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_App.class, args); } }
@EnableEurekaClient
测试
先要启动EurekaServer
http://localhost:7001/

微服务注册名配置说明

actuator与注册微服务信息完善
主机名称:服务名称修改
当前问题
 含有主机名称
修改microservicecloud-provider-dept-8001
YML
修改部分
 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microservicecloud-dept8001
完整内容
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路径 type-aliases-package: com.atguigu.springcloud.entities #entity别名类 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microservicecloud-dept8001
修改之后

访问信息有IP信息提示
当前问题
没有IP提示
修改microservicecloud-provider-dept-8001
YML
修改部分
 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microservicecloud-dept8001 #自定义服务名称信息 prefer-ip-address: true #访问路径可以显示IP地址
完整内容
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路径 type-aliases-package: com.atguigu.springcloud.entities #entity别名类 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microservicecloud-dept8001 #自定义服务名称信息 prefer-ip-address: true #访问路径可以显示IP地址
修改之后

微服务info内容详细信息
当前问题
超链接点击服务报告ErrorPage
修改microservicecloud-provider-dept-8001
POM
修改部分
dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-actuatorartifactId> dependency>
完整内容
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-provider-dept-8001artifactId> dependencies> dependency> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloud-apiartifactId> version>${project.version}version> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-eurekaartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-configartifactId> dependency> org.springframework.boot spring-boot-starter-actuator dependency> groupId>junitgroupId> artifactId>junitartifactId> dependency> dependency> groupId>mysqlgroupId> artifactId>mysql-connector-javaartifactId> dependency> dependency> groupId>com.alibabagroupId> artifactId>druidartifactId> dependency> dependency> groupId>ch.qos.logbackgroupId> artifactId>logback-coreartifactId> dependency> dependency> groupId>org.mybatis.spring.bootgroupId> artifactId>mybatis-spring-boot-starterartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-jettyartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-webartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-testartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependencies> project>
总的父工程microservicecloud修改pom.xml添加构建build信息
POM
修改部分
build> finalName>microservicecloudfinalName> resources> resource> directory>src/main/resourcesdirectory> filtering>truefiltering> resource> resources> plugins> plugin> groupId>org.apache.maven.pluginsgroupId> artifactId>maven-resources-pluginartifactId> configuration> delimiters> delimit>$delimit> delimiters> configuration> plugin> plugins> build>
完整内容
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> packaging>pompackaging> properties> project.build.sourceEncoding>UTF-8project.build.sourceEncoding> maven.compiler.source>1.8maven.compiler.source> maven.compiler.target>1.8maven.compiler.target> junit.version>4.12junit.version> log4j.version>1.2.17log4j.version> lombok.version>1.16.18lombok.version> properties> dependencyManagement> dependencies> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-dependenciesartifactId> version>Dalston.SR1version> type>pomtype> scope>importscope> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-dependenciesartifactId> version>1.5.9.RELEASEversion> type>pomtype> scope>importscope> dependency> dependency> groupId>mysqlgroupId> artifactId>mysql-connector-javaartifactId> version>5.0.4version> dependency> dependency> groupId>com.alibabagroupId> artifactId>druidartifactId> version>1.0.31version> dependency> dependency> groupId>org.mybatis.spring.bootgroupId> artifactId>mybatis-spring-boot-starterartifactId> version>1.3.0version> dependency> dependency> groupId>ch.qos.logbackgroupId> artifactId>logback-coreartifactId> version>1.2.3version> dependency> dependency> groupId>junitgroupId> artifactId>junitartifactId> version>${junit.version}version> scope>testscope> dependency> dependency> groupId>log4jgroupId> artifactId>log4jartifactId> version>${log4j.version}version> dependency> dependencies> dependencyManagement> microservicecloud src/main/resources true org.apache.maven.plugins maven-resources-plugin $ modules> module>microservicecloud-apimodule> module>microservicecloud-provider-dept-8001module> module>microservicecloud-consumer-dept-80module> module>microservicecloud-eureka-7001module> modules> project>
修改microservicecloud-provider-dept-8001
YML
修改部分
info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
完整内容
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路径 type-aliases-package: com.atguigu.springcloud.entities #entity别名类 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microservicecloud-dept8001 #自定义服务名称信息 prefer-ip-address: true #访问路径可以显示IP地址 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
eureka自我保护
演示Case
故障现象
导致原因
什么是自我保护模式? 默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与EurekaServer之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题——当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,EurekaServer就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。 在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时,该Eureka Server节点就会自动退出自我保护模式。它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。一句话讲解:好死不如赖活着 综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。 在Spring Cloud中,可以使用eureka.server.enable-self-preservation = false 禁用自我保护模式。
一句话:某时刻某一个微服务不可用了,eureka不会立刻清理,依旧会对该微服务的信息进行保存
microservicecloud-provider-dept-8001 服务发现Discovery
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息
修改microservicecloud-provider-dept-8001工程的DeptController
package com.atguigu.springcloud.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.atguigu.springcloud.entities.Dept; import com.atguigu.springcloud.service.DeptService; @RestController public class DeptController { @Autowired private DeptService service; @Autowired private DiscoveryClient client; @RequestMapping(value = "/dept/add", method = RequestMethod.POST) public boolean add(@RequestBody Dept dept) { return service.add(dept); } @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET) public Dept get(@PathVariable("id") Long id) { return service.get(id); } @RequestMapping(value = "/dept/list", method = RequestMethod.GET) public List list() { return service.list(); } @RequestMapping(value = "/dept/discovery", method = RequestMethod.GET) public Object discovery() { List list = client.getServices(); System.out.println("**********" + list); List srvList = client.getInstances("MICROSERVICECLOUD-DEPT"); for (ServiceInstance element : srvList) { System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t" + element.getPort() + "\t" + element.getUri()); } return this.client; } }
DeptProvider8001_App主启动类
@SpringBootApplication @EnableEurekaClient //本服务启动后会自动注册进eureka服务中 @EnableDiscoveryClient //服务发现 public class DeptProvider8001_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_App.class, args); } }
@EnableDiscoveryClient
自测
先要启动EurekaServer
再启动DeptProvider8001_App主启动类,需要稍等一会儿
http://localhost:8001/dept/discovery
修改microservicecloud-consumer-dept-80工程的DeptController_Consumer
//测试@EnableDiscoveryClient,消费端可以调用服务发现 @RequestMapping(value="/consumer/dept/discovery") public Object discovery() { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery", Object.class); }
集群配置
原理说明
 基本原理 上图是来自eureka的官方架构图,这是基于集群配置的eureka; - 处于不同节点的eureka通过Replicate进行数据同步 - Application Service为服务提供者 - Application Client为服务消费者 - Make Remote Call完成一次服务调用 服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。 当服务注册中心Eureka Server检测到服务提供者因为宕机、网络原因不可用时,则在服务注册中心将服务置为DOWN状态,并把当前服务提供者状态向订阅者发布,订阅过的服务消费者更新本地缓存。 服务提供者在启动后,周期性(默认30秒)向Eureka Server发送心跳,以证明当前服务是可用状态。Eureka Server在一定的时间(默认90秒)未收到客户端的心跳,则认为服务宕机,注销该实例。
新建microservicecloud-eureka-7002/microservicecloud-eureka-7003
按照7001为模板粘贴POM
修改7002和7003的主启动类
修改映射配置
找到C:\Windows\System32\drivers\etc路径下的hosts文件
修改映射配置添加进hosts文件
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
127.0.0.1 eureka7003.com
3台eureka服务器的yml配置
7001
server: port: 7001 eureka: instance: hostname: eureka7001.com #eureka服务端的实例名称 client: register-with-eureka: false #false表示不向注册中心注册自己。 fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务 service-url: #单机 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址(单机)。 defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
7002
server: port: 7002 eureka: instance: hostname: eureka7002.com #eureka服务端的实例名称 client: register-with-eureka: false #false表示不向注册中心注册自己。 fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务 service-url: #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
7003
server: port: 7003 eureka: instance: hostname: eureka7003.com #eureka服务端的实例名称 client: register-with-eureka: false #false表示不向注册中心注册自己。 fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务 service-url: #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
microservicecloud-provider-dept-8001 微服务发布到上面3台eureka集群配置中
YML
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路径 type-aliases-package: com.atguigu.springcloud.entities #entity别名类 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: microservicecloud-dept8001 #自定义服务名称信息 prefer-ip-address: true #访问路径可以显示IP地址 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
作为服务注册中心,Eureka比Zookeeper好在哪里
作为服务注册中心,Eureka比Zookeeper好在哪里 著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。由于分区容错性P在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡。 因此 Zookeeper保证的是CP, Eureka则是AP。 4.1 Zookeeper保证CP 当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。 4.2 Eureka保证AP Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况: 1. Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务 2. Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用) 3. 当网络稳定时,当前实例新的注册信息会被同步到其它节点中 因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。
Ribbon负载均衡
概述
是什么
Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。
能干吗
LB(负载均衡)
LB,即负载均衡(Load Balance),在微服务或分布式集群中经常用的一种应用。 负载均衡简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA。 常见的负载均衡有软件Nginx,LVS,硬件 F5等。 相应的在中间件,例如:dubbo和SpringCloud中均给我们提供了负载均衡,SpringCloud的负载均衡算法可以自定义。
集中式LB
集中式LB 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;
进程内LB
进程内LB 将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。 Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
官网资料
https://github.com/Netflix/ribbon/wiki/Getting-Started
Ribbon配置初步
修改microservicecloud-consumer-dept-80工程
修改pom.xml文件
内容
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-consumer-dept-80artifactId> description>部门微服务消费者description> dependencies> dependency> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloud-apiartifactId> version>${project.version}version> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-webartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> org.springframework.cloud spring-cloud-starter-eureka org.springframework.cloud spring-cloud-starter-ribbon org.springframework.cloud spring-cloud-starter-config dependencies> project>
修改application.yml 追加eureka的服务注册地址
内容
server: port: 80 eureka: client: register-with-eureka: false service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
对ConfigBean进行新注解@LoadBalanced 获得Rest时加入Ribbon的配置
package com.atguigu.springcloud.cfgbeans; 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 public class ConfigBean { @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } }
主启动类DeptConsumer80_App添加@EnableEurekaClient
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class DeptConsumer80_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_App.class, args); } }
修改DeptController_Consumer客户端访问类
package com.atguigu.springcloud.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; 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 com.atguigu.springcloud.entities.Dept; @RestController public class DeptController_Consumer { //private static final String REST_URL_PREFIX = "http://localhost:8001"; private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT"; @Autowired private RestTemplate restTemplate; @RequestMapping(value="/consumer/dept/add") public boolean add(Dept dept) { return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add", dept, Boolean.class); } @RequestMapping(value="/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id, Dept.class); } @SuppressWarnings("unchecked") @RequestMapping(value="/consumer/dept/list") public List list() { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list", List.class); } //测试@EnableDiscoveryClient,消费端可以调用服务发现 @RequestMapping(value="/consumer/dept/discovery") public Object discovery() { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery", Object.class); } }
先启动3个eureka集群后,再启动microservicecloud-provider-dept-8001并注册进eureka

启动microservicecloud-consumer-dept-80
测试
http://localhost/consumer/dept/get/1
http://localhost/consumer/dept/list
http://localhost/consumer/dept/add?dname=大数据部
小总结
Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心地址和端口号

Ribbon负载均衡
架构说明
 Ribbon在工作时分成两步 第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server. 第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。 其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。
参考microservicecloud-provider-dept-8001,新建两份,分别命名为8002,8003
新建8002/8003数据库,各自微服务分别连各自的数据库
8002SQL脚本
DROP DATABASE IF EXISTS cloudDB02; CREATE DATABASE cloudDB02 CHARACTER SET UTF8; USE cloudDB02; CREATE TABLE dept ( deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, dname VARCHAR(60), db_source VARCHAR(60) ); 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()); INSERT INTO dept(dname,db_source) VALUES('运维部',DATABASE()); SELECT * FROM dept;
8003SQL脚本
DROP DATABASE IF EXISTS cloudDB03; CREATE DATABASE cloudDB03 CHARACTER SET UTF8; USE cloudDB03; CREATE TABLE dept ( deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, dname VARCHAR(60), db_source VARCHAR(60) ); 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()); INSERT INTO dept(dname,db_source) VALUES('运维部',DATABASE()); SELECT * FROM dept;
修改8002/8003各自YML
8002YML
server: port: 8002 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路径 type-aliases-package: com.atguigu.springcloud.entities #entity别名类 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB02 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: microservicecloud-dept8002 #自定义服务名称信息 prefer-ip-address: true #访问路径可以显示IP地址 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
8003YML
server: port: 8003 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路径 type-aliases-package: com.atguigu.springcloud.entities #entity别名类 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB03 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: microservicecloud-dept8003 #自定义服务名称信息 prefer-ip-address: true #访问路径可以显示IP地址 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
备注
端口
数据库链接
对外暴露的统一的服务实例名
启动3个eureka集群配置区
启动3个Dept微服务并各自测试通过
http://localhost:8001/dept/list
http://localhost:8002/dept/list
http://localhost:8003/dept/list
启动microservicecloud-consumer-dept-80
客户端通过Ribbo完成负载均衡并访问上一步的Dept微服务
http://localhost/consumer/dept/list
注意观察看到返回的数据库名字,各不相同,负载均衡实现
总结:Ribbon其实就是一个软负载均衡的客户端组件, 他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。
Ribbon核心组件IRule
IRule:根据特定算法中从服务列表中选取一个要访问的服务
RoundRobinRule
轮询
RandomRule
随机
AvailabilityFilteringRule
会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务, 还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问
WeightedResponseTimeRule
根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。 刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够, 会切换到WeightedResponseTimeRule
RetryRule
先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务
BestAvailableRule
会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
ZoneAvoidanceRule
默认规则,复合判断server所在区域的性能和server的可用性选择服务器
Ribbon自定义
修改microservicecloud-consumer-dept-80
主启动类添加@RibbonClient
在启动该微服务的时候就能去加载我们的自定义Ribbon配置类,从而使配置生效,形如: @RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class)
注意配置细节
官方文档明确给出了警告: 这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下, 否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,也就是说 我们达不到特殊化定制的目的了。 
步骤
新建package com.atguigu.myrule
新建自定义Robbin规则类
package com.atguigu.myrule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.RandomRule; @Configuration public class MySelfRule { @Bean public IRule myRule() { return new RandomRule();//Ribbon默认是轮询,我自定义为随机 } }
修改主启动类
package com.atguigu.springcloud; 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; import com.atguigu.myrule.MySelfRule; @SpringBootApplication @EnableEurekaClient @RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class) public class DeptConsumer80_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_App.class, args); } }
测试
http://localhost/consumer/dept/list
自定义规则深度解析
问题:依旧轮询策略,但是加上新需求,每个服务器要求被调用5次。也即 以前是每台机器一次,现在是每台机器5次
解析源码:https://github.com/Netflix/ribbon/blob/master/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer/RandomRule.java

参考源码修改为我们需求要求的RandomRule_ZY.java
package com.atguigu.myrule; import java.util.List; import java.util.Random; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; public class RandomRule_ZY extends AbstractLoadBalancerRule { private int total = 0; //总共被调用的次数,目前要求每台被调用5次 private int currentIndex = 0;//当前提供服务的机器号 public Server choose(ILoadBalancer lb, Object key) { if (lb == null) { return null; } Server server = null; while (server == null) { if (Thread.interrupted()) { return null; } List upList = lb.getReachableServers(); List allList = lb.getAllServers(); int serverCount = allList.size(); if (serverCount == 0) { /* * No servers. End regardless of pass, because subsequent passes * only get more restrictive. */ return null; } // int index = rand.nextInt(serverCount); // server = upList.get(index); if(total { server = upList.get(currentIndex); total++; }else { total = 0; currentIndex++; if(currentIndex >= upList.size()) { currentIndex = 0; } } if (server == null) { /* * The only time this should happen is if the server list were * somehow trimmed. This is a transient condition. Retry after * yielding. */ Thread.yield(); continue; } if (server.isAlive()) { return (server); } // Shouldn't actually happen.. but must be transient or a bug. server = null; Thread.yield(); } return server; } @Override public Server choose(Object key) { return choose(getLoadBalancer(), key); } @Override public void initWithNiwsConfig(IClientConfig clientConfig) { } }
调用
MySelfRule.java
package com.atguigu.myrule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.RandomRule; @Configuration public class MySelfRule { @Bean public IRule myRule() { //return new RandomRule();//Ribbon默认是轮询,我自定义为随机 return new RandomRule_ZY();//我自定义为每个机器被访问5次 } }
主启动类

测试
http://localhost/consumer/dept/list
Feign负载均衡
概述
官网解释: http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。  ; Feign是一个声明式的Web服务客户端,使得编写Web服务客户端变得非常容易, 只需要创建一个接口,然后在上面添加注解即可。 参考官网:https://github.com/OpenFeign/feign Feign能干什么 Feign旨在使编写Java Http客户端变得更容易。 前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端的开发量。 Feign集成了Ribbon 利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用
Feign使用步骤
参考microservicecloud-consumer-dept-80
新建microservicecloud-consumer-dept-feign
修改主启动类名字
DeptConsumer80_Feign_App
microservicecloud-consumer-dept-feign工程pom.xml修改,主要添加对feign的支持
dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-feignartifactId> dependency>
修改microservicecloud-api工程
POM
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-apiartifactId> dependencies> dependency> groupId>org.projectlombokgroupId> artifactId>lombokartifactId> dependency> org.springframework.cloud spring-cloud-starter-feign dependencies> project>
新建DeptClientService接口并新增注解@FeignClient
package com.atguigu.springcloud.service; import java.util.List; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.atguigu.springcloud.entities.Dept; @FeignClient(value = "MICROSERVICECLOUD-DEPT") public interface DeptClientService { @RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET) public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list",method = RequestMethod.GET) public List list(); @RequestMapping(value = "/dept/add",method = RequestMethod.POST) public boolean add(Dept dept); }
@FeignClient
mvn clean
mvn install
microservicecloud-consumer-dept-feign工程修改Controller,添加上一步新建的DeptClientService接口
package com.atguigu.springcloud.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.atguigu.springcloud.entities.Dept; import com.atguigu.springcloud.service.DeptClientService; @RestController public class DeptController_Feign { @Autowired private DeptClientService service = null; @RequestMapping(value = "/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return this.service.get(id); } @RequestMapping(value = "/consumer/dept/list") public List list() { return this.service.list(); } @RequestMapping(value = "/consumer/dept/add") public Object add(Dept dept) { return this.service.add(dept); } }
microservicecloud-consumer-dept-feign工程修改主启动类
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; @SpringBootApplication @EnableEurekaClient @EnableFeignClients(basePackages= {"com.atguigu.springcloud"}) @ComponentScan("com.atguigu.springcloud") public class DeptConsumer80_Feign_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_Feign_App.class, args); } }
@EnableFeignClients
测试
启动3个eureka集群
启动3个部门微服务8001/8002/8003
启动Feign自己启动
http://localhost/consumer/dept/list
Feign自带负载均衡配置项
小总结
Feign通过接口的方法调用Rest服务(之前是Ribbon+RestTemplate), 该请求发送给Eureka服务器(http://MICROSERVICECLOUD-DEPT/dept/list), 通过Feign直接找到服务接口,由于在进行服务调用的时候融合了Ribbon技术,所以也支持负载均衡作用。
Hystrix断路器
概述
分布式系统面临的问题
分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。  服务雪崩 多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”. 对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。 备注:一般情况对于服务依赖的保护主要有3中解决方案: (1)熔断模式:这种模式主要是参考电路熔断,如果一条线路电压过高,保险丝会熔断,防止火灾。放到我们的系统中,如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。 (2)隔离模式:这种模式就像对系统请求按类型划分成一个个小岛的一样,当某个小岛被火少光了,不会影响到其他的小岛。例如可以对不同类型的请求使用线程池来资源隔离,每种类型的请求互不影响,如果一种类型的请求线程资源耗尽,则对后续的该类型请求直接返回,不再调用后续资源。这种模式使用场景非常多,例如将一个服务拆开,对于重要的服务使用单独服务器来部署,再或者公司最近推广的多中心。 (3)限流模式:上述的熔断模式和隔离模式都属于出错后的容错处理机制,而限流模式则可以称为预防模式。限流模式主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。这种模式不能解决服务依赖的问题,只能解决系统整体资源分配问题,因为没有被限流的请求依然有可能造成雪崩效应。
是什么
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。 “断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
能干嘛
服务降级
备注:Hystrix服务降级,其实就是线程池中单个线程障处理,防止单个线程请求时间太长,导致资源长期被占有而得不到释放,从而导致线程池被快速占用完,导致服务崩溃。 Hystrix能解决如下问题: 1.请求超时降级,线程资源不足降级,降级之后可以返回自定义数据 2.线程池隔离降级,分布式服务可以针对不同的服务使用不同的线程池,从而互不影响 3.自动触发降级与恢复 4.实现请求缓存和请求合并
服务熔断
备注:熔断模式:这种模式主要是参考电路熔断,如果一条线路电压过高,保险丝会熔断,防止火灾。放到我们的系统中,如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。
服务限流
备注:限流模式主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。这种模式不能解决服务依赖的问题,只能解决系统整体资源分配问题,因为没有被限流的请求依然有可能造成雪崩效应。
接近实时的监控
。。。。。。
官网资料
https://github.com/Netflix/Hystrix/wiki/How-To-Use
服务熔断
是什么
服务熔断 熔断机制是应对雪崩效应的一种微服务链路保护机制。 当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回"错误"的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。
参考microservicecloud-provider-dept-8001
新建microservicecloud-provider-dept-hystrix-8001
POM
修改内容
org.springframework.cloud spring-cloud-starter-hystrix
全部内容
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-provider-dept-hystrix-8001artifactId> dependencies> org.springframework.cloud spring-cloud-starter-hystrix dependency> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloud-apiartifactId> version>${project.version}version> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-eurekaartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-configartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-actuatorartifactId> dependency> dependency> groupId>junitgroupId> artifactId>junitartifactId> dependency> dependency> groupId>mysqlgroupId> artifactId>mysql-connector-javaartifactId> dependency> dependency> groupId>com.alibabagroupId> artifactId>druidartifactId> dependency> dependency> groupId>ch.qos.logbackgroupId> artifactId>logback-coreartifactId> dependency> dependency> groupId>org.mybatis.spring.bootgroupId> artifactId>mybatis-spring-boot-starterartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-jettyartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-webartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-testartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependencies> project>
YML
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路径 type-aliases-package: com.atguigu.springcloud.entities #entity别名类 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: microservicecloud-dept8001-hystrix #自定义服务名称信息 prefer-ip-address: true #访问路径可以显示IP地址 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
修改DeptController
@HystrixCommand报异常后如何处理

一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法
代码内容
package com.atguigu.springcloud.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.atguigu.springcloud.entities.Dept; import com.atguigu.springcloud.service.DeptService; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; @RestController public class DeptController { @Autowired private DeptService service = null; @RequestMapping(value="/dept/get/{id}",method=RequestMethod.GET) @HystrixCommand(fallbackMethod = "processHystrix_Get") public Dept get(@PathVariable("id") Long id) { Dept dept = this.service.get(id); if(null == dept) { throw new RuntimeException("该ID:"+id+"没有没有对应的信息"); } return dept; } public Dept processHystrix_Get(@PathVariable("id") Long id) { return new Dept().setDeptno(id) .setDname("该ID:"+id+"没有没有对应的信息,null--@HystrixCommand") .setDb_source("no this database in MySQL"); } }
修改主启动类DeptProvider8001_Hystrix_App并添加新注解@EnableCircuitBreaker
package com.atguigu.springcloud; 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 //本服务启动后会自动注册进eureka服务中 @EnableDiscoveryClient //服务发现 @EnableCircuitBreaker//对hystrixR熔断机制的支持 public class DeptProvider8001_Hystrix_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_Hystrix_App.class, args); } }
测试
3个eureka先启动
主启动类DeptProvider8001_Hystrix_App

Consumer启动microservicecloud-consumer-dept-80
http://localhost/consumer/dept/get/112
 如果对应的ID:112,数据库里面没有这个记录,我们报错后统一返回。
服务降级
是什么
整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来。
服务降级处理是在客户端实现完成的,与服务端没有关系
修改microservicecloud-api工程, 根据已经有的DeptClientService接口新建一个实现了 FallbackFactory接口的类DeptClientServiceFallbackFactory
package com.atguigu.springcloud.service; import java.util.List; import org.springframework.stereotype.Component; import com.atguigu.springcloud.entities.Dept; import feign.hystrix.FallbackFactory; @Component//不要忘记添加,不要忘记添加 public class DeptClientServiceFallbackFactory implements FallbackFactory { @Override public DeptClientService create(Throwable throwable) { return new DeptClientService() { @Override public Dept get(long id) { return new Dept().setDeptno(id) .setDname("该ID:"+id+"没有没有对应的信息,Consumer客户端提供的降级信息,此刻服务Provider已经关闭") .setDb_source("no this database in MySQL"); } @Override public List list() { return null; } @Override public boolean add(Dept dept) { return false; } }; } }
千万不要忘记在类上面新增@Component注解,大坑!!!
修改microservicecloud-api工程,DeptClientService接口在注解@FeignClient中添加fallbackFactory属性值
package com.atguigu.springcloud.service; import java.util.List; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.atguigu.springcloud.entities.Dept; @FeignClient(value = "MICROSERVICECLOUD-DEPT",fallbackFactory=DeptClientServiceFallbackFactory.class) public interface DeptClientService { @RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET) public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list",method = RequestMethod.GET) public List list(); @RequestMapping(value = "/dept/add",method = RequestMethod.POST) public boolean add(Dept dept); }
microservicecloud-api工程
mvn clean install
microservicecloud-consumer-dept-feign工程修改YML
YML
server: port: 80 feign: hystrix: enabled: true eureka: client: register-with-eureka: false service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
测试
3个eureka先启动
微服务microservicecloud-provider-dept-8001启动
microservicecloud-consumer-dept-feign启动
正常访问测试
http://localhost/consumer/dept/get/1
故意关闭微服务microservicecloud-provider-dept-8001
客户端自己调用提示
http://localhost/consumer/dept/get/1
此时服务端provider已经down了,但是我们做了服务降级处理,让客户端在服务端不可用时也会获得提示信息而不会挂起耗死服务器
服务监控hystrixDashboard
概述
除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。
Case步骤
新建工程microservicecloud-consumer-hystrix-dashboard
POM
修改内容
dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-hystrixartifactId> dependency> dependency> org.springframework.cloud spring-cloud-starter-hystrix-dashboard dependency>
全部内容
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-consumer-hystrix-dashboardartifactId> dependencies> dependency> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloud-apiartifactId> version>${project.version}version> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-webartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-eurekaartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-ribbonartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-configartifactId> dependency> dependency> org.springframework.cloud spring-cloud-starter-feign dependency> org.springframework.cloud spring-cloud-starter-hystrix org.springframework.cloud spring-cloud-starter-hystrix-dashboard dependencies> project>
YML
server: port: 9001
主启动类改名+新注解@EnableHystrixDashboard
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; @SpringBootApplication @EnableHystrixDashboard public class DeptConsumer_DashBoard_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer_DashBoard_App.class,args); } }
所有Provider微服务提供类(8001/8002/8003)都需要监控依赖配置
dependency> org.springframework.boot spring-boot-starter-actuator dependency>
启动microservicecloud-consumer-hystrix-dashboard该微服务监控消费端
http://localhost:9001/hystrix

启动3个eureka集群
启动microservicecloud-provider-dept-hystrix-8001
http://localhost:8001/dept/get/1
http://localhost:8001/hystrix.stream

启动的相关微服务工程

监控测试
多次刷新http://localhost:8001/dept/get/1
观察监控窗口
填写监控地址
 1:Delay:该参数用来控制服务器上轮询监控信息的延迟时间,默认为2000毫秒,可以通过配置该属性来降低客户端的网络和CPU消耗。 2:Title:该参数对应了头部标题Hystrix Stream之后的内容,默认会使用具体监控实例的URL,可以通过配置该信息来展示更合适的标题。
监控结果
 如何看上图
如何看?
7色
1圈
实心圆:共有两种含义。它通过颜色的变化代表了实例的健康程度,它的健康度从绿色 该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大该实心圆就越大。所以通过该实心圆的展示,就可以在大量的实例中快速的发现故障实例和高压力实例。
1线
曲线:用来记录2分钟内流量的相对变化,可以通过它来观察到流量的上升和下降趋势。
整图说明

搞懂一个才能看懂复杂的

zuul路由网关
概述
是什么
Zuul包含了对请求的路由和过滤两个最主要的功能: 其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础.Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。 注意:Zuul服务最终还是会注册进Eureka 提供=代理+路由+过滤三大功能
能干嘛
路由
过滤
官网资料
https://github.com/Netflix/zuul/wiki/Getting-Started
路由基本配置
新建Module模块microservicecloud-zuul-gateway-9527
POM
修改内容
dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-eurekaartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-zuulartifactId> dependency>
全部内容
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-zuul-gateway-9527artifactId> dependencies> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-zuulartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-eurekaartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-actuatorartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-hystrixartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-configartifactId> dependency> dependency> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloud-apiartifactId> version>${project.version}version> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-jettyartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-webartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-testartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependencies> project>
YML
server: port: 9527 spring: application: name: microservicecloud-zuul-gateway eureka: client: service-url: defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: instance-id: gateway-9527.com prefer-ip-address: true info: app.name: atguigu-microcloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
hosts修改
127.0.0.1 myzuul.com
主启动类
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableZuulProxy public class Zuul_9527_StartSpringCloudApp { public static void main(String[] args) { SpringApplication.run(Zuul_9527_StartSpringCloudApp.class, args); } }
@EnableZuulProxy
启动

三个eureka集群
一个服务提供类microservicecloud-provider-dept-8001
一个路由
测试
不用路由
http://localhost:8001/dept/get/2
启用路由
http://myzuul.com:9527/microservicecloud-dept/dept/get/2
路由访问映射规则
工程microservicecloud-zuul-gateway-9527
代理名称
YML
before http://myzuul.com:9527/microservicecloud-dept/dept/get/2 zuul: routes: mydept.serviceId: microservicecloud-dept mydept.path: /mydept/** after http://myzuul.com:9527/mydept/dept/get/1
此时问题
路由访问OK
http://myzuul.com:9527/mydept/dept/get/1
原路径访问OK
http://myzuul.com:9527/microservicecloud-dept/dept/get/2
原真实服务名忽略
YML
zuul: ignored-services: microservicecloud-dept routes: mydept.serviceId: microservicecloud-dept mydept.path: /mydept/**
单个具体,多个可以用"*"
zuul: ignored-services: "*" routes: mydept.serviceId: microservicecloud-dept mydept.path: /mydept/**
设置统一公共前缀
YML
zuul: prefix: /atguigu ignored-services: "*" routes: mydept.serviceId: microservicecloud-dept mydept.path: /mydept/**
http://myzuul.com:9527/atguigu/mydept/dept/get/1
最后YML
server: port: 9527 spring: application: name: microservicecloud-zuul-gateway zuul: prefix: /atguigu ignored-services: "*" routes: mydept.serviceId: microservicecloud-dept mydept.path: /mydept/** eureka: client: service-url: defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: instance-id: gateway-9527.com prefer-ip-address: true info: app.name: atguigu-microcloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
SpringCloud Config 分布式配置中心
概述
分布式系统面临的---配置问题
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。SpringCloud提供了ConfigServer来解决这个问题,我们每一个微服务自己带着一个application.yml,上百个配置文件的管理....../(ㄒoㄒ)/~~
是什么
 是什么 SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。 怎么玩 SpringCloud Config分为服务端和客户端两部分。 服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口 客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。
能干嘛
集中管理配置文件
不同环境不同配置,动态化的配置更新,分环境部署比如dev/test/prod/beta/release
运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置
将配置信息以REST接口的形式暴露
与GitHub整合配置
由于SpringCloud Config默认使用Git来存储配置文件(也有其它方式,比如支持SVN和本地文件), 但最推荐的还是Git,而且使用的是http/https访问的形式
SpringCloud Config服务端配置
用自己的GitHub账号在GitHub上新建一个名为microservicecloud-config 的新Repository

由上一步获得SSH协议的git地址
git@github.com:zzyybs/microservicecloud-config.git
本地硬盘目录上新建git仓库并clone

本地地址:D:\44\mySpringCloud
git命令:git clone git@github.com:zzyybs/microservicecloud-config.git
在本地D:\44\mySpringCloud\microservicecloud-config里面新建一个application.yml
YML内容
spring: profiles: active: - dev --- spring: profiles: dev #开发环境 application: name: microservicecloud-config-atguigu-dev --- spring: profiles: test #测试环境 application: name: microservicecloud-config-atguigu-test # 请保存为UTF-8格式
保存格式必须为UTF-8
将上一步的YML文件推送到github上
git add .
git commit -m "init yml"
git push origin master
步骤结果
命令清单

GitHub

新建Module模块microservicecloud-config-3344 它即为Cloud的配置中心模块
POM
修改内容
dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-config-serverartifactId> dependency>
全部内容
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-config-3344artifactId> dependencies> org.springframework.cloud spring-cloud-config-server org.eclipse.jgit org.eclipse.jgit 4.10.0.201712302008-r dependency> org.springframework.boot spring-boot-starter-actuator dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-hystrixartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-eurekaartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-configartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-jettyartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-webartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-testartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependencies> project>
YML
server: port: 3344 spring: application: name: microservicecloud-config cloud: config: server: git: uri: git@github.com:zzyybs/microservicecloud-config.git #GitHub上面的git仓库名字
主启动类Config_3344_StartSpringCloudApp
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.config.server.EnableConfigServer; @SpringBootApplication @EnableConfigServer public class Config_3344_StartSpringCloudApp { public static void main(String[] args) { SpringApplication.run(Config_3344_StartSpringCloudApp.class,args); } }
@EnableConfigServer
windows下修改hosts文件,增加映射
127.0.0.1 config-3344.com
测试通过Config微服务是否可以从GitHub上获取配置内容
启动微服务3344
http://config-3344.com:3344/application-dev.yml
http://config-3344.com:3344/application-test.yml
http://config-3344.com:3344/application-xxx.yml(不存在的配置)
配置读取规则
官网

/{application}-{profile}.yml
http://config-3344.com:3344/application-dev.yml
http://config-3344.com:3344/application-test.yml
http://config-3344.com:3344/application-xxx.yml(不存在的配置)
/{application}/{profile}[/{label}]
http://config-3344.com:3344/application/dev/master
http://config-3344.com:3344/application/test/master
http://config-3344.com:3344/application/xxx/master
/{label}/{application}-{profile}.yml
http://config-3344.com:3344/master/application-dev.yml
http://config-3344.com:3344/master/application-test.yml
成功实现了用SpringCloud Config通过GitHub获取配置信息
SpringCloud Config客户端配置与测试
在本地D:\44\mySpringCloud\microservicecloud-config路径下新建文件 microservicecloud-config-client.yml
microservicecloud-config-client.yml内容
spring: profiles: active: - dev --- server: port: 8201 spring: profiles: dev application: name: microservicecloud-config-client eureka: client: service-url: defaultZone: http://eureka-dev.com:7001/eureka/ --- server: port: 8202 spring: profiles: test application: name: microservicecloud-config-client eureka: client: service-url: defaultZone: http://eureka-test.com:7001/eureka/
将上一步提交到GitHub中
新建microservicecloud-config-client-3355
POM
修改内容
dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-configartifactId> dependency>
全部内容
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-config-client-3355artifactId> dependencies> org.springframework.cloud spring-cloud-starter-config dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-actuatorartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-hystrixartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-eurekaartifactId> dependency> dependency> org.springframework.cloud spring-cloud-starter-config dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-jettyartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-webartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-testartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependencies> project>
bootstrap.yml
是什么
applicaiton.yml是用户级的资源配置项 bootstrap.yml是系统级的,优先级更加高 Spring Cloud会创建一个`Bootstrap Context`,作为Spring应用的`Application Context`的父上下文。初始化的时候,`Bootstrap Context`负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的`Environment`。`Bootstrap`属性有高优先级,默认情况下,它们不会被本地配置覆盖。 `Bootstrap context`和`Application Context`有着不同的约定, 所以新增了一个`bootstrap.yml`文件,保证`Bootstrap Context`和`Application Context`配置的分离。
内容
spring: cloud: config: name: microservicecloud-config-client #需要从github上读取的资源名称,注意没有yml后缀名 profile: dev #本次访问的配置项 label: master uri: http://config-3344.com:3344 #本微服务启动后先去找3344号服务,通过SpringCloudConfig获取GitHub的服务地址
application.yml
spring: application: name: microservicecloud-config-client
windows下修改hosts文件,增加映射
127.0.0.1 client-config.com
新建rest类,验证是否能从GitHub上读取配置
package com.atguigu.springcloud.rest; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ConfigClientRest { @Value("${spring.application.name}") private String applicationName; @Value("${eureka.client.service-url.defaultZone}") private String eurekaServers; @Value("${server.port}") private String port; @RequestMapping("/config") public String getConfig() { String str = "applicationName: "+applicationName+"\t eurekaServers:"+eurekaServers+"\t port: "+port; System.out.println("******str: "+ str); return "applicationName: "+applicationName+"\t eurekaServers:"+eurekaServers+"\t port: "+port; } }
主启动类ConfigClient_3355_StartSpringCloudApp
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ConfigClient_3355_StartSpringCloudApp { public static void main(String[] args) { SpringApplication.run(ConfigClient_3355_StartSpringCloudApp.class,args); } }
测试
启动Config配置中心3344微服务并自测
http://config-3344.com:3344/application-dev.yml
启动3355作为Client准备访问
bootstrap.yml里面的profile值是什么,决定从github上读取什么
假如目前是 profile: dev
dev默认在github上对应的端口就是8201
http://client-config.com:8201/config
假如目前是 profile: test
test默认在github上对应的端口就是8202
http://client-config.com:8202/config
成功实现了客户端3355访问SpringCloud Config3344通过GitHub获取配置信息
SpringCloud Config配置实战
目前情况
1 Config服务端配置配置OK且测试通过,我们可以和config+GitHub进行配置修改并获得内容 2 此时我们做一个eureka服务+一个Dept访问的微服务,将两个微服务的配置统一由于github获得实现统一配置分布式管理,完成多环境的变更
步骤
Git配置文件本地配置
在本地D:\44\mySpringCloud\microservicecloud-config路径下新建文件 microservicecloud-config-eureka-client.yml
microservicecloud-config-eureka-client.yml内容
spring: profiles: active: - dev --- server: port: 7001 #注册中心占用7001端口,冒号后面必须要有空格 spring: profiles: dev application: name: microservicecloud-config-eureka-client eureka: instance: hostname: eureka7001.com #冒号后面必须要有空格 client: register-with-eureka: false #当前的eureka-server自己不注册进服务列表中 fetch-registry: false #不通过eureka获取注册信息 service-url: defaultZone: http://eureka7001.com:7001/eureka/ --- server: port: 7001 #注册中心占用7001端口,冒号后面必须要有空格 spring: profiles: test application: name: microservicecloud-config-eureka-client eureka: instance: hostname: eureka7001.com #冒号后面必须要有空格 client: register-with-eureka: false #当前的eureka-server自己不注册进服务列表中 fetch-registry: false #不通过eureka获取注册信息 service-url: defaultZone: http://eureka7001.com:7001/eureka/
在本地D:\44\mySpringCloud\microservicecloud-config路径下新建文件 microservicecloud-config-dept-client.yml
microservicecloud-config-dept-client.yml内容
spring: profiles: active: - dev --- server: port: 8001 spring: profiles: dev application: name: microservicecloud-config-dept-client datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml type-aliases-package: com.atguigu.springcloud.entities mapper-locations: - classpath:mybatis/mapper/**/*.xml eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://eureka7001.com:7001/eureka instance: instance-id: dept-8001.com prefer-ip-address: true info: app.name: atguigu-microservicecloud-springcloudconfig01 company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$ --- server: port: 8001 spring: profiles: test application: name: microservicecloud-config-dept-client datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB02 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml type-aliases-package: com.atguigu.springcloud.entities mapper-locations: - classpath:mybatis/mapper/**/*.xml eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://eureka7001.com:7001/eureka instance: instance-id: dept-8001.com prefer-ip-address: true info: app.name: atguigu-microservicecloud-springcloudconfig02 company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
Config版的eureka服务端
新建工程microservicecloud-config-eureka-client-7001
POM
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-config-eureka-client-7001artifactId> dependencies> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-configartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-eureka-serverartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependencies> project>
bootstrap.yml
spring: cloud: config: name: microservicecloud-config-eureka-client #需要从github上读取的资源名称,注意没有yml后缀名 profile: dev label: master uri: http://config-3344.com:3344 #SpringCloudConfig获取的服务地址
application.yml
spring: application: name: microservicecloud-config-eureka-client
主启动类Config_Git_EurekaServerApplication
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; /** * EurekaServer服务器端启动类,接受其它微服务注册进来 * @author zhouyang */ @SpringBootApplication @EnableEurekaServer public class Config_Git_EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(Config_Git_EurekaServerApplication.class, args); } }
测试
先启动microservicecloud-config-3344微服务,保证Config总配置是OK的
再启动microservicecloud-config-eureka-client-7001微服务
http://eureka7001.com:7001/
出现eureak主页表示成功启动
Config版的dept微服务
参考之前的8001拷贝后新建工程microservicecloud-config-dept-client-8001
POM
project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0modelVersion> parent> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloudartifactId> version>0.0.1-SNAPSHOTversion> parent> artifactId>microservicecloud-config-dept-client-8001artifactId> dependencies> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-configartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-actuatorartifactId> dependency> dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-eurekaartifactId> dependency> dependency> groupId>com.atguigu.springcloudgroupId> artifactId>microservicecloud-apiartifactId> version>${project.version}version> dependency> dependency> groupId>junitgroupId> artifactId>junitartifactId> dependency> dependency> groupId>mysqlgroupId> artifactId>mysql-connector-javaartifactId> dependency> dependency> groupId>com.alibabagroupId> artifactId>druidartifactId> dependency> dependency> groupId>ch.qos.logbackgroupId> artifactId>logback-coreartifactId> dependency> dependency> groupId>org.mybatis.spring.bootgroupId> artifactId>mybatis-spring-boot-starterartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-jettyartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-webartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-starter-testartifactId> dependency> dependency> groupId>org.springframeworkgroupId> artifactId>springloadedartifactId> dependency> dependency> groupId>org.springframework.bootgroupId> artifactId>spring-boot-devtoolsartifactId> dependency> dependencies> project>
bootstrap.yml
spring: cloud: config: name: microservicecloud-config-dept-client #需要从github上读取的资源名称,注意没有yml后缀名 #profile配置是什么就取什么配置dev or test #profile: dev profile: test label: master uri: http://config-3344.com:3344 #SpringCloudConfig获取的服务地址
application.yml
spring: application: name: microservicecloud-config-dept-client
主启动类及其它一套业务逻辑代码
主启动类
package com.atguigu.springcloud; 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 //本服务启动后会自动注册进eureka服务中 @EnableDiscoveryClient //服务发现 public class DeptProvider8001_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_App.class, args); } }
其它业务逻辑代码

配置说明
spring: cloud: config: name: microservicecloud-config-dept-client #需要从github上读取的资源名称,注意没有yml后缀名 #profile配置是什么就取什么配置dev or test #profile: dev profile: test label: master uri: http://config-3344.com:3344 #SpringCloudConfig获取的服务地址 主要看bootstrap.yml文件里面的 profile: 属性具体值是什么,从而确定它能从github上取得什么样的配置 假如配置dev左图,如果配置test那就找右图,具体各自数据库不同,从而依据配置得到分布式配置的目的  
测试
test配置默认访问
http://localhost:8001/dept/list
可以看到数据库配置是02
本地换配置成dev
http://localhost:8001/dept/list
可以看到数据库配置是01
第1季总结/第2季展望
第一季内容技术梳理与架构

整套开发技术栈以SpringCloud为主,单个微服务模块以SpringMVC+SpringBoot/Spring+MyBatis组合进行开发
前端层,页面H5+thymeleaf/样式CSS3+Bootstrap/前端框架JQuery+Node|Vue等
负载层,前端访问通过Http或Https协议到达服务端的LB,可以是F5等硬件做负载均衡,还可以自行部署LVS+Keepalived等(前期量小可以直接使用Nginx)
网关层,请求通过LB后,会到达整个微服务体系的网关层Zuul(Gateway),内嵌Ribbon做客户端负载均衡,Hystrix做熔断降级等
服务注册,采用Eureka来做服务治理,Zuul会从Eureka集群获取已发布的微服务访问地址,然后根据配置把请求代理到相应的微服务去
docker容器,所有的微服务模块都部署在Docker容器里面,而且前后端的服务完全分开,各自独立部署后前端微服务调用后端微服务,后端微服务之间会有相互调用
服务调用,微服务模块间调用都采用标准的Http/Https+REST+JSON的方式,调用技术采用Feign+HttpClient+Ribbon+Hystrix
统一配置,每个微服务模块会跟Eureka集群、配置中心(SpringCloudConfig)等进行交互
第3方框架,每个微服务模块根据实现的需要,通常还需要使用一些第三发框架,比如常见的有:缓存服务(Redis)、图片服务(FastDFS)、搜索服务(ElasticSearch)、安全管理(Shiro)等等
Mysql数据库,可以按照微服务模块进行拆分,统一访问公共库或者单独自己库,可以单独构建MySQL集群或者分库分表MyCat等
架构图
一期架构图
第二季展望
微服务架构体系知识展望,包含但不限于 SpringCloud Stream:数据流操作开发包 SpringCloud Turbine是聚合服务器发送事件流数据的一个工具,用来监控集群下hystrix的metrics情况。 SpringCloud Task:提供云端计划任务管理、任务调度。 SpringCloud Sleuth:日志收集工具包实现了一种分布式追踪解决方案,封装了Dapper和log-based追踪以及Zipkin和HTrace操作, SpringCloud Security:基于spring security的安全工具包,为应用程序添加安全控制 服务部署:Kubernetes , OpenStack 全链路追踪:Zipkin,brave 服务监控:zabbix SpringCloud CLI:基于 Spring Boot CLI,可以让你以命令行方式快速建立云组件。 全局控制:选举leader、全局锁、全局唯一id 安全鉴权: auth2、 openId connect 自动化构建与部署: gitlab + jenkins + docker 服务监控和告警(Spring Boot Admin) ……