Spring Cloud(二):Eureka 服务注册中心

前言

服务治理

随着业务的发展,微服务应用也随之增加,这些服务的管理和治理会越来越难,并且集群规模、服务位置、服务命名都会发生变化,手动维护的方式极易发生错误或是命名冲突等问题。而服务治理正是为了解决这个问题,服务治理是微服务架构中最为核心和基础的模块,它主要实现各个微服务实例的自动化注册和发现

服务注册

在服务治理框架中,都会构建一个或多个服务注册中心。

每个服务模块向注册中心登记自己所提供的服务,将主机host、端口号、版本号、通信协议等一些附加信息告知注册中心,注册中心按服务名分类组织服务清单。

服务注册中心还需要以心跳的方式去监测清单中的服务是否可用,若不可用需要从服务清单中剔除,达到排除故障服务的效果。

服务发现

服务间调用不再通过指定具体实例地址来实现,而是通过向服务名发起请求调用实现。

服务调用方需要先从服务注册中心获取所有服务的实例清单,才能实现对具体服务实例的访问。

服务调用方在发起调用时,会以某种策略取出一个具体的服务实例进行服务调用(客户端负载均衡)。

在生产环境中为了考虑性能等因素,不会采用每次都向服务注册中心获取服务的方式,并且不同的应用场景在缓存和服务剔除等机制上也会采用不同的实现策略。

Spring Cloud Eureka

Spring Cloud Eureka 是基于 Netflix Eureka 来实现服务注册和发现的。它主要包括两个组件:

  • Eureka Server(服务端):服务注册中心,支持高可用配置,依托于强一致性提供良好的服务实例可用性,服务注册中心之间可以通过异步模式互相复制各自的状态。
  • Eureka Client(客户端):处理服务的注册与发现,客户端可以通过注解和参数配置的方式实现注册与发现,客户端向注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约,Eureka客户端从服务端查询当前注册的服务信息并把它们缓存到本地并周期性的刷新服务状态。

Eureka 基础架构

  • 服务注册中心(Eureka Server):服务端,提供服务注册和发现功能。
  • 服务提供者(Service Provider):提供服务的应用,将自己提供的服务注册到 Eureka Server,供其他应用发现。
  • 服务消费者(Service Consumer):消费者应用从 Eureka Server 获取服务列表,从而调用对应的服务(ribbon或者feign)。

基础架构图


image

image

快速搭建服务注册中心(Eureka Server)

1. 创建 Spring Boot 项目,添加依赖

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

    <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-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </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>

2. @EnableEurekaServer 注解启动服务注册中心

@SpringBootApplication
@EnableEurekaServer
public class SpringCloudEurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudEurekaServerApplication.class, args);
    }

}

3. 配置文件 application.properties

server.port=9999
#eureka
eureka.instance.hostname=127.0.0.1
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
  • eureka.client.register-with-eureka:当前应用为服务注册中心,所以设置为false,代表不向注册中心注册自己。
  • eureka.client.fetch-registry:注册中心的职责主要是维护服务实例,所以设置为false,代表不去检索当前应用的服务。
  • eureka.client.serviceUrl.defaultZone:用于与 Eureka Server 交互的地址,注册服务和发现服务都需要依赖这个地址。

4.启动应用,访问:http://127.0.0.1:9999/

可以看到 Eureka 的信息面板,其中 Instances currently registered with Eureka 中列表显示 No instances available,说明该注册中心还没有注册任何服务。


image

服务提供者(Service Provider)

1. 创建 Spring Boot 项目,添加依赖

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

    <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-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </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>

2. @EnableDiscoveryClient 注解启动 Eureka 客户端

@SpringBootApplication
//@EnableEurekaClient  该注解在采用eureka作为注册中心时使用,场景较为单一
@EnableDiscoveryClient //场景更为广泛
public class SpringCloudEurekaServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudEurekaServiceApplication.class, args);
    }

}

@EnableEurekaClient@EnableDiscoveryClient 在当前示例中使用效果好是一样的,@EnableEurekaClient 注解在采用eureka作为注册中心时使用,场景较为单一,@EnableDiscoveryClient 场景更为广泛。

3. 配置文件 application.properties

server.port=8888
spring.application.name=spring-cloud-eureka-service
#info 应用信息
info.app.name=spring-cloud-eureka-service
info.app.version=v1.0.0
info.app.description=spring-cloud-eureka-service
#eureka
eureka.instance.hostname=127.0.0.1
#每隔5s心跳一次,证明本服务还活着
eureka.instance.lease-renewal-interval-in-seconds=5
#本服务10s内没有心跳,就将该服务从服务端剔除
eureka.instance.lease-expiration-duration-in-seconds=10
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:9999/eureka/

  • eureka.instance.lease-renewal-interval-in-seconds:设置心跳间隔秒数
  • eureka.instance.lease-expiration-duration-in-seconds:设置秒数内无心跳,则剔除服务

4. 启动应用,访问:http://127.0.0.1:9999/

在服务注册中心的控制台中我们可以看到如下输出,说明服务被注册成功了。

 c.n.e.registry.AbstractInstanceRegistry  : Registered instance SPRING-CLOUD-EUREKA-SERVICE/192.168.101.201:spring-cloud-eureka-service:8888 with status UP (replication=false)

而在 Eureka 的信息面板上,在 Instances currently registered with Eureka 列表中同样可以看到服务的注册信息。如下图:

image

高可用注册中心(集群)

上面介绍了单节点模式的服务注册中心,不过在实际生产环境中,通常不会采用这种模式。在分布式系统中,服务注册中心是非常重要的组成部分,如果是单节点模式,发生故障的话将会是毁灭性的灾害。所以为了维护服务的高可用性,通常采用集群的解决方案。

Eureka 的服务治理设计中,所有的节点既是服务提供方,也是服务消费方,服务注册中心也不例外。Eureka 通过互相注册服务的方式,以实现服务清单的互相同步,达到高可用的效果。

双节点注册中心

  1. 搭建服务注册中心 A,配置文件如下:
server.port=9991
spring.application.name=eureka-server
spring.profiles.active=nodea
#eureka
eureka.instance.hostname=nodea
#设置微服务调用地址为IP优先(缺省为false)
#eureka.instance.prefer-ip-address=true
eureka.client.serviceUrl.defaultZone=http://nodeb:9992/eureka/
  1. 搭建服务注册中心 B,配置文件如下:
server.port=9992
spring.application.name=eureka-server
spring.profiles.active=nodeb
#eureka
eureka.instance.hostname=nodeb
#设置微服务调用地址为IP优先(缺省为false)
#eureka.instance.prefer-ip-address=true
eureka.client.serviceUrl.defaultZone=http://nodea:9991/eureka/
  1. 在 /etc/hosts(windows系统路径为 C:\Windows\System32\drivers\etc\hosts) 文件中添加 nodea 和 nodeb 的转换,如下:
127.0.0.1 nodea
127.0.0.1 nodeb
  1. 启动两个项目,分别访问http://nodea:9991/http://nodeb:9992/,我们可以看到两个节点都已经被注册,如下图所示:
image
  1. 搭建完多节点服务注册中心之后,服务提供者也需要做一些简单的配置,以上面的服务提供者为例,修改如下:
eureka.client.serviceUrl.defaultZone=http://nodea:9991/eureka/,http://nodeb:9992/eureka/

启动项目后,访问两个服务注册中心,我们看到服务被注册到这两个节点内。

image
  1. 这时我们关闭服务注册中心节点 A,我们可以看到服务注册中心节点 B 依然可以提供服务,而节点 A 从 available-replicas(可以分片) 变为 unavailable-replicas(不可用分片)。
image

服务消费者(Service Consumer)

使用 Ribbon 调用服务

1. pom 相关依赖配置
<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </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>

2. 配置文件 application.properties
spring.application.name=spring-cloud-ribbon-consumer
server.port=8081
eureka.client.serviceUrl.defaultZone=http://nodea:9991/eureka/,http://nodeb:9992/eureka/
3. 启动类配置

通过 @EnableDiscoveryClient 注解将应用注册为 Eureka 客户端,获得服务发现能力。

创建 RestTemplate 的 Spring Bean 实例用来调用服务。

通过 @LoadBalanced 注解来开启客户端的负载均衡。

@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudRibbonConsumerApplication {

    @Bean
    @LoadBalanced
    RestTemplate restTemplate(){
        return new RestTemplate();
    }
    
    public static void main(String[] args) {
        SpringApplication.run(SpringCloudRibbonConsumerApplication.class, args);
    }

}
4. ConsumerController 来实现服务调用
@RestController
public class ConsumerController {

    @Autowired
    RestTemplate restTemplate;
    
    @RequestMapping("/test")
    public String test() {
        return restTemplate.getForEntity("http://spring-cloud-eureka-service/test", String.class).getBody();
    }
}

spring-cloud-eureka-service 为服务注册中心的应用名称,大小写均可。

使用 Feign 调用服务

1. pom 相关依赖配置
<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </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>
2. 配置文件 application.properties
spring.application.name=spring-cloud-feign-consumer
server.port=8080
eureka.client.serviceUrl.defaultZone=http://nodea:9991/eureka/,http://nodeb:9992/eureka/
3. 启动类配置

通过 @EnableDiscoveryClient 注解将应用注册为 Eureka 客户端,获得服务发现能力。

通过 @EnableFeignClients 注解来启用feign进行远程调用。

@SpringBootApplication
@EnableDiscoveryClient//启用服务注册与发现
@EnableFeignClients//启用feign进行远程调用
public class SpringCloudFeignConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudFeignConsumerApplication.class, args);
    }

}
4. 实现服务调用接口
@FeignClient(name = "spring-cloud-eureka-service")
public interface TestService {

    @RequestMapping("/test")
    public String test();
}

spring-cloud-eureka-service 为服务注册中心的应用名称,大小写均可。

此接口中的方法和远程服务中contoller中的方法名和参数需保持一致。

5. ConsumerController 来实现服务调用
@RestController
public class ConsumerController {

    @Autowired
    private TestService testService;
    
    @RequestMapping("/test")
    public String test() {
        return testService.test();
    }
}

示例代码

github

码云

非特殊说明,本文版权归 朝雾轻寒 所有,转载请注明出处.

原文标题:Spring Cloud(二):Eureka 服务注册中心

原文地址: https://www.zwqh.top/article/info/28

如果文章有不足的地方,欢迎提点建议,后续会完善~

如果文章对您有帮助,请给我点个赞哦~

关注下我的公众号,文章持续更新中...

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

推荐阅读更多精彩内容