学习笔记源码
SpringCloud
回顾之前学的
- javaSE
- 数据库
- 前端
- servlet
- http
- mybatis
- spring
- springmvc
- springboot
- dubbo(javaRPC框架)+zookeeper(协调注册服务和调用服务的站点)
- maven,git
- ajax,json
串一下自己会的
-
数据库
-
mybatis
-
spring
-
springmvc
-
springboot
-
dubbo(javaRPC框架)+zookeeper(协调注册服务和调用服务的站点)
-
maven,git
-
ajax,json
这个阶段如何学?
微服务的四个问题?
1.客户端如何访问这么多服务? 访问一个接口,接口在分发到不同的服务
2.服务之间如何通信?HTTP/RPC
3.这么多服务?如何治理? 通过注册中心
4.服务挂了,如何处理?备份多个服务,容灾机制,防止整条链断开
解决方案:
SpringCloud,是一套生态,就是来解决以上分布式架构的4个问题
想使用SpringCloud,必须要掌握SpringBoot,因为SpringCloud是基 于SpringBoot;
1. Spring Cloud NetFlix ,出来了一套解决方案! - -站式解决方案。我们都可以直接去这里拿?
问题一解决:Api网关,zuu1组件
问题二解决:Feign --> HttpClient ---> HTTP的通信方式,同步并阻塞
问题三解决:服务注册与发现,Eureka
问题四解决:熔断机制,Hystrix
2018年年底,NetFlix宣布无限期停止维护。生态不再维护,就会脱节。
2. Apache Dubbo zookeeper,第二套解决系统
API : 没有! 要么找第三方组件,要么自己实现
Dubbo是一个高性能的基于Java实现的RPC通信框架! 2.6.x
服务注册与发现,zookeeper: 动物园管理者(Hadoop ,Hive)
没有: 借助了Hystrix
不完善,Dubbo .
3. SpringCloud Alibaba-站式解决方案 !
所有微服务都有类似的内容:
1、API
2、HTTP/RPC
3、服务注册与发现
4、熔断机制
根本原因:
分布式
1、常见面试题
1.1 什么是微服务
1.2 微服务之间如何通讯?
1.3 springcloud和dubbo有什么区别?
1.4 springboot和springcloud,谈谈你的理解?
1.5 什么是服务熔断?什么是服务降级
1.6 微服务的优缺点是什么?说下在项目中遇到的坑
1.7 你知道的微服务技术栈有哪些?请列举一二
1.8 eureka和zookeeper都可以提供服务注册和发现的区别,请说说两个的区别?
2、微服务
2.1 微服务简介
将传统的一站式应用,根据业务拆分成一个个的服务。一个服务做一件事情。类似进程,可以单出启动和销毁。有自己独立的数据库。
2.2 微服务和微服务架构
微服务
关注服务的大小,狭义可以看做IDEA的一个个微服务工程,或者module。
微服务架构
是一种架构模式。提倡将单一应用程序划分成小的服务,服务之间互相协调,为用户提供最终价值。
2.3 优点和缺点
优点
- 每个服务高内聚,代码易理解。可聚焦特定的业务功能和需求。
- 低耦合,在开发阶段和部署阶段都是独立的
- 开发简单效率高,可被小团队单独开发
- 微服务可以用不同的语言开发
- 可以容易,灵活的方式集成自动部署
- 只有业务逻辑代码,无HTML,css等其他混合
- 每个微服务可以有自己的数据库,也可以共用数据库
缺点
- 开发人员承担分布式系统复杂性增加
- 服务增加,运维压力增大
- 服务间通信成本
- 数据一致性问题
- 系统集成测试
2.4 微服务技术栈
2.5 为什么选择springcloud作为微服务架构
1、选型依据
- 框架成熟
- 社区热度高
- 可维护性高
- 学习难度低
2、微服务框架对比
服务框架 | Netflix/SpringCloud | Motan | gRPC | Thrift | Dubbo/DubboX |
---|---|---|---|---|---|
功能定位 | 完整的微服务框架 | RPC框架,整合了ZK和Consul,实现了集群环境的基本服务注册/发现 | RPC框架 | RPC框架 | 服务框架 |
支持Rest | 是,Ribbon支持多种可插拔的序列化选择 | 否 | 否 | 否 | 否 |
支持RPC | 否 | 是(Hession2) | 是 | 是 | 是 |
支持多种语言 | 是(Rest形式) | 否 | 是 | 是 | 否 |
负载均衡 | 是(服务端zuul+客户端Ribbon),zuul-服务,动态路由,云端负载均衡 | 是(客户端) | 否 | 否 | 是(客户端) |
配置服务 | Netfix Archaius,Spring Cloud Config Server集中配置 | 是(zookeeper提供) | 否 | 否 | 否 |
服务调用链监控 | 是(zuul),zuul提供边缘服务,API网关 | 否 | 否 | 否 | 否 |
高可用/容错 | 是(服务端Hystrix+客户端Ribbon) | 是(客户端) | 否 | 否 | 是(客户端) |
应用案例 | Netflix | Sina | |||
社区活跃度 | 高 | 一般 | 高 | 一般 | 17年重新开始 |
学习难度 | 中 | 低 | 高 | 高 | 低 |
文档丰富程度 | 高 | 一般 | 一般 | 一般 | 高 |
其他 | springcloud bus为程序提供了更多管理端点 | 支持降级 | Netflix内部在开发继承gRPC | IDL定义 | 使用的公司比较多 |
3、springcloud
3.1 是什么
3.2 springcloud与springboot的关系
- springboot专注于开发单个微服务。-jar
- springcloud关注全局的微服务协调整理框架。将springboot开发的微服务整合 起来。提供以下功能:
- 配置管理
- 服务发现
- 断路器
- 路由
- 微代理
- 事件总线
- 全局锁
- 决策竞选
- 分布式会话等
- springboot可以历来springcloud单独使用,springcloud离不开springboot,属于依赖关系
3.3 Dubbo和springcloud技术选型
1、分布式+服务治理dubbo
成熟的架构:应用服务化拆分+消息中间件
网站架构图
2、dubbo和springcloud区别
定位不同:dubbo是RPC框架,SpringCloud是微服务架构下的一站式解决方案
最大区别:springcloud不使用rpc通信方式,使用基于http的rest方式。
品牌机和组装机的区别:
springcloud的功能更加强大,能够与framework,springboot,springdata等项目完美融合。使用dubbo构建的微服务架构就像组装电脑,各个环节的自由度很高,但最终结果可能因为某个部分质量问题而出问题。
3、参考文档
- https://springcloud.cc/spring-cloud-netflix.html
- 中文API文档:https://springcloud.cc/spring-cloud-dalston.html
- springcloud中文社区:http://springcloud.cn/
- springcloud中文网:https://springcloud.cc
4、实践
4.1 springcloud版本选择
实际开发版本关系
4.2 SpringCloud之demo
首先准备数据库环境,新建数据库db01,在其建立表dept。
并插入数据:
1、首先建立一个maven项目,并引入相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.plancer</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>springcloud-api</module>
<module>springcloud-provider-dept-8001</module>
<module>springcloud-consumer-dept-80</module>
</modules>
<!--特别注意:打包方式使用pom-->
<packaging>pom</packaging>
<!--指定下方引入依赖的版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- springcloud的依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- springboot依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- springboot启动器-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 日志测试-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2、新建实体类模块springcloud-api
引入pom依赖,版本为其父项目中指定的版本。
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
建立实体类,orm关系映射
@Data
@NoArgsConstructor
@Accessors
public class Dept implements Serializable {
private Long deptno;
private String dname;
private String db_source;
public Dept(String dname) {
this.dname = dname;
}
}
3、新建服务提供者模块springcloud-provider-dept-8001
引入相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.plancer</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-provider-dept-8001</artifactId>
<dependencies>
<!-- 配置api的module,来拿到实体类-->
<dependency>
<groupId>com.plancer</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- jetty:当做服务器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!-- 热部署工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
- 在resources下建立服务提供者的配置文件
server:
port: 8001
#mybatis配置
mybatis:
type-aliases-package: com.plancer.springcloud.pojo
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
#spring配置
spring:
application:
name: springcloud-provider-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
- 新建mybatis目录,并在其中编写mybatis核心配置文件
<?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>
- dao层写操作数据库的接口
@Mapper
@Repository
public interface DeptDao {
public boolean addDept(Dept dept);
public Dept queryById(Long id);
public List<Dept> queryAll();
}
- mapper下落地sql语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.plancer.springcloud.dao.DeptDao">
<insert id="addDept" parameterType="Dept">
insert into dept (dname,db_source)
values (#{dname},DATABASE())
</insert>
<select id="queryById" parameterType="Long" resultType="Dept">
select * from db01.dept where deptno=#{id}
</select>
<select id="queryAll" resultType="Dept">
select * from db01.dept
</select>
</mapper>
- 编写service层(service层调用dao层)
service接口
public interface DeptService {
public boolean addDept(Dept dept);
public Dept queryById(Long id);
public List<Dept> queryAll();
}
service接口的实现类
@Service
public class DeptServiceImpl implements DeptService{
@Autowired
private DeptDao deptDao;
@Override
public boolean addDept(Dept dept) {
return deptDao.addDept(dept);
}
@Override
public Dept queryById(Long id) {
return deptDao.queryById(id);
}
@Override
public List<Dept> queryAll() {
return deptDao.queryAll();
}
}
- 编写controller层(调用service层)
对服务端的请求进行处理
注意:RestController,是为了将类中方法的返回值转换json,而不走视图解析器,否则报404错误
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@PostMapping("/dept/add")
public boolean addDept(Dept dept){
return deptService.addDept(dept);
}
@GetMapping("/dept/get/{id}")
public Dept get(@PathVariable("id") Long id){
return deptService.queryById(id);
}
@GetMapping("/dept/list")
public List<Dept> queryAll(){
return deptService.queryAll();
}
}
4、新建消费者模块springcloud-consumer-dept-80
- 引入pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.plancer</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-consumer-dept-80</artifactId>
<!-- 实体类+web+热部署-->
<dependencies>
<dependency>
<groupId>com.plancer</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
- 在客户端的配置文件中设置客户端的端口
server:
port: 80
- 客户端要使用restTemplate,通过请求服务端的url,来调用服务端的服务,为此需要把restTemplate注入容器
@Configuration//相当于applicationContext.xml
public class ConfigBean {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
- 客户端的controller
@RestController
public class DeptConsumerController {
//消费者无service层
//RestTemplate直接调用,需要将其注册到spring中
//restTemplate方法的参数类型(url,携带的实体 Map,Class<T> responseType方法返回值的类型)
@Autowired
private RestTemplate restTemplate;//通过此模板访问远程http服务的方法
private static final String REST_URL_PREFIX="http://localhost:8001";//将几个请求方法共有的部分提取出来
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept){
return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
}
@RequestMapping("/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id){
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
}
@RequestMapping("/consumer/dept/list")
public List<Dept> list(){
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
}
}
- 添加客户端的启动类
@SpringBootApplication
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.class,args);
}
}
最后,先启动服务端,提供服务,在通过客户端,调用服务端的服务,在客户端也能通过服务端操作数据库。
5、Eureka服务注册与发现
5.1 是什么
- Eureka是NetFlix的一个子模块。Eureka基于REST的服务,用于定位,有了服务注册与发现,只需要使用服务的标识符,就可以访问到服务,而无需膝盖服务调用的配置文件。功能类似dubbo的注册中心,如zookeeper。
Eureka注册中心示意图
新建服务的固定步骤
1、导入依赖
2、编写配置文件
3、开启功能 @EnableXXXX
4、配置类
Eureka注册中心模块的设置
1、新建模块springcloud-eureka-7001,导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.plancer</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-provider-dept-8001</artifactId>
<dependencies>
<!--eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--监控完善actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 配置api的module,来拿到实体类-->
<dependency>
<groupId>com.plancer</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- jetty:当做服务器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!-- 热部署工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
2、注册中心配置文件设置
server:
port: 7001
#Eureka配置
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
register-with-eureka: false #表示服务端不需要像eureka注册中心注册自己,本身就是注册中心
fetch-registry: false #为false表示自己就是注册中心
service-url: #通过访问该url来访问管理服务的注册中心
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
3、注册中心的启动类,并开启eureka服务端的服务
package com.plancer.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @author plancer16
* @create 2020-08-11 17:56
*/
//访问注册中心页面:http://localhost:7001/
@SpringBootApplication
@EnableEurekaServer//表示eureka服务端的启动类
public class EurekaServer_7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer_7001.class,args);
}
}
将服务注册进注册中心
1、对之前的provide服务引入eureka依赖,并引入监控信息的actuator依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--监控完善actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、配置文件中配置eureka相关配置
#Eureka的配置,服务注册的地址
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/
instance:
instance-id: springcloud-provider-dept8001 #表示注册到euraka中心的描述信息
#info配置 为eureka注册中心的描述信息点击后的页面填写信息
info:
app.name: plancer-springcloud
company.name: plancer16.github.io
3、主启动类开启eureka客户端服务和服务发现
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class DeptProvider_8001{
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class,args);
}
}
最后,开启eureka那个模块后,再启动provider服务,就会发现eureka中注册了该服务
另外:得到微服务的具体信息:
1、服务的controller中自动注入discoveryClient
//通过client得到微服务的具体信息
@Autowired
private DiscoveryClient client;
2、配置访问url来输出微服务的信息
//注册进来的微服务,获取信息
@GetMapping("/dept/discovery")
public Object discovery(){
//获取微服务列表的清单
List<String> services = client.getServices();
System.out.println("discovery=>services" + services);
List<ServiceInstance> instances = client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");
for (ServiceInstance instance : instances) {
System.out.println(instance.getHost() + "\t" +
instance.getPort() + "\t" +
instance.getUri() + "\t" +
instance.getServiceId()
);
}
return this.client;
}
3、服务的启动类开启discoveryClient
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class DeptProvider_8001{
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class,args);
}
}
效果:
eureka的自我保护机制
是什么:某个时刻微服务不能使用,eureka不会立刻清理,依旧对该微服务的信息进行保存
- 默认情况,在eurekaServer在一定时间内(通常是90s)没有接收到微服务实例的心跳,就会注销该实例。但是当因为网络分区故障时,微服务和eureka之间无法通信,不应该注销该微服务,因为该微服务是健康的。此时,通过自我保护机制,eurekaServer在短时间内丢失大量客户端时,不会删除服务注册表中的任何微服务,待网络正常后,eurekaServer退出自我保护机制。
- 综上,其实一种应对网络故障的保护措施,宁可保留所有服务,也不盲目注销任何健康的微服务。
6、eureka集群
本机模拟eureka集群
1、首先在host文件中添加三个eureka的url,由于只有本机一台电脑,所以三个域名映射本机地址。
C:\Windows\System32\drivers\etc中的host文件添加如下:
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
127.0.0.1 eureka7003.com
2、配置eureka7001的配置文件
server:
port: 7001
#Eureka配置
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #表示服务端不需要像eureka注册中心注册自己,本身就是注册中心
fetch-registry: false #为false表示自己就是注册中心
service-url: #通过访问该url来访问管理服务的注册中心
#单机时,绑定自己defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#集群时,绑定其他服务
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
3、新建eureka7002,eureka7003,并引入与eureka7001相同的依赖。各自编写配置文件,设置好本机名称和对应绑定的集群中其他eureka的地址。
7002配置文件:
server:
port: 7002
#Eureka配置
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
register-with-eureka: false #表示服务端不需要像eureka注册中心注册自己,本身就是注册中心
fetch-registry: false #为false表示自己就是注册中心
service-url: #通过访问该url来访问管理服务的注册中心
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
7003配置文件:
server:
port: 7003
#Eureka配置
eureka:
instance:
hostname: eureka7003.com #eureka服务端的实例名称
client:
register-with-eureka: false #表示服务端不需要像eureka注册中心注册自己,本身就是注册中心
fetch-registry: false #为false表示自己就是注册中心
service-url: #通过访问该url来访问管理服务的注册中心
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
4、分别编写eureka7002和eureka7003的启动类
5、将provider服务注册到集群中,只需要将配置文件的url添加集群中所有的eureka注册中心
#Eureka的配置,服务注册的地址
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: springcloud-provider-dept8001 #表示注册到euraka中心的描述信息
6、最后,依次启动eureka7001,eureka7002,eureka7003,provider服务。
可见,每个eureka注册中心都注册了provider服务。并与其他注册中心构成了一个集群。
CAP原则和对比zookeeper
RDBMS(Mysql,Oracle,sqlServer)==>满足ACID
NoSQL(redis,mongdb)==>满足CAP原则
CAP是什么?
- C(Consistency)一致性
- A(Availablilty)可用性
- P(Partition tolerence)分区容错性
CAP只能三选二:CA/AP/CP
- CA:单点集群,满足一致性和可用性,可扩展性较差
- CP:满足一致性和分区容错性,性能不是很高
- AP:满足可用性和分区容错性,对一致性要求低
zookeeper保证CP
服务注册功能对可用性的要求比一致性高。zookeeper在一个节点因为网络 问题而与其他节点失去联系后,会进行leader选举,长时间导致集群中的所有节点都不可用。
Eureka保证AP
eureka的每个节点都是平等的。几个节点挂点并不影响正常节点的工作。剩余节点仍然提供注册与查询服务。eureka的客户端向某个eureka注册时,若注册失败,则自动切换其他节点,只有有其他eureka节点存在,就能保证注册服务的可用性,只是可能查到的数据不是最新的。
eureka可以很好应对网络问题导致部分节点失去联系的情况,而不是像zookeeper一样整个注册服务瘫痪。
7、负载均衡和SpringCloud Ribbon
什么是负载均衡?
客户端访问服务端的服务,请求被平摊地分发到不同的服务器,防止服务器上的请求不均。实现系统的高可用。
有两种方式:
- 轮询:请求按顺序依次分发
- 随机:根据hash等算法被分配到不同的服务器
常用的负载均衡软件:
- Nginx
- Lvs
负载均衡简单分类:
- 集中式LB
在服务的消费方和提供方之间提供LB设施,如Nginx,由该设施将请求分发至服务的提供方
- 进程式LB
将LB逻辑集成到消费方,消费方从注册中心获知到有哪些地址可用,然后从这些地址中选择一个合适的服务器。
Ribbon是什么?
一套客户端负载均衡的工具。
在配置文件中列出LoadBalance的所有机器。Ribbon自动基于某种规则帮助客户端连接这些机器。
属于进程内LB,是一个类库,集成于消费方进程,消费方通过ribbon获取到服务提供方的地址。
用Ribbon实现负载均衡
1、客户端(消费方)导入ribbon依赖
<!-- ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
2、配置ribbon向哪里查询可用的服务(用于将请求分发给不同的服务器)
server:
port: 80
#Eureka配置
eureka:
client:
register-with-eureka: false #客户端不向eureka注册自己
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
3、给restTemplate加上负载均衡注解@LoadBalanced。默认为ribbon实现。
@Configuration//相当于applicationContext.xml
public class ConfigBean {
@Bean
@LoadBalanced //Ribbon
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
实现结果:
三个服务开启,默认是轮询策略,会在服务提供方1,2,3中不断切换:
自定义负载均衡算法:
1、在启动类的上一级目录中添加自定义Rule
@Configuration
public class KuangRule{
//将自定义的IRule(ribbon负载均衡算法)加入容器
@Bean
public IRule myRule(){
return new KuangRandomRule();
}
}
2、KuangRandomRule类中自定义实现的具体算法(可根据默认的RandomRule来更改)
3、在主启动类上添加自定义ribbon类的注解,指定名称和其具体的ribbon类,该ribbon类必须是@Configuration注解标注的。
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "xxx",configuration = KuangRule.class)
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.class,args);
}
}
8、Feign
feign是声明式的web Service客户端,简化微服务之间的调用。
方式:创建一个接口,然后添加注解
调用微服务的两种方法:
1、微服务名字(ribbon)
2、接口和注解(feign)
**能干什么?**简化java Http客户端的编写
- Feign实现下,只需要创建一个微服务接口,并在上面标注Feign注解即可(类似DAO接口上面标注Mapper接口)
Feign方式实现负载均衡
1、springcloud实体(springcloud-api模块)添加feign依赖,编写service
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
service编写
@Component//加入容器
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")//服务端注册到注册中心的服务名(服务端配置文件中spring的名字)
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id);
@GetMapping("/dept/list")
public List<Dept> queryAll();
@PostMapping("/dept/add")
public boolean addDept(Dept dept);
}
2、编写consumer-dept-feign(客户端使用feign)
首先导入feign依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.plancer</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
controller里注入springcloud-api中的service,对消费方的请求,采用该service来处理
@RestController
public class DeptConsumerController {
@Qualifier("deptClientService")
@Autowired
private DeptClientService service;
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept){
return this.service.addDept(dept);
}
@RequestMapping("/consumer/get/{id}")
public Dept get(@PathVariable("id") Long id){
return this.service.queryById(id);
}
@RequestMapping("/consumer/dept/list")
public List<Dept> list(){
return this.service.queryAll();
}
}
在consumer-dept-feign启动类上添加扫描springcloud-api的包,使得Feign生效的注解
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.plancer.springcloud"})
public class FeignDeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(FeignDeptConsumer_80.class,args);
}
}
4、依次启动eureka7001,deptProvider8001,deptProvider8002,consumer-dept-feign,输入客户端方面的请求,验证结果
总结:
实体中添加service,与服务端的服务名称相绑定。并与服务端处理服务端请求一样,处理服务端的请求。
feign客户端的controller,引入实体的service,并通过实体的service来处理客户端方面的请求。
9、Hystrix
服务雪崩
多个微服务之间调用,如果微服务A调用微服务B,微服务B调用C…,称为“扇出”。扇出的链路上某个微服务的调用响应时间过长,对微服务的A的调用就会占用越来越多的系统资源,导致系统崩溃,即“雪崩效应”。
什么是Hystrix
用于处理分布式系统延迟和容错的开源库。Hystrix保证一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障。提高整个分布式系统的弹性。
通过断路器的故障监控,向调用方法返回一个服务预期的,可处理的备选响应(CallBack),而不会长时间等待或者抛出调用方法无法处理的异常,从而服务调用线程不会长时间的占用。
服务熔断
是应对雪崩效应的一种链路保护机制。
当链路中的某个服务不可用时,对服务进行降级。熔断该节点微服务的调用,快速返回错误的响应信息。
springcloud中的熔断由hystrix实现。熔断机制注解是@HystrixCommand。
Hystrix实例(应用在服务端)
1、拷贝一份服务提供者的代码,并做如下的修改
引入hystrix依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
编写controller,在运行到抛出异常的代码时,跳到hystrix指定的代码,fallbackmethod指定的方法。
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@GetMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixGet")
public Dept get(@PathVariable("id") Long id) {
Dept dept = deptService.queryById(id);
if (dept == null) {
throw new RuntimeException("id=>" + id + "不存在该用户,信息无法找到");//当抛出异常时,走补救的方法;原来如果没有捕获异常,就崩溃
}
return dept;
}
//备选方法
public Dept hystrixGet(@PathVariable("id") Long id) {
return new Dept()
.setDeptno(id)
.setDname("id=>"+id+"没有对应的信息,null--@Hystrix")
.setDb_source("no this data_source");
}
}
启动类添加断路器支持
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableCircuitBreaker//添加断路器,支持hystrix
public class DeptProvider_Hystrix_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_Hystrix_8001.class,args);
}
}
最后依次开启集群7001,7002,provider-dept-hystrix-8001,deptConsumer-80。测试结果。
成功结果:
对比没有添加hystrix功能的结果:
在服务端的配置文件中添加描述信息指向ip地址,而不是localhost。
服务降级
访问服务C时,由于用户量少,客户端接收到信息,服务降级,服务C不可用,将更多的系统资源留给A去使用。
1、实体springcloud-api中添加服务失败回调工厂
此处:当提供服务方断开服务时,查询指定id的Dept服务就会走自定义fallbackFactory中的函数,并返回相应的结果
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory {
@Override
public DeptClientService create(Throwable throwable) {
return new DeptClientService() {
@Override
public Dept queryById(Long id) {
return new Dept()
.setDeptno(id)
.setDname("id=>"+id+"没有对应的信息,客户端提供了降级信息,现在该服务已经关闭")
.setDb_source("没有数据");
}
@Override
public List<Dept> queryAll() {
return null;
}
@Override
public boolean addDept(Dept dept) {
return false;
}
};
}
}
实体springcloud-api的service绑定相应的fallbackFactory
@Component//加入容器
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)//服务端注册到注册中心的服务名(服务端配置文件中spring的名字)
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id);
@GetMapping("/dept/list")
public List<Dept> queryAll();
@PostMapping("/dept/add")
public boolean addDept(Dept dept);
}
consumer-dept-feign客户端中添加feign支持hystrix的配置文件支持。
#feign-hystrix开启降级
feign:
hystrix:
enabled: true
2、依次启动7001集群,provider-8001,consumer-dept-feign。此时正常访问没有问题,当关闭provider-8001,再次访问时,服务降级功能就体现出来了:
服务熔断和服务降级的区别:
服务熔断:
-
服务端
-
某个服务超时或者异常,引起熔断
服务降级:
- 客户端
- 当某个服务熔断或者关闭后,该服务不能被调用。在客户端,写一个fallbackfactory,返回默认值,从客户端的实体发出信息:提醒用户,服务端的该服务已经不可调用(已经关闭)
hystrix之Dashboard流监控
1、新建consumer-hystrix-dashboard模块,用以启动dashboard
导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--监控完善actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 配置api的module,来拿到实体类-->
<dependency>
<groupId>com.plancer</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- jetty:当做服务器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!-- 热部署工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
配置文件配置端口
server:
port: 9001
主启动设置启动dashboard,并设置不扫描mybatis
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableHystrixDashboard//开启监控页面,服务端相应的也要引入actuator依赖,显示监控信息
public class DeptConsumerDashboard_9001 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashboard_9001.class,args);
}
}
2、服务提供方要使用带有hystrix功能的,并在主启动类类中将如下类,加入容器,url地址为之后监控服务端行为需要的地址。
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableCircuitBreaker//添加断路器,支持hystrix
public class DeptProvider_Hystrix_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_Hystrix_8001.class,args);
}
@Bean
public ServletRegistrationBean getServlet(){
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
}
最终,依次启动eureka7001,provider-hystrix-8001,consumerDashboard9001。
访问http://localhost:9001/hystrix,进入dashboard界面。
输入服务端指定的url地址,进入监控界面,然后向浏览器输入8001provider服务端的请求,可根据监控界面看到流量情况
10.zuul网关
整个springcloud都是围绕以下结构图来展开,下面介绍网关
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pjwz3J5z-1597980719950)(SpringCloud.assets/image-20200815154023380.png)]
zuul网关的作用:
原本用户访问注册到eureka注册中心的微服务,需要输入不同的url地址,但是如果把zuul注册到eureka中,就可以通过网关统一管理这些微服务。
zuul的功能:
- 代理
- 路由
- 过滤
zuul之demo步骤
1、新建zuul模块,导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--监控完善actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 配置api的module,来拿到实体类-->
<dependency>
<groupId>com.plancer</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- jetty:当做服务器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!-- 热部署工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
2、编写配置文件
server:
port: 9527
spring:
application:
name: springcloud-zuul
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: zuul9527
prefer-ip-address: true
info:
app.name: plancer-springcloud
company.name: plancer16.github.io
zuul:
routes:
mydept.serviceId: springcloud-provider-dept #实现路由
mydept.path: /mydept/** #实现路由
ignored-services: "*" #不能使用服务名(serviceId)进行访问,只能使用path进行访问;实现过滤
prefix: /kuang #设置统一的前缀
其中,serviceId和path进行绑定,将eureka注册中心的服务和指定的访问路径相绑定
3、编写启动类,并配置启用zuul的注解
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableZuulProxy
public class ZuulApplication_9527 {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication_9527.class,args);
}
}
最后,依次启动eureka7001,springcloud-provider-dept-hystrix-8001,zuul-9527。访问如下路径:http://kuangstudy.com:9527/kuang/mydept/dept/get/2
通过zuul网关,得到了查询结果
11、SpringCloud config分布式配置
背景
每一个微服务都有一个application.yml,很多服务需要管理配置文件,麻烦,springcloud提供ConfigServer来解决这个问题
SpringCloud config分布式配置中心
springcloud config为微服务架构中的微服务提供了一个中心化的外部配置。SpringCloud是C/S架构,分为:
- 客户端
- 服务端
springcloud config与github整合
思想:客户端只需要连接服务端,服务端连接git,通过git上的操作,就能让不同的客户端能读取同样的线上修改后的配置文件
服务端设置
1、首先准备一个文件夹。在gitee上创建一个项目,down到本地。
添加application.yml文件。不同环境的name不能相同
spring:
profiles:
active: dev
---
spring:
profiles: dev
---
spring:
profiles: test
并push到远程仓库。
2、建立config-server-3344模块。
导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监控完善actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-config-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
</dependencies>
编写配置文件
server:
port: 3344
spring:
application:
name: springcloud-config-server
#远程连接仓库设置,可以通过服务端端口+git上的文件名,读取上面的文件和配置
cloud:
config:
server:
git:
uri: https://gitee.com/plancer16/springcloud-config.git #为git上项目的https地址
配置config-server的主启动类
server:
port: 3344
spring:
application:
name: springcloud-config-server
#远程连接仓库设置,可以通过服务端端口+git上的文件名,读取上面的文件和配置
cloud:
config:
server:
git:
uri: https://gitee.com/plancer16/springcloud-config.git #为git上项目的https地址
访问测试,config-server(服务端)是否和git远程仓库连接起来:可以发现连接成功
上述url路径的格式:localhost:端口号/分支/配置文件名-环境.文件种类
其中访问的url可以参考springcloud中文文档有四种方式:
application:文件名
profile:环境
label:分支
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
客户端设置
1、导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监控完善actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-config -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
</dependencies>
2、编写配置文件
application.yml
#用户级别的配置
spring:
application:
name: springcloud-config-client-3355
bootstrap.yml
#系统级别的配置
spring:
cloud:
config:
name: config-client #从git上获取的文件名,不要后缀
profile: test #指定环境
label: master
uri: http://localhost:3344 #客户端连接到服务端
3、编写controller
其中value值,表示git上配置文件中取到的值
@RestController
public class ConfigClientController {
@Value("${spring.application.name}")
private String applicationName;
@Value("${eureka.client.service-url.defaultZone}")
private String eurekaServer;
@Value("${server.port}")
private String port;
@RequestMapping("/config")
public String getConfig(){
return "applicationName:"+applicationName+
"eurekaServer:"+eurekaServer+
"port"+port;
}
}
4、配置启动类
@SpringBootApplication
public class ConfigClient_3355 {
public static void main(String[] args) {
SpringApplication.run(ConfigClient_3355.class,args);
}
}
当指定访问的是test环境,对应的端口是git配置文件中的8202,因此访问8202下config请求,就会被client的Controller处理,响应相应的结果,而client本事3355的端口并没有访问到。
eureka注册中心连接从config-server
1、编写config-eureka.yml作为远程eureka注册中心的配置文件,并上传到git上
spring:
profiles:
active: dev
---
server:
port: 7001
spring:
profiles: dev
application:
name: springcloud-config-eureka
eureka:
instance:
hostname: eureka7001.com
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
---
server:
port: 7001
spring:
profiles: test
application:
name: springcloud-config-eureka
eureka:
instance:
hostname: eureka7001.com
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
2、创建config-eureka-7001模块
- 导入依赖
<dependencies>
<!--config-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
- 编写配置文件,bootstrap.yml仍然指向config-server(用于连接远程git)application.yml只需要存放spring的名称
spring:
cloud:
config:
name: config-eureka
label: master
profiles: dev
uri: http://localhost:3344
- 编写启动类
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableEurekaServer//表示eureka服务端的启动类
public class EurekaServer_7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer_7001.class,args);
}
}
依次启动config-server,config-eureka,可将注册中心连接到server,间接连接到git上
config-dept-8001的配置(将dept服务提供者的配置文件通过远程git文件管理)
只需要将之前的provider-dept-8001模块复制一份到config-dept-8001。并删除application.yml中大段配置。只配置应用名称。
在bootstrap.yml中编写连接到config-server的配置文件,就可通过config-server获取远程git上的配置文件,而不需要在本地编写大量配置文件,方便协同开发
spring:
cloud:
config:
name: config-eureka
label: master
profiles: dev
uri: http://localhost:3344
name: springcloud-config-eureka
eureka:
instance:
hostname: eureka7001.com
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
2、创建config-eureka-7001模块
- 导入依赖
~~~xml
<dependencies>
<!--config-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
- 编写配置文件,bootstrap.yml仍然指向config-server(用于连接远程git)application.yml只需要存放spring的名称
spring:
cloud:
config:
name: config-eureka
label: master
profiles: dev
uri: http://localhost:3344
- 编写启动类
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableEurekaServer//表示eureka服务端的启动类
public class EurekaServer_7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer_7001.class,args);
}
}
依次启动config-server,config-eureka,可将注册中心连接到server,间接连接到git上
config-dept-8001的配置(将dept服务提供者的配置文件通过远程git文件管理)
只需要将之前的provider-dept-8001模块复制一份到config-dept-8001。并删除application.yml中大段配置。只配置应用名称。
在bootstrap.yml中编写连接到config-server的配置文件,就可通过config-server获取远程git上的配置文件,而不需要在本地编写大量配置文件,方便协同开发
spring:
cloud:
config:
name: config-eureka
label: master
profiles: dev
uri: http://localhost:3344