SpringCloud(一)

一.简介

1.SpringCloud

SpringCloud是一套微服务开发一站式解决方案,它提供了微服务开发所需要的很多功能组件,
比如服务统一管理、配置统一管理、路由网关、断路器、事件总线、集群状态配置等等。而且
SpringCloud与SpringBoot无缝衔接,配合SpringBoot能够更轻松的搭建出一套微服务架构平
台。

2.微服务

微服务其实是一种架构的设计风格,并没有明确的技术绑定和架构概念。简单来说,微服务架构
风格其实就是将原来的单一架构开发为一组小型服务(微服务)的方法,每个服务都运行在自己
独立的进程中(服务间的隔离),服务间采用轻量级的通讯机制(HTTP、RPC - Netty、 WebService),这些服务按照业务拆分,并且独立部署(自动化部署)。服务会由一个统一的管
理中心管理(Zookeeper、Eureka、Nacos),服务可以采用不同的语言开发,并且使用不同
的存储技术(数据库垂直拆分)。

二.服务的注册与发现--Eureka

1.注册中心

注册中心的作用就是为了减少服务间的调用耦合

2.Eureka

(1)Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。
(2)Eureka包含两个组件:Eureka Server和Eureka Client。
(3)Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
(4)Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就是一个内置的、使用轮询(round-robin)负载算法的负载均衡器。
(5)在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。

3.Eureka 对比 Zookeeper

(1)zookeeper可以独立运行,但是Eureka不可以独立运行,需要依赖web服务,tomcat
(2)zookeeper的分布式服务中存在着角色的关系,有服务的提供者与消费者,但是Eureka每个微服务既是消费者,也是服务的提供者.


zookeeper与Eureka的区别

4.Eureka服务端的搭建

(1)配置自定义的父工程(继承SpringBoot、SpringCloud)

<?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>
    <packaging>pom</packaging>
    <modules>
        <module>springcloud_Eureka</module>
        <module>springcloud_microservice_student</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>nz.study</groupId>
    <artifactId>springcloud_demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
<!--    <name>springcloud_demo</name>
    <description>Demo project for Spring Boot</description>-->

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR5</spring-cloud.version>
    </properties>

    <!-- 相当于让当前得工程继承了SpringCloud的父工程,用这种方式可以实现Maven的多继承 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <!--导入pom工程,相当于多继承-->
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- 只有微服务才要依赖<build> -->
<!--    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>-->

</project>

(2)创建Eureka服务

1)创建一个Maven工程(Eureka微服务),继承自定义的父工程(springcloud_demo)
2)修改当前maven工程的pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud_demo</artifactId>
        <groupId>nz.study</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud_Eureka</artifactId>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
3)配置当前springboot的启动类
package nz.study.application;

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

        //run方法的第一个参数是添加了@SpringBootApplication注解的类
        //不是当前类
        SpringApplication.run(EurekaServerApplication.class,args);
    }
}
4)配置application.yml
server:
  port: 20000
spring:
  application:
    #配置微服务的名称,以后所有的微服务,都必须配置这个属性,不然注册中心的名称会变成unable
    name: eureka-server
#配置eureka的相关属性
eureka:
  client:
    service-url:
    #配置eureka的注册地址
    #defaultZone没有提示,必须手写
      defaultZone: http://eureka1:20000/eureka,http://eureka2:20001/eureka,http://eureka3:20002/eureka
    #当前的微服务就是注册中心,注册中心不能从注册中心抓取服务,所以该配置需要配置成false
    fetch-registry: false
    #使得当前微服务不注册到注册中心
    register-with-eureka: false
5)启动SpringBoot工程 - 启动Eureka服务端
6)访问注册中心,http://localhost:20000

5.微服务(Eureka客户端)的搭建

(1)Eureka客户端的搭建

  • 创建一个Maven工程,继承springcloud_demo工程
  • 配置Maven工程的pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud_demo</artifactId>
        <groupId>nz.study</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud_microservice_student</artifactId>

    <dependencies>
        <!-- 微服务需要对外提供功能,所以需要添加web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 同时为了能够让微服务注册到注册中心上 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

    <!-- 打包插件,不写不影响运行,但是打包会出问题 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  • 配置启动类
package nz.study.student;

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

@SpringBootApplication(scanBasePackages = "nz.study")
//springcloud 2.x 之后 该注解可以省略
@EnableEurekaClient
public class StudentApplication {
    public static void main(String[] args) {
        SpringApplication.run(StudentApplication.class,args);
    }
}
  • 配置application.yml
server:
  port: 8080
#微服务的名称
spring:
  application:
    #特别注意:微服务的名称一定不要用下划线
    name: micro-student
eureka:
  client:
    service-url:
      #配置注册中心的地址,因为微服务需要注册,也需要抓取服务所以另两个配置默认为true,可以不用配置.
      defaultZone: http://localhost:20000/eureka
  • 编写微服务的功能接口(根据微服务本身的业务不同,编写不同的接口)
package nz.study.controller;

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

@RestController
@RequestMapping("/stu")
public class StuController {

    /**
     * 根据学生id查询学生姓名
     *
     * @RequestBody -> 返回json (×)
     *
     * @RequestBody -> 将方法的返回值,放入response响应体中
     *
     * 响应体 -> 数值,字符串(json),二进制流,...
     *
     * @param sid
     * @return
     */
    @RequestMapping("/queryName")
    public String getNameById(Integer sid){
        switch (sid){
            case 1:
                return "小红";
            case 2:
                return "小明";
            case 3:
                return "小刚";
            default:
                return "查无此人";
        }
    }
}

三.Eureka集群(伪)

1.eureka集群的工作模式

eureka集群的工作模式

2.Eureka集群的搭建(伪集群)

1)将eureka服务端复制2份
2)修改eureka服务的端口(因为是伪集群,在一台机器上,需要修改端口)
3)找到本机的hosts文件(C:\Windows\System32\drivers\etc\hosts),分别给本机设置3个主机名


设置主机名

注意:第一次修改hosts文件,一般没有权限,所以需要修改下文件权限。
4)修改3个eureka服务的service-url配置

server:
  port: 20002
spring:
  application:
    #配置微服务的名称,以后所有的微服务,都必须配置这个属性,不然注册中心的名称会变成unable
    name: eureka-server
#配置eureka的相关属性
eureka:
  client:
    service-url:
    #配置eureka的注册地址
    #defaultZone没有提示,必须手写
      defaultZone: http://eureka1:20000/eureka,http://eureka2:20001/eureka,http://eureka3:20002/eureka
    #当前的微服务就是注册中心,注册中心不能从注册中心抓取服务,所以该配置需要配置成false
    fetch-registry: false
    #使得当前微服务不注册到注册中心
    register-with-eureka: false

5)启动三台eureka服务
6)所有的微服务的注册地址必须改成eureka集群的地址

server:
  port: 8080
#微服务的名称
spring:
  application:
    #特别注意:微服务的名称一定不要用下划线
    name: micro-student
eureka:
  client:
    service-url:
      #配置注册中心的地址,因为微服务需要注册,也需要抓取服务所以另两个配置默认为true,可以不用配置.
      defaultZone: http://eureka1:20000/eureka,http://eureka2:20001/eureka,http://eureka3:20002/eureka

四.Eureka的自我保护机制

1.自我保护机制

Eureka如果收到的微服务心跳相对于应该收到的微服务心跳来说,如果低于了85%,那么就会触
发Eureka的自我保护机制。一旦自我保护机制启动,Eureka会保护所有的微服务,不被移除,哪
怕当前微服务已经下线,仍然会保留到Eureka微服务列表中。

2.Eureka自我保护机制触发后的表现

自我保护机制的表现

3. 自我保护机制的作用

(1)为什么Eureka要一种看起来如此傻逼的设计?- 自我保护机制是为了保证微服务间的高可用性,
避免脑裂的影响
(2)为什么Zookeeper要设计一个过半数存活原则?感觉特别浪费资源? - 为了让整个集群一定只有
一个Leader
(3)CAP原则:任何一个分布式系统,都只能满足CAP中的2个原则,因为分区问题不可避免,所以P
是必选的,一般的系统,都是从C和A中做选择。Zookeeper是CP设计,而Eureka是AP设计。
C(一致性)
A(可用性)
P(分区容错性)

4.zookeeper的过半数存活的设计

zookeeper的过半数存活的设计

5.Eureka的自我保护设计

Eureka的自我保护设计

6.总结

自我保护机制一旦启动,确实会保护那些真的出问题的微服务,所以Eureka设计了一个阈值,当
15%的心跳都丢失的时候,才会发生自我保护机制。因为这个时候,相对于15%的机器挂掉来
说,发生脑裂的概率大一些。但是有没有可能真的是15%机器挂掉了?这个时候Eureka是不能帮
我们判断的,需要客户端本身有一定的容错机制,比如断路器

7.在实际项目中,到底是AP设计好,还是CP设计好?

取决于业务,对于注册中心来说,偶尔拿到出问题的微服务,其实对于整个架构来讲没有太大问题,微服务架构最害怕整个注册中心服务不可用,因此对于注册中心来说,AP(高可用)设计强于CP(一致性)设计。并不是说一致性不好,对于分布式锁的业务来讲,一定要CP,不然整个集群的业务会混乱.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343