springcloud 学习项目

  • 概述
    • 1.springcloud是什么,为什么要学springcloud,不学springcloud又怎样呢。
  • 一、创建一个简单的springcloud项目
    • 1_1、创建数据库和一个maven项目
      • 1_1_1 创建数据库db01,并创建表格dept,数据如下
      • 1_1_2 创建maven项目并删掉src文件夹,然后添加依赖
    • 1_2、创建springcloud-api模块
      • 1_2_1.导入依赖
      • 1_2_2 创建实体类pojo
    • 1_3 创建一个微服务提供者(springcloud-provider-dept-8001):
      • 1_3_1导入依赖
      • 1_3_2 配置application.yml
      • 1_3_3 配置dao层,service层,controller层
        • 1_3_3_1 dao/DeptDao:实体类的的增删改查方法的实现
        • 1_3_3_2 service层
        • 1_3_3_4 controller层
      • 1_3_4配置开启springboot服务器的类
      • 1_3_5对controller进行测试
    • 1_4创建服务消费者springcloud-consumer-dept-80
      • 1_4_1 导入依赖
      • 1_4_2 在applicaction.yml中修改端口号
      • 1_4_3 将RestTemplate注册到bean中
      • 1_4_4 配置controller层(通过restTemplate调用服务器的url)
      • 1_4_5 配置开启springboot服务器的类的类名
      • 1_4_5测试
    • 1_5创建eureka服务器(springcloud-eureka-7001)(已过时)
      • 1_5_1导入依赖
      • 1_5_2application.yml配置
      • 1_5_3 配置springboot启动类
      • 1_5_4 测试
      • 1_5_5 将8001和80配置为eureka服务器的的Client
        • 1_5_5_1在原有依赖上加上eureka依赖
        • 1_5_5_2修改application.yml
        • 1_5_5_3该启动类添加@EnableEurekaClient注解
        • 1_5_5_4测试
    • 1_6 通过actuator完善eureka的监控信息
      • 1_6_1 导入actuator依赖
      • 1_6_2 在eureka界面查看客户详细信息:在application.yml中配置info
      • 1_6_2通过controller(即http请求)查看客户详细信息:使用discovery
        • 1_6_2_1配置访问信息的controller控制器
        • 1_6_2_2在启动类中添加@EnableDiscoveryClient注解
        • 1_6_2_3进入[http://localhost:8001/dept/discovery](http://localhost:8001/dept/discovery)查看效果
    • 1_7搭建eureka集群环境
      • 1_7_1复制eureka7001,生成7002,7003
      • 1_7_2修改各个eureka服务器的主机名hostname,使得主机名唯一
      • 1_7_3模拟多台独立服务器(域名)组成集群的效果:修改hosts中的域名映射关系
      • 1_7_4 测试:使用服务器提供者8001来进行测试
      • 1_7_5将服务提供者向所以eureka服务器连通
      • 1_7_5配置服务端集群
        • (1)复制数据库生成完全一样的db02和db03,并修改datasource属性为当前数据库。
        • (2)创建多台服务提供者:复制springcloud-provider-dept-8001模块生成8002和8003
    • 1_8在客户端实现负载均衡
      • 1_8_1 使用ribbon自带负载均衡算法:@LoadBalanced
      • 1_8_2 使用ribbon实现自定义负载均衡算法
        • (1)自己编写一个Rule类继承AbstractLoadBalancerRule,并添加choose(ILoadBalancer lb, Object key) 方法。
        • (2)将该策略添加到项目中(在启动类上使用@RibbonClient)
        • (3)测试
      • 1_8_3 使用nginx实现负载均衡思路图
      • 1_8_4 使用openFeign实现负载均衡
    • 1_9 使用feign替代RestTemplate(其内部集成了RestTemplate)
      • 1_9_1 复制然后创建一个新的服务消费者model用来测试feign
      • 1_9_2 在原来依赖的基础上添加feign依赖
      • 1_9_3 修改启动类名为FeignDeptConsumer_80,并添加注解@EnableFeignClients扫描FeignClient
      • 1_9_4在Fiegn所在的服务消费者中添加service层(使用@FeignClient)
      • 1_9_5在controller不使用RestTemplate,而是使用DeptClientService来调用服务提供者。
      • 1_9_6测试
    • 1_10分布式系统的延迟和容错处理方式
      • Hytrix实现服务熔断(已过时)
        • 1_10_1复制springcloud-provider-dept-8001生成一个新的服务提供者:springcloud-provider-dept-hystrix-8001
        • 1_10_2添加Hystrix依赖到原有依赖中
        • 1_10_3在application.yml中修改instance-id,方便区分
        • 1_10_4修改启动类名为:DeptProviderHystrix_8001.java,并添加@EnableCircuitBreaker
        • 1_10_5修改controller层(添加处理错误的功能)
        • 1_10_6测试`http://localhost/consumer/dept/get/6`
      • feign实现服务降级
        • 1_10_7在feign实现负载均衡的基础上添加一个类
        • 1_10_8给servicec层的接口添加服务降级画面显示(fallbackFactory)
        • 1_10_9测试
      • 熔断监控DashBoard监控请求(流量)
        • 1_10_10新建一个模块:`springcloud-consumer-hystrix-dashboard`,并往dashboard模块中添加依赖
        • 1_10_11设置dashboard模块的端口
        • 1_10_12配置启动类
        • 1_10_13在`springcloud-provider-dept-hystrix-8001`的启动类上添加servlet
        • 1_10_14测试
    • 1_11路由网关Zuul(已过时)
      • 1_11_1添加依赖
      • 1_11_2 配置application.yml
      • 1_11_3修改域名映射关系:C:\Windows\System32\drivers\etc\hosts
      • 1_11_4配置启动类ZuulApplication_9527
      • 1_11_5测试
      • 1_11_5实现域名伪装:修改9527一下application.yml的zuul配置,并测试
    • 1_12config
      • Git环境配置
        • 1_12_1配置Git项目环境
        • 1_12_2在git码云上创建一个项目,并获取到本地。然后新建一个application.yml文档,并添加上以下内容。
        • 1_12_3上传到git远程服务器。
      • 配置config服务端并连接git的远程仓库
        • 1_12_4导入依赖
        • 1_12_5配置application.yml
        • 1_12_6 配置启动类
        • 1_12_7测试是否联通
      • 通过git进行远程资源 配置 本地项目。
        • 1_12_8在git项目目录下添加一个yml文档。
        • 1_12_9 push到远程服务器
        • 1_12_10 创建springcloud-config-client-3355模块,并配置依赖
        • 1_12_11 配置配置文件
        • 1_12_12启动类和controller层
        • 1_12_12访问`http://localhost:8201/config`测试
      • 远程配置资源项目(这里以7001服务器为例)
      • 1_12_13 配置并上传远程资源
      • 1_12_14 创建一个7001模块,并导入依赖
      • 1_12_15创建bootstrap.yml和application.yml(核心)
      • 1_12_16 配置启动类
      • 1_12_17测试
  • -----------------------springcloud新技术-----------------------
  • 一、Nacos:服务中心+配置中心
    • 1、Nacos作为服务中心
      • 1.1 下载、启动nacos
      • 1.2 nacos替代eureka作为服务注册中心
        • (1) 在nacos客户端(如服务提供者、服务消费者)上添加依赖
        • (2) 对eureka客户端进行配置
        • (3)配置启动类
        • (4)在nacos中发现该客户端成功
      • 2.1.3 nacos替代Config作为服务配置中心
      • 2.1.4 nacos集群和持久化配置
    • 2、Nacos作为配置中心
  • GateWay网关
    • 2.1 GateWay+Eureka
      • 2.1.1 GateWay实现路由效果
        • (1) 添加依赖
        • (2)添加配置文件
        • (3)配置启动类
        • (4)测试:实现路由功能
      • 2.1.2 Gateway配置动态路由,实现负载均衡
        • (1)在2.1.1基础上更改配置文件
        • (2) 测试负载均衡效果
      • 2.1.2 Gateway如何自定义负载均衡策略呢
      • 2.1.3 Gateway的Predicate
      • 2.1.4 GateWay的filter
        • Gateway自带的filter
        • 使用自定义filter(全局GlobalFilter)
    • 2.2 Nacos+Eureka
      • 2.2.1
  • 【附加】springcloud原理和思想
    • CAP理论
    • ribbon:客户端负载均衡的工具

概述

1.springcloud是什么,为什么要学springcloud,不学springcloud又怎样呢。

一、创建一个简单的springcloud项目

本程序的结构图如下

  

1_1、创建数据库和一个maven项目

1_1_1 创建数据库db01,并创建表格dept,数据如下

  

1_1_2 创建maven项目并删掉src文件夹,然后添加依赖

点击查看dependencyManagement和dependencys的区别

1、关于打包方式:
pom:(父模块)用在父级工程或聚合工程中,用来做jar包的版本控制,必须指明这个聚合工程的打包方式为pom
war:(子模块)将会打包成war,发布在服务器上,如网站或服务。用户可以通过浏览器直接访问,或者是通过发布服务被别的工程调用
2、这里使用了propertieyManagement来管理依赖的版本:
dependencies即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承)
dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。实际上只要在最大的项目内使用dependencyManagement之后(可以不在子模块中写同样的代码重复控制版本),那么子子模块、子子子模块都会默认使用dependencyManagement规定的版本。

    <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.targer>1.8</maven.compiler.targer><junit.version>4.12</junit.version><lombok.version>1.16.18</lombok.version><log4j.version>1.2.17</log4j.version></properties>
<!--    1.:packaging使用pom的打包方式--><packaging>pom</packaging>
<!--    **************2.依赖管理:仅管理依赖,但不导入依赖***********--><dependencyManagement><dependencies>
<!--     springcloud的依赖(与其他依赖相比是pom类型)--><!-- 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 启动器(内涵Mybatis)--><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>
<!--        junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version><scope>test</scope></dependency>
<!--            lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></dependency>
<!--           log4j--><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>${log4j.version}</version></dependency></dependencies></dependencyManagement><!--配置打包插件build--><!--        <build>--><!--         <resources></resources>   --><!--        </build>-->

1_2、创建springcloud-api模块

  

1_2_1.导入依赖

<?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_01</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>springcloud-api</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties>
<!--    当前module中自己需要的依赖,如果父依赖中已经配制了版本,这里就不用写了--><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>
</project>

1_2_2 创建实体类pojo

@Data
@NoArgsConstructor
//使用链式写法(该类中的所有setter和getter方法的返回值都是this哦)
//@Accessors(prefix = "xxx")是忽略以xxx开头的属性,其余属性使用链式写法
@Accessors(chain = true)
public class Dept implements Serializable {//Dept实体列,orm对象关系映射private Long deptno;//主键private String dname;//这个数据是存在哪个数据库的字段~微服务,一个服务对应一个数据库,同一个信息可能存在不同的数据库private String db_source;public Dept(String name){this.dname=dname;}
}

1_3 创建一个微服务提供者(springcloud-provider-dept-8001):

  

1_3_1导入依赖

热部署工具非常好用,是指我们在程序中修改java代码之后能够生效。
使用方法很简单:1、添加依赖 2、修改服务器设置
参考文章

    <dependencies>
<!--    1、添加Pojo实体类--><dependency><groupId>org.junjun</groupId><artifactId>springcloud-api</artifactId><version>1.0-SNAPSHOT</version></dependency><!--    2、springboot和测试类--><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><scope>com.junjun.test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><scope>com.junjun.test</scope></dependency><!--    3、数据库相关--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId></dependency><!--     4、热部署工具:就是我们改动java代码后不用手动重启项目--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency></dependencies>

1_3_2 配置application.yml

server:port: 8001
#  mybatis的配置
mybatis:type-aliases-package: com.junjun.springcloud.pojomapper-locations: classpath:mybatis/mapper/*.xmlconfig-location: classpath:mybatis/mybatis-config.xml#spring服务器和数据库的配置
spring:application:name: springcloud-provider-deptdatasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: org.gjt.mm.mysql.Driverurl: jdbc:mysql://localhost:3306/db01?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezeno=GMT%2B8username: rootpassword: 3333

1_3_3 配置dao层,service层,controller层

1_3_3_1 dao/DeptDao:实体类的的增删改查方法的实现

使用@Mapper就能被对应的xml文档用namespace=""给找到(而且有提示)。

@Mapper
@Repository
public interface DeptDao {public boolean addDept(Dept dept);public Dept queryById(Long id);public List<Dept> queryAll();
}

—DeptDao在sources中的对应的mapper.xml

虽然会爆红报错(xml中找不到Dept),但是可以正常运行

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--命名空间是对应的接口--><mapper namespace="com.junjun.springcloud.dao.DeptDao"><insert id="addDept" parameterType="Dept">insert into dept(dname,db_source)value (#{dname},DATABASE())</insert>
<!--    只有一个参数,因此#{}中可以随便写--><select id="queryById" resultType="Dept" parameterType="Long">select  * from dept where deptno=#{deptno};</select><select id="queryAll" resultType="Dept">select  * from dept;</select>
</mapper>
1_3_3_2 service层

--------service/DeptService

public interface DeptService {public boolean addDept(Dept dept);public Dept queryById(Long id);public List<Dept> queryAll();
}

--------service/DeptServiceImpl

@Service
public class DeptServiceImpl implements DeptService{@Autowiredprivate DeptDao deptDao;@Overridepublic boolean addDept(Dept dept) {return deptDao.addDept(dept);}@Overridepublic Dept queryById(Long id) {return deptDao.queryById(id);}@Overridepublic List<Dept> queryAll() {return deptDao.queryAll()  ;}
}
1_3_3_4 controller层

-------controller/DeptController

//提供Restful服务!
@RestController
public class DeptController {@Autowiredprivate DeptService deptService;@PostMapping("/dept/add")public boolean addDept(Dept dept){return deptService.addDept(dept);}
//  带占位符的url是springMVC的重要功能,请求中的{xxx}将会被传送到@PathVariable("xxx")中去@GetMapping("/dept/get/{id}")public Dept getDept(@PathVariable("id") Long id){return deptService.queryById(id);}@GetMapping("/dept/list")public List<Dept> getAll(){return deptService.queryAll();}
}

1_3_4配置开启springboot服务器的类

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

1_3_5对controller进行测试

  

1_4创建服务消费者springcloud-consumer-dept-80

  

1_4_1 导入依赖

    <dependencies><!--    1、添加Pojo实体类--><dependency><groupId>org.junjun</groupId><artifactId>springcloud-api</artifactId><version>1.0-SNAPSHOT</version></dependency><!--    2、springboot--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>

1_4_2 在applicaction.yml中修改端口号

server:port: 80

1_4_3 将RestTemplate注册到bean中

相当于在xml中用< bean/>注册,这种方式常用于框架中已经存在的类,自己定义的类通常会使用@Component在定义时就一步注册

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

1_4_4 配置controller层(通过restTemplate调用服务器的url)

1.消费者不应该有service层,而是调用服务提供者的service层,我们可以通过RestTemplate来申请调用服务提供者的url。
2.RestTemplate是Spring提供的一个访问Http服务的客户端类。服务消费者通过restTamplate给服务提供者发送HTTP请求并接受响应。。简单来说就是restTamplate可以用来调用请求并得到该服务器运行后的返回结果。

@RestController
public class DeptConsumerController {@Autowireprivate RestTemplate restTemplate;private static final String REST_URL_PREFIX="http://localhost:8001";//getForObject的三个参数是:url,返回值类型,占位符传参@RequestMapping("/consumer/dept/add")public boolean add(@RequestBody 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);}
}

1_4_5 配置开启springboot服务器的类的类名

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

1_4_5测试

1_5创建eureka服务器(springcloud-eureka-7001)(已过时)

eureka会提供服务注册和发现

1_5_1导入依赖

只需要eureka服务器,这样就能开启服务器了。当然,eureka-server只是具有服务器最基本的功能(@SpringBootApplication),但是却没有springboot的各种注解,如@Component,@Autowired等。

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

1_5_2application.yml配置

  1. eureka: client: register-with-eureka
    表示是否想eureka注册中心注册自己,默认是true。
    1,如果true表示要注册的话得在defaultZone提供一个注册中心地址,说明在这个注册中心注册
    2.如果false表示不注册。一般eureka服务器不会在注册中心注册,只有服务提供者和消费者才要注册。
  2. eureka: client: fetch-registry
    表示是否从Eureka Server获取注册中心的服务信息,默认值是true
    1.eureka服务器没有必要获取注册中心的注册信息,所以用false
    2.eureka客户才需要获取注册信息来决定给哪一个服务器发送信息
  3. eureka: client: service-url: defaultZone:的作用?????:
    service-url: defaultZone:是默认服务注册中心地址,默认是http://localhost:端口/eureka ;多个地址可使用 , 分隔。在eureka服务器和客户开启时都向这个地址进行注册,实际上,eureka服务器集群原理就是注册中心相互注册,但是不开启检索服务的能力(fetch-registry: false)。
    如果服务器或客户开启了register-with-eureka但是填写的defaultZone是无效地址 >就会报错Eureka was unable to refresh its cache! status = Cannot execute request on any known server
    如果服务器不开启register-with-eureka但是填写的defaultZone是非http:地址(不合语法)>就会无法显示查询注册者的信息。如下
server:port: 7001
eureka:instance:hostname: localhost   #Eureka服务端的实例名称client:register-with-eureka: false  # 表示是否想eureka注册中心注册自己,默认值都是truefetch-registry: false  #表示是否从Eureka Server获取注册中心的服务信息,eureka服务端没有必要获取注册中心的注册信息,默认值都是trueservice-url:defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/# http://${eureka.instance.hostname}:${server.port}/eureka/就是http://localhost:7001/eureka/,使用了赋值操作,实际上$(eureka.instance.hostname)就是localhost,${server.port}就是7001,这都在上面定义过了。

1_5_3 配置springboot启动类

@SpringBootApplication
@EnableEurekaServer//EnableEurekaServer是开启服务器的启动类,他能够接受别人注册进来~
public class EurekaServer_7001 {public static void main(String[] args) {SpringApplication.run(EurekaServer_7001.class);}
}

1_5_4 测试

即使能显示出如下界面也不代表没有配置错误,application.yml仍然有可能错误通过http://localhost:7001/来访问测试Eureka服务器是否搭建是否成功。

  

1_5_5 将8001和80配置为eureka服务器的的Client

1_5_5_1在原有依赖上加上eureka依赖

spring-cloud-starter-eureka已经可以作为服务器开启了,但是没有springboot的核心功能。

    <dependencies>
<!--    1、添加Pojo实体类--><dependency><groupId>org.junjun</groupId><artifactId>springcloud-api</artifactId><version>1.0-SNAPSHOT</version></dependency><!--    2、springboot,都可以不用了,可以用eureka启动服务器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--    3、数据库相关--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId></dependency><!--     4、热部署工具:就是我们改动java代码后不用手动重启项目--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency><!--      5、eureka客户端--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId><version>1.4.6.RELEASE</version></dependency></dependencies>
1_5_5_2修改application.yml
server:port: 8001
#  mybatis的配置
mybatis:type-aliases-package: com.junjun.springcloud.pojomapper-locations: classpath:mybatis/mapper/*.xmlconfig-location: classpath:mybatis/mybatis-config.xml#spring的配置
spring:application:name: springcloud-provider-deptdatasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: org.gjt.mm.mysql.Driverurl: jdbc:mysql://localhost:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezeno=GMT%2B8username: rootpassword: 3333#Eureka的配置
eureka:client:service-url:defaultZone: http://localhost:7001/eureka/
1_5_5_3该启动类添加@EnableEurekaClient注解
@SpringBootApplication
@EnableEurekaClient//在程序启动之后会自动注册到Eureka服务端中!通过http://localhost:7001/能进入Eureka界面能看见注册的Eureka
public class DeptProvider_8001 {public static void main(String[] args) {SpringApplication.run(DeptProvider_8001.class,args);}
}
1_5_5_4测试

先启动7001,进入http://localhost:7001/,再启动8001,然后刷新http://localhost:7001/
1.若没有出现也由是springcloud-eureka-7001的application.yml出现了问题。
  

1_6 通过actuator完善eureka的监控信息

1_6_1 导入actuator依赖

    <dependencies>
<!--    1、添加Pojo实体类--><dependency><groupId>org.junjun</groupId><artifactId>springcloud-api</artifactId><version>1.0-SNAPSHOT</version></dependency><!--    2、springboot,都可以不用了,可以用eureka启动服务器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--    3、数据库相关--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId></dependency><!--     4、热部署工具:就是我们改动java代码后不用手动重启项目--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency><!--      5、eureka客户端--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId><version>1.4.6.RELEASE</version></dependency>
<!--     6、actuator完善监控信息--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency></dependencies>

1_6_2 在eureka界面查看客户详细信息:在application.yml中配置info

server:port: 8001
#  mybatis的配置
mybatis:type-aliases-package: com.junjun.springcloud.pojomapper-locations: classpath:mybatis/mapper/*.xmlconfig-location: classpath:mybatis/mybatis-config.xml
#spring的配置
spring:application:name: springcloud-provider-dept #本应用在Eureka中的Application名称datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: org.gjt.mm.mysql.Driverurl: jdbc:mysql://localhost:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezeno=GMT%2B8username: rootpassword: 3333
#Eureka的配置
eureka:client:service-url:defaultZone: http://localhost:7001/eureka/instance:instance-id: springcloud-provider-dept8001 #修改eureka中的默认描述信息
#info配置:点击Status:UP就会得到eureka客户详细信息:{"app":{"name":"junjun-springcloud"},"company":{"name":"blog.junjun.com"}}
info:app.name: junjun-springcloudcompany.name: blog.junjun.com

再先后开启7001和8001,然后进入http://localhost:7001/网页。
  

1_6_2通过controller(即http请求)查看客户详细信息:使用discovery

1_6_2_1配置访问信息的controller控制器
@RestController
public class DeptController {@Autowiredprivate DeptService deptService;@Autowired//用来获取一些配置的信息,得到具体的微服务private DiscoveryClient client;//import org.springframework.cloud.client.discovery.DiscoveryClient;@PostMapping("/dept/add")public boolean addDept(Dept dept){return deptService.addDept(dept);}
//  带占位符的url是springMVC的重要功能,请求中的{xxx}将会被传送到@PathVariable("xxx")中去@GetMapping("/dept/get/{id}")public Dept getDept(@PathVariable("id") Long id){return deptService.queryById(id);}@GetMapping("/dept/list")public List<Dept> getAll(){return deptService.queryAll();}//注册进来的微服务~获取一些消息@GetMapping("/dept/discovery")public Object discovery(){//获取微服务列表的清单List<String> services = client.getServices();System.out.println("discovery=>services"+services);//通过eureka中的application(即"SPRINGCLOUD-PROVIDER-DEPT")来得到一个具体的微服务的信息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;}}
1_6_2_2在启动类中添加@EnableDiscoveryClient注解
@SpringBootApplication
@EnableEurekaClient//在程序启动之后会自动注册到Eureka服务端中!通过http://localhost:7001/能进入Eureka界面能看见注册的Eureka
@EnableDiscoveryClient
public class DeptProvider_8001 {public static void main(String[] args) {SpringApplication.run(DeptProvider_8001.class,args);}
}
1_6_2_3进入http://localhost:8001/dept/discovery查看效果

  

实际上我们完全可以通过status链接跳转到discorery界面或者是swagger界面等其他链接,只需要修改eureka.instance.status-page-url地址就行。

server:port: 8001#springboot和数据库相关配置
spring:application:name: server-provider-8001  #本应用在Eureka中的Application名称datasource:username: rootpassword: 3333url: jdbc:mysql://localhost:3306/db01?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezeno=GMT%2B8driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource
mybatis:mapper-locations: classpath:/mapper/DeptMapper.xml#Eureka的配置
eureka:client:service-url:defaultZone: http://localhost:7001/eureka/#Eureka Client注册到Eureka Server要用上这个地址instance:instance-id: provider_dept8001  #修改eureka中status的up的默认描述信息status-page-url: http://localhost:8001/dept/discovery #默认地址:http://desktop-8aqan37:8001/actuator/info##info配置:点击UP就会得到信息:{"app":{"name":"junjun-springcloud"},"company":{"name":"blog.junjun.com"}}
#info:
#  app.name: junjun-springcloud
#  company.name: blog.junjun.com

1_7搭建eureka集群环境

1_7_1复制eureka7001,生成7002,7003

  

1_7_2修改各个eureka服务器的主机名hostname,使得主机名唯一

1.把hostname和defaultZone修改一下,每个和其他所有eureka服务器相互注册。
2.要想搭配成集群环境,必须满足以下两个条件
(1)每台eureka服务器主机名唯一eureka.instance.hostname:
(2)每两个服务器service-url.defaultZone相互关联
实际上,eureka服务器集群原理就是注册中心相互注册,但是不开启检索服务的能力(fetch-registry: false)。
如果注册中心a的defaultZone为空或指向自己(不向b注册),注册中心b向a进行注册,那么注册信息是单向传递的(b会共享给a,a不会共享给b)参考文章。
3.测试结果:集群中所有服务器共享注册信息。即在一台eureka服务器上注册,另外两条也能显示注册信息。

--------7001的application.yml

server:port: 7001
eureka:instance:hostname: eureka7001.com   #Eureka服务端的实例名称client:register-with-eureka: false  # 表示是否想eureka注册中心注册自己,1,如果要注册的话得在defaultZone提供注册中心地址fetch-registry: false  #表示是否从Eureka Server获取注册中心的服务信息,eureka服务端没有必要获取注册中心的注册信息,默认值都是trueservice-url:#  单机:defaultZone:  http://${eureka.instance.hostname}:${server.port}/eureka/#集群(关联):defaultZone:  http://localhost:7002/eureka/,http://localhost:7003/eureka/

--------7002的application.yml

server:port: 7002
eureka:instance:hostname: eureka7002.com   #Eureka服务端的实例名称client:register-with-eureka: false  # 表示是否想eureka注册中心注册自己,1,如果要注册的话得在defaultZone提供注册中心地址fetch-registry: false  #表示是否从Eureka Server获取注册中心的服务信息,eureka服务端没有必要获取注册中心的注册信息,默认值都是trueservice-url:#  单机:defaultZone:  http://${eureka.instance.hostname}:${server.port}/eureka/#集群(关联):defaultZone:  http://localhost:7001/eureka/,http://localhost:7003/eureka/

--------7003的application.yml

server:port: 7003
eureka:instance:hostname: eureka7003.com   #Eureka服务端的实例名称client:register-with-eureka: false  # 表示是否想eureka注册中心注册自己,1,如果要注册的话得在defaultZone提供注册中心地址fetch-registry: false  #表示是否从Eureka Server获取注册中心的服务信息,eureka服务端没有必要获取注册中心的注册信息,默认值都是trueservice-url:#  单机:defaultZone:  http://${eureka.instance.hostname}:${server.port}/eureka/#集群(关联):defaultZone:  http://localhost:7001/eureka/,http://localhost:7002/eureka/

1_7_3模拟多台独立服务器(域名)组成集群的效果:修改hosts中的域名映射关系

其实只要每个eureka服务器主机名不一样就能搭配成集群环境了,但是因为所有eureka服务器都部署在本地显得DS Replicas显示域名都是localhost。为了把eureka服务器做出区分,我们在hosts中修改域名映射关系来模拟在多台独立服务器(域名)组成集群的效果。要想让这两个url生效得在C:\Windows\System32\drivers\etc\hosts文档中添加域名映射关系
1.修改hosts域名关系映射表

2.修改defaultZone:注册中心地址。

server:port: 7001
eureka:instance:hostname: eureka7001.com   #Eureka服务端的实例名称client:register-with-eureka: false  # 表示是否想eureka注册中心注册自己,1,如果要注册的话得在defaultZone提供注册中心地址fetch-registry: false  #表示是否从Eureka Server获取注册中心的服务信息,eureka服务端没有必要获取注册中心的注册信息,默认值都是trueservice-url:#  单机:defaultZone:  http://${eureka.instance.hostname}:${server.port}/eureka/#集群(关联):defaultZone:  http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
server:port: 7002
eureka:instance:hostname: eureka7002.com   #Eureka服务端的实例名称client:register-with-eureka: false  # 表示是否想eureka注册中心注册自己,1,如果要注册的话得在defaultZone提供注册中心地址fetch-registry: false  #表示是否从Eureka Server获取注册中心的服务信息,eureka服务端没有必要获取注册中心的注册信息,默认值都是trueservice-url:#  单机:defaultZone:  http://${eureka.instance.hostname}:${server.port}/eureka/#集群(关联):defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/ #eureka7002.com等这三个会在hosts文档中添加这种映射关系
server:port: 7003
eureka:instance:hostname: eureka7003.com   #Eureka服务端的实例名称client:register-with-eureka: false  # 表示是否想eureka注册中心注册自己,1,如果要注册的话得在defaultZone提供注册中心地址fetch-registry: false  #表示是否从Eureka Server获取注册中心的服务信息,eureka服务端没有必要获取注册中心的注册信息,默认值都是trueservice-url:#  单机:defaultZone:  http://${eureka.instance.hostname}:${server.port}/eureka/#集群(关联):defaultZone:  http://eureka7002.com:7002/eureka/, http://eureka7001.com:7001/eureka/#这三个会在hosts文档中添加这种映射关系

1_7_4 测试:使用服务器提供者8001来进行测试

1、先开启7001,7002,7003,http://localhost:7001/
再开启8001,注意8001的service-url:defaultZone: http://localhost:7001/eureka/即仅在一台eureka服务器上注册,但是在eureka集群环境eureka服务器会进行注册信息同步.因此刷新http://localhost:7001/http://localhost:7002/http://localhost:7003/后都能找到8001,那集群环境就算配置成功!
  

1_7_5将服务提供者向所以eureka服务器连通

2、然后我们会将服务提供者进行配置:defaultZone:http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/,使得服务提供者可以在任意一台eureka服务器上进行注册。

server:port: 8001
#  mybatis的配置
mybatis:type-aliases-package: com.junjun.springcloud.pojomapper-locations: classpath:mybatis/mapper/*.xmlconfig-location: classpath:mybatis/mybatis-config.xml#spring和数据库的配置
spring:application:name: springcloud-provider-dept #本应用在Eureka中的名称(会变成大写)datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: org.gjt.mm.mysql.Driverurl: jdbc:mysql://localhost:3306/db01?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezeno=GMT%2B8username: rootpassword: 3333#Eureka的配置
eureka:client:service-url:defaultZone: http://localhost:7001/eureka/ #本机的7001,7002,7003端口可以访问Eurekainstance:instance-id:  springcloud-provider-dept8001,springcloud-provider-dept8002,springcloud-provider-dept8003  #修改eureka中的默认描述信息
#info配置:点击UP就会得到信息:{"app":{"name":"junjun-springcloud"},"company":{"name":"blog.junjun.com"}}
info:app.name: junjun-springcloudcompany.name: blog.junjun.com

1_7_5配置服务端集群

(1)复制数据库生成完全一样的db02和db03,并修改datasource属性为当前数据库。
CREATE TABLE db02.dept LIKE db01.dept;
INSERT INTO db02.dept SELECT * FROM db01.dept;
CREATE TABLE db03.dept LIKE db01.dept;
INSERT INTO db03.dept SELECT * FROM db01.dept;
(2)创建多台服务提供者:复制springcloud-provider-dept-8001模块生成8002和8003

1.记得要修改每个服务提供者端口号
2.修改每个服务提供者所使用的数据库spring.datasource.url
3.修改每个服务提供者Eureka的配置,
修改defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/,使得服务提供者能够在任意一台eureka服务器上进行注册
修改instance-id,使得每台服务提供者的id都不同。
4.修改每个服务提供者自定义启动类的名称
【注意】
要保证三个服务器的spring.application.name是一样的哦,只有三台服务器的spring.application.name是一样的才能形成服务器集群,不然就不是同一个应用的服务器了。

  

1_8在客户端实现负载均衡

负载均衡的实现方式有两种,分别是服务端负载均衡(nginx)客户端负载均衡(ribbon):
服务端负载均衡:当浏览器向后台发出请求的时候,会首先向反向代理服务器发送请求,反向代理服务器会根据客户端部署的ip:port映射表以及负载均衡策略,来决定向哪台服务器发送请求,一般会使用到nginx反向代理技术。
客户端负载均衡:当浏览器向后台发出请求的时候,客户端会向服务注册器(例如:Eureka Server),拉取注册到服务器的可用服务信息,然后根据负载均衡策略,直接命中哪台服务器发送请求。这整个过程都是在客户端完成的,并不需要一个独立的Ribbon服务器(反向代理服务器)的参与。

1_8_1 使用ribbon自带负载均衡算法:@LoadBalanced

在RestTemplate上使用@LoadBalanced,就能使得RestTemplate具有Ribbon的负载均衡的效果

-----------------------config/configBean

@Configuration
public class ConfigBean {//RestTemplate是一套接口,服务消费者都会通过RestTemplate来调用服务提供者的方法。@Bean@LoadBalanced//配置负载均衡,实现Ribbonpublic RestTemplate getRestTemplate(){return new RestTemplate();}
}

测试是否成功配置负载均衡 http://localhost/consumer/dept/list
  
【注意】我们不需要额外添加ribbon依赖,是因为spring-cloud-starter-eureka依赖带有spring-cloud-starter-netflix-eureka-client依赖,spring-cloud-starter-netflix-eureka-client自带了spring-cloud-starter-netflix-ribbon依赖。
  

1_8_2 使用ribbon实现自定义负载均衡算法

(1)自己编写一个Rule类继承AbstractLoadBalancerRule,并添加choose(ILoadBalancer lb, Object key) 方法。

  

---------------------com.myrule.junRandomRule.java(注意:没有和启动类在同一级目录)

package com.junjun.myrule;import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;import java.util.List;
import java.util.concurrent.ThreadLocalRandom;@Component
public class junRandomRule extends AbstractLoadBalancerRule {private int total=0;private int currentIndex=0;public junRandomRule() {}//@SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})public Server choose(ILoadBalancer lb, Object key) {if (lb == null) {return null;} else {Server server = null;while(server == null) {if (Thread.interrupted()) {return null;}List<Server> upList = lb.getReachableServers();//获取活着的服务List<Server> allList = lb.getAllServers();//获取所有的服务int serverCount = allList.size();//serverCount是所有服务的数量if (serverCount == 0) {return null;}
//              int index = this.chooseRandomInt(serverCount);//随机获取一个序号
//              server = (Server)upList.get(index);//从活着的服务中获取对应序号的服务
////*******************这里是我改写的算法**************************************if(total<5){server = upList.get(currentIndex);total++;}else{total=0;currentIndex++;if(currentIndex>=upList.size()){currentIndex=0;}server=upList.get(currentIndex);}//*******************我的部分结束**************************************if (server == null) {Thread.yield();} else {if (server.isAlive()) {return server;}server = null;Thread.yield();}}return server;}}protected int chooseRandomInt(int serverCount) {return ThreadLocalRandom.current().nextInt(serverCount);}public Server choose(Object key) {return this.choose(this.getLoadBalancer(), key);}public void initWithNiwsConfig(IClientConfig clientConfig) {}
}

(2)将该策略添加到项目中(在启动类上使用@RibbonClient)

如果把rule类放在和DeptConsumer_80同一目录下,那么该负载均衡算法是能够被本服务器扫描到的,因此@RibbonClient都不用写了(当然,@Component注册bean还是要写的)。

@SpringBootApplication
@EnableEurekaClient
//1、当客户端存在自定义Ribbon和原有Ribbon时,自定义会覆盖原有Ribbon
// 2、MyRule不应该在@ComponentScan中(所以不应该在application同级目录下),否则会被所有RibbonClients共享,所有RibbonClients都会采取这个策略
@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = junRandomRule.class)
public class DeptConsumer_80 {public static void main(String[] args) {SpringApplication.run(DeptConsumer_80.class);}
}

(3)测试

本负载均衡的效果是每个服务器都能5次,5次后就换一个服务器

1_8_3 使用nginx实现负载均衡思路图

1_8_4 使用openFeign实现负载均衡

1_9 使用feign替代RestTemplate(其内部集成了RestTemplate)

1.feign不是做负载均衡的,feign只是集成了ribbon(负载均衡还是feign内置的ribbon做)。feign的作用的替代RestTemplate,这会导致性能降低,但是可以使代码可读性很强。
2.狂神的视频是把service层发在springcloud-api中,我觉得不是很懂,就自己放在了消费者里面了,并精简了config文件夹,不知道我这样做有没有什么问题,后期了解了原理再探讨这个问题吧。
3.若把service放在springcloud-api中,需要我们把依赖放在springcloud-api中,而springcloud-consumer-dept-feign就不需要添加这个依赖了。

1_9_1 复制然后创建一个新的服务消费者model用来测试feign

复制springcloud-consumer-dept-80,创建springcloud-consumer-dept-feign

  

1_9_2 在原来依赖的基础上添加feign依赖

    <dependencies><!--        添加feign依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</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>org.example</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>

1_9_3 修改启动类名为FeignDeptConsumer_80,并添加注解@EnableFeignClients扫描FeignClient

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.junjun.springcloud"})//这里是扫描springcloud_api模块中的DeptClientService作为Feign的接口类
public class FeignDeptConsumer_80 {public static void main(String[] args) {SpringApplication.run(FeignDeptConsumer_80.class);}
}

1_9_4在Fiegn所在的服务消费者中添加service层(使用@FeignClient)

----------------service/DeptClientService

@Component
@FeignClient(value= "SPRINGCLOUD-PROVIDER-DEPT")//这个接口将会被动态代理实现,参考内容是服务提供者("SPRINGCLOUD-PROVIDER-DEPT")中的mapper.xml???
public interface DeptClientService {@GetMapping("/dept/add")public boolean addDept(Dept dept);@GetMapping("/dept/get/{id}")public Dept queryById(@PathVariable("id") Long id);@GetMapping("/dept/list")public List<Dept> queryAll();
}

1_9_5在controller不使用RestTemplate,而是使用DeptClientService来调用服务提供者。

@RestController
public class DeptConsumerController {@Qualifier("com.junjun.springcloud.service.DeptClientService")//有多个DeptClientService的bean,所以要用@Qualifier@Autowiredprivate DeptClientService service;@RequestMapping("/consumer/dept/add")public boolean add(@RequestBody Dept dept){return this.service.addDept(dept);}@RequestMapping("/consumer/dept/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();}
}

1_9_6测试

进入http://localhost/consumer/dept/list,多次刷新查看负载均衡的策略(默认是轮询)。
  

1_10分布式系统的延迟和容错处理方式

1.服务熔断:某个服务超时或者异常,会引起服务熔断(在服务端实现)
2.服务降级:从服务端整体考虑,关掉某些服务(在客户端实现)
3.服务雪崩:

Hytrix实现服务熔断(已过时)

1_10_1复制springcloud-provider-dept-8001生成一个新的服务提供者:springcloud-provider-dept-hystrix-8001

1_10_2添加Hystrix依赖到原有依赖中

    <dependencies><!--    添加hystrix依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-hystrix</artifactId><version>1.4.6.RELEASE</version></dependency><!--     actuator完善监控信息--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--   Eureka依赖添加--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId><version>1.4.6.RELEASE</version></dependency><!--   我们需要拿到api模块中的实体类,所以需要配置api module--><dependency><groupId>org.example</groupId><artifactId>springcloud-api</artifactId><version>1.0-SNAPSHOT</version></dependency><!--        2.junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId></dependency><!--        logback是log4j的日志组件--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId></dependency><!--    Mybatis依赖:通过Mybatis管理mysql数据库--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><!--        springboot的web项目的必备依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--   springboot-test:@SpringBootTest注解的所在的依赖   --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test</artifactId></dependency><!--        jetty--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jetty</artifactId></dependency><!--        热部署工具:devtools--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency></dependencies>

1_10_3在application.yml中修改instance-id,方便区分

server:port: 8001
#  mybatis的配置
mybatis:type-aliases-package: com.junjun.springcloud.pojomapper-locations: classpath:mybatis/mapper/*.xmlconfig-location: classpath:mybatis/mybatis-config.xml#spring的配置
spring:application:name: springcloud-provider-dept #本应用在Eureka中的名称(会变成大写)datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: org.gjt.mm.mysql.Driverurl: jdbc:mysql://localhost:3306/db01?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezeno=GMT%2B8username: rootpassword: 3333#Eureka的配置
eureka:client:service-url:defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/ #本机的7001,7002,7003端口可以访问Eurekainstance:instance-id: springcloud-provider-hystrix-dept8001 #修改eureka中的默认描述信息
#info配置:点击UP就会得到信息:{"app":{"name":"junjun-springcloud"},"company":{"name":"blog.junjun.com"}}
info:app.name: junjun-springcloudcompany.name: blog.junjun.com

1_10_4修改启动类名为:DeptProviderHystrix_8001.java,并添加@EnableCircuitBreaker

@EnableCircuitBreaker是将@HystrixCommand注册到bean中去

@SpringBootApplication
@EnableEurekaClient//在程序启动之后会自动注册到Eureka服务端中!通过http://localhost:7001/能进入Eureka界面能看见注册的Eureka
@EnableDiscoveryClient
@EnableCircuitBreaker//添加对熔断注解的支持(即将@HystrixCommand注册到bean中去)。
public class DeptProviderHystrix_8001 {public static void main(String[] args) {SpringApplication.run(DeptProviderHystrix_8001.class,args);}
}

1_10_5修改controller层(添加处理错误的功能)

@RestController
public class DeptController {@Autowiredprivate DeptService deptService;@GetMapping("/dept/get/{id}")@HystrixCommand(fallbackMethod = "hystrixGet")//失败就会调用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){System.out.println("*****************失败了*************************");return new Dept().setDeptno(id).setDname("id=>"+id+"没有对应的信息-@Hystrix").setDb_source("no this database in MySQL");}
}

1_10_6测试http://localhost/consumer/dept/get/6

1.注意我们只写了add函数,没写list函数,所以不要用list来测试
2.可能会出现服务器崩坏的现象,这时候一个一个重启服务器就行 。

  

feign实现服务降级

1_10_7在feign实现负载均衡的基础上添加一个类

package com.junjun.springcloud.service;import com.junjun.springcloud.pojo.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;import java.util.List;
//降级
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory {@Overridepublic DeptClientService create(Throwable throwable) {return new DeptClientService() {@Overridepublic boolean addDept(Dept dept) {return false;}@Overridepublic Dept queryById(Long id) {return new Dept().setDeptno(id).setDname("id=>"+id+"没有对应的信息,客户端提供了降级的信息,这个服务现在已经被关闭了").setDb_source("没有数据");}@Overridepublic List<Dept> queryAll() {return null;}};}}

1_10_8给servicec层的接口添加服务降级画面显示(fallbackFactory)

提供服务降级提示的服务器是哪个呢??

//通过Feign来指定熔断降级的操作
@Component
@FeignClient(value= "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)//这个接口将会被动态代理实现,参考内容是服务提供者("SPRINGCLOUD-PROVIDER-DEPT")中的mapper.xml???
public interface DeptClientService {@GetMapping("/dept/add")public boolean addDept(Dept dept);@GetMapping("/dept/get/{id}")public Dept queryById(@PathVariable("id") Long id);@GetMapping("/dept/list")public List<Dept> queryAll();
}

1_10_9测试

  

熔断监控DashBoard监控请求(流量)

1_10_10新建一个模块:springcloud-consumer-hystrix-dashboard,并往dashboard模块中添加依赖

    <dependencies>
<!--        导入Hystrix和他的监控页面这两个依赖1.服务端必须要有actuator才能监控得到
--><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><!--        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>org.example</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>

1_10_11设置dashboard模块的端口

server:port: 9001

1_10_12配置启动类

@SpringBootApplication
@EnableHystrixDashboard//开启DashBoard
public class DeptConsumerDashboard_9001 {public static void main(String[] args) {SpringApplication.run(DeptConsumerDashboard_9001.class);}
}

1_10_13在springcloud-provider-dept-hystrix-8001的启动类上添加servlet

使用springcloud-provider-dept-8001就不行,无论是添加依赖还是添加@EnableCircuitBreaker、servlet都不行。

@SpringBootApplication
@EnableEurekaClient//在程序启动之后会自动注册到Eureka服务端中!通过http://localhost:7001/能进入Eureka界面能看见注册的Eureka
@EnableDiscoveryClient
@EnableCircuitBreaker//添加对熔断注解的支持(即将@HystrixCommand注册到bean中去)。
public class DeptProviderHystrix_8001 {public static void main(String[] args) {SpringApplication.run(DeptProviderHystrix_8001.class,args);}@Bean//增加一个servletpublic ServletRegistrationBean hystrixMetricsStreamServlet(){ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());registrationBean.addUrlMappings("/actuator/hystrix.stream");return registrationBean;}
}

1_10_14测试

  

进入http://localhost:9001/hystrix。如果能实现上面界面,就可以进入dashboard界面了。

  
  

1_11路由网关Zuul(已过时)

1_11_1添加依赖

    <dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zuul</artifactId><version>1.4.6.RELEASE</version></dependency><!--        导入Hystrix和他的监控页面这两个依赖1.服务端必须要有actuator才能监控得到--><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><!--        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>org.example</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>

1_11_2 配置application.yml

server:port: 9527spring:application:name: springcloud-zuul#Eureka的配置
#Eureka的配置
eureka:client:service-url:defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/ #本机的7001,7002,7003端口可以访问Eurekainstance:instance-id: zuul9527.com #修改eureka中的默认描述信息prefer-ip-address: trueinfo:app.name: junjun-springcloudcompany.name: blog.junjunstudy.com

1_11_3修改域名映射关系:C:\Windows\System32\drivers\etc\hosts

1_11_4配置启动类ZuulApplication_9527

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

1_11_5测试

访问http://www.junjunstudy.com:9527/springcloud-provider-dept/dept/get/2

1_11_5实现域名伪装:修改9527一下application.yml的zuul配置,并测试

server:port: 9527spring:application:name: springcloud-zuul#Eureka的配置
#Eureka的配置
eureka:client:service-url:defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/ #本机的7001,7002,7003端口可以访问Eurekainstance:instance-id: zuul9527.com #修改eureka中的默认描述信息prefer-ip-address: trueinfo:app.name: junjun-springcloudcompany.name: blog.junjunstudy.comzuul:#实现域名伪装:用mydept代替springcloud-provider-deptroutes:  mydept.serviceId: springcloud-provider-deptmydept.path: /mydept/**  #使得原来的服务器名称不可访问服务器ignored-services: springcloud-provider-dept#ignored-services: "*"  #忽略所有,只有通过mydept才能访问得到。

用代理名称代替服务提供者的名称

完整版如下:

server:port: 9527spring:application:name: springcloud-zuul#Eureka的配置
#Eureka的配置
eureka:client:service-url:defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/ #本机的7001,7002,7003端口可以访问Eurekainstance:instance-id: zuul9527.com #修改eureka中的默认描述信息prefer-ip-address: trueinfo:app.name: junjun-springcloudcompany.name: blog.junjunstudy.comzuul:#实现域名伪装:用mydept代替springcloud-provider-deptroutes:mydept.serviceId: springcloud-provider-deptmydept.path: /mydept/**#使得原来的服务器名称不可访问服务器ignored-services: "*"  #忽略所有,只有通过mydept才能访问得到。prefix: /junjun  #设置统一的访问前缀`

访问http://www.junjunstudy.com:9527/junjun/mydept/dept/get/2

1_12config

Git环境配置

1_12_1配置Git项目环境

【码云环境配置】
包括:1.官网下载Git工具 2.更改Git姓名和邮箱 3.在本机上配置公钥

1_12_2在git码云上创建一个项目,并获取到本地。然后新建一个application.yml文档,并添加上以下内容。

spring:profiles: active: dev---
spring:profiles: devapplication:name: springcloud-config-dev---
spring:profiles: testapplication:name: springcloud-config-test

1_12_3上传到git远程服务器。

配置config服务端并连接git的远程仓库

1_12_4导入依赖

<dependencies>
<!--    springcloud-config--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-config-server</artifactId><version>2.1.1.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>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

1_12_5配置application.yml

server:port: 3344
spring:application:name: springcloud-config-server#连接远程仓库cloud:config:server:git:uri: https://gitee.com/junjunlllll/spring-config.git #这是https的地址,不是SSH

1_12_6 配置启动类

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

1_12_7测试是否联通

  
  

通过git进行远程资源 配置 本地项目。

1_12_8在git项目目录下添加一个yml文档。

  

在git上部署多套环境,而我们只要修改spring.profiles就能配置git上对应配置(如名字,端口号)。

spring:profiles:active: dev
---
server:port: 8201spring:profiles: devapplication:name: springcoud-provider-dept
eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/
---
server:port: 8202spring:profiles: testapplication:name: springcoud-provider-dept
eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka/

1_12_9 push到远程服务器

  

1_12_10 创建springcloud-config-client-3355模块,并配置依赖

    <dependencies><!--    springcloud-config--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId><version>2.1.1.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>

1_12_11 配置配置文件

bootstrap系统级别的配置,而application是用户级别的配置
--------------bootstrap.yml

#bootstrap系统级别的配置,而application是用户级别的配置
spring:cloud:config:profile: test #激活了dev,所以这个client的端口号是8201,如果激活test该模块的端口号就是8202name: config-client #从git上读取的资源名称(我们在git上有一个config-client.yml),不需要后缀label: masteruri: http://localhost:3344

------------application.yml

spring:application:name: springcloud-config-client-3355

1_12_12启动类和controller层

-----------ConfigClient_3355启动类

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

----------------controller层

@RestController
public class ConfigClientControler {@Value("${spring.application.name}")private String application;@Value("${eureka.client.service-url.defaultZone}")private String eurekaServer;@Value("${server.port}")private String port;@RequestMapping("/config")public String getConfig(){return "application:"+application+"eurekaServer:"+eurekaServer+"port:"+port;}
}

1_12_12访问http://localhost:8201/config测试

  

远程配置资源项目(这里以7001服务器为例)

前提是配置服务器3344成功,我们将通过3344获取资源文件并配置资源

1_12_13 配置并上传远程资源

  
  
---------代码如下

spring:profiles:active: dev
---
server:port: 7001
spring:profiles: devapplication:name: springcloud-config-eureka
eureka:instance:hostname: eureka7001.com   #Eureka服务端的实例名称client:register-with-eureka: false  # 表示是否想eureka注册中心注册自己fetch-registry: false  #false表示自己为注册中心(开集群需要注册自己)service-url:defaultZone:  http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #eureka7002.com等这三个会在hosts文档中添加这种映射关系
---
server:port: 7001spring:profiles: testapplication:name: springcloud-config-eurekaeureka:instance:hostname: eureka7001.com   #Eureka服务端的实例名称client:register-with-eureka: false  # 表示是否想eureka注册中心注册自己fetch-registry: false  #false表示自己为注册中心(开集群需要注册自己)service-url:defaultZone:  http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #eureka7002.com等这三个会在hosts文档中添加这种映射关系

1_12_14 创建一个7001模块,并导入依赖

   <dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId><version>2.1.1.RELEASE</version></dependency><!--    导入Eureka包--><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>

1_12_15创建bootstrap.yml和application.yml(核心)

--------------bootstrapyml

 spring:cloud:config:name: config-eureka #这是远程资源的名称label: masterprofile: devuri: http://localhost:3344
spring:application:name: springcloud-config-eureka-7001

1_12_16 配置启动类

@SpringBootApplication
@EnableEurekaServer//EnableEurekaServer是开启服务器的启动类,他能够接受别人注册进来~
public class EurekaServer_7001 {public static void main(String[] args) {SpringApplication.run(EurekaServer_7001.class);}
}

1_12_17测试

  

-----------------------springcloud新技术-----------------------

在上述中很多技术都已经过时不再更新了,所以我们要用到新的技术

一、Nacos:服务中心+配置中心

1、Nacos作为服务中心

Nacos(Naming configuration service)是一个服务发现、配置管理、服务管理平台。所以Nacos=Eureka+Config+Bus。

1.1 下载、启动nacos

**********************1.下载
下载地址


**********************2.启动nacos,并登入
1、在bin中双击startup.cmd就行。
2、然后访问http://localhost:8848/nacos/index.html
3、通过账号密码:nacos/nacos登录。
4、右上角切换中文

1.2 nacos替代eureka作为服务注册中心

在服务的yml中spring☁️nacos:discovery:server-addr:localhost:8848。来在nacos中注册。

(1) 在nacos客户端(如服务提供者、服务消费者)上添加依赖

    <dependencies>
<!--        springboot版本为2.3.9.RELEASE--><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><scope>test</scope></dependency><!--        nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>2.2.0.RELEASE</version></dependency></dependencies>

【注意】
springboot版本低于nacos版本会出现异常;

(2) 对eureka客户端进行配置

server:port: 9001spring:application:name: nacos-test #本应用在nacos的名称cloud:nacos:discovery:server-addr: localhost:8848

(3)配置启动类

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

(4)在nacos中发现该客户端成功

这可比Eureka方便多了,不需要自己手动搭建Eureka服务端。

2.1.3 nacos替代Config作为服务配置中心

2.1.4 nacos集群和持久化配置

2、Nacos作为配置中心

GateWay网关

2.1 GateWay+Eureka

网关有两种常用的类型:zool和GateWay。使用一种简单有效的方法来对API进行路由、过滤、熔断、限流、重试。
Springcloud GateWay是基于WebFlux框架实现的,而WebFlux框架底层是使用了高性能的Reactor模式的框架Netty。

2.1.1 GateWay实现路由效果

(1) 添加依赖

    <dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--   Eureka依赖添加--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId><version>1.4.6.RELEASE</version></dependency>

【注意】
不能要spring-boot依赖不然会报错

(2)添加配置文件

------------------------------方法一:在application.yml中进行配置

server:port: 9527
#我们往往不想暴露我们的服务器ip和端口,因此用GateWay的9527端口来掩饰
spring:application:name: cloud-gatewaycloud:gateway:routes:- id: payment_routh                  #第一个路由,路由id要保证唯一uri: http://localhost:8001        #匹配后提供服务的路由地址predicates:                             #断言,与uri路径进行匹配- Path=/dept/**- id: pay                                   #第二个路由,路由id要保证唯一uri: http://localhost:8001predicates:- Path=/aaa/**eureka:instance:hostname: cloud-gateway-serviceclient:service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/ #本机的7001,7002,7003端口可以访问Eureka

------------------------------方法二:在config/Gatewaay中使用配置bean的方式进行路由设置

@Configuration
class GatewayConfig {@Beanpublic RouteLocator routes(RouteLocatorBuilder builder) {RouteLocatorBuilder.Builder routes = builder.routes();routes.route("path_route1",r->r.path("/guonei").uri("http://news.baidu.com/guonei")).build();//访问地址http://localhost:9527/guonei时会自动转发到地址:http://news.baidu.com/guoneireturn routes.build();}
}

(3)配置启动类

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

(4)测试:实现路由功能

http://localhost:9527/dept/list

发现即使是使用http://localhost:8001/dept/list也能成功访问。

2.1.2 Gateway配置动态路由,实现负载均衡

1、默认情况下,Gateway会根据注册中心的服务列表,以服务中心(eureka,nacos)上的服务名为路径创建动态路由进行转发,从而实现动态路由功能,实现服务器的负载均衡(默认轮询策略)。

(1)在2.1.1基础上更改配置文件

server:port: 9527
#我们往往不想暴露我们的服务器ip和端口,因此用GateWay的9527端口来掩饰
spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启Gateway从注册中心动态创建路由的功能,利用微服务名进行路由routes:- id: payment_routh                  #第一个路由,路由id要保证唯一
#          uri: http://localhost:8001        #匹配后提供服务的路由地址uri: lb://springcloud-provider-dept  #1、lb是指loaderBalance的意思 2、springcloud-provider-dept是服务提供者集群的spring:application:namepredicates:                             #断言,与uri路径进行匹配- Path=/dept/**- id: pay                                   #第二个路由,路由id要保证唯一
#          uri: http://localhost:8001uri: lb://springcloud-provider-dept  #1、lb是指loaderBalance的意思 2、springcloud-provider-dept是服务提供者集群的spring:application:namepredicates:- Path=/aaa/**eureka:instance:hostname: cloud-gateway-serviceclient:service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/ #本机的7001,7002,7003端口可以访问Eureka

(2) 测试负载均衡效果

2.1.2 Gateway如何自定义负载均衡策略呢

2.1.3 Gateway的Predicate

Spring Cloud Gateway有很多内置工厂Route Predicate Factory

server:port: 9527
spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启Gateway从注册中心动态创建路由的功能,利用微服务名进行路由routes:- id: payment_routh                  #第一个路由,路由id要保证唯一
#          uri: http://localhost:8001        #匹配后提供服务的路由地址uri: lb://springcloud-provider-dept  #1、lb是指loaderBalance的意思 2、springcloud-provider-dept是服务提供者集群的spring:application:namepredicates:                             #断言,满足以下条件才会成功通过gateway把请求发送给服务器。- Path=/dept/**         #地址匹配要正确- After=2020-10-12T16:51:37.485+08:00[Asia/Shanghai]  #时间满足在2020-10-12T16:51:37之后- Cookie=username,zzyy #Cookie里面有个键值对,第一个参数是key:username,第二个参数是value:zzyy- Header=X-Request-Id,\d+ #对请求头进行匹配,value:\d+是为整数的正则表达式- id: pay
#          uri: http://localhost:8001uri: lb://springcloud-provider-dept  predicates:- Path=/aaa/**eureka:instance:hostname: cloud-gateway-serviceclient:service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/ #本机的7001,7002,7003端口可以访问Eureka

测试效果

2.1.4 GateWay的filter

Gateway自带的filter

使用自定义filter(全局GlobalFilter)

************filter/MyLoGateWayFilter

@Component
@Slf4j//这是lombok中的依赖. import lombok.extern.slf4j.Slf4j;
public class MyLoGateWayFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("*************************com in MyLogGateWayFilter:"+new Date());String username = exchange.getRequest().getQueryParams().getFirst("username");if(null==username){log.info("***************不合法,用户名为null");exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);return exchange.getResponse().setComplete();}return chain.filter(exchange);}@Overridepublic int getOrder() {//日志顺序return 0;}
}

测试

2.2 Nacos+Eureka

2.2.1

【附加】springcloud原理和思想

CAP理论

C:Consistency一致性:读写(在同一个集群中的不同服务器上)内容保存一致。不存在在server1写完后,在server2读取的却是旧数据>A:Availability可用性:只要我对服务器,发送请求,服务器必须对我进行相应,保证服务器一直是可用的。
P:Partition tolerance,分区容错::分布式的服务器之间的数据不能同步。
为什么CAP只能达到 CP 或者 AP?
不懂!eureka是基于ap的。zookeeper是基于cp的。所有,eureka各个节点完全平等,当有些节点坏掉时,剩余节点还是可以提供注册和查询服务,因此eureka一定能得到数据,但是不一定是最新的;而zookeeper得到的数据一定是最新的,但是不一定能成功得到数据:当某些节点坏掉时,我们就不能访问了。

ribbon:客户端负载均衡的工具

ribbon是为客户端提供简单的负载均衡(LB,LoadBalancer)的算法。常见的负载均衡算法:随机 轮询 最少响应比。
常见的负载均衡软件:NginxLvsApache+Tomcat
负载均衡:为请求分配集群中的服务器
负载均衡的类别:1、集中式 (如Nginx反向代理服务器)2、进程式(将LB集成到消费方如上面的7001)

springcloud 学习项目相关推荐

  1. SpringCloud学习笔记(1)- Spring Cloud Alibaba

    文章目录 SpringCloud学习笔记(1)- Spring Cloud Alibaba 服务治理 Nacos 服务注册 Nacos 服务发现与调用 Ribbon 负载均衡 Sentinel 服务限 ...

  2. SpringCloud学习笔记(1)- Spring Cloud Netflix

    文章目录 SpringCloud学习笔记(1)- Spring Cloud Netflix 单体应用存在的问题 Spring Cloud Eureka Eureka Server代码实现 Eureka ...

  3. SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理

    前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...

  4. SpringCloud学习笔记(十四)Zuul网关

    专辑目录:SpringCloud学习日志 网关的概念: 我举个例子,我们到银行取钱,但是我们不能自己到金库里去拿钱,而是通过柜台服务员取钱.这时候柜台服务员就是网关,如果你没有存折和密码(相当于账号和 ...

  5. 10个Spring Boot 优秀学习项目

    10个Spring Boot 优秀学习项目 10个SpringBoot项目分享(好像多了一个项目) 一.mall (虽然培训机构已经把电商推广了烂大街了,但技术还是可以学习的) 二.Cloud-Pla ...

  6. SpringCloud学习笔记(十二)基于Hystrix解决雪崩效应

    专辑目录:SpringCloud学习日志 什么是雪崩效应? 当请求数量远超出服务器承受能力或者服务器无法再处理请求时,导致请求等待时间比较久,也就是平常说的卡.由于微服务是利用RPC相互请求的,所以可 ...

  7. 开源的13个Spring Boot 优秀学习项目

    开源的13个Spring Boot 优秀学习项目!超53K星,一网打尽! 原创: 徐刘根 Java后端技术 5月19日 Spring Boot 算是目前 Java 领域最火的技术栈了,也是Java开发 ...

  8. SpringCloud学习Day1

    这SpringCloud学习 1.基本的杂乱概念 CAP 2.SpringCloud概述 2.1 微服务中的相关概念 2.1.1 服务注册与发现 2.1.2 负载均衡 2.1.3 熔断 2.1.4 链 ...

  9. SpringCloud学习记录 | 第十篇:Hystrix DashBoard 实时图像监控界面(豪猪哥)

    一.Hystrix DashBoard Hystrix提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续记录所有的通过Hystrix发起的请求执行信息,并以统计报表和图 ...

最新文章

  1. eclipse下的spring环境配置
  2. mysql主从架构搭建_MySQL主从架构搭建
  3. 2.1.1 Speed Limit
  4. Android Studio使用Google Flutter完整教程
  5. 初识Ildasm.exe——IL反编译的实用工具(转自Youngman)
  6. python 合并word文件,在Python上的WordCloud中,我想合并两种语言
  7. c语言程序设计的几种循环,C语言程序设计教案 第六章 循环程序设计.doc
  8. 谷歌浏览器中打开IE
  9. windows server2008 r2 下启用 sqlserver 2008的远程连接
  10. 失意时,你是怎么救自己的?
  11. Builder 模式在 Guava 中的应用
  12. ModelAttribue注解的使用
  13. 实验室耗材管理系统,医院各科室如何进行耗材管理
  14. STM32智能锁指纹锁密码锁WIFI远程开锁微信小程序临时密码源码PCBA方案
  15. anywhere无法获取服务器响应,使用Chat Anywhere可能出现的问题与解决方法
  16. SpringBoot —— 实现邮件、短信的发送功能
  17. python判断性别_惊呆|根据三围数据判断出用户性别竟是python使用逻辑回归算法搞的鬼!...
  18. 30天自制操作系统第10天harib07d
  19. LeetCode 分类练习(四):查找2
  20. idea 在创建maven 时出现报错org.codehaus.plexus.component.repository.exception.ComponentLookupException:

热门文章

  1. MIL-STD-1553B
  2. 关于带新人和作新人。
  3. mysql中堆和栈_堆和栈 - 矮油~ - 博客园
  4. 公开讲座笔记 | 雷达学报 雷达系统微课 - 第三讲 相控阵雷达 与 “1+1=2“
  5. 老男孩39期决心书——刘浩海
  6. 数组是否包含某个元素
  7. python 自动点击网页上按钮_python selenium自动化(一)点击页面链接测试
  8. android播放视频控件,视频播放控件VideoView的基本使用
  9. ppt技巧一四步法调整PPT
  10. ICPC2017香港赛区游记