SpringCloud

微服务概述

微服务是什么?

​ 微服务化的核心就是将传统的一站式应用根据业务拆分成一个一个的服务,彻底地去耦合化。每一个微服务提供单个业务功能的服务,一个服务做一件事。从技术角度来看就是一种小儿独立的处理过程,类似于进程的概念,能够自行单独启动或者销毁,用于自己独立的数据库。

微服务与微服务架构

微服务

​ 强调的是服务的大小,它关注的是一个个的个体,每个个体完成一个具体的任务或者技能。从狭义上来看,例如集成开发工具里面用maven开发的一个个独立的小moudle,它具体是使用springboot开发的一个小模块,专业的事情交给专业的模块来做,一个模块就做这一件事

微服务架构

是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,通常是基于HTTP协议的RESTFUL API。另外,应当尽量避免统一的、集中式的服务管理机制。

微服务优缺点

优点

1.微服务只是业务逻辑的代码,不会和HTML,CSS或其他界面组件混合

2.每个微服务都有自己的存储能力,可以有自己的数据库或统一的数据库

3.微服务能够被小团队单独开发

4.微服务能使用不同的语言开发,允许利用融合最新的技术

5.易于和第三方集成,微服务允许容易且灵活的方式集成自动部署,通过持续集成工具,如Jenkins,Hudson,bamboo

6.开发简单、开发效率提高,一个服务可能就是专一的只干一件事

缺点

服务间通信成本

数据一致性

开发人员要处理分布式系统的复杂性

性能监控

多服务运维难度,随着服务的增加,运维的压力也在增加

微服务技术栈有哪些

多种技术的集合体

image-20221021124325406

image-20221012223514477

为什么选择SpringCloud作为微服务架构

选型依据

1.整体解决方案和框架成熟度

2.社区热度

3.可维护性

4.学习曲线

主流IT公司用的微服务架构

阿里Dubbo/HSF

京东JSF

新浪微博Motan

当当网DubboX

SpringCloud入门概述

SpringCloud是什么

SpringCloud是分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶

SpringCloud和SpringBoot的关系

1.SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供各种集成服务

2.SpringCloud可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖关系

image-20221012225046635

Rest微服务案例

microservicecloud父工程构建步骤

1.命名为microservicecloud,pom文件中packing类型为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">
<modelVersion>4.0.0</modelVersion>

<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>1.0-SNAPSHOT</version>
<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>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.4</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</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>
<scope>test</scope>
</dependency>

<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>

</project>

microervicecloud-api公共子模块Module

1.新建microservicecloud-api模块

2.修改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">
<modelVersion>4.0.0</modelVersion>

<!-- 子类里面显示声明才能有明确的继承表现,无意外就是父类的默认版本否则自己定义 -->
<parent>
<artifactId>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>microservicecloud-api</artifactId>



<dependencies>
<!-- 当前Module需要用到的jar包,按自己需求添加,如果父类已经包含了,可以不用写版本号 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>

<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</dependency>

</dependencies>

</project>

3.新建部门Entity且配合lombok使用

image-20221013154142845

package com.atguigu.springcloud.entities;

import jdk.jfr.DataAmount;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
* @ClassName Dept
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 10:43
* @Version 1.0
*/

@SuppressWarnings("serial")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Dept implements Serializable
//Dept(Entity) orm mysql-Dept(table) 类表关系映射
//必须序列化
{
private Long deptno;//主键
private String dname;//部门名称
private String db_source;//来自哪个数据库,因为微服务架构可以一个服务对应一个数据库,同一个信息被存储到不同的数据库


}

4.mvn clean install后给其他模块引用,达到通用目的。也即是需要用到部门实体的话,不用每个工程都定义一份,直接引用本模块即可

解决的问题:

1.attention:maven中作用域import只能在中使用

2.Fatal error compiling: 无效的标记(maven启动失败)

解决方案:JDK版本不一致/maven与lombok结合编译出现问题,maven版本较高,lombok jar包版本较低,因此编译lombok时无法编译。升级lombok的jar包版本或者降低maven版本。例如我的maven版本为3.5.2,之前报错的lombok版本为1.16.10,升级为1.18.10就不会报错了.

部门微服务提供者模块:microservicecloud-provider-dept-8001

1.新建microservicecloud-provider-dept-8001模块,修改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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-provider-dept-8001</artifactId>

<dependencies>
<dependency>
<!-- 引入自己定义的api通用包,可以使用Dept部门Entity -->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>

2.创建YML文件

server:
port: 8001

mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml #mybaits配置文件所在路径
type-aliases-package: com.atguigu.springcloud.entities #所有Entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml #mapper映射文件


spring:
application:
name: microservicecloud-dept #对外暴露的微服务名字
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/cloudDB01 #数据库名称
username: root
password: root
dbcp2:
min-idle: 5 #数据库连接池的最小维持连接数
initial-size: 5 #初始化连接数
max-total: 5 #最大连接数
max-wait-millis: 200 #等待连接获取的最大超时时间

3.新建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>

4.MySQL创建部门数据库脚本

DROP DATABASE IF EXISTS cloudDB01;
CREATE DATABASE cloudDB01 CHARACTER SET UTF8;
USE cloudDB01;
CREATE TABLE dept
(
deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
dname VARCHAR(60),
db_source VARCHAR(60)
);
INSERT INTO dept(dname, db_source)
VALUES ('开发部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('人事部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('财务部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('市场部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('运维部', DATABASE());

select * from dept


5.DeptDao部门接口

package com.atguigu.springcloud.dao;

import com.atguigu.springcloud.entities.Dept;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
* @ClassName dao
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 16:55
* @Version 1.0
*/

@Mapper
public interface DeptDao {

public boolean addDept(Dept dept);

public Dept findById(Long id);

public List<Dept> findAll();
}

6.创建mapper文件夹,再创键DeptMapper.xml映射文件

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.springcloud.dao.DeptDao">

<select id="findById" resultType="Dept" parameterType="Long">
select deptno,dname,db_source from dept where deptno = #{deptno};
</select>

<select id="findAll" resultType="Dept">
select deptno,dname,db_source from dept;
</select>

<insert id="addDept" parameterType="Dept">
INSERT INTO dept(dname,db_source) VALUES(#{dname},DATABASE());
</insert>
</mapper>

7.DeptService部门服务接口

package com.atguigu.springcloud.service;

import com.atguigu.springcloud.entities.Dept;

import java.util.List;

public interface DeptService {

public boolean add(Dept dept);

public Dept get(Long id);

public List<Dept> list();
}

8.DeptServiceImpl部门服务接口实现类

package com.atguigu.springcloud.service.impl;

import com.atguigu.springcloud.dao.DeptDao;
import com.atguigu.springcloud.entities.Dept;
import com.atguigu.springcloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
* @ClassName DeptServiceImpl
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 17:10
* @Version 1.0
*/

@Service
public class DeptServiceImpl implements DeptService {

@Autowired
private DeptDao dao;

@Override
public boolean add(Dept dept) {
return dao.addDept(dept);
}

@Override
public Dept get(Long id) {
return dao.findById(id);
}

@Override
public List<Dept> list() {
return dao.findAll() ;
}
}

9.DeptController部门微服务提供者REST

package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.Dept;
import com.atguigu.springcloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* @ClassName DeptController
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 18:23
* @Version 1.0
*/

@RestController
public class DeptController {

@Autowired
private DeptService deptService;

@RequestMapping(value = "/dept/add",method = RequestMethod.POST)
public boolean add(@RequestBody Dept dept)
{
return deptService.add(dept);
}

@RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET)
public Dept get(@PathVariable("id") Long id)
{
return deptService.get(id);
}

@RequestMapping(value = "/dept/list",method = RequestMethod.GET)
public List<Dept> list()
{
return deptService.list();
}
}

10.DeptProvider8001_App主启动类:DeptProvider8001_App

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* @ClassName DeptProvider8001_App
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 19:04
* @Version 1.0
*/

@SpringBootApplication
public class DeptProvider8001_App {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001_App.class,args);
}
}

11.测试

image-20221013193604610

image-20221013193625902

部门微服务消费者模块:microservicecloud-consumer-dept-80

image-20221015100602811

1.新建新建microservicecloud-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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-consumer-dept-80</artifactId>
<description>部门微服务消费者</description>

<dependencies>
<dependency>
<!-- 自己定义的api -->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</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>

2.创建并编写YML文件

server:
port: 80

3.com.atguigu.springcloud.cfgbeans包下ConfigBean的编写(类似spring里面的applicationContext.xml写入的注入Bean)

package com.atguigu.springcloud.cfgbeans;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
* @ClassName ConfigBena
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 19:57
* @Version 1.0
*/

@Configuration
public class ConfigBean
{
@Bean
public RestTemplate getRestTemplate()
{
return new RestTemplate();
}
}

4.com.atguigu.springcloud.controller包下新建DeptController_Consumer部门微服务消费者REST

package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
* @ClassName DeptController_Consumer
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 9:25
* @Version 1.0
*/

@RestController
public class DeptController_Consumer {

private static final String REST_URL_PREFIX = "localhost:8001";

/**
* 使用restTemplate访问restful接口非常的简单粗暴无脑。
* (url, requestMap, ResponseBean.class)这三个参数分别代表
* REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。
*/
@Autowired
private RestTemplate restTemplate;

@RequestMapping(value = "/consumer/dept/add")
public boolean add(Dept dept)
{
return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
}

@RequestMapping(value = "/consumer/dept/list")
public List<Dept> list()
{
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
}

@RequestMapping(value = "/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id)
{
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
}
}

什么是RestTemplate?

RestTemplate提供了多种便捷访问远程Http服务的方法, 是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集 。使用使用restTemplate访问restful接口非常的简单粗暴无脑。(url, requestMap, ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。

5.DeptConsumer80_App主启动类

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* @ClassName DeptConsumer80_APP
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 9:50
* @Version 1.0
*/

@SpringBootApplication
public class DeptConsumer80_APP {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80_APP.class,args);
}
}

6.测试

http://localhost/consumer/dept/list

image-20221015101149505

http://localhost/consumer/dept/get/2

image-20221015101205390

Eureka服务注册与发现

Eureka是什么?

   Eureka是什么 Eureka是Netflix的一个子模块,也是核心模块之一。Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。**服务注册与发现**对于微服务架构来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了。功能类似于dubbo的注册中心,比如Zookeeper。  

Eureka的原理讲解

基本架构

​ Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务注册和发现(请对比Zookeeper)。 Eureka 采用了 C-S 的设计架构。Eureka Server 作为服务注册功能的服务器,它是服务注册中心。 而系统中的其他微服务,使用 Eureka 的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。

​ SpringCloud 的一些其他模块(比如Zuul)就可以通过 Eureka Server 来发现系统中的其他微服务,并执行相关的逻辑。请注意和Dubbo的架构对比

​ Eureka包含两个组件:Eureka Server和Eureka Client。Eureka Server提供服务注册服务各个节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到 Eureka Client是一个Java客户端,用于简化Eureka Server的交互。

​ 客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)

三大角色

Eureka Server 提供服务注册和发现

Service Provider服务提供方将自身服务注册到Eureka,从而使服务消费方能够找到

Service Consumer服务消费方从Eureka获取注册服务列表,从而能够消费服务

eureka服务注册中心模块:microservicecloud-eureka-7001

1.新建microservicecloud-eureka-7001模块,并修改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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-eureka-7001</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>

<!-- eureka-server服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

</dependencies>

</project>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.6.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>

image-20221015104445279

切记切记切记!!!!!!!!!!!!!!!!!!!!!!!!父工程里的springboot和cloud版本一定要匹配,否则就会出各种错,例如Eureka初始化不能

image-20221015110131954

2.新建对应的YML文件

server:
port: 7001

eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#设置与Eureka Server交互的地址查询服务和注册服务

3.EurekaServer7001_App主启动类

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;


/**
* @ClassName EurekaServer7001_APP
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 10:43
* @Version 1.0
*/

@SpringBootApplication
@EnableEurekaServer
//EurekaServer服务端启动类,接受其它微服务注册进来
public class EurekaServer7001_APP {
public static void main(String[] args) {
SpringApplication.run(EurekaServer7001_APP.class, args);
}
}

4.测试

http://localhost:7001/

image-20221015154954776

结果页面No application available 没有服务被发现,因为没有注册服务进来当然不可能有服务被发现

将已有的部门微服务注册进eureka服务中心:microservicecloud-provider-dept-8001

1.修改microservicecloud-provider-dept-8001模块的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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-provider-dept-8001</artifactId>

<dependencies>
<dependency>
<!-- 引入自己定义的api通用包,可以使用Dept部门Entity -->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- 修改新增加的部分 -->
<!-- 将微服务provider侧注册进eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
</project>
attention!!!!SpringCloud Config配置出现“No spring.config.import property has been defined“问题,即是在微服务provider侧注册进eureka时发生的问题,这样解决:

在SpringCloud 2020.* 版本把bootstrap禁用了,导致在读取文件的时候读取不到而报错,所以我们只要把bootstrap从新导入进来就会生效了。

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.2</version>
</dependency>

2.修改YML文件

server:
port: 8001

mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml #mybaits配置文件所在路径
type-aliases-package: com.atguigu.springcloud.entities #所有Entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml #mapper映射文件


spring:
application:
name: microservicecloud-dept #对外暴露的微服务名字
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/cloudDB01 #数据库名称
username: root
password: root
dbcp2:
min-idle: 5 #数据库连接池的最小维持连接数
initial-size: 5 #初始化连接数
max-total: 5 #最大连接数
max-wait-millis: 200 #等待连接获取的最大超时时间


#新增加部分
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka

3.DeptProvider8001_App主启动类

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
* @ClassName DeptProvider8001_App
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 19:04
* @Version 1.0
*/

@SpringBootApplication
@EnableEurekaClient//本服务启动后会自动注册进eureka服务中
public class DeptProvider8001_App {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001_App.class,args);
}
}

4.测试

先要启动EurekaServer7001和8001

http://localhost:7001/

image-20221015163516309

actuator与注册微服务信息完善

1.主机名称:服务名称修改

修改microservicecloud-provider-dept-8001模块中的YML文件

eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
instance:
instance-id: 20001223 #自定义服务名称信息

image-20221015164650160

2.访问信息有IP信息提示

现在问题:没有IP提示

解决方案:修改microservicecloud-provider-dept-8001模块中的YML文件

eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
instance:
instance-id: 20001223 #自定义服务名称信息
prefer-ip-address: true #访问路径可以显示IP地址

image-20221015164759147

3.微服务info内容详细信息

当前问题:超链接点击服务报告ErrorPage

解决方案:

1.修改microservicecloud-provider-dept-8001模块中的POM文件

<!-- actuator监控信息完善  -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>

2.总的父工程microservicecloud修改pom.xml添加构建build信息

<?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.atguigu.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>microservicecloud-api</module>
<module>microservicecloud-provider-dept-8001</module>
<module>microservicecloud-consumer-dept-80</module>
<module>microservicecloud-eureka-7001</module>
</modules>
<packaging>pom</packaging>



<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.18.24</lombok.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.6.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.4</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</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>
<scope>test</scope>
</dependency>

<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>

</dependencies>
</dependencyManagement>

<!-- 新增内容-->
<build>
<finalName>microservicecloud</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimit>$</delimit>
</delimiters>
</configuration>
</plugin>
</plugins>
</build>
</project>

3.修改microservicecloud-provider-dept-8001模块中的YML文件

server:
port: 8001

mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml #mybaits配置文件所在路径
type-aliases-package: com.atguigu.springcloud.entities #所有Entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml #mapper映射文件


spring:
application:
name: microservicecloud-dept #对外暴露的微服务名字
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/cloudDB01 #数据库名称
username: root
password: root
dbcp2:
min-idle: 5 #数据库连接池的最小维持连接数
initial-size: 5 #初始化连接数
max-total: 5 #最大连接数
max-wait-millis: 200 #等待连接获取的最大超时时间

eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
instance:
instance-id: 20001223 #自定义服务名称信息
prefer-ip-address: true #访问路径可以显示IP地址

#微服务info内容详细信息
info:
app.name: atguigu-microservicecloud
company.name: www.atguigu.com
build.artifactId: $project.artifactId$
build.version: $project.version$

image-20221015171008369

eureka自我保护

image-20221015171308047

image-20221015171317403

某时刻某一个微服务不可用了,eureka不会立刻清理,依旧会对该微服务的信息进行保存

在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时,该Eureka Server节点就会自动退出自我保护模式。它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。一句话:好死不如赖活着

image-20221015171717497

microservicecloud-provider-dept-8001模块:服务发现Discovery

image-20221015172251162

1.对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息

2.修改microservicecloud-provider-dept-8001工程的DeptController

package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.Dept;
import com.atguigu.springcloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* @ClassName DeptController
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 18:23
* @Version 1.0
*/

@RestController
public class DeptController {

@Autowired
private DeptService deptService;



@RequestMapping(value = "/dept/add",method = RequestMethod.POST)
public boolean add(@RequestBody Dept dept)
{
return deptService.add(dept);
}

@RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET)
public Dept get(@PathVariable("id") Long id)
{
return deptService.get(id);
}

@RequestMapping(value = "/dept/list",method = RequestMethod.GET)
public List<Dept> list()
{
return deptService.list();
}


//新增部分
@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;
}
}

3.DeptProvider8001_App主启动类

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
* @ClassName DeptProvider8001_App
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 19:04
* @Version 1.0
*/

@SpringBootApplication
@EnableEurekaClient//本服务启动后会自动注册进eureka服务中
@EnableDiscoveryClient//服务发现
public class DeptProvider8001_App {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001_App.class,args);
}
}

4.自测

image-20221015182342189

5.修改microservicecloud-consumer-dept-80工程的DeptController_Consumer

package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
* @ClassName DeptController_Consumer
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 9:25
* @Version 1.0
*/

@RestController
public class DeptController_Consumer {

private static final String REST_URL_PREFIX = "http://localhost:8001";

/**
* 使用restTemplate访问restful接口非常的简单粗暴无脑。
* (url, requestMap, ResponseBean.class)这三个参数分别代表
* REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。
*/
@Autowired
private RestTemplate restTemplate;

@RequestMapping(value = "/consumer/dept/add")
public boolean add(Dept dept)
{
return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
}

@RequestMapping(value = "/consumer/dept/list")
public List<Dept> list()
{
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
}

@RequestMapping(value = "/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id)
{
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
}

//新增的part

//测试@EnableDiscoveryClient,消费端可以调用服务发现
@RequestMapping(value = "/consumer/dept/discovery")
public Object discovery()
{
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery",Object.class);
}
}

image-20221015182427214

集群配置

1.新建microservicecloud-eureka-7002模块以及microservicecloud-eureka-7003模块并编写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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-eureka-7002</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>

<!-- eureka-server服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
<?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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-eureka-7003</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>

<!-- eureka-server服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>

</project>

2.修改7002和7003的主启动类

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;


/**
* @ClassName EurekaServer7001_APP
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 10:43
* @Version 1.0
*/

@SpringBootApplication
@EnableEurekaServer
//EurekaServer服务端启动类,接受其它微服务注册进来
public class EurekaServer7003_APP {
public static void main(String[] args) {
SpringApplication.run(EurekaServer7003_APP.class, args);
}
}
package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;


/**
* @ClassName EurekaServer7001_APP
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 10:43
* @Version 1.0
*/

@SpringBootApplication
@EnableEurekaServer
//EurekaServer服务端启动类,接受其它微服务注册进来
public class EurekaServer7002_APP {
public static void main(String[] args) {
SpringApplication.run(EurekaServer7002_APP.class, args);
}
}

3.修改映射配置

找到C:\Windows\System32\drivers\etc路径下的hosts文件

image-20221015183713618

4.3台eureka服务器的yml文件配置

#server:
# port: 7001
#
#eureka:
# instance:
# hostname: localhost #eureka服务端的实例名称
# client:
# register-with-eureka: false #false表示不向注册中心注册自己
# fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
# service-url:
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# #设置与Eureka Server交互的地址查询服务和注册服务


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/
#server:
# port: 7001
#
#eureka:
# instance:
# hostname: localhost #eureka服务端的实例名称
# client:
# register-with-eureka: false #false表示不向注册中心注册自己
# fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
# service-url:
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# #设置与Eureka Server交互的地址查询服务和注册服务


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/
#server:
# port: 7001
#
#eureka:
# instance:
# hostname: localhost #eureka服务端的实例名称
# client:
# register-with-eureka: false #false表示不向注册中心注册自己
# fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
# service-url:
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# #设置与Eureka Server交互的地址查询服务和注册服务


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://eureka7002.com:7002/eureka/,http://eureka7001.com:7001/eureka/

5.微服务发布到上面3台eureka集群配置中:microservicecloud-provider-dept-8001

server:
port: 8001

mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml #mybaits配置文件所在路径
type-aliases-package: com.atguigu.springcloud.entities #所有Entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml #mapper映射文件


spring:
application:
name: microservicecloud-dept #对外暴露的微服务名字
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/cloudDB01 #数据库名称
username: root
password: root
dbcp2:
min-idle: 5 #数据库连接池的最小维持连接数
initial-size: 5 #初始化连接数
max-total: 5 #最大连接数
max-wait-millis: 200 #等待连接获取的最大超时时间

eureka:
client:
service-url:
defaultZone:
#修改的这part http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: 20001223 #自定义服务名称信息
prefer-ip-address: true #访问路径可以显示IP地址


info:
app.name: atguigu-microservicecloud
company.name: www.atguigu.com
build.artifactId: $project.artifactId$
build.version: $project.version$

image-20221015185543269

image-20221015185636446

作为服务注册中心,Eureka比Zookeeper好在哪里

RDBMS(mysql/oracle/sqlServer) ===>> ACID

NOSQL(redis/mongdb) ===>> CAP

1.什么是ACID

A(Atomicity)原子性

C(Consistency)一致性

I(Isolation)独立性

D(Durability)持久性

2.CAP

C(Consistency)强一致性

A(Availability)可用性

P(Partition tolerance)分区容错性

3.经典CAP图

image-20221015192153670

image-20221015192208098

4.Eureka比Zookeeper好在哪里

著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。由于分区容错性P在是分布式系统中必须要保证的,所以我们只能在A和C之间进行权衡

Zookeeper保证的是CP

Eureka则是AP

image-20221015192755974

image-20221015193225204

因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪

Ribbon负载均衡

Ribbon概述

1.Ribbon是什么

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。

2.Ribbon的作用

LB(负载均衡):即负载均衡(Load Balance),在微服务或分布式集群中经常用的一种应用。负载均衡简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA。常见的负载均衡有软件Nginx,LVS,硬件 F5等。相应的在中间件,例如:dubbo和SpringCloud中均给我们提供了负载均衡,SpringCloud的负载均衡算法可以自定义。

集中式LB:集中式LB即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方

进程内LB: 进程内LB将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

Ribbon配置初步

1.修改microservicecloud-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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-consumer-dept-80</artifactId>
<description>部门微服务消费者</description>

<dependencies>
<dependency>
<!-- 自己定义的api -->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</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>

<!-- Ribbon相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies>
</project>

2.修改application.yml 追加eureka的服务注册地址

server:
port: 80


eureka:
client:
register-with-eureka: 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/,http://eureka7001.com:7001/eureka/

3.对ConfigBean进行新注解@LoadBalanced 获得Rest时加入Ribbon的配置

package com.atguigu.springcloud.cfgbeans;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
* @ClassName ConfigBena
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 19:57
* @Version 1.0
*/

@Configuration
public class ConfigBean
{
@Bean
@LoadBalanced//Spring Cloud Ribbon是基于Netflix Ribbon实现的一套**客户端负载均衡**的工具。
public RestTemplate getRestTemplate()
{
return new RestTemplate();
}
}

4.主启动类DeptConsumer80_App添加@EnableEurekaClient

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;


/**
* @ClassName DeptConsumer80_APP
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 9:50
* @Version 1.0
*/

@SpringBootApplication
@EnableEurekaClient
public class DeptConsumer80_APP {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80_APP.class,args);
}
}

5.修改DeptController_Consumer客户端访问类

package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
* @ClassName DeptController_Consumer
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 9:25
* @Version 1.0
*/

@RestController
public class DeptController_Consumer {

//第一次修改这part——ribbon
// private static final String REST_URL_PREFIX = "http://localhost:8001";
private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";

/**
* 使用restTemplate访问restful接口非常的简单粗暴无脑。
* (url, requestMap, ResponseBean.class)这三个参数分别代表
* REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。
*/
@Autowired
private RestTemplate restTemplate;

@RequestMapping(value = "/consumer/dept/add")
public boolean add(Dept dept)
{
return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
}

@RequestMapping(value = "/consumer/dept/list")
public List<Dept> list()
{
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
}

@RequestMapping(value = "/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id)
{
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
}

//测试@EnableDiscoveryClient,消费端可以调用服务发现
@RequestMapping(value = "/consumer/dept/discovery")
public Object discovery()
{
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery",Object.class);
}
}

6.先启动3个eureka集群后,再启动microservicecloud-provider-dept-8001并注册进eureka

7.启动microservicecloud-consumer-dept-80

8.测试

http://localhost/consumer/dept/get/1

image-20221016202545019

http://localhost/consumer/dept/list

image-20221016202556847

http://localhost/consumer/dept/add?dname=大数据部

image-20221016202606968

9.小总结

Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心地址和端口号

Ribbon负载均衡

image-20221016202707794

image-20221016202822963

1.参考microservicecloud-provider-dept-8001模块,新建两份,分别命名为8002,8003,复用8001的pom文件

image-20221016203413463

2.新建8002/8003数据库,各自微服务分别连各自的数据库

DROP DATABASE IF EXISTS cloudDB02;
CREATE DATABASE cloudDB02 CHARACTER SET UTF8;
USE cloudDB02;
CREATE TABLE dept
(
deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
dname VARCHAR(60),
db_source VARCHAR(60)
);
INSERT INTO dept(dname, db_source)
VALUES ('开发部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('人事部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('财务部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('市场部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('运维部', DATABASE());
DROP DATABASE IF EXISTS cloudDB03;
CREATE DATABASE cloudDB03 CHARACTER SET UTF8;
USE cloudDB03;
CREATE TABLE dept
(
deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
dname VARCHAR(60),
db_source VARCHAR(60)
);
INSERT INTO dept(dname, db_source)
VALUES ('开发部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('人事部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('财务部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('市场部', DATABASE());
INSERT INTO dept(dname, db_source)
VALUES ('运维部', DATABASE());

3.修改8002/8003各自YML

server:
port: 8002

mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml #mybaits配置文件所在路径
type-aliases-package: com.atguigu.springcloud.entities #所有Entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml #mapper映射文件


spring:
application:
name: microservicecloud-dept #对外暴露的微服务名字
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/cloudDB02 #数据库名称
username: root
password: root
dbcp2:
min-idle: 5 #数据库连接池的最小维持连接数
initial-size: 5 #初始化连接数
max-total: 5 #最大连接数
max-wait-millis: 200 #等待连接获取的最大超时时间

eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: 20001223 #自定义服务名称信息
prefer-ip-address: true #访问路径可以显示IP地址


info:
app.name: atguigu-microservicecloud
company.name: www.atguigu.com
build.artifactId: $project.artifactId$
build.version: $project.version$
server:
port: 8003

mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml #mybaits配置文件所在路径
type-aliases-package: com.atguigu.springcloud.entities #所有Entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml #mapper映射文件


spring:
application:
name: microservicecloud-dept #对外暴露的微服务名字
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/cloudDB03 #数据库名称
username: root
password: root
dbcp2:
min-idle: 5 #数据库连接池的最小维持连接数
initial-size: 5 #初始化连接数
max-total: 5 #最大连接数
max-wait-millis: 200 #等待连接获取的最大超时时间

eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: 20001223 #自定义服务名称信息
prefer-ip-address: true #访问路径可以显示IP地址


info:
app.name: atguigu-microservicecloud
company.name: www.atguigu.com
build.artifactId: $project.artifactId$
build.version: $project.version$

3.1 修改对应的端口

3.2数据库链接

3.3对外暴露的统一的服务实例名

image-20221016205509745

4.启动3个eureka集群配置区

5.启动3个Dept微服务启动并各自测试通过

http://localhost:8001/dept/list

image-20221016205541414

http://localhost:8002/dept/list

image-20221016205558067

http://localhost:8003/dept/list

image-20221016205630958

5.启动microservicecloud-consumer-dept-80

6.客户端通过Ribbon完成负载均衡并访问上一步的Dept微服务

http://localhost/consumer/dept/list

注意观察看到返回的数据库名字,各不相同,负载均衡实现

image-20221016205825670

7.总结:Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。

Ribbon核心组件IRule

注意:springcloud在2020.0.0之后,移除掉了netflix-ribbon 使用eureka-client中的loadbalancer,使用自定义负载均衡不使用IRule接口。官方文档上有写,可以写一个配置类,可以与启动类同级

IRule:根据特定算法中从服务列表中选取一个要访问的服务

image-20221016220251180

image-20221016222606772

Ribbon自定义

image-20221016232058029

1.修改microservicecloud-consumer-dept-80模块

2.主启动类添加@RibbonClient

package com.atguigu.springcloud;

import com.atguigu.myrule.MySelfRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;


/**
* @ClassName DeptConsumer80_APP
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 9:50
* @Version 1.0
*/

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "MICROSERVICECLOUD-DEPT",configuration = MySelfRule.class)
public class DeptConsumer80_APP {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80_APP.class,args);
}
}

3.注意配置细节

image-20221016233534402

1.新建package com.atuigu.myrule,新建自定义Robbin规则类

package com.atguigu.myrule;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @ClassName MySelfRule
* @Description TODO
* @Author 百里诀
* @Date 2022/10/16 23:30
* @Version 1.0
*/

@Configuration
public class MySelfRule {

@Bean
public IRule myRule()
{
return new RandomRule();//Ribbon默认是轮询,自定义为随机
}
}

2.测试

4.自定义规则深度解析

image-20221016232907768

问题:依旧是轮询策略,但是加上新的需求,每个服务器要求被调用5次。也即是以前是每台机器一次,现在是每台机器5次

1.参考源码修改为我们需求要求的RandomRule_ZY.java

package com.atguigu.myrule;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.Server;

import java.util.List;
import java.util.Random;

/**
* @ClassName RandomRule_ZY
* @Description TODO
* @Author 百里诀
* @Date 2022/10/17 10:23
* @Version 1.0
*/

public class RandomRule_ZY extends AbstractLoadBalancerRule {
Random rand;
//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; //当前提供服务的机器号

@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {

}

@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}


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;
}

// int index = rand.nextInt(serverCount);
// server = upList.get(index);

if (total < 5) {
server = upList.get(currentIndex);
total++;
} else {
total = 0;
currentIndex++;
if (currentIndex >= upList.size()) {
currentIndex = 0;
}
}

if (server == null) {
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}

server = null;
Thread.yield();
}
return server;
}
}

image-20221017102356781

2.测试

SpringCloud Ribbon 解决java.lang.IllegalStateExcepti No instances available for MICROSERVICECLOUD-DEPT

Spring Cloud 2020版本以后,默认移除了对Netflix的依赖,其中就包括Ribbon,官方默认推荐使用Spring Cloud Loadbalancer正式替换Ribbon,并成为了Spring Cloud负载均衡器的唯一实现。

依赖的变化

<!--        <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>-->
<!-- <version>2.2.5.RELEASE</version>-->
<!-- </dependency>-->

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>2.2.1.RELEASE</version>

由此可见,自定义ribbon负载均衡策略会与依赖,版本产生一定的冲突,使用的时候需要注意。按照本项目的版本自定义规则暂时无法使用

Feign负载均衡

什么是Feign?

​ Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。

Feigin是一个声明式的Web服务客户端,使得编写Web服务客户端变得非常容易,只需要创建一个接口,然后在上面添加注解即可

image-20221017120404385

Feign集成了Ribbon利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用

Feign使用步骤

1.参考microservicecloud-consumer-dept-80模块新建microservicecloud-consumer-dept-feign模块,修改对应的pom文件,主要添加对fegin的支持,修改主启动类的名字

<?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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-consumer-dept-feign</artifactId>
<dependencies>
<dependency>
<!-- 自己定义的api -->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</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>

<!-- Ribbon相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>

</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.3</version>
</dependency>

<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>-->
<!-- <version>2.2.5.RELEASE</version>-->
<!-- </dependency>-->

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>

<!-- 主要添加对fegin的支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
</dependencies>

</project>
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.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;


/**
* @ClassName DeptConsumer80_APP
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 9:50
* @Version 1.0
*/

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.atguigu.springcloud"})
public class DeptConsumer80_Feign_APP {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80_Feign_APP.class,args);
}
}

2.修改microservicecloud-api工程

2.1 修改对应的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">
<modelVersion>4.0.0</modelVersion>

<!-- 子类里面显示声明才能有明确的继承表现,无意外就是父类的默认版本否则自己定义 -->
<parent>
<artifactId>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>microservicecloud-api</artifactId>



<dependencies>
<!-- 当前Module需要用到的jar包,按自己需求添加,如果父类已经包含了,可以不用写版本号 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>

<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</dependency>

<!-- 修改对应的pom文件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>


</dependencies>

</project>

2.2 新建DeptClientService接口并新增注解@FeignClient

image-20221017162407477

package com.atguigu.springcloud.service;

import com.atguigu.springcloud.entities.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;

@Service
@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/get/add",method = RequestMethod.POST)
public boolean add(Dept dept);
}

2.3 mvn clean

2.4 mvn install

3.microservicecloud-consumer-dept-feign工程修改Controller,添加上一步新建的DeptClientService接口

package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.Dept;
import com.atguigu.springcloud.service.DeptClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
* @ClassName DeptController_Consumer
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 9:25
* @Version 1.0
*/

@RestController
public class DeptController_Consumer {

@Autowired
private DeptClientService service;

@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);
}

}

4.microservicecloud-consumer-dept-feign工程修改主启动类

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;



/**
* @ClassName DeptConsumer80_APP
* @Description TODO
* @Author 百里诀
* @Date 2022/10/15 9:50
* @Version 1.0
*/

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.atguigu.springcloud"})
public class DeptConsumer80_Feign_APP {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80_Feign_APP.class,args);
}
}

5.测试

5.1 启动3个eureka集群

5.2 启动3个部门微服务8001/8002/8003

5.3 启动Feign自己启动

5.4 http://localhost/consumer/dept/list

5.5 Feign自带负载均衡配置项

6.总结

Feign通过接口的方法调用Rest服务(之前是Ribbon+RestTemplate),该请求发送给Eureka服务器(http://MICROSERVICECLOUD-DEPT/dept/list),通过Feign直接找到服务接口,由于在进行服务调用的时候融合了Ribbon技术,所以也支持负载均衡作用。

Hystrix断路器

1.概述

1.1 分布式系统面临的问题

分布式系统面临的问题:复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。 服务雪崩多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。

**如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”. **

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。

1.2 hystrix是什么?

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

1.3 hystrix能干什么?

服务降级

服务熔断

服务限流

接近实时的监控

1.4 哪些情况会触发降级

程序运行异常

超时

服务熔断触发服务降级

线程池/信号量打满也会导致服务降级

2.服务熔断

2.1 服务熔断是什么?

服务熔断熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回”错误”的响应信息。

当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。

2.2 参考microservicecloud-provider-dept-8001模块新建microservicecloud-provider-dept-hystrix-8001模块,修改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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-provider-dept-hystrix-8001</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<!-- 引入自己定义的api通用包,可以使用Dept部门Entity -->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- 将微服务provider侧注册进eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.2</version>
</dependency>
<!-- actuator监控信息完善 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>

</project>

2.3 引入Hystrix熔断器启动项目失败

在pom.xml中引入Hystrix后,启动项目失败,pom依赖如下:

img

报错信息如下:
BeanDefinitionStoreException 和 FileNotFoundException,这是因ServerPropertiesAutoConfiguration 在springboot 2.x.x中已经废弃,所以找不到该文件。

解决方案是需要改换使用spring-cloud-starter-netflix-hystrix,如下:

img

2.4 修改YML文件

server:
port: 8001

mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml #mybaits配置文件所在路径
type-aliases-package: com.atguigu.springcloud.entities #所有Entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml #mapper映射文件


spring:
application:
name: microservicecloud-dept #对外暴露的微服务名字
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/cloudDB01 #数据库名称
username: root
password: root
dbcp2:
min-idle: 5 #数据库连接池的最小维持连接数
initial-size: 5 #初始化连接数
max-total: 5 #最大连接数
max-wait-millis: 200 #等待连接获取的最大超时时间

eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: microservicecloud-dept8001-hystrix #自定义hystrix服务名称信息 #新修改的
prefer-ip-address: true #访问路径可以显示IP地址


info:
app.name: atguigu-microservicecloud
company.name: www.atguigu.com
build.artifactId: $project.artifactId$
build.version: $project.version$

2.5 修改DeptController

@HystrixCommand报异常后如何处理?

一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法

package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.Dept;
import com.atguigu.springcloud.service.DeptService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* @ClassName DeptController
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 18:23
* @Version 1.0
*/

@RestController
public class DeptController {

//一但调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod
//调用类中的指定方法

@Autowired
private DeptService service = null;

@RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET)
@HystrixCommand(fallbackMethod = "processHystrix_Get")
public Dept get(@PathVariable("id") Long id)
{
Dept dept = this.service.get(id);
if(null==dept)
{
throw new RuntimeException("该ID:" + id + "没有对应的信息");
}
return dept;
}
public Dept processHystrix_Get(@PathVariable("id") Long id)
{
return new Dept().setDeptno(id).setDname("该Id:" + id + "没有对应的信息,null-@HystrixComnand")
.setDb_source("no this database in MySQl");
}
}

2.6 修改主启动类DeptProvider8001_Hystrix_App并添加新注解@EnableCircuitBreaker

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
* @ClassName DeptProvider8001_App
* @Description TODO
* @Author 百里诀
* @Date 2022/10/13 19:04
* @Version 1.0
*/

@SpringBootApplication
@EnableEurekaClient//本服务启动后会自动注册进eureka服务中
@EnableDiscoveryClient//服务发现
@EnableCircuitBreaker
public class DeptProvider8001_Hystrix_App {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001_Hystrix_App.class,args);
}
}

2.7 测试

3个eureka先启动

主启动类DeptProvider8001_Hystrix_App

Consumer启动microservicecloud-consumer-dept-80

http://localhost/consumer/dept/get/112

image-20221017210755642

image-20221017211143421

3.服务降级

1.服务降级是什么?

整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来。

2.服务降级处理是在客户端实现完成的,与服务端没有关系

3.修改microservicecloud-api工程,根据已经有的DeptClientService接口新建一个实现了FallbackFactory接口的DeptClientServiceFallbackFactory

千万不要忘记在类上面新增@Component注解,大坑!!!

package com.atguigu.springcloud.service;

import com.atguigu.springcloud.entities.Dept;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.List;

/**
* @ClassName DeptClientServiceFallbackFactory
* @Description TODO
* @Author 百里诀
* @Date 2022/10/18 10:03
* @Version 1.0
*/

@Component//不要忘记添加
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
@Override
public DeptClientService create(Throwable cause) {
return new DeptClientService() {
@Override
public Dept get(long id) {
return new Dept().setDeptno(id).setDname("该Id:" + id + "没有对应的信息,Consumer客户端提供的降级信息")
.setDb_source("no this database in MySQl");
}

@Override
public List<Dept> list() {
return null;
}

@Override
public boolean add(Dept dept) {
return false;
}
};
}
}

4.修改microservicecloud-api工程,DeptClientService接口在注解@FeignClient中添加fallbackFactory属性值

package com.atguigu.springcloud.service;

import com.atguigu.springcloud.entities.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;

@Service
//@FeignClient(value = "microservicecloud-dept")//微服务名字
@FeignClient(value = "microservicecloud-dept",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {

@RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET)
public Dept get(@PathVariable("id") long id);

@RequestMapping(value = "/dept/list",method = RequestMethod.GET)
public List<Dept> list();

@RequestMapping(value = "/dept/get/add",method = RequestMethod.POST)
public boolean add(Dept dept);
}

5.microservicecloud-api工程

mvn clean

mvn install

6.microservicecloud-consumer-dept-feign工程修改YML

2020版的SpringCloud熔断器fallback失效的问题

将配置文件改成:feign.circuitbreaker.enabled=true

feign:
circuitbreaker:
enabled: true

7.3个eureka先启动

8.微服务microservicecloud-provider-dept-8001启动

9.microservicecloud-consumer-dept-feign启动

10.http://localhost/consumer/dept/get/1,正常访问测试

11.故意关闭微服务microservicecloud-provider-dept-8001

12.http://localhost/consumer/dept/get/1

13.客户端自己调用提示

image-20221018110416016

此时服务端provider已经down了,但是我们做了服务降级处理,让客户端在服务端不可用时也会获得提示信息而不会挂起耗死服务器

服务监控hystrixDashboard

1.概述

​ 除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。

​ Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。

2.新建工程microservicecloud-consumer-hystrix-dashboard模块

image-20221018152114871

3.修改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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-consumer-hystrix-dashboard</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>

</project>

4.修改YML文件

server:
port: 9001

5.主启动类改名+新注解@EnableHystrixDashboard

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

/**
* @ClassName DeptConsumer_DashBoard_App
* @Description TODO
* @Author 百里诀
* @Date 2022/10/18 11:18
* @Version 1.0
*/

@SpringBootApplication
@EnableHystrixDashboard
public class DeptConsumer_DashBoard_App {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_DashBoard_App.class,args);
}
}

6.所有Provider微服务提供类(8001/8002/8003)都需要监控依赖配置

<!-- actuator监控信息完善  -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

7.启动microservicecloud-consumer-hystrix-dashboard该微服务监控消费端

http://localhost:9001/hystrix

image-20221018152441921

8.启动3个eureka集群

9.启动microservicecloud-provider-dept-hystrix-8001模块

http://localhost:8001/dept/get/1

image-20221018152929853

http://localhost:8001/hystrix.stream

image-20221018155313980

10.监控测试

多次刷新http://localhost:8001/dept/get/1,填写监控地址http://localhost:8001/hystrix.stream,监控结果

image-20221018155313980

image-20221018155450059

7色

1圈:实心圆:共有两种含义。它通过颜色的变化代表了实例的健康程度,它的健康度从绿色<黄色<橙色<红色递减。该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大该实心圆就越大。所以通过该实心圆的展示,就可以在大量的实例中快速的发现故障实例和高压力实例。

1线:曲线:用来记录2分钟内流量的相对变化,可以通过它来观察到流量的上升和下降趋势。

3.解决:SpringCloud出现Unable to connect to Command Metric Stream.的异常

当输入URL并且点击Monitor Stream按钮后界面出现:Unable to connect to Command Metric Stream.

解决方案:

1.被监视项目中使用如下配置:

package hystrix.feign.consumer7.config;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JavaConfig {
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/hystrix.stream");//访问路径
registrationBean.setName("hystrix.stream");
return registrationBean;
}
}

2.监视项目使用如下配置:


hystrix:
dashboard:
proxy-stream-allow-list: "*"

image-20221018155956496

image-20221018160033081

zuul路由网关

image-20221018160322082

zuul的概述

zuul是什么?

Zuul包含了对请求的路由和过滤两个最主要的功能:其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础.

Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。

注意:Zuul服务最终还是会注册进Eureka

提供=代理+路由+过滤三大功能

zuul能干什么?

路由

过滤

路由基本配置

1.新建Module模块microservicecloud-zuul-gateway-9527模块,并修改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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-zuul-gateway-9527</artifactId>


<dependencies>


<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>

<!-- springcloud2.0 以上一定要添加 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>

</project>

2.创建并编写YML文件,将host修改为myzuul.com

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 #访问路径可以显示IP地址
hostname: myzuul.com


info:
app.name: atguigu-microservicecloud
company.name: www.atguigu.com
build.artifactId: $project.artifactId$
build.version: $project.version$

3.主启动类,@EnableZuulProxy

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

/**
* @ClassName Zuul_9527_StartSpringCloudApp
* @Description TODO
* @Author 百里诀
* @Date 2022/10/18 16:20
* @Version 1.0
*/

@SpringBootApplication
@EnableZuulProxy
public class Zuul_9527_StartSpringCloudApp {
public static void main(String[] args) {
SpringApplication.run(Zuul_9527_StartSpringCloudApp.class,args);
}
}

4.启动

三个eureka集群

一个服务提供类microservicecloud-provider-dept-8001

一个路由

5.测试

不用路由

http://localhost:8001/dept/get/2

image-20221018163525022

启用路由

http://myzuul.com:9527/microservicecloud-dept/dept/get/2

image-20221018164319296

路由访问映射规则

1.代理名称修改YML文件

zuul:
routes:
mydept.serviceId: mycroservicecloud-dept
mydept.path: /mydept/**
# ignored-services: "*"
# ignored-services: mycroservicecloud-dept
# prefix: /atguigu

此时出现的问题:

路由访问OK,http://myzuul.com:9527/mydept/dept/get/1

原路径访问OK,http://myzuul.com:9527/microservicecloud-dept/dept/get/2

2.原真实服务名忽略

zuul:
routes:
mydept.serviceId: mycroservicecloud-dept
mydept.path: /mydept/**
# ignored-services: "*"
ignored-services: mycroservicecloud-dept

单个具体,多个可以用”*”

3.设置统一公共前缀

zuul:
routes:
mydept.serviceId: mycroservicecloud-dept
mydept.path: /mydept/**
# ignored-services: "*"
ignored-services: mycroservicecloud-dept
prefix: /atguigu

http://myzuul.com:9527/atguigu/mydept/dept/get/1

SpringCloudConfig分布式配置中心

概述

1.分布式系统面临的配置问题

image-20221018165413884

2.是什么?

image-20221018165525138

SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置

3.怎么玩?

SpringCloud Config分为服务端合客户端两部分

服务端也被称为分布式配置中心,它是一个独立的微服务应用。用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问端接口

客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。

4.能干嘛?

image-20221018171204194

5.与GitHub整合配置image-20221018171239256

SpringConfig服务端配置

1.用自己的GitHub账号在GitHub上新建一个名为microservicecloud-config的新Repository

image-20221019232546756

2.由上一步获得SSH协议的git地址

git@github.com:Starhunter-23/microservicecloud-config.git

3.本地硬盘目录上新建git仓库并clone

本地地址:D:\myspringcloud-git

git命令:git clone git@github.com:Starhunter-23/microservicecloud-config.git

image-20221019233002777

4.在本地D:\myspringcloud-git\microservicecloud-config里面新建一个yml文件

image-20221019233401807

yml内容:

spring:
profiles:
active:
- dev

---

spring:
profiles: dev #开发环境
application:
name: microservicecloud-config-atguigu-dev

---

spring:
profiles: test #测试环境
application:
name: microservicecloud-config-atguigu-test

#请保存为UTF-8格式

保存格式一定为UTF-8

5.将上一步的YML文件推送到github上

git add .

git commit -m “init yml”

git push origin master

image-20221020210410414

image-20221020210427006

image-20221020210448840

image-20221020210456759

6.新建Module模块microservicecloud-config-3344它即为Cloud的配置中心模块并编写POM文件

image-20221020211039945

<?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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-config-3344</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.3</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>6.1.0.202203080745-r</version>
</dependency>
</dependencies>
</project>

7.YML文件

server:
port: 3344

spring:
application:
name: microservicecloud-config
cloud:
config:
server:
git:
uri: https://github.com/Starhunter-23/microservicecloud-config.git #GitHub上面的git仓库名字
username: 2312460355@qq.com
password: HOPEhope00
search-paths:
- springcloud-config #搜索目录
label: main #读取分支

8.主启动类Config_3344_StartSpringCloudApp

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;


/**
* @ClassName Config_3344_StartSpringCloudApp
* @Description TODO
* @Author 百里诀
* @Date 2022/10/20 21:28
* @Version 1.0
*/

@SpringBootApplication
@EnableConfigServer
public class Config_3344_StartSpringCloudApp {
public static void main(String[] args) {
SpringApplication.run(Config_3344_StartSpringCloudApp.class,args);
}
}

9.windows下修改hosts文件,增加映射

image-20221020213142633

10.测试通过Config微服务是否可以从GitHub上获取配置内容

image-20221020232349581

image-20221020232432353

image-20221020232518902

image-20221020232558040

11.配置读取规则

image-20221020232833894

12.SpringCloud Config通过GitHub获取配置信息

3.SpringCloud Config客户端配置与测试

1.在本地D:\myspringcloud-git\microservicecloud-config路径下新建文件microservicecloud-config-client.yml

image-20221020233445936

2.microservicecloud-config-client.yml内容

	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/

3.将上一步提交到GitHub中

image-20221020234702614

4.新建microservicecloud-config-client-3355模块并修改POM文件

image-20221020234954199

<?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>microservicecloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservicecloud-config-client-3355</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.3</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>

<!-- SpringCloud Config客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

</dependencies>

</project>

5.bootstrap.yml

image-20221021102426499

image-20221021102927017

spring:
cloud:
config:
name: microservicecloud-config-client #需要从github上读取的资源名称,注意没有yml后缀名
profile: dev #本次访问的配置项
label: master
uri: http://config-3344.com:3344 #本微服务启动后先去找3344号服务,通过SpringCloudConfig获取Github的服务地址

6.application.yml

spring:
application:
name: microservicecloud-config-client

7.windows下修改hosts文件,增加映射

image-20221021103444590

8.新建rest类,验证是否能从GitHub上读取配置

package com.atguigu.springcloud.rest;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @ClassName ConfigClientRest
* @Description TODO
* @Author 百里诀
* @Date 2022/10/21 10:35
* @Version 1.0
*/
@RestController
public class ConfigClientRest {

@Value("${spring.application.name}")
private String applicationName;

@Value("${eureka.client.service-url.defaultZone}")//不支持驼峰命名
private String eurekaServers;

@Value("${server.port}")
private String port;

@RequestMapping("/config")
public String getConfig()
{
String str = "applicationName: "+applicationName+"\t eurekaServers:"+eurekaServers+"\t port:"+port;
System.out.println("***********str: "+str);
return "applicationName: "+applicationName+"\t eurekaServers:"+eurekaServers+"\t port: "+port;
}
}

9.主启动类ConfigClient_3355_StartSpringCloudApp

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
* @ClassName ConfigClient_3355_StartSpringCloudApp
* @Description TODO
* @Author 百里诀
* @Date 2022/10/21 10:41
* @Version 1.0
*/

@SpringBootApplication
@EnableDiscoveryClient
public class ConfigClient_3355_StartSpringCloudApp {
public static void main(String[] args) {
SpringApplication.run(ConfigClient_3355_StartSpringCloudApp.class,args);
}
}

10.测试

1.启动Config配置中心3344微服务并且自测

http://config-3344.com:3344/application-dev.yml

image-20221021104800302

2.启动3355作为Client准备访问

暂时无法解决问题

Injection of auto wired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder ‘eureka.client.service-url.defaultZone’ in value “${eureka.client.service-url.defaultZone}”

3.bootstrap.yml里面的profile值是什么,决定从github上读取什么

image-20221021114557414

成功实现了客户端3355访问SpringCloud Config3344通过GitHub获取配置信息

仙之巅,傲世间,有我Magi就有天