尚硅谷阳哥SpringCloud第二季学习笔记(一)

导航目录

  • 一、微服务架构概述
    • 1.什么是微服务架构
    • 2.SpringCloud简介
      • 2.1是什么
      • 2.2 SpringCloud技术栈
  • 二、微服务架构编码构建
    • 2.1 创建父工程cloud2020
    • 2.2 设置项目字符编码为UTF-8
    • 2.3 注解生效激活
    • 2.4 Java编译版本选择8
    • 2.5 导入父工程依赖
      • 2.5.1 dependencyManagement
    • 2.6 支付模块构建
      • 2.6.1 建module
      • 2.6.2 引pom
      • 2.6.3 写yml
      • 2.6.4 主启动
      • 2.6.5 创建表
      • 2.6.6 主实体Payment
      • 2.6.7 JSON封装体
      • 2.6.8 Dao
      • 2.6.9 Mapper文件
      • 2.6.10 Service
      • 2.6.11 ServiceImpl
      • 2.6.12 Controller
    • 2.7 热部署
      • 2.7.1 子工程添加依赖
      • 2.7.2 添加插件到父工程的pom.xml文件中
      • 2.7.3 开启自动编译
      • 2.7.4 开启更新值
      • 2.7.5 重启IDEA
    • 2.8 RestTemplate
      • 2.8.1 是什么
      • 2.8.2 客户端使用RestTemplate调用服务端的服务
    • 2.9 工程重构
      • 2.9.1 提取公共模块
      • 2.9.2 把这个公共模块做成依赖被其他模块导入
      • 2.9.3 在要用到的模块中引入
  • 三、Eureka服务注册和发现
    • 3.1 Eureka基础知识
      • 3.1.1 什么是服务治理
      • 3.1.2 什么是服务注册与发现
      • 3.1.3 Eureka两组件
    • 3.2 单机Eureka构建步骤
      • 3.2.1 IDEA生成eurekaServer端服务注册中心
      • 3.2.2 EurekaClient端cloud-provider-payment8001将注册进EurekaServer成为服务提供者provider,对外提供服务
      • 3.2.3 EurekaClient端cloud-consumer-order80将注册进EurekaServer成为服务消费者consumer,类似消费者
    • 3.3 集群Eureka构建步骤
      • 3.3.1 Eureka集群原理
      • 3.3.2 EurekaServer集群环境构建步骤
      • 3.3.3 服务发现
    • 3.4 actuator微服务信息完善
      • 3.4.1 主机名称:服务名称修改
      • 3.4.2 访问信息有IP信息提示
    • 3.5 服务发现Discovery
      • 3.5.1 功能
      • 3.5.2 实现
    • 3.6 Eureka自我保护
      • 3.6.1 概述
      • 3.6.2 导致的原因
      • 3.6.3 什么是自我保护模式?
      • 3.6.4 怎么关闭自我保护机制
    • 3.7 Eureka停更说明
  • 四、Zookeeper服务注册与发现
    • 4.1 Zookeeper的安装
    • 4.2 使用Zookeeper进行服务注册的步骤
    • 4.3 一些细节
  • 五、Consul服务注册与发现
    • 5.1 简介
      • 5.1.1 是什么
      • 5.1.2 能干嘛
      • 5.1.3 去哪下
      • 5.1.4 怎么玩
    • 5.2 安装并运行
    • 5.3 服务提供者
    • 5.4 服务消费者
    • 5.5 三个注册中心的区别

一、微服务架构概述

1.什么是微服务架构

微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务于服务之间采用轻量级的通信机制互相协作(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第1张图片

2.SpringCloud简介

2.1是什么

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

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第2张图片

2.2 SpringCloud技术栈

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第3张图片

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第4张图片

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第5张图片

二、微服务架构编码构建

2.1 创建父工程cloud2020

2.2 设置项目字符编码为UTF-8

2.3 注解生效激活

File–>Build–>Compiler–>Annotation Processors

2.4 Java编译版本选择8

File–>Build–>Compiler–>Java Compiler

2.5 导入父工程依赖



<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.jg.springcloudgroupId>
    <artifactId>cloud2020artifactId>
    <version>1.0-SNAPSHOTversion>
    
    <packaging>pompackaging>

    <modules>
        <module>cloud-provider-payment8001module>
    modules>

    
    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <maven.compiler.source>1.8maven.compiler.source>
        <maven.compiler.target>1.8maven.compiler.target>
        <junit.version>4.12junit.version>
        <lombok.version>1.16.18lombok.version>
        <log4j.version>1.2.17log4j.version>
        <mysql.version>5.1.47mysql.version>
        <druid.version>1.1.16druid.version>
        <mybatis.spring.boot.version>1.3.0mybatis.spring.boot.version>
    properties>

    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>2.2.2.RELEASEversion>
                <type>pomtype>
                <scope>importscope>
            dependency>

            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>Hoxton.SR1version>
                <type>pomtype>
                <scope>importscope>
            dependency>


            
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                <version>2.1.0.RELEASEversion>
                <type>pomtype>
                <scope>importscope>
            dependency>

            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>${mysql.version}version>
                <scope>runtimescope>
            dependency>
            
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>druidartifactId>
                <version>${druid.version}version>
            dependency>

            
            <dependency>
                <groupId>org.mybatis.spring.bootgroupId>
                <artifactId>mybatis-spring-boot-starterartifactId>
                <version>${mybatis.spring.boot.version}version>
            dependency>
            
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>${junit.version}version>
            dependency>
            
            <dependency>
                <groupId>log4jgroupId>
                <artifactId>log4jartifactId>
                <version>${log4j.version}version>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <configuration>
                    <fork>truefork>
                    <addResources>trueaddResources>
                configuration>
                <version>2.2.2.RELEASEversion>
            plugin>
        plugins>
    build>

project>

2.5.1 dependencyManagement

Maven使用dependencyManagement元素来提供了一种管理依赖版本号的方式

通常会在一个组织或者项目的最顶层的父POM中看到dependencyManagement元素。

使用pom.xml中的dependencyManagement元素能让所有在子项目中引用一个依赖而不用显式的列出版本号。

Maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用这个dependencyManagement元素中指定的版本号。

这样做的好处就是:如果有多个子项目都引用同一样依赖,则可以避免在每个使用的子项目中都声明一个版本号,这样当想升级或切换到另一个版本时,只需要在顶层容器里更新,而不需要一个一个子项目的修改;另外如果某个子项目需要另外的一个版本,只需要声明version即可。

2.6 支付模块构建

2.6.1 建module

2.6.2 引pom

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-actuatorartifactId>
    dependency>
    <dependency>
        <groupId>org.mybatis.spring.bootgroupId>
        <artifactId>mybatis-spring-boot-starterartifactId>
    dependency>
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>druid-spring-boot-starterartifactId>
        <version>1.1.10version>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-jdbcartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
        <scope>runtimescope>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
dependencies>

2.6.3 写yml

# 端口号信息
server:
  port: 8001

spring:
  application:
    name: cloud-payment-service

  datasource:
    type: com.alibaba.druid.pool.DruidDataSource            # 当前数据源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver              # mysql驱动包
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456

mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities    # 所有Entity别名类所在包

2.6.4 主启动

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

2.6.5 创建表

CREATE TABLE `payment`(
	`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
    `serial` varchar(200) DEFAULT '',
    PRIMARY KEY(`id`)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

2.6.6 主实体Payment

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment {
    private Long id;
    private String serial;
}

2.6.7 JSON封装体

@Data
@AllArgsConstructor
@NoArgsConstructorpublic class CommonResult<T> {    
	private Integer code;    
	private String message;    
	private T data;    
	public CommonResult(Integer code,String message){        
		this(code,message,null);    
	}
}

2.6.8 Dao

@Mapper
public interface PaymentDao {    
	int create(Payment payment);    
	Payment getPaymentByID(@Param("id") Long id);
}

2.6.9 Mapper文件



<mapper namespace="com.jg.springcloud.dao.PaymentDao">

    <resultMap id="BaseResultMap" type="com.jg.springcloud.entities.Payment">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <id column="serial" property="serial" jdbcType="VARCHAR"/>
    resultMap>
    <insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
        insert into payment(serial) values(#{serial});
    insert>

    <select id="getPaymentByID" parameterType="Long" resultMap="BaseResultMap">
        select * from payment where id=#{id};
    select>
mapper>

2.6.10 Service

public interface PaymentService {    
	int create(Payment payment);    
	Payment getPaymentByID(Long id);
}

2.6.11 ServiceImpl

@Service
public class PaymentServiceImpl implements PaymentService {    
    @Autowired    
    private PaymentDao paymentDao;    
    @Override    
    public int create(Payment payment) {        
        return paymentDao.create(payment);    
    }    
    @Override    
    public Payment getPaymentByID(Long id) {        
        return paymentDao.getPaymentByID(id);    
    }
}

2.6.12 Controller

@RestController
@Slf4j
public class PaymentController {    
    @Autowired    
    private PaymentService paymentService;    
    //返回给前端的结果集    
    @PostMapping(value = "/payment/create")    
    public CommonResult create(Payment payment) {        
        Integer result = paymentService.create(payment);        
        log.info("******插入结果:" + result);        
        if (result > 0) {           
            return new CommonResult(200, "插入数据库成功",result);        
        } else {            
            return new CommonResult(444, "插入数据库失败", null);       
        }   
    }    
    @GetMapping(value = "/payment/get/{id}")   
    public CommonResult getPaymentByID(@PathVariable("id") Long id) {       
        Payment payment = paymentService.getPaymentByID(id);        
        log.info("******插入结果:" + payment);        
        if (payment != null) {            
            return new CommonResult(200, "查询成功", payment);        
        } else {            
            return new CommonResult(444, "没有查询记录", null);        
        }    
    }
}

2.7 热部署

2.7.1 子工程添加依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-devtoolsartifactId>
    <scope>runtimescope>
    <optional>trueoptional>
dependency>

2.7.2 添加插件到父工程的pom.xml文件中

<plugin>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-maven-pluginartifactId>
    <configuration>
        <fork>truefork>
        <addResources>trueaddResources>
    configuration>
plugin>

2.7.3 开启自动编译

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第6张图片

2.7.4 开启更新值

使用快捷键Ctrl+Alt+Shift+/打开更新值设置

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第7张图片

2.7.5 重启IDEA

2.8 RestTemplate

2.8.1 是什么

RestTemplate提供了多种便携访问远程Http服务的方法,是一种简单便携的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集。

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第8张图片

2.8.2 客户端使用RestTemplate调用服务端的服务

配置

@Configuration
public class ApplicationContextConfig {

    @Bean //@Bean相当于applicationContext.xml文件中的bean标签
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

controller层

@RestController
@Slf4j
public class OrderController {
    //定义服务端URL
    public static final String PAYMENT_URL = "http://localhost:8001";

    //客户端通过RestTemplate调用服务端
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment) {
        return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
    }

    @GetMapping("consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
        return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }
}

前端返回给后端json类型的数据实体在接收的时候,参数前应该加@RequestBody注解

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第9张图片

2.9 工程重构

2.9.1 提取公共模块

把服务间公共部分提取出来抽象成一个公共的模块,这个模块不对外暴露接口

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第10张图片

在cloud-provider-payment8001和cloud-consumer-order80服务里面均用到了CommonResult和Payment,所以把它们提取出来,放在一个公共模块中,这个模块不对外暴露端口号。

2.9.2 把这个公共模块做成依赖被其他模块导入

maven-clean AND maven-install

2.9.3 在要用到的模块中引入

<dependency>
    <groupId>com.jg.springcloudgroupId>
    <artifactId>cloud-api-commonsartifactId>
    <version>${project.version}version>
dependency>

三、Eureka服务注册和发现

3.1 Eureka基础知识

3.1.1 什么是服务治理

Spring Cloud封装了Netflix公司开发的Eureka模块来实现服务治理

在传统的rpc远程调用框架中,管理每个服务于服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务与服务之间的依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。

3.1.2 什么是服务注册与发现

Eureka采用了CS的设计架构,Eureka Server作为服务注册功能的服务器,它是服务注册中心。而系统中的其它微服务,使用Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。

在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息,比如服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者|服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务于服务之间的一个依赖关系(服务治理概念)。在任何RPC远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))。

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第11张图片

3.1.3 Eureka两组件

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第12张图片

3.2 单机Eureka构建步骤

3.2.1 IDEA生成eurekaServer端服务注册中心

经典五步

  1. 建module

  2. 改pom

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
            <version>2.2.2.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>com.jg.springcloudgroupId>
            <artifactId>cloud-api-commonsartifactId>
            <version>${project.version}version>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        
        
        
        
        
        
        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
        dependency>
    dependencies>
    
  3. 写yml

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

    @SpringBootApplication
    //表示这个服务是Eureka的注册中心
    @EnableEurekaServer
    public class EurekaMain7001{
        public static void main(String[] args) {
            SpringApplication.run(EurekaMain7001.class,args);
        }
    }
    
  5. 业务类

Eureka注册中心Web页面

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第13张图片

3.2.2 EurekaClient端cloud-provider-payment8001将注册进EurekaServer成为服务提供者provider,对外提供服务

导入依赖


<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>

application.xml修改配置

#Eureka配置
eureka:
  client:
#    表示是否将自己注册进EurekaServer,默认为true
    register-with-eureka: true
#    是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
#    EurekaServer的地址
    service-url:
      defaultZone: http://localhost:7001/eureka

修改主启动类

@EnabkeEurekaClient //在主启动类上添加注解

如此配置,启动服务,该服务就可以注册到EurekaServer中

3.2.3 EurekaClient端cloud-consumer-order80将注册进EurekaServer成为服务消费者consumer,类似消费者

跟上面步骤相同

3.3 集群Eureka构建步骤

3.3.1 Eureka集群原理

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第14张图片

微服务RPC远程服务调用最核心的是什么

高可用,试想你的注册中心只有一个only one,它出故障了那就全都完了,会导致整个微服务环境不可用,所以解决办法是需要搭建Eureka注册中心集群,实现负载均衡和故障容错。

集群注册的原理是互相注册,相互守望

3.3.2 EurekaServer集群环境构建步骤

  1. 参考cloud-eureka-server7001,新建一个cloud-eureka-server7002

  2. 修改系统的映射文件–>hosts

    #SpringCloud
    127.0.0.1 eureka7001.com
    127.0.0.1 eureka7002.com
    
  3. 集群环境下,EurekaServer的配置

    server:
      port: 7001
    eureka:
      instance:
        hostname: eureka7001.com #eureka服务端的实例名称
      client:
        #    false表示不向注册中心注册自己
        register-with-eureka: false
        #    false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
    #      设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
          defaultZone: http://eureka7002.com:7002/eureka/
    
  4. 把服务注册进EurekaServer

    修改配置文件

       service-url:
          #defaultZone: http://localhost:7001/eureka
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
    
  5. 支付服务的集群环境搭建

    直接复制cloud-provider-payment8001即可,只有一些小的细节需要完善。

3.3.3 服务发现

微服务提供方如果有多节点集群环境,需要配置才能被服务调用方正常发现并调用

具体实现

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第15张图片

在配置类对应方法上添加@LoadBalanced注解,用于实现RestTemplate的负载均衡能力

服务调用方在的请求URL不是像以前那样写死,而是直接写服务提供方的应用名(服务提供方已经做了集群环境)

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第16张图片

后续可以使用Ribbon整合Eureka实现负载均衡,可以直接调用服务而不用在关心地址和端口号

3.4 actuator微服务信息完善

3.4.1 主机名称:服务名称修改

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第17张图片

解决方案:修改cloud-provider-payment8001的application.yml的中关于Eureka的配置

添加如下内容

instance:
    instance-id: payment8002

修改之后的效果**

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第18张图片

3.4.2 访问信息有IP信息提示

  instance:
    instance-id: payment8002
    #此配置是为了让访问路径可以显示IP地址
    prefer-ip-address: true

3.5 服务发现Discovery

3.5.1 功能

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

3.5.2 实现

修改服务提供方的Controller和主启动类

Controller上的修改

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第19张图片

主启动类上的修改

主启动类上添加@EnableDiscoveryClient注解

效果

后台发现的服务

3.6 Eureka自我保护

3.6.1 概述

保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不在删除服务注册表中的数据,也就是不会注销任何微服务。

如果在Eureka Server的首页看到以下这段提示,则说明Eureka进入了保护模式

3.6.2 导致的原因

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

为了防止EurekaClient可以正常运行,但是与EurekaServer网络不通情况下,EurekaServer不会立刻将EurekaClient服务剔除。

3.6.3 什么是自我保护模式?

默认情况西,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与EurekaServer之间无法正常通信,以上行为可能变得非常危险了-因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题----当EurekaServer节点在短时间内丢失过多客户端是(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。

3.6.4 怎么关闭自我保护机制

在EurekaServer服务端的application.yml中配置

server:
	#关闭自我保护机制,保证不可用服务被及时剔除
	enable-self-preservation: false	
	eviction-interval-timer-in-ms: 2000

在服务端设置心跳检测和续约时间application.yml

#心跳检测与续约时间
#开发时设置小些,保证服务关闭后注册中心及时剔除服务
instance:
	#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
	lease-renewal-interval-in-seconds: 1
	#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
	lease-expiration-duration-in-seconds: 2

3.7 Eureka停更说明

SpringCloud整合Zookeeper代替Eureka

四、Zookeeper服务注册与发现

4.1 Zookeeper的安装

  1. 解压Zookeeper的安装包到指定目录
  2. 创建Zookeeper的存放数据的文件夹(一般在解压之后的目录下)
  3. 修改Zookeeper的配置文件,加上刚才创建的文件夹的路径
  4. 安装完毕,启动

4.2 使用Zookeeper进行服务注册的步骤

经典五步

  1. 建module

  2. 引pom

    <dependencies>
        <groupId>com.jg.springcloudgroupId>
        <artifactId>cloud-api-commonsartifactId>
        <version>${project.version}version>
        dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-zookeeper-discoveryartifactId>
        
        <exclusions>
            <exclusion>
                <groupId>org.apache.zookeepergroupId>
                <artifactId>zookeeperartifactId>
            exclusion>
        exclusions>
    dependency>
    
    <dependency>
        <groupId>org.apache.zookeepergroupId>
        <artifactId>zookeeperartifactId>
        <version>3.4.10version>
    dependency>
    
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
        <scope>runtimescope>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
    dependencies>
    
  3. 写yml

    #8004表示注册到Zookeeper服务器的支付服务提供者端口号
    server:
      port: 8004
    
    #服务别名----注册到Zookeeper到注册中心名称
    spring:
      application:
        name: cloud-provider-payment
      cloud:
        zookeeper:
          #Zookeeper的地址
          connect-string: 192.168.170.132:2181
    
  4. 主启动

    @SpringBootApplication
    //该注解用于使用Consul或者Zookeeper作为注册中心是注册服务
    @EnableDiscoveryClient
    public class PaymentMain8004 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8004.class,args);
        }
    }
    
  5. 业务类

    @RestController
    @Slf4j
    public class PaymentController {
        @Value("${server.port}")
        private String serverPort;
    
        @RequestMapping(value = "/payment/zk")
        public String paymentZK(){
            return "springcloud with zookeeper:"+serverPort+"\t"+ UUID.randomUUID().toString();
        }
    }
    

如上配置,启动服务,进入zookeeper的服务中心页面bin/zkCli.sh,就可以看到刚才启动的服务已经注册成功。

zookeeper上服务信息

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第20张图片

4.3 一些细节

Zookeeper上面的服务节点是临时的

在这里插入图片描述
可以看到,当我们把注册进Zookeeper的服务关掉之后,过了一段时间,注册进Zookeeper中的服务就会被Zookeeper从节点中移除。而并不是说服务挂掉,Zookeeper还会保证这个服务一直存活在Zookeeper的节点上。

五、Consul服务注册与发现

5.1 简介

5.1.1 是什么

官网

Consul是一套开源的分布式服务发现和配置管理系统,由HashiCorp公司用Go语言开发的。

提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网络,总之Consul提供了一种完整的服务网格解决方案。

它具有很多优点。包括:基于raft协议,比较简洁;支持健康检查,同时支持HTTP和DNS协议,支持跨数据中心的WAN集群,提供图形界面,跨平台,支持Linux、Mac、Windows。

5.1.2 能干嘛

服务发现

提供HTTP和DNS两种发现方式。

健康监测

支持多种方式,HTTP、TCP、Docker、Shell脚本定制化

KV存储

Key、Value的存储方式

多数据中心

Consul支持多数据中心

可视化Web界面

5.1.3 去哪下

下载地址

5.1.4 怎么玩

参考文档

5.2 安装并运行

可以参考官网的安装说明进行安装

下载完成之后只有一个consul.exe文件

在consul.exe目录下运行cmd命令行窗口,输入consul --version可以查看当前安装的consul的版本

使用开发模式启动

consul agent -dev

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第21张图片

通过以下地址可以访问Consul的首页:

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第22张图片

5.3 服务提供者

新建Module支付服务cloud-providerconsul-payment8006

导入依赖

<dependencies>
    
    <dependency>
        <groupId>com.jg.springcloudgroupId>
        <artifactId>cloud-api-commonsartifactId>
        <version>1.0-SNAPSHOTversion>
    dependency>
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-consul-discoveryartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-actuatorartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
        <scope>runtimescope>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
    <dependency>
        <groupId>cn.hutoolgroupId>
        <artifactId>hutool-allartifactId>
        <version>RELEASEversion>
        <scope>testscope>
    dependency>
    <dependency>
        <groupId>cn.hutoolgroupId>
        <artifactId>hutool-allartifactId>
        <version>RELEASEversion>
        <scope>testscope>
    dependency>
dependencies>

修改application.yml文件

server:
  port: 8006

spring:
  application:
    name: consul-provider-payment
# Consul注册中心地址
  cloud:
    consul:
      port: 8500
      discovery:
        service-name: ${spring.application.name}
        hostname: 127.0.0.1

主启动

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

如此配置,服务启动之后会注册到Consul中

尚硅谷阳哥SpringCloud第二季学习笔记(一)_第23张图片

5.4 服务消费者

依旧是好经典五步走

pom

<dependencies>
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-consul-discoveryartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-actuatorartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
        <scope>runtimescope>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
dependencies>
###consul服务端口号
server:
  port: 80

spring:
  application:
    name: cloud-consumer-order
  ####consul注册中心地址
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        #hostname: 127.0.0.1
        service-name: ${spring.application.name}


Main

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

Controller

@RestController
@Slf4j
public class OrderConsulController {
    public static final String INVOKE_URL = "http://consul-provider-payment";

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/consul")
    public String paymentInfo(){
        return restTemplate.getForObject(INVOKE_URL+"/payment/consul",String.class);
    }
}

5.5 三个注册中心的区别

组件名 开发语言 CAP 服务健康检查 对外暴露接口 Spring Cloud集成
Eureka Java AP 可配支持 HTTP 已集成
Consul GO CP 支持 HTTP/DNS 已集成
Zookeeper Java CP 支持 客户端 已集成

你可能感兴趣的:(spring,spring,cloud)