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

目录

  • 一.微服务概述
    • 1.1 什么是微服务
    • 1.2 微服务与微服务架构
    • 1.3 微服务的优缺点
    • 1.4 微服务架构4个核心问题
    • 1.5 核心问题解决方案
    • 1.6 微服务技术栈
  • 二、SpringCloud入门概述
    • 2.1、SpringCloud是什么?
    • 2.2、 SpringCloud 和 SpringBoot 的关系
    • 2.3、 SpringCloud主要框架
    • 2.4、 SpringCloud版本
    • 2.5 Dubbo 和 SpringCloud技术选型
  • 三、SpringCloud Rest 环境搭建
    • 3.1 服务提供者
      • 3.1.1 SpringCloud版本选择
      • 3.1.2 创建父工程
    • 3.2 服务消费者
      • 3.2.1 创建工程
      • 3.2.2 测试
  • 四、服务发现组件Eureka
    • 4.1、Eureka简介
    • 4.2、环境测试(eureka-server)
    • 4.3、环境测试(eureka-client)
    • 4.4 EureKa自我保护机制:好死不如赖活着

一.微服务概述

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 Cloud - SOA、Eureka、服务调用(1)_第1张图片
十八、Spring Cloud - SOA、Eureka、服务调用(1)_第2张图片

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版本的对照表,大家看看有没有找到什么规律呢?

SpringBoot SpringCloud
1.2.x Angel版本
1.3.x Brixton版本
1.4.x Camden版本
1.5.x Dalston版本、Edgware版本
2.0.x Finchley版本
2.1.x Greenwich版本

2.5 Dubbo 和 SpringCloud技术选型

Dubbo SpringCloud
服务注册中心 Zookeeper Spring Cloud Netfilx Eureka
服务调用方式 RPC REST API
服务监控 Dubbo-monitor Spring 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 Netflix 中文文档
  • SpringCloud 中文API文档(官方文档翻译版)
  • SpringCloud中国社区
  • 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版本选择

大版本说明

SpringBoot SpringCloud 关系
1.2.x Angel版本(天使) 兼容SpringBoot1.2x
1.3.x Brixton版本(布里克斯顿) 兼容SpringBoot1.3x,也兼容SpringBoot1.4x
1.4.x Camden版本(卡姆登) 兼容SpringBoot1.4x,也兼容SpringBoot1.5x
1.5.x Dalston版本(多尔斯顿) 兼容SpringBoot1.5x,不兼容SpringBoot2.0x
1.5.x Edgware版本(埃奇韦尔) 兼容SpringBoot1.5x,不兼容SpringBoot2.0x
2.0.x Finchley版本(芬奇利) 兼容SpringBoot2.0x,不兼容SpringBoot1.5x
2.1.x Greenwich版本(格林威治)

实际开发版本关系

spring-boot-starter-parent spring-cloud-dependencles
版本号 发布日期 版本号 发布日期
1.5.2.RELEASE 2017-03 Dalston.RC1 2017-x
1.5.9.RELEASE 2017-11 Edgware.RELEASE 2017-11
1.5.16.RELEASE 2018-04 Edgware.SR5 2018-10
1.5.20.RELEASE 2018-09 Edgware.SR5 2018-10
2.0.2.RELEASE 2018-05 Fomchiey.BULD-SNAPSHOT 2018-x
2.0.6.RELEASE 2018-10 Fomchiey-SR2 2018-10
2.1.4.RELEASE 2019-04 Greenwich.SR1 2019-03

使用后两个

3.1.2 创建父工程

  1. 新建父工程项目 springcloud

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第3张图片
3. 删掉不需要的src

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第4张图片

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

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


<packaging>pompackaging>
<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>
    <log4j.version>1.2.17log4j.version>
    <lombok.version>1.16.18lombok.version>
properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-alibaba-dependenciesartifactId>
            <version>0.2.0.RELEASEversion>
            <type>pomtype>
            <scope>importscope>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-dependenciesartifactId>
            <version>Greenwich.SR1version>
            <type>pomtype>
            <scope>importscope>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-dependenciesartifactId>
            <version>2.1.4.RELEASEversion>
            <type>pomtype>
            <scope>importscope>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.47version>
        dependency>
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.1.10version>
        dependency>
        
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
            <version>1.3.2version>
        dependency>
        
        <dependency>
            <groupId>ch.qos.logbackgroupId>
            <artifactId>logback-coreartifactId>
            <version>1.2.3version>
        dependency>
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>${junit.version}version>
        dependency>
        <dependency>
            <groupId>log4jgroupId>
            <artifactId>log4jartifactId>
            <version>${log4j.version}version>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>${lombok.version}version>
        dependency>
    dependencies>
dependencyManagement>
  1. 创建子模块 springcloud-api

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第5张图片
下一步点击 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

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第6张图片

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

<dependencies>
    <dependency>
        <groupId>com.zqlgroupId>
        <artifactId>springcloud-apiartifactId>
        <version>1.0-SNAPSHOTversion>
    dependency>
    <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
    dependency>
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
    dependency>
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>druidartifactId>
    dependency>
    <dependency>
        <groupId>ch.qos.logbackgroupId>
        <artifactId>logback-coreartifactId>
    dependency>
    <dependency>
        <groupId>org.mybatis.spring.bootgroupId>
        <artifactId>mybatis-spring-boot-starterartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-testartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-jettyartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
    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


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


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

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第7张图片

3.2 服务消费者

3.2.1 创建工程

  1. 创建maven子工程 springcloud-consumer-dept-80
    十八、Spring Cloud - SOA、Eureka、服务调用(1)_第8张图片
    十八、Spring Cloud - SOA、Eureka、服务调用(1)_第9张图片

  2. 导入所需依赖

<dependencies>
    <dependency>
        <groupId>com.zqlgroupId>
        <artifactId>springcloud-apiartifactId>
        <version>1.0-SNAPSHOTversion>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
    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 responseType)
     * 

* 提供多种便捷访问远程http服务的方法,简单的Restful服务模板~ */ @Autowired private RestTemplate restTemplate; /** * 服务提供方地址前缀 *

* 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

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第10张图片

四、服务发现组件Eureka

4.1、Eureka简介

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

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第11张图片
十八、Spring Cloud - SOA、Eureka、服务调用(1)_第12张图片

4.2、环境测试(eureka-server)

步骤:

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

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第13张图片
十八、Spring Cloud - SOA、Eureka、服务调用(1)_第14张图片
2. pom.xml 配置


<dependencies>
    
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-eureka-serverartifactId>
        <version>1.4.6.RELEASEversion>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
    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/

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第15张图片

4.3、环境测试(eureka-client)

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

  1. 导入Eureka 依赖


<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-eurekaartifactId>
    <version>1.4.6.RELEASEversion>
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);
    }
}

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第16张图片

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

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第17张图片

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

这样模拟集群就搭建号了,就可以把一个项目挂载到三个服务器上了
结果如图:
十八、Spring Cloud - SOA、Eureka、服务调用(1)_第18张图片
6. 如果此时停掉 springcloud-provider-dept-8001 等30s后 监控会开启保护机制:

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第19张图片

  1. 配置关于服务加载的监控信息
    十八、Spring Cloud - SOA、Eureka、服务调用(1)_第20张图片
    当点击进去出现
    十八、Spring Cloud - SOA、Eureka、服务调用(1)_第21张图片

  2. pom.xml中添加依赖


<dependency>
 <groupId>org.springframework.bootgroupId>
 <artifactId>spring-boot-starter-actuatorartifactId>
dependency>

application.yml中添加配置

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

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

十八、Spring Cloud - SOA、Eureka、服务调用(1)_第22张图片

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【不推荐关闭自我保护机制】

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

文章地址

你可能感兴趣的:(#,计算机(Java进阶)中级,进阶阶段,1024程序员节,spring,cloud,eureka,微服务)