1.什么是微服务
2.微服务之间是如何独立通讯的
3.SpringCloud 和 Dubbo 有哪些区别?
4.SpringBoot 和 SpringCloud ,请你谈谈对他们的理解
5.什么是服务熔断?什么是服务降级
6.微服务的优缺点分别是什么?请说下你在项目开发中遇到的坑
7.你所知道的微服务技术栈有哪些?请列举一二
8.eureka 和 zookeeper 都可以提供服务注册于发现的功能,说说两个的区别?
1.微服务
技术维度:
1.将传统的单一应用程序,根据业务拆分成一个一个的服务,彻底的去耦合,每一个服务提供单个业务功能的服务,
一个服务只做一件事。能够自行启动或销毁,拥有自己独立的数据库。
自己的理解:将单一应用程序根据业务拆分成一个一个的服务,拆分后,每个服务都只实现一种业务功能,独立部署,独立启动运行,
有自己独立的数据库。其他业务模块出现问题,对其他也不会有所影响。
4.SpringBoot 和 SpringCloud 的关系
1.SpringBoot 用于开发一个个单体的微服务,专注于单体个体
SpringCloud 是一个微服务架构,专注于全局,将 SpringBoot 的单体微服务整合起来并管理。
2.SpringBoot 可以离开SpringCloud 进行开发启动,但是 SpringCloud 离不开 SpringBoot,属于依赖关系。
1.SpringBoot专注于快速方便的开发单个个体微服务。
SpringCloud 是关注全局的微服务协调整理治理框架,他将 SpringBoot 开发的一个个单体微服务整合并管理起来,
为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务。
2.SpringBoot 可以离开 SpringCloud 独立使用开发项目,但是 SpringCloud 离不开 SpringBoot,属于依赖关系。
3.SpringBoot 专注于快速、方便的开发单个微服务个体,SpringCloud 关注全局的服务治理框架。
微服务架构:微服务架构是一种架构模式或者说是一种架构风格,提倡将单一应用程序划分为一组小的程序,每个服务运行在其独立的自己的进程中,服务之间互相协调、互相配合,
为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 Restful API).每个服务都围绕着具体业务进行构建,并且能够被独立的部署
到生产环境、类生产环境等。另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建,可以
有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储。
微服务(技术维度)
微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个微服务提供单个业务功能的服务,一个服务做一件事,
从技术角度看就是一种而独立的处理过程,类似进程概念,能够自行单独启动或销毁,拥有自己独立的数据库。
课堂作业:微服务架构提出者马丁富勒论文阅读。
微服务:
强调的是服务的大小,它关注的是某一个点,是具体解决某一个问题/提供落地对应服务的一个服务应用,
狭义的看,可以看做 Eclipse 里面的一个个微服务工程/或者 Module
微服务架构:
微服务架构是一种架构模式或者说是一种架构风格,提倡将单一应用程序划分为一组小的程序,每个服务运行在其独立的自己的进程中,服务之间互相协调、互相配合,
为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 Restful API).每个服务都围绕着具体业务进行构建,并且能够被独立的部署
到生产环境、类生产环境等。另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建,可以
有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储。
1.1.将单一应用程序划分为一组小的服务
1.2.每个服务运行在自己独立的进程中,服务之间相互协调,相互配合
1.3.服务之间采用轻量级的通讯机制(Dubbo 采用 RPC,SpringCloud 采用 RESTFul API)
1.4.独立发布,独立部署
优点:
1.每个服务足够内聚,足够小,代码容易理解这样能聚焦一个指定的业务功能或业务需求。
2.开发简单、开发效率提高,一个服务可能就是专一的只做一件事。
3.微服务能够被小团队单独开发,这个小团队是2到5人的开发人员组成。
4.微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或者是部署阶段都是独立的。
5.微服务可以使用不同的语言进行开发。
6.易于和第三方集成,微服务允许容易且灵活的方式集成自动部署,通过持续集成工具,如 Jenkins,Hudson,bamboo
7.微服务允许你利用融合最新技术
8.微服务只是业务逻辑的代码,不会和 HTML,CSS 或其他界面组件混合。
9.每个微服务都有自己的存储能力,可以有自己的数据库。也可以有统一数据库。
缺点:
1.开发人员要处理分布式系统的复杂性
2.多服务运维难度,随着服务的增加,运维的压力也在增大
3.系统部署依赖
4.服务间通信成本增加
5.数据一致性
6.系统集成测试
7.性能监控...
开发模式:
1.前后端分离
我们 Java 程序员,相对而言比较幸福,
我们只需要管理后端,给前端的 H5 工程师就按照约定
Rest 地址 + 输入参数格式和报文约定+输出参数
2.全栈工程师
H5+JavaEE+....
微服务技术栈:多种技术的集合体
一个分布式的微服务架构:
维度:
服务治理 Dubbo
服务注册 zookeeper
服务调用
服务负载均衡 nginx
服务监控....
微服务条目 | 落地技术 | 备注 |
---|---|---|
服务开发 | 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 等发送接收消息) | |
事件消息总线 | SpringCloud Bus | |
… |
选型依据:
整体解决方案和框架成熟度
社区热度
可维护性
学习曲线
当前各大 IT 公司用的微服务架构有哪些?
阿里 Dubbo/HSF
京东 JSF
新浪微博 Motan
当当网 DubboX
...
各微服务框架对比
功能点/服务框架 | 备选方案1/Netflix/SpringCloud | 备选方案2/Motan(新浪) | 备选服务3/gRPC(谷歌) | 备选服务4/Thrift(facebook) | Dubbo/DubboX |
---|---|---|---|---|---|
功能定位 | 完整的微服务框架 | RPC框架,但整合了zk 或 Consul,实现集群环境的基本的服务注册/发现 | RPC框架 | RPC框架 | 服务框架 |
支持Rest | 是,Ribbon 支持多种可插拔的序列化选择 | 否 | 否 | 否 | 否 |
支持RPC | 否 | 是(Hession2) | 是 | 是 | 是 |
支持多语言 | 是(Rest形式) | 否 | 是 | 是 | 否 |
服务注册/发现 | 是(Eureka),Eureka 服务注册表,Karyon 服务端框架支持服务自注册和健康检查 | 是(zookeeper/consul) | 否 | 否 | 是 |
负载均衡 | 是(服务端zuul+客户端Ribbon) Zuul-服务,动态路由云端负载均衡Eureka(针对中间层服务器) | 是(客户端) | 否 | 否 | 是(客户端) |
配置服务 | Netflix Archaius Spring Cloud Config Server 集中配置 | 是(zookeeper提供) | 否 | 否 | 佛 |
服务调用链监控 | 是(zuul) Zuul提供边缘服务,API网关 | 否 | 否 | 否 | |
高可用/容错 | 是(服务端Hystrix+客户端Ribbon) | 是(客户端) | 否 | 否 | 是(客户端) |
典型应用案例 | Netflix | Sina | |||
社区活跃程度 | 高 | 一般 | 高 | 一般 | 已经不维护了 |
学习难度 | 中等 | 低 | 高 | 高 | 低 |
文档丰富度 | 高 | 一般 | 一般 | 一般 | 高 |
其他 | Spring Cloud Bus 为我们提供的应用程序带来了更多管理端点 | 支持降低 | Netflix内部在开发集成gRPC | IDL定义 | 实践的公司比较多 |
https://spring.io
SpringCloud,基于SpringBoot 提供了一套微服务解决方案,包括注册与实现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件,
除了基于 NetFlix 的开源组件做高度抽象封装之外,还有一些选型中立的开源组件。
SpringCloud 利用 SpringBoot 的开发便利性巧妙的简化了分布式系统基础设施的开发,SpringCloud 为开发人员提供了快速构建分布式系统的
一些工具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等,他们都可以用 Spring Boot 的开发风格
做到一键启动和部署。
通过 SpringBoot 风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
SpringCloud = 分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶。
1.SpringBoot专注于快速方便的开发单个个体微服务。
SpringCloud 是关注全局的微服务协调整理治理框架,他将 SpringBoot 开发的一个个单体微服务整合并管理起来,
为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务。
2.SpringBoot 可以离开 SpringCloud 独立使用开发项目,但是 SpringCloud 离不开 SpringBoot,属于依赖关系。
3.SpringBoot 专注于快速、方便的开发单个微服务个体,SpringCloud 关注全局的服务治理框架。
应用服务化拆分+消息中间件
[外链图片转存失败(img-5d0Ka3GN-1566610512879)(C:\Users\laughig\Desktop\成熟的互联网架构图)]
活跃度
1.https://github/com/dubbo : 低
2.https://github.com/spring-cloud : 高
对比结果
Dubbo | Spring Cloud | |
---|---|---|
服务注册中心 | Zookeeper | Spring Cloud NetFlix Eureka |
服务调用方式 | RPC(远程调用) | REST API |
服务监控 | Dubbo-monitor | Spring Boot Admin |
断路器 | 不完善 | Spring Cloud NetFlix Hystrix |
服务网关 | 无 | Spring Cloud Netflix Zuul |
分布式配置 | 无 | Spring Cloud Config |
服务跟踪 | 无 | Spring Cloud Sleuth |
消息总线 | 无 | Spring Cloud Bus |
数据流 | 无 | Spring Cloud Stream |
批量任务 | 无 | Spring Cloud Task |
… | … | … |
SpringCloud 和 Dubbo 对比结果:
1.最大区别: SpringCloud 抛弃了 Dubbo 的 RPC 通信,采用的是基于 HTTP 的 REST 方式。
严格来说,这两种方式各有优势。虽然从一定程度上来说,后者牺牲了服务调用的性能,但是也避免了上面提到的原生 RPC 带来的问题。
而且 REST 相比 RPC 更为灵活,服务提供方和调用方的依赖只依赖一纸契约,不存在代码级别的强依赖,这在强调快速眼花的微服务环境下,显得更为合适。
2.品牌机与组装机的区别
很明显,SpringCloud 的功能比 Dubbo 更加强大,涵盖面更广,而且作为 Spring 的拳头项目,他也能够与 Spring Framework、Spring Boot、Spring Data、
Spring Batch 等其他 Spring 项目完美融合,这些对于微服务而言是至关重要的。使用 Dubbo 构建的微服务架构就像组装电脑,各环节我们的选择自由度很高,但是
最终结果很可能因为一条内存质量不行就点不亮了,总是让人不怎么放心,但是如果你是一名高手,那这些都不是问题;而Spring Cloud 就像品牌机,在 Spring Source
的整合下,做了大量的兼容性测试,保证了机器拥有更高的稳定性,但是如果要在使用非原装组件外的东西,就需要对其基础有足够的了了解。
3.社会支持与更新力度
最为重要的是,Dubbo 停止了5年左右的更新,虽然2017.7月重启了。对于技术发展的新需求,需要由开发者自行扩展升级,这对于很多想要采用微服务架构的中小
软件组织,显然是不太合适的,中小公司没有这么强大的技术能力去修改 Dubbo 源码+周边的一整套解决方案,并不是每一个公司都有阿里的大牛+真实的线上生产
环境测试过。
Distributed/versioned configutation
Service registration and discorvery
Routing
Service-to-service calls
Load balancing
Circuit Breakers
Distributed messaging
…
http://projects.spring.io/spring-cloud/
1.https://springcloud.cc/spring-cloud-netflix.html
2.开发 API 说明:
http://cloud.spring.io/spring-cloud-static/Dalston.SR1/ 英文版
https://springcloud.cc/spring-cloud-dalston.html 中文版
3.springcloud 中国社区 http://springcloud.cn/
4.springcloud 中文网 https://springcloud.cc/
…
中国联通子公司、上海米么金服、指点无限科技有限公司、易保软件、广州简法网络、深圳睿云智合科技、猪八戒网、上海云首科技、
华为、东软、南京云账房网络、四众互联、深圳魔令技术、广州万表网、视觉中国、上海秦苍信息、爱油科技
微服务:
1.microservicecloud-api : 封装的整体 entity/接口/公共配置等
2.microservicecloud-provider-dept-8001 微服务落地的服务提供者
3.microservicecloud-consumer-dept-80 微服务调用的客户端使用 / 80端口
SpringCloud 版本: Dalston.SR1
构建步骤:
microservicecloud : 整体父工程 Project
1.新建父工程 microservicecloud, 切记是 Packaging 是 pom 模式。
2.主要是定义 pom 文件,将后续各个子模块公用的 jar 包等统一提出来,类似一个抽象父类
3.pom
microservicecloud-api 公共子模块 Module
1.新建 microservicecloud-api
2.修改 pom
3.新建部门 Entity 且配合 lombok 使用
4.mvn clean install 后给其他模块引用,达到通用目的。
也就是需要用到部门实体的话,不用每个工程都定义一份,直接引用本模块即可。
microservicecloud-provider-dept-8001 部门微服务提供者 Module
microservicecloud-consumer-dept-80 部门微服务消费者
1.创建的 maven module 模块工程;
1.1.不存在 src 目录结构: 解决方法: https://blog.csdn.net/hpuxiaofang/article/details/83503462
解决方法:1.检查 maven 配置,修改为我们自定义的 maven
2.配置 Runner 中 : VM Options 添加配置 -Dmaven.multiModuleProjectDirectory=$M2_HOME
3.创建 maven 项目 时,添加键值对: archetypeCatalog internal
1.2.新建的 maven 项目不能创建 class 类等
解决方法:https://blog.csdn.net/qq_24949727/article/details/52097838
选择 src/main 下 java ,右键选择 Make Directory as ——> source root
创建一个简单 maven 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>springcloudgroupId>
<artifactId>microservicecloudartifactId>
<packaging>pompackaging>
<version>1.0-SNAPSHOTversion>
<modules>
<module>microservicecloud-apimodule>
modules>
<name>microservicecloudname>
<url>http://www.example.comurl>
<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>
<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>2.1.7.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>
project>
<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/maven-v4_0_0.xsd">
<parent>
<artifactId>microservicecloudartifactId>
<groupId>springcloudgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>microservicecloud-apiartifactId>
<packaging>jarpackaging>
<dependencies>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.16.18version>
dependency>
dependencies>
project>
需要引入 org.projectlombok.lombok 依赖
@NoArgsConstructor //无参构造
//@AllArgsConstructor //全参构造
@Data //set,get方法
@Accessors(chain=true) //通过链式访问
public class Dept implements Serializable {
private Long deptno; // 主键
private String dname; // 部门名称
private String db_source;// 来自那个数据库,因为微服务架构可以一个服务对应一个数据库,同一个信息被存储到不同数据库
public Dept(String dname)
{
super();
this.dname = dname;
}
}
1.新建 microservicecloud-provider-dept-8001
2.pom.xml
3.yml
4.工程 src/main/resources 目录下新建 mybatis 文件后新建 mybatis.cfg.xml 文件
5.MySQL 创建部门数据库脚本
6.DeptDao 部门接口
7.工程 src/main/resources/mybatis 目录下新建 mapper 文件夹后再创建 DeptMapper.xml
8.DeptService 部门服务接口
9.DeptServiceImpl 部门服务接口实现类
10.DeptController 部门微服务提供者 REST
11.DeptProvider8001_App主启动类 DeptProvider8001_App
12.测试
13.最终工程展现
约定 》 配置 》 编码
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">
<parent>
<artifactId>microservicecloudartifactId>
<groupId>springcloudgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>microservicecloud-provider-dept-8001artifactId>
<dependencies>
<dependency>
<groupId>springcloudgroupId>
<artifactId>microservicecloud-apiartifactId>
<version>1.0-SNAPSHOTversion>
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.spirng.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spirng.bootgroupId>
<artifactId>spring-boot-starter-jettyartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spirng.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spirng.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>
application.yml
server:
port: 8001
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml #mybatis 配置文件所在路径
type-aliases-package: 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: com.mysql.cj.jdbc.Driver #mysql 驱动包
url: jdbc:mysql://localhost:3306/cloudDB01?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true #数据库名称
username: root
password: 123456
dbcp2:
initial-size: 5 #初始化连接数
min-idle: 5 #数据库连接池的最小维持连接数
max-total: 5 #最大连接数
max-wait-millis: 200 #等待连接获取的最大超时时间
mybatis.cfg.xml
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
settings>
configuration>
创建数据库脚本
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());
DeptDao.java
注意: @Mapper
@Mapper
public interface DeptDao {
public boolean addDept();
public Dept findById(Long id);
public List<Dept> findAll();
}
DeptMapper.xml
<mapper namespace="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.java
package springcloud.service;
import springcloud.entities.Dept;
import java.util.List;
public interface DeptService {
public boolean add(Dept dept);
public Dept get(Long id);
public List<Dept> list();
}
DeptServiceImpl.java
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptDao deptDao;
@Override
public boolean add(Dept dept) {
return deptDao.addDept();
}
@Override
public Dept get(Long id) {
return deptDao.findById(id);
}
@Override
public List<Dept> list() {
return deptDao.findAll();
}
}
DeptController.java
@RestController //@Controller + @ResponseBody
public class DeptController {
@Autowired
private DeptService deptService;
@PostMapping("/dept/add")
public boolean add(@RequestBody Dept dept) {
return deptService.add(dept);
}
@GetMapping("/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
return deptService.get(id);
}
@GetMapping("/dept/list")
public List<Dept> list() {
return deptService.list();
}
}
主启动类:
@SpringBootApplication
public class DeptProvider8001_App {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001_App.class,args);
}
}
1.新建 microservicecloud-consumer-dept-80
2.pom.xml
3.application.yml
4.ConfigBean 的编写(类似 Spring 里面的 applicationContext.xml 的注入 Bean)
5.新建 DeptController_Consumer 部门微服务消费者 REST
1.RestTemplate
2.代码
6.DeptConsumer80_App 主启动类
7.测试
配置类:
@Configuration
public class ConfigBean{
@Bean @Bean 标注的相当于 <bean id="restTemplate" class=""></bean>
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
controller.java
@RestController
public class DeptController_Consumer {
private static final String REST_URL_PREFIX = "http://localhost:8001";
@Autowired
RestTemplate restTemplate;
@GetMapping("/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,id,Dept.class);
}
@RequestMapping(value="/consumer/dept/list")
public List<Dept> get(){
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list,id,List.class);
}
}
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
使用:
使用 restTempalte 访问 restful 接口非常的简单。
(url,requestMap,ResponseBean.class)这三个参数分别代表 REST 请求地址、请求参数、HTTP 响应转换被转换成的对象类型。
主配置类:
@SpringBootApplication
public class DeptConsumer80_App {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80_App.class, args);
}
}
Netflix 在设计 Eureka 时遵守的就是 AP 原则。
Eureka 是 Netflix 的一个子模块,也是核心模块之一。Eureka 是一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移。
服务注册与发现对于微服务架构来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了。
功能类似于 Dubbo 的注册中心,比如 Zookeeper.
CAP:
Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务注册和发现(对比 Zookeeper)
Eureka 采用了 C-S 的设计架构。Eureka Server 作为服务注册功能的服务器,它是服务注册中心。
系统中的其他微服务,使用 Eureka 的客户端连接到 Eureka Server 并维持心跳连接。这样系统的维护人员就可以通过
Eureka Server 来监控系统中各个微服务是否正常运行。Spring Cloud 的一些其他模块(比如 Zuul) 就可以通过
Eureka Server 来发现系统中的其他微服务,并执行相关的逻辑。
Eureka 包含两个组件:Eureka Server 和 Eureka Client
Eureka Server 提供服务注册服务
各个节点启动后,会在 EurekaServer 中进行注册,这样 EurekaServer 中的服务注册表中将会存储所有可用服务节点的信息,
服务节点的信息可以在界面中直观的看到。
EurekaClient 是一个 Java 客户端,用于简化 Eureka Server 的交互,客户端同时也具备一个内置的、使用轮询(round-robin)
负载算法的负载均衡器。在应用启动后,将会向 Eureka Server 发送心跳(默认周期为 30 秒)。如果 Eureka Server 在多个
心跳周期内没有接收到某个节点的心跳,EurekaServer 将会从服务注册表中把这个服务节点移除(默认90秒)。
[外链图片转存失败(img-9kP6iJ3F-1566610512880)(C:\Users\laughig\AppData\Roaming\Typora\typora-user-images\1566140640745.png)]
Eureka Server 提供服务注册和发现
Service Provider 服务提供方将自身服务注册到 Eureka, 从而使服务消费方能够找到
Service Consumer 服务消费方从 Eureka 获取注册服务列表,从而能够消费服务
总父工程
通用模块 api
服务提供方 Provider
服务消费方 Consumer
构建步骤:
1.新建 microservicecloud-eureka-7001
2.pom.xml
3.application.yml
4.EurekaServer7001_App 主启动类
5.测试
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eureka-serverartifactId>
dependency>
application.yml
server:
port: 7001
eureka:
instance:
hostname: localhost #eureka 服务端的实例名称
client:
register-with-eureka: false # false 表示不向注册中心注册自己
fetch-registry: false #false 表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
server-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与 Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址
主启动类:
注意: @EnableEurekaServer
@SpringBootApplication
@EnableEurekaServer //EurekaServer 服务器启动类,接受其他微服务注册进来
public class EurekaServer7001_App{
public static void main(String[] args) {
SpringApplication.run(EurekaServer7001_App.class, args);
}
}
测试:
1.访问:http://localhost:7001
构建步骤:
1.修改 microservicecloud-provider-dept-8001
2.pom.xml
3.application.yml
4.DeptProvider8001_App 主启动类
5.测试
修改 pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eurekaartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
修改 application.yml
eureka:
client: # 客户端注册服务进 eureka 服务列表内
service-url:
defautlZone: http://localhost:7001/eureka
修改主启动类:
注意注解:@EnableEurekaClient //本服务启动后悔自动注册进 Eureka 服务中
@SpringBootApplication
@EnableEurekaClient
public class DeptProvider8001_App{
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001_App.class, args);
}
}
测试:
1.先要启动 EurekaServer
2.http://localhost:7001/
3.微服务名注册配置说明
1.主机名称:服务名称修改
2.访问信息有 IP 信息提示
3.微服务 info 内容详细信息
主机名称修改:
修改 microservicecloud-provider-dept-8001
application.yml
eureka:
instance:
instance-id: microservicecloud-dept8001
访问信息有 IP 信息提示:
修改 microservicecloud-provider-dept-8001
application.yml
eureka:
instance:
instance-id: microservicecloud-dept8001
prefer-ip-address: true #访问路径可以显示 IP 地址
微服务 info 内容详细信息
修改 microservicecloud-provider-dept-8001
pom.xml
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
总的父工程 microservicecloud 修改 pom.xml 添加构建 build 信息
pom.xml
<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>
修改 microservicecloud-providero-dept-8001
application.yml
info:
app.name: laughing-microservicecloud
company.name: www.lanbao.com
build.artifactId: $project.artifactId$
build.version: $project.version$
自我保护机制:好死不如赖活着
导致原因:某时刻某一个微服务不可用了, eureka 不会立刻清理,依旧会对该微服务的信息进行保存。
自我保护模式:
默认情况下,如果 EurekaServer 在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会默认注销该实例(默认90秒)。
但是当网络分区故障发生时,微服务与 EurekServer 之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,
此时本不应该注销这个微服务。Eureka 通过"自我保护模式" 来解决这个问题——当 EurekaServer 节点在短时间内丢失过多客户端
时(可能发生了网络分区故障),那么这个节点就会进入自我 保护模式。一旦进入该模式,EurekaServer 就会保护服务注册表中的信息,
不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该 EurekaServer节点会自动退出自我保护模式。
在自我保护模式中,Eureka Server 会保护服务注册表中的信息,不再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时,该
Eureka Server 节点就会自动退出自我保护模式。它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。
一句话讲解:好死不如赖活着。
综上,自我保护模式是一种应对网络异常的安全保护措施。它的哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目
注销任何健康的微服务。使用自我保护模式,可以让 Eureka 集群更加健壮、稳定。
在 Spring Cloud 中,可以使用 eureka.server.enable-self-preservation = false 禁用自我保护模式。
不建议不推荐修改 Eureka 自我保护模式。
Eureka 服务发现:
1.对于注册进 eureka 里面的微服务,可以通过服务发现来获得该服务的信息。
2.修改 mircoervicecloud-provider-dept-8001工程的 DeptController
3.DeptProvider8001_App 主启动类
4.自测
5.修改 microservicecloud-consumer-dept-80工程的 DeptController_Consumer
8001 —— DeptController.java
import org.springframework.cloud.client.discovery.DiscoveryClient;
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@Autowired
private DiscoveryClient client;
@RequestMapping(value="/dept/discovery", method=RequestMethod.GET)
public Object discovery() {
List<String> list = client.getServices();
System.out.println("****"+list);
List<ServiceInstance> 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;
}
...
}
主启动类:
@EnableDiscoveryClient : 服务发现
80 :
DeptController_Consumer.java
@RequestMapping(value = "/consumer/dept/discovery")
public Object discovery() {
return this.restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery",Object.class)
}
1.原理说明
2.新建 microservicecloud-eureka-7002/microservicecloud-eureka-7003
3.按照 7001 为模板粘贴 pom.xml
4.修改 7002 和 7003 的主启动类
5.修改映射配置
5.1. 找到C:\Windows\System32\drivers\etc路径下的hosts文件
5.2. 修改映射配置添加进hosts文件
5.2.1. 127.0.0.1 eureka7001.com
5.2.2. 127.0.0.1 eureka7002.com
5.2.3. 127.0.0.1 eureka7003.com
6.3台 Eureka 服务器的 yml 配置
7.microservicecloud-provider-dept-8001 微服务发布到上面 3 台 eureka 集群配置中
7001 : application.yml
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 : application.yml
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 : application.yml
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 : application.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 对比:
1.Eureka 遵守 AP 原则;Zookeeper 遵守 CP 原则。
著名的 CAP 理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和 P(分区容错性)。由于分区容错性 P 是在分布式系统中必须要保证的,
因此只能在 C 和 P 之间进行权衡。 Zookeeper 是 CP,Eureka 是 AP.
1.1.Zookeeper 保证 CP
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接 down 掉不可用。也就是说,服务注册功能对可用性
的要求要高于一致性。但是 zk 会出现这样的一种情况,当 master 节点因为网络故障与其他节点失去联系时,剩余节点会重新进行 leader 选举。问题在于,
选举 leader 的时间太长,30~120s,且选举期间整个 zk 集群都是不可用的,这样就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得 zk
集群失去 master 节点是较大概率会发生的事情,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
1.2.Eureka 保证 AP
Eureka 看明白了这一点,因此在设计时就优先保证可用性。Eureka 各个节点都是平等,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和
查询服务。而 Eureka 的客户端在向某个 Eureka 注册或如果发现连接失败,则会自动切换至其他节点,只要有一台 Eureka 还在,就能保证注册服务可用(
保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka 还有一种自我保护机制,如果在15分钟内超过 85% 的节点都没有正
常的心跳,那么 Eureka 就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
1.Eureka 不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。
2.Eureka 仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点依然可用)
3.当网络稳定时,当前实例新的注册信息会被同步到其他节点中
因此,Eureka 可以很好的应对网络故障导致部分节点失去联系的情况,而不会像 zookeeper 那样使整个注册服务瘫痪。
传统的关系型数据:ACID: A(Atomicity)原子性、C(Consistency):一致性、I(Isolation) 独立性、D(Durability)持久性
NOSQL : C:Consistency(强一致性)、A:Availability(可用性)、P:Partition tolerance(分区容错性)
经典 CAP 图
最多只能同时较好的满足两个。
CAP 理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,因此,根据 CAP 原理将
NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三大类:
CA —— 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。 RDBMS
CP —— 满足一致性,分区容忍比的系统,通常性能不是特别高。 MongoDB、HBase 、Redis
AP —— 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
CAP 的三进二
CAP 理论就是说在分布式存储系统中,最多只能实现上面的两点。而由于当前的网络硬件肯定会出现延迟丢包等问题,所以
分区容忍性是我们必须实现的。P
所以我们只能在一致性和可用性之间进行权衡,没有 NoSQL 系统能够同时保证这三点。
Spring Cloud Ribbon 是基于 Netflix Ribbon 实现的一套 客户端 负载均衡的工具。
简单的说,Ribbon 是 Netflix 发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起。
Ribbon 客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出 Load Balancer(简称 LB)后面
所有的机器,Ribbon 会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用 Ribbon 实现自定义
的负载均衡算法。
LB,负载均衡,在微服务或分布式集群中经常用的一种应用。
负载均衡简单的说就是将用户的请求平摊的分配到多个服务商,从而达到系统的HA。
常见的负载均衡器软件有:Nginx,LVS,硬件 F5等。
相应的在中间件:如:dubbo 和 SpringCloud 中均给我们提供了负载均衡,SpringCloud 的负载均衡算法可以自定义。
集中式LB:
即在服务的消费方和提供方之间使用独立的 LB 设施(可以是硬件,如 F5,也可以是软件,如Nginx),由该设施负责把访问请求通过某种策略转发至服务的提供方。
进程内LB:
将 LB 逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。
Ribbon(客户端负载均衡) 就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
https://github.com/Netflix/ribbon/wiki/Getting-Started.
1.修改 microservicecloud-consumer-dept-80工程
2.修改 pom.xml 文件
3.修改 application.yml 追加 eureka 的服务注册地址
4.对 ConfigBean 进行新注解 @LoadBalanced 获得 Rest 时加入 Ribbon 的配置
5.主启动类 DeptConsumer80_App 添加 @EnableEurekaClient
6.修改 DeptController_Consumer 客户端访问类
7.先启动3个eureka 集群后,再启动 microservicecloud-provider-dept-8001并注册进 eureka
8.启动 microservicecloud-consumer-dept-80
9.测试
修改 pom.xml : 添加 ribbon 相关依赖:
<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>
修改 application.yml 文件
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.java
@Configuration
public class ConfigBean {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
主启动类:
@SpringBootApplication
@EnableEurekaClient
public class DeptConsumer80_App {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80_App.class, args);
}
}
修改客户端访问类 DeptController_Consumer.java:
@RestController
public class DeptController_Consumer {
private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD_DEPT";
}
小结:
Ribbon 和 Eureka 整合后 Consumer 可以直接调用服务而不用再关心地址和端口号
private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD_DEPT";
1.架构说明
2.参考 microservicecloud-provider-dept-8001 ,新建两份,分别命名为8002,8003
3.新建 8002/8003 数据库,各自微服务分别连各自的数据库
4.修改 8002/8003 各自 yml
修改:端口号以及数据库连接的数据库名。
5.启动3个 eureka 集群配置区
6.启动3个 Dept 微服务并各自测试通过
7.启动 microservicecloud-consumer-dept-80
8.客户端通过 Ribbon 完成负载均衡并访问上一步的 Dept 微服务。
总结:Ribbon 其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和 eureka 结合只是其中的一个案例。
Ribbon 在工作时分成两步:
第一步:先选择 EurekaServer,它优先选择在同一个区域内负载较少的 Server.
第二步:再根据用户指定的策略,在从 Server 取到的服务注册里列表中选择一个地址。
其中,Ribbon 提供了多种策略:比如轮询、随机和根据响应时间加权。
IRule : 根据特定算法从服务列表中选取一个要访问的服务。
轮询
随机
会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,
然后对剩余的服务列表按照轮询策略进行访问
根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。
刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够,会切换到 WeightedResponseTimeRule
先按照 RoundRobinRule 的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务
会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量小的服务
默认规则,复合判断 Server 所在区域的性能和 Server 的可用性选择服务器
指定 IRule 规则:
@Configuration
public class ConfigBean{
@Bean
@LoadBalanced
public RestTempalte getRestTemplate() {
return new RestTemplate();
}
//指定 IRule 规则
@Bean
public IRule myRule() {
return new RoundRobinRule(); //指定 IRule 规则,选择新的算法替代默认的轮询算法
}
}
1.修改 microservicecloud-consumer-dept-80
2.主启动类添加 @RibbonClient
在启动微服务的时候就能去加载我们的自定义 Ribbon 配置类,从而使配置生效。形如:
@RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRunle.class)
MySelfRunle 类不能与主启动类在同一个包下或它的子包下。
3.注意配置细节
MySelfRunle 类不能与主启动类在同一个包下或它的子包下。
4.步骤
1.新建包
2.修改主启动类
3.测试
5.自定义规则深度解析
@Configuration
public class MySelfRunle {
@Bean
public IRule myRule() {
return new RandomRule(); //Ribbon 默认是轮询,自定义为随机
}
}
自定义规则深度解析:
1.问题:依旧轮询策略,但是加上新需求,每个服务器要求被调用 5 次。也即以前是每台机器一次,现在是每台机器 5 次。
2.解析源码: https://github.com/Netflix/ribbon/blob/master/ribbon-laodbalancer/src/main/java/com/netflix/loadbalancer/Random.java
3.参考源码修改为我们需求要求的 RandomRule_ZY.java
4.调用
5.测试
public class RandomRule_ZY extends AbstractLoadBalancerRule {
//total=0 //当 total == 5 以后,我们指针才能往下走,
//index=0 //当前对外提供服务的服务器地址,
// total 需要重新置为0,但是已经达到过一个5次,我们的 index = 1
//分析 : 我们5次,但是微服务只有 8001, 8002, 8003 三台, OK?
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<Server> upList = lb.getReachableServers();
List<Server> allList = lb.getAllServers();
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
if (total < 5) {
server = upList.get(currentIndex);
total ++;
} else {
totatl = 0;
currentIndex ++;
if(currentIndex >= upList.size()) {
currentIndex = 0;
}
}
if (server == null) {
Thread.yield();
continue;
}
}
}
return server;
}
@Configuration
public class MySelfRule{
@Bean
public IRule myRule() {
return new RandomRule_ZY();
}
}
Feign 是一个声明式的 Web 服务客户端,使得编写 Web 服务客户端变得非常容易,只需要创建一个接口,然后在上面添加注解即可。
Feign 能干什么?
Feign 旨在使编写 Java Http 客户端变得更容易。
前面在使用 Ribbon + RestTemplate 时,利用 RestTemplate 对 http 请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于
对服务依赖的调用可能不止一处,往往一个接口会被多出调用,所以通常会针对每个微服务自行封装一些客户端类来包装 这些依赖服务的调用。所以,Feign
在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务饥饿阔的定义。在 Feign 的实现下,我们只需要创建一个接口并使用注解的方式来配置它
(以前是 Dao 接口上面标注 Mapper 注解,现在是一个微服务接口上面标注一个 Feign 注解即可),即可完成对服务提供方的接口绑定,简化了使用
Spring Cloud Ribbon 时,自动封装服务调用客户端的开发量。
1.官网解释:
http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign
Feign 是一个声明式 WebService 客户端。使用 Feign 能让编写 WebService 客户端更加简单,它的使用方法是定义一个接口,然后在上面添加注解,
同时也支持 JAX-RS 标准的注解。Feign 也支持可插拔式的编码器和解码器。Spring Cloud 对 Feign 进行了封装,使其支持了 SpirngMVC 标准注解
和 HttpMessageConverters.Feign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡。
Feign 是一个声明式的 Web 服务客户端,使得编写 WEB 服务客户端变得非常容易,只需要创建一个接口,然后在上面添加注解即可。
参考官网: https://github.com/OpenFeign/feign
Feign 集成了 Ribbon
利用 Ribbon 维护了 MicoserviceCloud-Dept 的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与 Ribbon 不同的是,
通过 feign 只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用
1.参考 microservicecloud-consumer-dept-80
2.新建 microservicecloud-consumer-dept-feign
1.修改主启动类的名字
DeptConsumer80_Feign_App
3.microservicecloud-consumer-dept-feign 工程 pom.xml, 主要添加对 feign 的支持。
4.修改 microservicecloud-api 工程
1.pom.xml
org.springframework.cloud
spring-cloud-starter-feign
2.新建 DeptClientService 接口并新增注解 @FeignClient
3.mvn clean
4.mvn install
5.microservicecloud-consumer-dept-feign 工程修改 Controller,添加上一不新建的 DeptClientService
6.microservicecloud-consumer-dept-feign 工程修改主启动类
@EnableFeignClients
7.测试
8.小结
pom.xml 添加对 feign 的支持
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-feignartifactId>
dependency>
microservicecloud-api
@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<Dept> list();
@RequestMapping(value="/dept/add", method=RequestMethod.POST)
public boolean add(Dept dept);
}
microservicecloud-consumer-dept-feign
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<Dept> list()
{
return this.service.list();
}
@RequestMapping(value = "/consumer/dept/add")
public Object add(Dept dept)
{
return this.service.add(dept);
}
}
主启动类
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);
}
}
总结:
Feign通过接口的方法调用Rest服务(之前是Ribbon+RestTemplate),
该请求发送给Eureka服务器(http://MICROSERVICECLOUD-DEPT/dept/list),
通过Feign直接找到服务接口,由于在进行服务调用的时候融合了Ribbon技术,所以也支持负载均衡作用。
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败。
服务雪崩:
多个微服务之间调用的时候,假设微服务A 调用微服务 B 和微服务 C,微服务B和微服务C 又调用其他的微服务,这就是所谓的"扇出"。
如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会张勇越来越多的系统资源,进而引起系统能够雪崩,这就是
所谓的 "雪崩效应"。
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,
备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消
整个应用程序或系统。
Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix 能够保证在一个
依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
"断路器"本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),
而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
…
https://github.com/Netflix/Hystrix/wiki/How-To-Use
1.是什么
2.参考 microservicecloud-provider-dept-8001
1.新建 mircoservicecloud-provider-dept-hystrix-8001
3.pom.xml
4.yml
5.修改 DeptController
1.@HystrixCommand 报异常后如何处理
1.一旦调用服务方法失败并抛出了错误信息后,会自动调用 @HystrixCommand 标注
6.修改主启动类 DeptProvider8001_Hystrix_App 并添加 @EnableCircuitBreaker
7.测试
服务熔断:
熔断机制是应对雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回"错误"
的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在 Spring Cloud 框架里熔断机制通过 Hystrix 实现。
Hystrix 会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的
注解是 @HystrixCommand.
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-hystrixartifactId>
dependency>
eureka:
instance:
instance-id: microservicecloud-dept8001-hystrix # 自定义服务名称信息
@RestController
public class DeptController{
@Autowired
private DeptService deptService;
@RequestMapping(value="/dept/get/{id}", method=RequestMethod.GET)
//一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand 标注好的 fallbackMethod 调用类中的指定方法
@HystrixCommand(fallbackMethod = "processHystrix_Get")
public Dept get(@PathVarialbe("id") Long id) {
Dept dept = this.deptService.get(id);
if(null == dept) {
throw new RuntimeException("该 ID "+ id + "没有对应的信息");
}
}
public Dept processHystrix_Get(@PathVariable("id") Long id) {
return new Dept().setDeptno(id)
.setDname("该 ID:" + id + " 没有对应的信息, null -- @HystrixComaand")
.setDb_source("no this database in MySQL");
}
}
@SpringBootApplication
@EnableEurekaClient //本服务启动后会自动注册进 eureka 服务中
@EnableDiscoveryClient //服务发现
@EnableCircuitBreaker //对 Hystrix 熔断机制的支持
public class DeptProvider8001_Hystrix_App {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001_Hystrix_App.class, args);
}
}
1.是什么
2.服务降低处理是在客户端完成实现的,与服务端没有关系
3.修改 microservicecloud-api 工程,根据已经有的 DeptClientService 接口新建一个实现了 FallbackFactory 接口的类 DeptClientServiceFallbackFactory
4.修改 mircroservicecloud-api 工程,DeptClientService 接口 在注解 @FeignClient 中添加 fallbackFactory 属性值
5.microservicecloud-api 工程
6.mircoservicecloud-consumer-dept-feign 工程修改 Yml
7.测试
服务降级:
整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来。
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
public DeptClientService create(Throwable cause) {
public List<Dept> list() {
return new Dept().setDeptno(id).setDname("该 ID:" + id + "没有对应的信息,Consumer
客户端提供的降级信息,此刻服务 Provider已经关闭")
.setDb_source("no this database in MySQL");
}
public Dept get(long id)
{
return null;
}
public boolean add(Dept dept) {
return false;
}
}
}
@FeignClient(value = "MICROSERVICECLOUD-DEPT",fallbackFactory=DeptClientServiceFallbackFactory.class)
public interface DeptClientService{
}
microservicecloud-api: mvn clean install
@RestController
public class DeptController{
@Autowired
private DeptService deptService;
@RequestMapping(value="/dept/get/{id}", method=RequestMethod.GET)
//一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand 标注好的 fallbackMethod 调用类中的指定方法
// @HystrixCommand(fallbackMethod = "processHystrix_Get")
public Dept get(@PathVarialbe("id") Long id) {
Dept dept = this.deptService.get(id);
if(null == dept) {
throw new RuntimeException("该 ID "+ id + "没有对应的信息");
}
}
public Dept processHystrix_Get(@PathVariable("id") Long id) {
return new Dept().setDeptno(id)
.setDname("该 ID:" + id + " 没有对应的信息, null -- @HystrixComaand")
.setDb_source("no this database in MySQL");
}
}
server:
port: 80
feign:
hystrix:
enabled: true
服务降级,服务熔断总结:
服务熔断
一把是某个服务故障或者异常引起,类似现实世界中的"保险丝",当某个异常条件被触发,直接熔断整个服务,而不是一直等着服务超时。
服务降级:
所谓降级,一般是从整体负荷考虑。就是当某个服务熔断之后,服务器将不再被调用。此时客户端可以自己准备一个本地 fallback 回调 ,返回一个
缺省值。这样做,虽然服务水平下降,但可用,比直接挂掉要强。
除了隔离依赖服务的调用外, Hystrix 还提供了准实时的调用监控,Hystrix 会持续的记录所有通过 Hystrix 发起的请求的执行信息,并以统计报表和图形的样式进行展示
给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix 通过 hystrix-metrics-event-stream 项目实现了对以上指标的监控。Spring Cloud 提供了 Hystrix
DashBoard 的整合,对监控内容转化成可视化界面。
1.新建工程 microservicecloud-consumer-hystrix-dashboard
2.pom.xml
3.yml
4.主启动类 + 新注解 @EnableHystrixDashboard
5.所有 Provider 微服务提供类都需要监控依赖配置
6.启动 microservicecloud-consumer-hystrix-dashboard 该微服务监控消费端
7.启动 3 个 eureka 集群
8.启动 microservicecloud-provider-dept-hystrix-8001
9.启动相关的微服务工程
10.监控测试
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-hystrixartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-hystrix-dashboardartifactId>
dependency>
server:
port: 9001
@SpringBootApplication
@EnableHystrixDashBoard
public class .. {
}
监控依赖配置
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
Zuul 包含了对请求的路由和过滤两个最主要的功能:
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现
请求校验、服务聚合等功能的基础.Zuul 和 Eureka 进行整合,将 Zuul 自身注册为 Eureka 服务治理下的应用,同时从 Eureka 中获得其他
微服务的消息,也即以后的访问微服务都是通过 Zuul 跳转后获得的。
Zuul 服务最终还是会注册进 Eureka
提供 = 代理 + 路由 + 过滤三大功能
路由、过滤
地址: https://github.com/Netflix/zuul/wiki/Getting-Started
1.新建 Module 模块 microservicecloud-zuul-gateway-9527
2.pom.xml
3.yml
4.hosts 修改
5.主启动类
6.启动
7.测试
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eurekaartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zuulartifactId>
dependency>
application.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
主启动类:
@SpringBootApplication
@EnableZuulProxy
public class Zuul_9527_StartSpringCloudApp
{
public static void main(String[] args)
{
SpringApplication.run(Zuul_9527_StartSpringCloudApp.class, args);
}
}
测试
不用路由: http://localhost:8001/dept/get/2
启用路由: http://myzuul.com:9527/microservicecloud-dept/dept/get/2
1.工程 microservicecloud-zuul-geteway-9527
2.代理名称
3.原真实服务名忽略
4.设置统一公共前缀
5.最后 Yml
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
测试存在的问题
http://myzuul.com:9527/microservicecloud-dept/dept/get/2
http://myzuul.com:9527/mydept/dept/get/1
均可访问此服务
原真实服务名忽略
zuul:
ignored-services: microservicecloud-dept
routes:
mydept.serviceId: microservicecloud-dept
mydept.path: /mydept/**
禁掉所有:
zuul:
ignored-services: "*"
routes:
mydept.serviceId: microservicecloud-dept
mydept.path: /mydept/**
设置统一公共前缀
zuul:
prefix: /atguigu
ignored-services: "*"
routes:
mydept.serviceId: microservicecloud-dept
mydept.path: /mydept/**
最终的 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$
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统会出现大量的服务。
由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。
Spring Cloud 提供了 ConfigServer 来解决这个问题,我们每一个微服务自己带着一个 application.yml,
上百个配置文件的管理...
是什么
SpringCloud Config 为微服务框架中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个
中心化的外部配置。
怎么玩
Spring Cloud Config 分为服务端和客户端两部分。
服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口。
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息配置服务器默认
采用 git 来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以管理 git 客户端工具来方便的管理和访问配置内容。
1.集中管理配置文件
2.不同环境不同配置,动态化的配置更新,分环境部署比如 dev/test/prod/beta/release
3.运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
4.当配置发生变动时,服务不再需要启动即可感知到配置的变化并应用新的配置
5.将配置信息以 REST 接口的形势暴露
由于 SpringCloud Config 默认使用 git 来存储配置文件(也有其他方式,比如支持 SVN 和本地文件),
但最推荐的还是 Git,而且使用的是 http/https 访问的形式
1.用自己的 GitHub 账号在 Github 上新建一个名为 microservicecloud-config 的新 Repository
2.由上一步获得 SSH 协议的 git 地址 [email protected]:zzyybs/microservicecloud-config.git
3.本地硬盘目录上新建 git仓库并clone
1.本地地址: d:\44\mySpringCloud
2.git 命令: git clone [email protected]:zzyybs/microservicecloud-config.git
4.在本地 d:\44\mySpringCloud\microservicecloud-config 里面新建一个 application.yml
5.将上一步的 yml 文件推送到 github 上
6.新建 module 模块 microservicecloud-config-3344 它即为 cloud 的配置中心模块
7.pom.xml
8.yml
9.主启动类 Config_33_44_StartSpringCloudApp
10.windows 下修改 hosts 文件,增加映射
11.测试通过 Config 微服务是否可以从 Github 上获取配置文件
12.配置读取规则
13.成功实现了用 SpringCloud Config 通过 GitHub 获取配置文件
4.yml
保存格式必须为 UTF-8
spring:
profiles:
active:
- dev
--- #注意分隔符
spring:
profiles: dev
application:
name: microservicecloud-config-atguigu-dev
--- #注意分隔符
spring:
profiles: test
application:
name: microservicecloud-config-atguigu-test
#保存格式为 UTF-8
5.将 yml 推送到 github 上
git add .
git commit -m 'init file'
git push origin master
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-config-serverartifactId>
dependency>
application.yml
server:
port: 3344
Spring:
application:
name: microservicecloud-config
cloud:
config:
server:
git:
uri: [email protected]:zzyybs/microservicecloud-config.git #GitHUb 上面的 git 仓库的名字
主启动类
@SpringBootApplication
@EnableConfigServer
public class Config_3344_StartSpringCloudApp{
public static void main(String[] args) {
SpringApplication.run(Config_3344_StartSpringCloudApp.class, args)
}
}
hosts : 127.0.0.1 config-3344.com
测试:
1.启动微服务3344
2.http://config-3344.com:3344/application.dev.yml
3.http://config-3344.com:3344/application-test.yml
4.http://config-3344.com:3344/application-xxx.yml(不存在的配置)
配置读取规则:
1.官网
2./{application}-{profile}.yml
3./{application}/{profile}[/{label}]
4./{label}/{application}-{profile}.yml
1.在本地 d:\44\mySpringCloud\microservicecloud-config 路径下新建文件 microservicecloud-config-client.yml
2.microservicecloud-config-client.yml 内容
3.将上一步提交到 GitHub 中
4.新建 microservicecloud-config-client-3355
5.pom.xml
6.bootstrap.yml
7.application.yml
8.windows 下修改 hosts 文件,增加映射
127.0.0.1 client-config.com
9.新建 rest 类,验证是否能从 GitHub 上读取配置
10.主启动类 ConfigClient_3355_StartSpringCloudApp
11.测试
12.成功实现了客户端 3355 访问 SpringCloud Config 3344通过 GitHub 获取配置信息
micoservicecloud-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/
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
bootstrap.yml
application.yml : 是用户级的资源配置项
bootstrap.yml : 是系统级的,优先级更高
SpringCloud 会创建一个 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://http://config-3344.com:3344 #本次微服务启动后先去找 3344 服务,通过 SpringCloudConfig 获取 GitHub 的服务地址
步骤:
1.Git 配置文件本地配置
1.1.在本地 d:\44\mySpringCloud\microservicecloud-config 路径下新建文件 microservicecloud-config-eureka-client.yml
1.2.microservicecloud-config-eureka-client.yml 内容
1.3.在本地 d:\44\mySpringCloud\microservicecloud-config 路径下新建文件 microservicecloud-config-dept-client.yml
1.4.microservicecloud-config-dept-client.yml 内容
2.Config 版的 eureka 服务端
2.1.新建工程microservicecloud-config-eureka-client-7001
2.2.pom.xml
2.3.bootstrap.yml
2.4.application.yml
2.5.主启动类 Config_Git_EurekaServerApplication
2.6.测试
3.Config 版的 dept 微服务
3.1.参考之前的8001拷贝后新建工程 mircroservicecloud-config-dept-client-8001
3.2.pom.xml
3.3.bootstrap.yml
3.4.application.yml
3.5.主启动类及其他一套业务逻辑代码
3.6.配置说明
3.7.测试
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
---
server:
port: 7001 #注册中心占用 7001 端口,冒号后面必须要有空格
spring:
profiles: test
application:
name: microservicecloud-config-eureka-client
eureka:
instance:
hostname: eureka7001.com
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.git.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 服务列表内
server-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.git.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 服务列表内
server-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$
microservicecloud-config-eureka-client-7001
pom.xml
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
主启动类:
@SpringBootApplication
@EnableEurekaServer
public class Config_Git_EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(Config_Git_EurekaServerApplication.class, args);
}
}
3.3. bootstrap.yml
spring:
cloud:
config:
name: microservicecloud-config-dept-client #需要从 github 上读取的资源名称
#profile 配置是什么就取什么配置 dev or test
#profile: dev
profile: test
label: master
uri: http://config-3344.com:3344
整套开发技术栈以 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)等进行交互
第三方框架:每个微服务模块根据实现的需要,通常还需要使用一些第三方框架,比如常见的有:缓存服务(Reis)、图片服务(FastDFS)、搜索引擎(Elasticsearch)、安全管理(Shiro)等
MySQL数据库:可以按照微服务模块进行拆分,统一访问公共库或者单独自己库,可以单独构建 MySQL 集群或分库分表 MyCat 等。
reka7001.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: p r o j e c t . a r t i f a c t I d project.artifactId project.artifactId
build.version: p r o j e c t . v e r s i o n project.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.git.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 服务列表内
server-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: p r o j e c t . a r t i f a c t I d project.artifactId project.artifactId
build.version: p r o j e c t . v e r s i o n project.version project.version
```xml
microservicecloud-config-eureka-client-7001
pom.xml
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
主启动类:
@SpringBootApplication
@EnableEurekaServer
public class Config_Git_EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(Config_Git_EurekaServerApplication.class, args);
}
}
3.3. bootstrap.yml
spring:
cloud:
config:
name: microservicecloud-config-dept-client #需要从 github 上读取的资源名称
#profile 配置是什么就取什么配置 dev or test
#profile: dev
profile: test
label: master
uri: http://config-3344.com:3344
整套开发技术栈以 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)等进行交互
第三方框架:每个微服务模块根据实现的需要,通常还需要使用一些第三方框架,比如常见的有:缓存服务(Reis)、图片服务(FastDFS)、搜索引擎(Elasticsearch)、安全管理(Shiro)等
MySQL数据库:可以按照微服务模块进行拆分,统一访问公共库或者单独自己库,可以单独构建 MySQL 集群或分库分表 MyCat 等。
[外链图片转存失败(img-EXARO4LM-1566610512883)(C:\Users\laughig\AppData\Roaming\Typora\typora-user-images\1566609953323.png)]