• Spring Cloud 详细入门系列(一)


    在入门前,第一件事是了解全貌。

    首先,让我们先大概知悉 Spring Cloud 能为我们做到什么。

    从官网、各类博客、以及相关技术类论坛中提炼了下述比较关键的作用,这也是它大放异彩的基本要素:

    1. 微服务框架,提供全套的分布式系统解决方案,比较传统的技术,会更加稳定且具有容错性;
    2. 只作集成封装(挺多开源框架与组件,包括对 SpringBoot 的深度集成,继承了其优秀的“约定大于配置”,能通过注解以及 yml 进行配置)
    3. 对开发者友好,十分容易上手,如配置、断路机制、选举、分布式 session、状态管理等常规处理提供了简便的操作,便于上手。
    4. 对 IDE 其实也友好,只要支持 Spring Boot,基本上也能开发 Spring Cloud,例如我的 VsCode 就可以进行使用。

    第三点最为重要,决定了这项技术是否是通用的,或者是仅适用小部分组织,目前来看,它甚至适用于个人开发。

    了解 Spring Cloud 的基础概念「重要」

    截至至此随笔的发布日期,目前的Spring Cloud有着下述的基本概念,先尝试理清楚它们之间的关系,然后逐个实践,这样有助于你继续了解此框架。

    • EureKa(服务注册与发现)
    • Config(分布式统一管理配置)
    • Zuul(服务网关)
    • Ribbon(客户端负载均衡器)
    • Feign(声明 Web 服务客户端)
    • Hystrix(断路器「熔断器」

    上述概念仅需记忆中文即可,因为除了核心服务外,其余都是类似于积木的存在,是可被替换的,例如服务网关 Spring Cloud Zuul,也可能被替换为 Spring Cloud Gateway,故此特别说明;

    嗯。。怎么说呢,积木的形状是确切的,但是颜色我们管不着,所以只需要记住形状就可以。

    那么,它们之间的关系是怎样的呢?

    Spring Cloud for Microservices Compared to Kubernetes | Red Hat Developer

    图来自网络,大概讲解一下:

    整体来说,就像是一个有序的机构:既有招待 client 的服务员,指引他们到各个分工明确的窗口办理业务,也有保安针对某窗口排队人数过多的情况进行处理,比如让新来的人先去其它窗口,这个窗口先不开放。。

    而这个机构的名字就叫做“服务注册与发现”,内部是各类服务,有序且分工明确。机构之间能产生互动,即集群,在此篇随机也有提及,如双注册服务中心,当然你也能套娃,三个四个五个也是看你需求了。

    现在你不会发懵了吧,起码了解了大概的流程、以及 Spring Cloud 究竟是干啥的,如果不了解,请先放下你的中指,然后再多看一遍。

    开始实践:服务注册与发现

    ps:其余本篇不介绍,接下来也仅有 EureKa 的实践和说明,比如双注册,多注册的形式,假设你想了解网关之类的其它“积木”,那么你打开错随笔了,可以看看首页是否有此系列的续篇,如果没有的话就下次一定。

    笔者仅学习了半天,并实践完成,过程中一次通过,花了些时间写了随笔,如果有错误麻烦你在评论区留言,我会进行修改。

    在开始之前,你应该时刻注意“版本号”的依赖,事实上,学习的开始最应该注意的就是这些细节了,否则你一定会遇到报错。

    另外,已经假设你初始化了 Spring Boot 的框架环境,通常各种 IDE 都具备新建 Spring Boot 项目。

    可进入官网查看粗略的依赖情况,每个版本号又会细分很多种,可以选择相邻日期来推测合适的依赖。

    https://spring.io/projects/spring-cloud

    我的 VsCode 会显示相应的发布日期,这能有效地提示依赖情况:

    此篇文章所使用的依赖为:Spring Boot 2.3.12.RELEASE,对应 Spring Cloud Hoxton.SR12,其依赖如下:

    <?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>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.3.12.RELEASE</version>
    		<relativePath/> <!-- lookup parent from repository -->
    	</parent>
    	<groupId>com.dome</groupId>
    	<artifactId>backend</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>backend</name>
    	<description>Demo project for Spring Boot</description>
    
    	<!-- 指定 JDK 版本 -->
      <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
      </properties>
    
    	<dependencies>
          <!-- 框架类 -->
    	  <dependency>
    	    <groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    	  <dependency>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-devtools</artifactId>
    		<scope>runtime</scope>
    		<optional>true</optional>
    	  </dependency>
          <dependency>
    	    <groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-configuration-processor</artifactId>
    		<optional>true</optional>
    	  </dependency>
    	  <dependency>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-test</artifactId>
    		<scope>test</scope>
    	  </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aspects</artifactId>
          <version>4.3.9.RELEASE</version>
        </dependency>
        <!--引入springcloud的euekea server依赖-->
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    	</dependencies>
    
      <!-- 指定下载源和使用 SpringCloud 版本 -->
      <dependencyManagement>
        <dependencies>
          <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR12</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
        </dependencies>
      </dependencyManagement>
    
    </project>
    

    搞定依赖关系后,就可以进入下一步操作,此时你的项目结构大致有以下几个关键文件:

    • ApplicationStartup.java (包含用于启动应用的主函数,名称不必在意,随便敲的)
    • pom.xml(依赖管理)
    • application.yml(应用配置)

    上述三个文件是最为重要的核心部件,它们分别在:

    • ApplicationStartup 放置在 src/main/java/com/dome/backend 目录下,当然这个是IDE生成的,我只是举个例子,IDE 对此文件命名可能为:BackendApplication.java ——假设你的命名空间最后是 backend 的话。
    • pom.xml 通常在项目的根目录,与 src 同级
    • application.yml 通常可新建文件夹并纳入编译区供程序使用,而大部分 IDE 会默认于 src/resources 目录下放置

    了解完关键文件后,接下来,我们仅需对它们进行简单的处理(pom.xml 略,上面有了),就可以得到一个 Spring Cloud 的基本结构了。

    pom.xml 处理完毕后,IDE 会自动下载依赖 jar 包,所以你可以直接在 .java 文件中直接引用,所以,让我们先从 ApplicationStartup.java 文件(强调,可能为其它名字,不信你看看上述说明)开始吧。

    对此启动类的处理,仅需加上一行代码即可。

    package com.dome.backend;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer
    public class ApplicationStartup {
    
    	public static void main(String[] args) {
    		SpringApplication.run(BackendApplication.class, args);
    	}
    
    }
    

    是的,相比较 IDE 为 SpringBoot 生成的启动类代码,仅多加了注解:@EnableEurekaServer

    那么这个注解有什么作用呢?好问题,篇幅过长,不想解释,大概理解为:

    它的作用是一个标识,同理,还有一个叫做 @EnableEurekaClient,另外的作用是,它会调用数个类,比如 EurekaServerAutoConfiguration、EurekaServerInitializerConfiguration,前者用于配置,如其中的方法:@ConditionalOnBean({Marker.class}) 去装载适用于 Eureka 服务端主要功能的 Bean,后者主要是初始化 EureKa 的实现类,以生命周期回调方法去初始化 EureKa。

    只是粗略了解,所以有错误你可以指出,我会记录并改掉此问题。

    接下来配置 yml,如下:

    server:
      port: 8080
    
    eureka:
      client:
        # 是否要将本身注册至 EureKa Server 上,默认为 true,但是当前我们不是使用集群,本身即为服务,故设置为 false
        register-with-eureka: false
        # 是否从 EureKa Server 中获取注册信息,默认为 true,很遗憾,本身即为服务,并不需要从其它 EureKa Server 节点同步信息,故设置为 false
        fetch-registry: false
        service-url:
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      instance:
        hostname: node1
    
    spring:
      application:
        # 本应用名称,集群时,此处较为重要
        name: eureka-server
      profiles:
        active: node1

     该注释的都注释了,就讲一下 ${eureka.instance.hostname} 之类的吧,你可以理解为,它会自动地到配置文件中寻找对应的节点里的值进行读取,具体就不讲解了,你也可以换成 http://node1:8080/eureka/

    其次是 node1 是什么呢?好问题,其实在同一台机器上,ip 地址是固定的(127.0.0.1),假设你使用了双节点服务注册与发现的话,那你就用不了副本了,具体情况可以在其余博客中找到,篇幅问题不作讲解,仅贴结果:

    你可以看见,即便注册了,也是不可用的。 

    这就是使用相同ip,不同端口的配置,且适配了使用 IP 的形式:prefer-ip-address: true,但是如果有多台服务器,使用 ip 应该是较为理想的方案(没试过,若有实践可以在评论区给大家参考噢)。

    所以,你需要在 hosts 文件中进行下述配置:

    127.0.0.1 node1
    127.0.0.1 node2

    node2 是为了下文作铺垫,可以先配置,当然你愿意的话,也能加到 node[N],例如 node123456789

    完成上述配置后,就可以启动你的应用程式了!

    接下来,在浏览器输入:node1:8080,就能看到下述界面:

    你已经掌握了 Spring Cloud EureKa 服务注册与发现的基本流程,接下来我们将尝试多注册中心的集群配置

    Spring Cloud 已经帮我们做到最简化了,这也是它的优势,也是开发者们乐于见到的,没有人会拒绝简单而有效的事物,不是吗?

    OK,将你的源码复制一份,第一份(原先)命名为 EureKa-1,当然你也可以按自己的喜好命名,第二份命名为 EureKa-2。

    接下来,你只需要改动 application.yml 配置文件即可,简单几行变动就可以达到集群的目的。

    Eureka-1 的 yml 如下:

    server:
      port: 8080
    
    eureka:
      client:
        # 是否要将本身注册至 EureKa Server 上,默认为 true,两个以上为团伙作案,故为 true
        register-with-eureka: true
        # 是否从 EureKa Server 中获取注册信息,默认为 true,两个以上为团伙作案,故设置为 true
        fetch-registry: true
        service-url:
          defaultZone: http://node2:8081/eureka/
      instance:
        hostname: node1
    
    spring:
      application:
        # 本应用名称,集群时,此处较为重要
        name: eureka-server
      profiles:
        active: node1

    EureKa-2 的 yml 如下:

    server:
      port: 8080
    
    eureka:
      client:
        # 是否要将本身注册至 EureKa Server 上,默认为 true,两个以上为团伙作案,故为 true
        register-with-eureka: true
        # 是否从 EureKa Server 中获取注册信息,默认为 true,两个以上为团伙作案,故设置为 true
        fetch-registry: true
        service-url:
          defaultZone: http://node1:8080/eureka/
      instance:
        hostname: node2
    
    spring:
      application:
        # 本应用名称,集群时,此处较为重要
        name: eureka-server
      profiles:
        active: node2

    在双注册的情况下,你会发现仅仅变动了三个属性就可以达到“团伙作案”的效果,至于为什么如此,你可以先实践后再接着往下看,先上一张效果图:

    嗯,可以看见底部的 registered-replicas 以及 available-replicas 是有内容的,说明它们互相注册成功了,至于 matrix2 ,只是我把 node 换成了计算机名 matrix 而已,先不必管这些细节。 

    接下来,你仅需了解 yml 中的 defaultZone 属性即可,其它几个都进行备注了,不过你也可以通过搜索引擎(比如 Bing,Google)了解,何况我还有注释

    那么,defaultZone 属性,是什么作用呢?答案是:注册 EureKa 的地址,假设有多台,那么你需要以“,”(英文逗号)隔开

    例如 A 服务器注册到 B、C、D 服务器,而 B 服务器注册到 A、C、D 服务器中

    假设 A 宕机了,那么并不会影响到 B 服务,因为 B 服务还注册了 C 、D,即便 C、D 都崩了,还有 B 自身,它自己也是一个服务。

    让我们模拟一下双注册服务下,其中一个崩掉的情况:

    可以看到,未停机的 EureKa-2 会每隔一定的时间段尝试连接停机的 EureKa-1,接下来,我们打开界面看看(EureKa-1):

    如期所料,无法访问,那么我们转而去 EureKa-2 的界面看看:

    正常使用,但 EureKa-1 被移到不可用中。那么,接下来的流量请求,就都会压到 EureKa-2 这个服务了,这也是集群的好处,一台崩了,还有另外一台顶着不是吗?

    但是这样未免。。太过暴力,假设最后一台没了,是不是就会损失客户了呢?肯定是有解决方案的,所以,敬请期待此系列后续讲解~

    至此,你掌握了什么?

    • Spring Cloud EureKa 服务注册与发现的基本流程
    • 多注册中心集群配置的基本要素

    写于 2021-07-13

    坐标:广州

    转载请联系博主,否则视为侵犯著作权,或者留下转载地址(http://www.cnblogs.com/chongsaid),我发至网络仅为分享(发现数篇文章被翻译了五六种外国语言了,有些需要充值才能解锁),勿当作牟利的工具噢。

  • 相关阅读:
    HDOJ 1028 母函数分析
    尼姆博弈的典型例题
    HDOJ1232 畅通工程 DFS
    第一个八皇后
    HDOJ 1242
    我的“插入算法”实现
    第五讲 this 类变量 类方法
    我的“二分查找算法”实现
    我对锤子ROM 功能的看法——视觉篇
    第六讲 Java 四大特性:抽象 封装 继承 多态
  • 原文地址:https://www.cnblogs.com/chongsaid/p/spring-cloud-1.html
Copyright © 2020-2023  润新知