二十六、Spring Cloud - SOA、Eureka、服务调用(1)

一.微服务概述

1.1 什么是微服务

目前的微服务并没有一个统一的标准,一般是以业务来划分将传统的一站式应用,拆分成一个个的服务,彻底去耦合,一个微服务就是单功能业务,只做一件事。

1.2 微服务与微服务架构

  • 微服务是一种架构模式或者一种架构风格,提倡将单一应用程序划分成一组小的服务独立部署,服务之间相互配合、相互协调,每个服务运行于自己的进程中。
  • 服务与服务间采用轻量级通讯,如HTTP的RESTful API等
  • 避免统一的、集中式的服务管理机制

1.3 微服务的优缺点

优点

  1. 每个服务足够内聚,足够小,比较容易聚焦
  2. 开发简单且效率高,一个服务只做一件事情
  3. 开发团队小,一般2-5人足以(当然按实际为准)
  4. 微服务是松耦合的,无论开发还是部署都可以独立完成
  5. 微服务能用不同的语言开发
  6. 易于和第三方集成,微服务允许容易且灵活的自动集成部署(持续集成工具有Jenkins,Hudson,bamboo等)
  7. 微服务易于被开发人员理解,修改和维护,这样可以使小团队更加关注自己的工作成果,而无需一定要通过合作才能体现价值
  8. 微服务允许你融合最新的技术
    微服务只是业务逻辑的代码,不会和HTML,CSS或其他界面组件融合
    每个微服务都可以有自己的存储能力,数据库可自有也可以统一,十分灵活

缺点

  1. 开发人员要处理分布式系统的复杂性
  2. 多服务运维难度,随着服务的增加,运维的压力也会增大
  3. 依赖系统部署
  4. 服务间通讯的成本
  5. 数据的一致性
  6. 系统集成测试
  7. 性能监控的难度

1.4 微服务架构4个核心问题

  1. 服务很多,客户端怎么访问
  2. 这么多服务?服务之间如何通信?
  3. 这么多服务?如何治理?
  4. 服务挂了怎么办?

1.5 核心问题解决方案

  1. 使用Spring Cloud 来解决因为类似一个生态。前提是要会 SpringBoot
  2. Spring Cloud NetFlix 一站式解决方案!
  3. Apache Dubbo Zookeeper 半自动,需要整合别人的!
  4. Spring Cloud Alibaba 一站式解决方案,更简单

1.6 微服务技术栈

微服务技术条目落地技术
服务开发SpringBoot、Spring、SpringMVC等
服务配置与管理Netfix公司的Archaius、阿里的Diamond等
服务注册与发现Eureka、Consul、Zookeeper等
服务调用Rest、PRC、gRPC
服务熔断器Hystrix、Envoy等
负载均衡Ribbon、Nginx等
服务接口调用(客户端调用服务的简化工具)Fegin等
消息队列Kafka、RabbitMQ、ActiveMQ等
服务配置中心管理SpringCloudConfig、Chef等
服务路由(API网关)Zuul等
服务监控Zabbix、Nagios、Metrics、Specatator等
全链路追踪Zipkin、Brave、Dapper等
数据流操作开发包SpringCloud Stream(封装与Redis,Rabbit,Kafka等发送接收消息)
时间消息总栈SpringCloud Bus
服务部署Docker、OpenStack、Kubernetes等

二、SpringCloud入门概述

Spring Cloud 官网

在这里插入图片描述
在这里插入图片描述

Spring的三大模块:SpringBoot(构建),Spring Cloud(协调),Spring Cloud Data Flow(连接)

2.1、SpringCloud是什么?

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简
化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、
熔断器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring并
没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框
架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给
开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

2.2、 SpringCloud 和 SpringBoot 的关系

  1. Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单
    个微服务,Spring Cloud是一个基于Spring Boot实现的云应用开发工具;Spring Boot专
    注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;
    Spring Boot使用了默认大于配置的理念,很多集成方案已经帮你选择好了,能不配置就
    不配置,Spring Cloud很大的一部分是基于Spring Boot来实现,可以不基于Spring Boot
    吗?不可以。
  2. Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开
    Spring Boot,属于依赖的关系。

2.3、 SpringCloud主要框架

  • 服务发现——Netflix Eureka
  • 服务调用——Netflix Feign
  • 熔断器——Netflix Hystrix
  • 服务网关——Netflix Zuul
  • 分布式配置——Spring Cloud Config
  • 消息总线 —— Spring Cloud Bus

2.4、 SpringCloud版本

目前总结采用的SpringCloud版本为Finchley.M9 。你可能会觉得这个版本怎么这么
奇怪?SpringCloud由于是一系列框架组合,为了避免与包含的自框架版本产生混淆,采
用伦敦地铁站的名称作为版本名,形式为版本名+里程碑号。 M9为第9个里程碑版本。
以下是SpringBoot与Spring Cloud版本的对照表,大家看看有没有找到什么规律呢?

SpringBootSpringCloud
1.2.xAngel版本
1.3.xBrixton版本
1.4.xCamden版本
1.5.xDalston版本、Edgware版本
2.0.xFinchley版本
2.1.xGreenwich版本

2.5 Dubbo 和 SpringCloud技术选型

DubboSpringCloud
服务注册中心ZookeeperSpring Cloud Netfilx Eureka
服务调用方式RPCREST API
服务监控Dubbo-monitorSpring Boot Admin
断路器不完善Spring Cloud Netfilx Hystrix
服务网关Spring Cloud Netfilx Zuul
分布式配置Spring Cloud Config
服务跟踪Spring Cloud Sleuth
消息总栈Spring Cloud Bus
数据流Spring Cloud Stream
批量任务Spring Cloud Task

最大区别:Spring Cloud 抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式

严格来说,这两种方式各有优劣。虽然从一定程度上来说,后者牺牲了服务调用的性能,但也避免了上面提到的原生RPC带来的问题。而且REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这个优点在当下强调快速演化的微服务环境下,显得更加合适。

品牌机和组装机的区别

总结:二者解决的问题域不一样:Dubbo的定位是一款RPC框架,而SpringCloud的目标是微服务架构下的一站式解决方案。

自学参考书:

三、SpringCloud Rest 环境搭建

3.1 服务提供者

我们会使用一个Dept部门模块做一个微服务通用案例 Consumer消费者(Client)通过REST调用Provider提供者(Server)提供的服务。

回顾Spring,SpringMVC,Mybatis等以往学习的知识。
Maven的分包分模块架构复习。

一个简单的Maven模块结构是这样的:
– app-parent: 一个父项目(app-parent)聚合了很多子项目(app-util\app-dao\app-web…)
|-- pom.xml
|
|-- app-core
||---- pom.xml
|
|-- app-web
||---- pom.xml

一个父工程带着多个Moudule子模块

MicroServiceCloud父工程(Project)下初次带着3个子模块(Module)

  • microservicecloud-api 【封装的整体entity/接口/公共配置等】
  • microservicecloud-consumer-dept-80 【服务消费者】
  • microservicecloud-provider-dept-8001 【服务提供者】

3.1.1 SpringCloud版本选择

大版本说明

SpringBootSpringCloud关系
1.2.xAngel版本(天使)兼容SpringBoot1.2x
1.3.xBrixton版本(布里克斯顿)兼容SpringBoot1.3x,也兼容SpringBoot1.4x
1.4.xCamden版本(卡姆登)兼容SpringBoot1.4x,也兼容SpringBoot1.5x
1.5.xDalston版本(多尔斯顿)兼容SpringBoot1.5x,不兼容SpringBoot2.0x
1.5.xEdgware版本(埃奇韦尔)兼容SpringBoot1.5x,不兼容SpringBoot2.0x
2.0.xFinchley版本(芬奇利)兼容SpringBoot2.0x,不兼容SpringBoot1.5x
2.1.xGreenwich版本(格林威治)

实际开发版本关系

spring-boot-starter-parentspring-cloud-dependencles
版本号发布日期版本号发布日期
1.5.2.RELEASE2017-03Dalston.RC12017-x
1.5.9.RELEASE2017-11Edgware.RELEASE2017-11
1.5.16.RELEASE2018-04Edgware.SR52018-10
1.5.20.RELEASE2018-09Edgware.SR52018-10
2.0.2.RELEASE2018-05Fomchiey.BULD-SNAPSHOT2018-x
2.0.6.RELEASE2018-10Fomchiey-SR22018-10
2.1.4.RELEASE2019-04Greenwich.SR12019-03

使用后两个

3.1.2 创建父工程

  1. 新建父工程项目 springcloud

在这里插入图片描述
3. 删掉不需要的src

在这里插入图片描述

  1. 在pom.xml中导入下面依赖

切记Packageing是 pom模式
主要是定义POM文件,将后续各个子模块公用的jar包等统一提取出来,类似一个抽象父类

<!--打包方式  pom-->
<packaging>pom</packaging>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <junit.version>4.12</junit.version>
    <log4j.version>1.2.17</log4j.version>
    <lombok.version>1.16.18</lombok.version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>0.2.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--springCloud的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Greenwich.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--SpringBoot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.1.4.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--SpringBoot 启动器-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--日志测试~-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>
  1. 创建子模块 springcloud-api

在这里插入图片描述
下一步点击 Finish即可.

创建数据库 db01

在 springcloud-api下面创建包 com.zql.springcloud.pojo 接着创建实体 Dept.java

package com.zql.springcloud.pojo;

import com.oracle.webservices.internal.api.databinding.DatabindingMode;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * @Author:Daniel
 * @Version 1.0
 */
@Data
@NoArgsConstructor
@Accessors(chain = true)  //链式
public class Dept implements Serializable {

    private Long deptno;

    private String dname;

    private String db_source;

    public Dept(String dname) {
        this.dname = dname;
    }

    /**
     * 链式写法
     * Dept dept = new Dept();
     *
     *dept.setDeptno(11).setDname('sss').setDb_Source('001')
     *
     */
}

  1. 创建子模块 springcloud-provider-dept-8001

在这里插入图片描述

导入如下依赖到 springcloud-api(pom.xml中)

<dependencies>
    <dependency>
        <groupId>com.zql</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>1.0-SNAPSHOT</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-test</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-jetty</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
</dependencies>

在resources下面创建 application.yml mybatis/mybatis-config.xml

server:
  port: 8001

#mybatis配置
mybatis:
  type-aliases-package: com.zql.springcloud.pojo
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml


#spring的配置
spring:
  application:
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8
    username: root
    password: root

application.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>

编写接口:

创建 com.zql.dao 再创建 DeptDao.java

package com.zql.mapper;

import com.zql.springcloud.pojo.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @Author:Daniel
 * @Version 1.0
 */

@Mapper
@Repository
public interface DeptMapper {

    public boolean addDept(Dept dept);

    public Dept queryById(Long id);

    public List<Dept> queryAll();
}

在resources下面创建 mybatis/mapper/DeptMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.zql.mapper.DeptMapper" >

    <insert id="addDept" parameterType="Dept">
        insert into dept(dname,db_source) values (#{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>

编写接口,创建com.zql.service 包,下面创建 DeptService.java接口

DeptService.java

package com.zql.service;

import com.zql.springcloud.pojo.Dept;

import java.util.List;

/**
 * @Author:Daniel
 * @Version 1.0
 */
public interface DeptService {

    public boolean addDept(Dept dept);

    public Dept queryById(Long id);

    public List<Dept> queryAll();
}

创建编写接口实现类 com.zql.service.impl.DeptServiceImpl.java

DeptServiceImpl.java

package com.zql.service.impl;

import com.zql.mapper.DeptMapper;
import com.zql.service.DeptService;
import com.zql.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Author:Daniel
 * @Version 1.0
 */
@Service
public class DeptServiceImpl implements DeptService {

    @Autowired
    private DeptMapper deptMapper;

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

    @Override
    public Dept queryById(Long id) {
        return deptMapper.queryById(id);
    }

    @Override
    public List<Dept> queryAll() {
        return deptMapper.queryAll();
    }
}

创建 com.zql.controller 包,再创建 DeptController.java

package com.zql.controller;

import com.zql.service.DeptService;
import com.zql.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @Author:Daniel
 * @Version 1.0
 */
@RestController   //提供Restful 风格
public class DeptController {

    @Autowired
    private DeptService deptService;


    @PostMapping("/dept/add")
    public boolean addDept(Dept dept){

        return deptService.addDept(dept);

    }

    @GetMapping("/dept/{id}")
    public Dept addDept(@PathVariable("id") Long id){

        return deptService.queryById(id);

    }

    @GetMapping("/dept/queryAll")
    public List<Dept> queryAll(){

        return deptService.queryAll();

    }

}

创建主启动程序类 DeptProvider.java

package com.zql;

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

/**
 * @Author:Daniel
 * @Version 1.0
 */
@SpringBootApplication
public class DeptProvider {

    public static void main(String[] args) {

        SpringApplication.run(DeptProvider.class,args);
    }
}

启动测试,浏览器输入 http://localhost:8001/dept/queryAll

在这里插入图片描述

3.2 服务消费者

3.2.1 创建工程

  1. 创建maven子工程 springcloud-consumer-dept-80
    在这里插入图片描述
    在这里插入图片描述

  2. 导入所需依赖

<dependencies>
    <dependency>
        <groupId>com.zql</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. 在resources下创建 application.yml
server:
  port: 80
  1. 使用RestTemplete先需要放入Spring容器中,创建包 com.zql.config,创建 ConfigBean.java
package com.zql.config;

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

/**
 * @Author:Daniel
 * @Version 1.0
 */
@Configuration
public class ConfigBean {

    //@Configuration -- spring  applicationContext.xml
    //配置负载均衡实现RestTemplate
    // IRule
    // RoundRobinRule 轮询
    // RandomRule 随机
    // AvailabilityFilteringRule : 会先过滤掉,跳闸,访问故障的服务~,对剩下的进行轮询~
    // RetryRule : 会先按照轮询获取服务~,如果服务获取失败,则会在指定的时间内进行,重试
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
  1. 创建 com.zql.controller 再创建 DeptconsumerController.java
package com.zql.controller;

import com.zql.springcloud.pojo.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;

/**
 * @Author:Daniel
 * @Version 1.0
 */
@RestController
public class DeptConsumerController {
    /**
     * 理解:消费者,不应该有service层~
     * RestTemplate .... 供我们直接调用就可以了! 注册到Spring中
     * (地址:url, 实体:Map ,Class<T> responseType)
     * <p>
     * 提供多种便捷访问远程http服务的方法,简单的Restful服务模板~
     */
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 服务提供方地址前缀
     * <p>
     * Ribbon:我们这里的地址,应该是一个变量,通过服务名来访问
     */
    private static final String REST_URL_PREFIX = "http://localhost:8001";
    //private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
    /**
     * 消费方添加部门信息
     * @param dept
     * @return
     */
    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept) {
        // postForObject(服务提供方地址(接口),参数实体,返回类型.class)
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
    }
    /**
     * 消费方根据id查询部门信息
     * @param id
     * @return
     */
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id) {
        // getForObject(服务提供方地址(接口),返回类型.class)
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/" + id, Dept.class);
    }
    /**
     * 消费方查询部门信息列表
     * @return
     */
    @RequestMapping("/consumer/dept/list")
    public List<Dept> list() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/queryAll", List.class);
    }
}
  1. 创建主启动类 DeptConsumer.java
package com.zql;

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

import java.util.function.Consumer;

/**
 * @Author:Daniel
 * @Version 1.0
 */
@SpringBootApplication
public class ConsumerDept {

    public static void main(String[] args) {

        SpringApplication.run(ConsumerDept.class,args);
    }
}

3.2.2 测试

先开启服务提供者 springcloud-provider-dept-8001,再次启动 springcloud-consumer-dept-80

http://localhost/consumer/dept/queryAll

在这里插入图片描述

四、服务发现组件Eureka

4.1、Eureka简介

  • Eureka是Spring Cloud Netflix微服务套件中的一部分,是一套成熟的服务注册和发现组件,可以与Springboot构建的微服务很容易的整合起来。
  • Eureka包含了服务器端和客户端组件。
  • Eureka服务器用作服务注册服务器。
  • Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持

在这里插入图片描述
在这里插入图片描述

4.2、环境测试(eureka-server)

步骤:

  1. 导入依赖
  2. 编写配置文件
  3. 开启这个功能 @Enable
  4. 配置类
  1. 创建 springcloud-eureka-7001

在这里插入图片描述
在这里插入图片描述
2. pom.xml 配置

<!--导包~-->
<dependencies>
    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
    <!--导入Eureka Server依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--热部署工具-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
</dependencies>
  1. application.yml
server:
  port: 7001

#Eureka配置
eureka:
  instance:
    hostname: localhost #Eureka服务端的实例名称
  client:
    register-with-eureka: false # 表示是否向eureka注册中心注册自己
    fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
    service-url:
      # 单机:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      # 集群(关联):
     # defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  1. 创建主启动类 EurekaServer_7001.java
package com.zql;

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

/**
 * @Author:Daniel
 * @Version 1.0
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer_7001 {

    public static void main(String[] args) {

        SpringApplication.run(EurekaServer_7001.class,args);
    }
}

启动测试 http://localhost:7001/

在这里插入图片描述

4.3、环境测试(eureka-client)

调整之前创建的springlouc-provider-dept-8001

  1. 导入Eureka 依赖
<!--Eureka依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
  1. application.yml 中新增Eureka 配置
# Eureka配置:配置服务注册中心地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
  1. 为主启动类添加 @EnableEurekaClient 注解
package com.zql;

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

/**
 * @Author:Daniel
 * @Version 1.0
 */
@SpringBootApplication
// @EnableEurekaClient 开启Eureka客户端注解,在服务启动后自动向注册中心注册服务
@EnableEurekaClient
public class DeptProvider {

    public static void main(String[] args) {

        SpringApplication.run(DeptProvider.class,args);
    }
}

在这里插入图片描述

  1. 先启动 7001 服务端后再启动8001客户端进行测试,然后访问监控页 http://localhost:7001/ 产看结果如图,成功

在这里插入图片描述

  1. 修改Eureka上的默认描述信息
# Eureka配置:配置服务注册中心地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
  instance:
    instance-id: springcloud-provider-dept-8001 #修改Eureka上的默认描述信息

这样模拟集群就搭建号了,就可以把一个项目挂载到三个服务器上了
结果如图:
在这里插入图片描述
6. 如果此时停掉 springcloud-provider-dept-8001 等30s后 监控会开启保护机制:

在这里插入图片描述

  1. 配置关于服务加载的监控信息
    在这里插入图片描述
    当点击进去出现
    在这里插入图片描述

  2. pom.xml中添加依赖

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

application.yml中添加配置

# info配置
info:
	# 项目的名称
	app.name: haust-springcloud
	# 公司的名称
	company.name: 腾讯股份有限公司

启动测试 http://localhost:7001/
此时刷新监控页,点击进入显示如下内容:

在这里插入图片描述

4.4 EureKa自我保护机制:好死不如赖活着

  • 一句话总结就是:某时刻某一个微服务不可用,eureka不会立即清理,依旧会对该微服务的信息进行保存!
  • 默认情况下,当eureka server在一定时间内没有收到实例的心跳,便会把该实例从注册表中删除(默认是90秒),但是,如果短时间内丢失大量的实例心跳,便会触发eureka server的自我保护机制,比如在开发测试时,需要频繁地重启微服务实例,但是我们很少会把eureka server一起重启(因为在开发过程中不会修改eureka注册中心),当一分钟内收到的心跳数大量减少时,会触发该保护机制。可以在eureka管理界面看到Renews threshold和Renews(last min),当后者(最后一分钟收到的心跳数)小于前者(心跳阈值)的时候,触发保护机制,会出现红色的警告:EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT.RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEGING EXPIRED JUST TO BE SAFE.从警告中可以看到,eureka认为虽然收不到实例的心跳,但它认为实例还是健康的,eureka会保护这些实例,不会把它们从注册表中删掉。
  • 该保护机制的目的是避免网络连接故障,在发生网络故障时,微服务和注册中心之间无法正常通信,但服务本身是健康的,不应该注销该服务,如果eureka因网络故障而把微服务误删了,那即使网络恢复了,该微服务也不会重新注册到eureka server了,因为只有在微服务启动的时候才会发起注册请求,后面只会发送心跳和服务列表请求,这样的话,该实例虽然是运行着,但永远不会被其它服务所感知。所以,eureka server在短时间内丢失过多的客户端心跳时,会进入自我保护模式,该模式下,eureka会保护注册表中的信息,不在注销任何微服务,当网络故障恢复后,eureka会自动退出保护模式。自我保护模式可以让集群更加健壮。
  • 但是我们在开发测试阶段,需要频繁地重启发布,如果触发了保护机制,则旧的服务实例没有被删除,这时请求有可能跑到旧的实例中,而该实例已经关闭了,这就导致请求错误,影响开发测试。所以,在开发测试阶段,我们可以把自我保护模式关闭,只需在eureka server配置文件中加上如下配置即可:eureka.server.enable-self-preservation=false【不推荐关闭自我保护机制】

详细内容可以参考下这篇博客内容

文章地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Daniel521-Spark

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值