SpringCloud学习--- Eureka详解(2021年10月最新_附代码包)

Posted 小样5411

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud学习--- Eureka详解(2021年10月最新_附代码包)相关的知识,希望对你有一定的参考价值。

一、前言

下一篇:Ribbon

1.1 简单介绍SpringCloud

简单介绍下SpringCloud,SpringCloud是基于SpringBoot的微服务全套解决方案,可保证高并发,高可用。何为微服务???从前我们没有高并发的时代,基本都用的是单体服务,也就是整个系统都编写在一个项目package下,但是随着现在互联网普及,用户量越来越大,如果还一个系统都只编写在一个项目包下,那么启动起来要花多少时间,而且万一崩了,整个项目就崩了,所以出现了微服务架构,将每个功能分别写成一个模块,比如支付模块,搜索模块,订单模块等等,每个模块部署在不同的服务器上,这样的话,启动也比较高效,响应也快,重要的是,就算一个服务器的模块崩了,其他模块并不会受影响,不同团队程序员负责自己模块即可。

1.2 Eureka是什么?

Eureka叫服务注册与发现,是SpringCloud下的一个组件,目的是让微服务架构的不同模块间的功能可以相互调用,只要通过Eureka中间桥梁,在其中注册,就可以用到其他模块提供的接口,Eureka的模型图如下

比如用户模块是Service Consumer(消费者),支付模块是Service Provider(生产者),那么不同模块怎么通信呢?就通过Eureka Server这个桥梁,如果用户需要对商品进行支付,那么支付模块和用户模块都会在Eureka Server中注册(也可以直接理解成就在Eureka中注册),相当于它们就产生关系了,然后Service Consumer就可以拿到支付模块的内容了(实际是调用支付模块提供的接口),这样就通过这个Server中间桥梁间接执行了支付模块中的支付,表面上用户是感觉不到的,就像一个黑盒,用户不管执行原理,只要支付成功就行。后面实战例子会让你有所体会。

注意:除了Eureka Server之外都是Client,只不过Client中分生产者和消费者,服务A调用另一个服务B,则服务A就是Consumer,服务B就是Provider,因为服务B为服务A提供了某个方法供它调用

二、Eureka创建Server

首先你要创建一个SpringBoot项目,也就是Spring Initializr,如果你跟我一样第一个Default的选项一直无法初始化,你就跟我一样用阿里云的创建,一直next,什么都不用√

然后将不要的都删除只剩最基本的

将maven配成自己的,不配就会用默认的,会保存在C盘的一个目录,可能下载依赖会非常慢

第一步:导入父工程pom依赖,这里用目前最新的Hoxton.SR12,配合与其兼容的2.3.12.RELEASE版本

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.yx</groupId>
    <artifactId>springcloud1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud1</name>
    <description>Demo project for Spring Boot</description>
    
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.12.RELEASE</spring-boot.version>
        <spring.cloud-version>Hoxton.SR12</spring.cloud-version>
    </properties>

    <packaging>pom</packaging>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

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

</project>

第二步:创建一个eureka_server01模块,new moudle,选择maven创建,然后向其导入依赖,这个模块是Eureka Server

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

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

第三步:在resources下配置application.yml文件

server:
  port: 8761  #EurekaServer服务端口

eureka:
  instance:
    hostname: localhost #主机名
  client: #这两个false是防止自己去尝试连接主机(EurekaServer),因为自己就是主机,单机版,就是只有一个Eureka时都写false
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

# 配置服务名
spring:
  application:
    name: Eureka

第四步:在java包下配置EurekaServerApplication启动类,@EnableEurekaServer很关键,是开启EurekaServer

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

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

最后运行EurekaServerApplication ,启动成功后在浏览器输入localhost:8761,然后就会运行出下面效果,这个就是可视化Eureka,可以看到哪些服务注册到了Eureka中。

这部分的目录结构如下

三、Eureka创建多个Client

多个Client,一个作为Consumer,一个作为Provider,我们就拿用户要支付为例子,用户是一个Client(Consumer),支付也是一个Client(Provider),然后它们之间通信,也就是用户通过Server调用支付功能

3.1 创建第一个Client,用户Client

新建一个module,选择maven创建,我将其命名为eureka_client_customer,同样经过几步,配pom.xml,配application.yml,写启动类,然后启动

第一步:pom.xml,新增下面依赖,注意这里就变成spring-cloud-starter-netflix-eureka-client,创建Client当然导入client相关依赖

<dependencies>
     <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
</dependencies>

第二步:resources下配application.yml,这里就表示这个client向http://localhost:8761/eureka/中注册,服务命名为client_customer,这里没有配端口,就会默认用8080端口

# 指定往哪个EurekaServer服务中注册
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

# 指定服务名称,为了区分创建的服务
spring:
  application:
    name: client_customer

第三步:写启动类ClientCustomerApplication ,@EnableEurekaClient开启EurekaClient,让它去配置文件application.yml中指定Eureka Server里注册

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

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

运行它,然后浏览器刷新之前运行的Eureka可视化页面,就会出现你注册的client服务

目录结构如下

3.2 创建第二个Client,支付Client

同理上面3.1一样注册,新建module,命名为eureka_client_pay,然后分三步,配pomx.ml,配application.yml,配启动类

第一步:pom.xml和之前client一样,新增依赖

 <dependencies>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
</dependencies>

第二步:resources下配application.yml,由于8080用了,所以我们这个用8081,同样向localhost:8761的Eureka注册,并指定服务名称

# 指定往哪个EurekaServer服务中注册
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

# 指定服务名称,为了区分创建的服务
spring:
  application:
    name: client_pay

server:
  port: 8081

第三步:启动类,开启EurekaClient,然后启动

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

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

启动后,刷新浏览器Eureka可视化界面,如果你电脑内存比较小,开的服务多就会很卡,建议加内存,开发现在一般都要16G内存才够了,正常出现注册的信息,现在Eureka Server中就注册了两个Client服务,接着不同的服务之间就可以通信了,形象的说,就是以前用户Client和支付Client没有在Eureka注册,他们两个根本不认识对方,然后注册后,两个就认识了,可以通信对话了

3.3 测试:两个Client服务之间的通信

我们开始讲了实现用户能访问到支付模块,也就是调用支付模块的接口,用户调用支付,用户就是消费者,支付就是生产者(提供支付功能)

先写支付Client提供的支付功能,新建一个controller,定义接口,返回支付成功,然后用户Clent访问这个接口

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PayController {

    @GetMapping("/pay")
    public String pay(){
        String msg = "小明购买了一个充电宝,支付成功";
        return msg;
    }
}

再定义用户这边Controller,这里需要介绍一个叫RestTemplate的东西,它的作用是:消费者需要利用restTemplate来获取提供者注册的功能

这里要做两个操作,1、注册restTemplate的bean 2、ClientController编写

ClientCustomerApplication中新增下面

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

CustomerController.java

import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class CustomerController {

    @Autowired
    private RestTemplate restTemplate; //消费者需要利用restTemplate来获取提供者注册的功能,配置new RestTemplate();

    @Autowired
    private EurekaClient eurekaClient;

    @GetMapping("/customer")
    public String client(){
        //1、通过eurekaClient获取到client_pay服务的信息
        InstanceInfo info = eurekaClient.getNextServerFromEureka("client_pay", false);//第二个参数false表示获取用的是http,true为安全的https

        //2、获取到访问的地址
        String url = info.getHomePageUrl();
        System.out.println(url);//控制台打印访问的地址

        //3、通过restTemplate访问
        String res = restTemplate.getForObject(url + "/pay", String.class);//第二个值为返回值类型
        //4、返回结果
        return res;
    }


}

重启ClientCustomerApplication和ClientPayApplication两个服务,重启完毕后到浏览器输入localhost:8080/customer,那么我们输入访问的是用户Client的/customer,但是却访问到了支付pay接口,这就是服务间的通信

四、Eureka的安全性

如何保证Eureka的安全性
SpringCloud提供了一种安全认证配置保证安全

首先需要在eureka_server01这个服务pom文件中新增一个安全的依赖

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

再新增一个配置类

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().ignoringAntMatchers("/eureka/**");//csrf做安全认证,底层用的是、HashSet
        super.configure(http);
    }
}

配置eureka_server01服务中application.yml,加上密码,账号密码要是root,root才能登录,重启EurekaServerApplication

刷新localhost:8761这个Eureka可视化界面,登录后,发现注册的两个Client服务不见了,为什么?因为还没配置他们登录到locahost:8761的账号密码,所以无法访问Eureka Server


配置两个Client账号密码,只要配置他们的application.yml即可,加上root:root@,表示访问localhost:8761/eureka/会自动以root,root为账号和密码登录

重新启动两个Client,然后刷新Eureka可视化界面,就出现了,这就是加上了安全验证的Eureka

五、Eureka的高可用


实际中就是宕机前已经输入localhost:8080/customer间接调用了localhost:8081/pay,那么在提供者一方会缓存调用执行的结果,即使Eureka宕机了,再运行localhost:8080/customer也还是有之前相同结果的,但是没有调用过,就不会有缓存,这样宕机就不会有结果。

如何保证高可用?那就是配置多个Eureka,就算宕机一台,还有其他的保证服务可用

我们现在来配两台Eureka,先全部stop停止

同样新建一个module,以maven创建,命名为eureka_server02,这里配置和eureka_server01一模一样,可以把eureka_server01内容都复制然后改改

1、pom.xml和server01的依赖一样
2、WebSecurityConfig不用改,直接复制
3、Server02Application除了名字不一样,和之前一样

4、eureka_server01的application.yml需要改下,也就是注册到8762的eureka上,eureka之间互相注册,实现数据同步,还有配置Eureka集群要把false变为true

eureka_server02的application.yml

两个Eureka Server就配置好了,并且能相互通信,保证数据同步

最后只要将两个Client注册到两个Eureka即可


重新启动四个

输入localhost:8761,另一个页面localhost:8762,登录后等几十秒,然后刷新才会同步,因为数据同步需要时间,同步后两个Eureka的服务一模一样,这样多个Eureka集群就能保证高可用,就算一个宕机了,其他也能使得Client服务正常进行


代码如下分享:
链接:https://pan.baidu.com/s/1-AZjb0-_ribbU_drIWL-Yw
提取码:6666

六、CAP定理

C(Consistency):一致性
A(Availability):可用性
P(Partition tolerance):分区容错性

一致性:不同服务器之间数据的一致性,也就是数据同步
可用性:客户端的请求能快速给出响应,这就是可用性好
分区容错性:不同地区的服务器因为网络延迟、信号传输等不可避免的因素,数据传输肯定是有微小延迟的,需要容忍这个微小误差。

以上三个特性在分布式环境下,无法都满足,只能满足两个,而且分区容错性P在分布式环境下必须满足,所以需要再A、C之间权衡

如果选择A,也就是AP组合,保证可用性,那么在一定时间内,可能几秒钟内,数据是不同步的,但是能保证很快响应

如果选择C,也就是CP组合,保证一致性,可能会造成系统在一定时间内是不可用的,因为使数据同步是需要时间的,可能时间太长,几分钟,造成的损失就巨大,比如双十一,用户不可能等几分钟加载。

Eureka选择的是AP组合保证高可用,所以开多个Eureka时,会感觉到,多个Eureka之间数据不会马上同步,通常需要等待十几秒或更长,然后刷新两个Eureka中注册的服务才会一致

下一篇:Ribbon

以上是关于SpringCloud学习--- Eureka详解(2021年10月最新_附代码包)的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud学习--- Ribbon详解

SpringCloud学习--- Ribbon详解

SpringCloud Eureka参数配置项详解

SpringCloud Eureka参数配置项详解(转)

SpringCloud - Spring Cloud Netflix 之 Eureka 控制台界面详解

实用篇SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud分布式