模拟实战(1) - 快速了解Eureka服务注册与发现、高可用安全注册中心

前言:本章是我记录的SpringCloud实战模拟业务场景系列第一篇,其主要讲解了SpringCloud各个服务之间是如何治理的,各个服务是如何注册到注册中心,是如何发现服务,以及高可用安全的服务注册中心架构模式。

一、项目骨架搭建、版本介绍


1、构建项目

因为是基于模拟实战业务场景,所以要先吧项目骨架搭建起来,这里我们采用maven来构建多模块父子依赖项目骨架,spring为我们提供了一个非常方便快速构建项目的工具 https://start.spring.io/ 进入网页后界面如下

image.png

因为我们需要构建SpringCloud依赖子模块项目结构,在 Dependencies 输入框中 输入cloud 选择 Cloud Bootstrap,然后构建并下载项目然后使用idea打开即可,打开后pom依赖如下

<?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">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging> 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springCloudExample</groupId>
    <artifactId>example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>example</name>
    <description>Demo project for Spring Boot</description>

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

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

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

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

</project>

2、版本介绍

现在我相信很多人应该有一些疑问,springboot和SpringCloud的关系倒是怎样的,他们的版本是如何对应的?为什么SpringCloud的版本不是数字形式的?,官网文档地址-> http://spring.io/projects/spring-cloud 一直滑到最底部如下图

image.png

至于为什么SpringCloud的版本不采用数字形式,这个就得去问springcloud的研发者们了。

二、Eureka介绍


网上对eureka介绍的文章有很多,这里我就不详细介绍了,主要围绕这几点来简单总结一下:

  • eureka能做什么?
    其实 eureka最主要的功能就两大点 服务注册服务发现
    eureka服务注册
    会将所有eureka的client端进行统一注册到eureka服务端,然后对所有注册了的客户端进行心跳检查并标记或者排除掉不可用的客户端。
    eureka服务发现
    eureka客户端会获取所有服务端已注册的服务信息,服务信息包括注册时候的服务名实际ip地址,而且eureka客户端结合Ribbon、或者Feign可直接使用服务名来对该服务进行请求调用。
  • 为什么需要eureka?
    至于为什么需要eureka呢,其实这个问题很简单,比方说我们这个模拟业务里面的商品服务,在实际的场景中我们可能会部署多个商品服务的实例,那么如果我们不采用注册中心的话,所有依赖商品服务的其他服务就必须在各自的配置里面配置商品服务的地址,然后再采用一些负载均衡的算法来对商品服务进行请求,并且也无法检测各个实例的存活情况,当然你也可以自己实现一套心跳机制... 好了 不说了 相信各位小伙伴应该已经能想到用eureka有多方便了,其实不止eureka可以做服务注册与发现 还有consul、zookeeper等,后续也会有专门的文章对其进行讲解。
  • eureka和其他同类产品优势是什么?
    这个疑问我相信也是大家比较想知道的,至于为什么服务注册与发现首选Eureka,而不用consul、zookeeper呢?
    在分布式系统领域我们始终摆脱不了CAP理论(C:一致性,A:服务可用性,P分区容错性),其中P是必须成立的,如果大家不清楚CAP理论的话,请自行google一下吧,这里就不再对其进行介绍了;eureka保证了AP,consul和zookeeper保证了CP。
    • 采用eureka作为服务中心,我们可以保证服务可用性,通俗点来讲就是如果往eureka服务集群的某个eureka服务节点进行注册的话,eureka不会强制将其全部都复制到集群中的其他节点上去,也不保证注册信息有没有复制成功,虽然说可能会出现各个eureka服务节点的数据不一致性问题,但这并不影响其正常使用,我们的业务服务可以对所有eureka服务节点都进行注册当有其他业务服务注册上来、或者业务服务注册信息有变化了,请求中一个eureka服务节点可能会查看不到最新的注册数据,但请求另一个eureka服务节点就能查看到最新的注册数据,也就是说eureka舍弃了 强一致性 来保证了整体eureka服务的 高可用性
      而且eureka还有一个特点,就是当出现一些网络问题导致eureka心跳机制响应的缓慢或者丢失心跳,eureka并不会马上吧这些暂时不可用的服务移除掉,而是会对暂时不可用的服务开启保护模式,但是如果持续多少秒后(默认90秒)还没有接收到该某些服务的心跳的话,则会吧对应服务移除掉。
    • 对比于consul、zookeeper来说,这两者更偏向于保证 数据的一致性 ,从而降低了 可用性;consul的服务注册相比 Eureka 会稍慢一些。因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功,而且当consul集群的Leader 挂掉时,重新选举期间整个 Consul集群是不可用的,所以其保证了强一致性但牺牲了可用性。zookeeper也是保证了CP,也就是说随便访问zookeeper集群的几个节点都能一致的数据,但是zookeeper并不能保证请求的 可用性 ,因为在一些特殊的极端场景,zookeeper会舍弃掉一部分请求,客户端需要重新请求才可能能获取到数据,而且zookeeper的master挂掉也需要重新选取新的master,并且这期间zookeeper集群是处于不可用状态的,而且最致命的就是,zookeeper的选举耗时会比较长,如果一单遇到网络波动,都会导致进行master的选举,从而增加zookeeper的不可用时间。

总的来说Eureka更加符合服务注册、发现的场景,虽然说现在Eureka2.x闭源了,但是Eureka1.x目前还是有很多大公司在商用了,而且最主要的服务注册与发现功能也得到了很多用户的证实,所以对于后续只是单纯的做服务注册与发现的话 Eureka至少还是个不二的选择,当然为了更长远的考虑,或者不只是单纯的想要服务注册于发现功能的话,也可以使用consul来搭建服务注册中心,并且consul还支持K-V键值对存储以及其他扩展功能;但是zookeeper的话,因为其中一些特性个人觉得还是不太适合做服务注册中心。

二、eureka服务端、客户端搭建 (单机版)


eureka服务端

打开刚才下载的骨架,创建一个 eureka-server module,并添依赖

<?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>example</artifactId>
        <groupId>com.springCloudExample</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>eureka-server</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
       
    </dependencies>
</project>
1、yml配置文件

在resource资源文件夹下创建application.yml配置文件,内容如下

spring:
  application:
    name: eureka-server
server:
  port: 8761
eureka:
  client:
    register-with-eureka: false #不去eureka服务注册信息,因为本身就是eureka server,除非需要eureka集群
    fetch-registry: false #是否从eureka服务获取注册表信息,默认为true,因为是单eureka server 不存在别的eureka服务 所以不需要开启
2、eureka-server启动类
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
 * @Description
 * @Author Joey
 * Date 2019/3/3 下午2:16
 * Version 1.0.0
 **/
@SpringBootApplication
@EnableEurekaServer //开启Eureka服务端
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

eureka客户端

这里的eureka我们就先拿模拟业务场景中的 用户服务、商品服务 来作为eureka客户端;先创建两个module,user-server、goods-server , pom依赖如下

    <dependencies>
        <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> 
1、user-server、goods-server yml配置
spring:
  application:
    name: provider-user-service #服务名称
server:
  port: 8001
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/ #eureka注册地址,默认注册地址也是这个
   instance:
    prefer-ip-address: true #将自己的ip注册到eureka 服务,如果为false 则将hostname注册到eureka服务

goods-server的话 配置类似,将服务名,端口号改一下即可。

2、user-server、goods-server 启动类
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
 * @Description
 * @Author Joey
 * Date 2019/3/3 下午2:16
 * Version 1.0.0
 **/
@SpringBootApplication
@EnableEurekaClient //标记为Eureka客户端
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

启动测试

为了方便起见,我们不采用打包的形式运行,直接在idea里面配置多个run,并且设置Xms,Xmx参数来限制一下堆空间,这样即使我们的电脑内存不大也能运行很多个服务,并不会占用太多的内存。


image.png
添加一个springboot run
image.png
配置启动类
image.png
限制内存大小
image.png
启动所有服务

image.png

查看 http://localhost:8761/ 可看到eureka管理界面,可以看到两个eureka客户端已经成功的注册了
image.png

三、eureka高可用、安全问题


当然,上面都是基于eureka单节点来的,在实际的生产环境中我们是不可能只有一台注册中心,而且目前eureka服务是没有任何安全措施的,也就是说谁都可以来进行注册以及做一些其他的操作,接下来将进行eureka服务改造为安全的高可用集群。

eureka-server 增加如下依赖
    <!--整合 spring security 用于设置注册到eureka服务的 用户名和密码-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
eureka-server 增加spring Security配置文件

springBoot 2.x后 security默认开启了 csrf校验,在eureka进行 安全注册的时候 需要关闭

package com.example;
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;
/**
 * @Description spring SecurityConf配置类
 * @Author Joey
 * Date 2019/1/27 下午2:48
 * Version 1.0.0
 **/
@EnableWebSecurity
public class SecurityConf extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable(); //关闭csrf校验
        super.configure(http);
    }
}
eureka-server yml配置文件改为如下

eureka服务高可用 其实就是把自己注册到别的eureka服务上,从而达到相互注册高可用的目的,并且也会将各自的注册表进行同步

所以在这里我们要准备多个profile, 启动的时候 只需要指定不同的profiles配置即可;完成eureka安全配置还差一步,就是设置spring security的用户名和密码,因为后续所有服务进行注册以及其他操作都需要用户名与密码进行basic验证。

spring:
  application:
    name: eureka-server
  security:  #springBoot2.X 默认就开启了 http basic认证, 网上大部分都停留在springboot以前的版本配置开启 basic认证
    user:
      name: user #用户名
      password: 123 #密码

---
server:
  port: 8761
spring:
  profiles: eureka1
eureka:
  client:
    service-url:
      #注册需要加上用户名密码  格式为 http://用户名:密码@地址:端口;注册多个可用 , 隔开
      defaultZone: http://user:123@localhost:8762/eureka/,http://user:123@localhost:8763/eureka/
    instance:
      prefer-ip-address: true

---
server:
  port: 8762
spring:
  profiles: eureka2
eureka:
  client:
    service-url:
      defaultZone: http://user:123@localhost:8761/eureka/,http://user:123@localhost:8763/eureka/
    instance:
      prefer-ip-address: true


---
server:
  port: 8763
spring:
  profiles: eureka3
eureka:
  client:
    service-url:
      defaultZone: http://user:123@localhost:8761/eureka/,http://user:123@localhost:8762/eureka/
    instance:
      prefer-ip-address: true

修改一下run config,添加多个eureka-server的run,并且分别指定不同的profiles


eureka 客户端修改

客户端只需要将defaultZone配置参数改一下即可,其他参数不变;而且defaultZone注册地址注册一个就好了,eureka会进行同步到其他eureka服务,但是为了避免在极端网络环境下可能会出现问题,这里建议将所有eureka服务都进行注册。

service-url:
      defaultZone: http://user:123@localhost:8761/eureka/,http://user:123@localhost:8762/eureka/,http://user:123@localhost:8763/eureka/
测试

启动所有eureka-server和客户端,随便打开一个eureka-server端输入用户名密码进入即可看到注册信息。


image.png

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

推荐阅读更多精彩内容