疯狂SpringCloud微服务架构实战 (Eureka -- 服务注册中心)

本文详细介绍了Eureka作为SpringCloud的服务注册中心,包括Eureka的介绍、架构、服务器端和客户端的工作原理。通过创建Eureka服务注册中心、服务提供者和调用者实例,阐述了如何配置和运行Eureka集群,实现服务的注册、心跳维持、服务发现和调用。
摘要由CSDN通过智能技术生成

一、Eureka介绍

Eureka 提供了基于 REST 的服务,在集群中主要用于服务管理。Eureka提供了基于Java语言的客户端组件,客户端组件实现了负载均衡的功能,为业务组件的集群部署创造了条件。使用该框架,可以将业务组件注册到 Eureka 容器中,这些组件可以进行集群部署,Eureka 主要负责维护这些服务的列表,并自动检查它们的状态。

二、Eureka 架构

一个简单的 Eureka 集群,需要一个 Eureka 服务器、若干个服务提供者;可以将业务组件注册到 Eureka 服务器中,其他客户端组件可以从 Eureka 服务器获取,并且进行远程调用。

Eureka 架构图

       例如以上的 Eureka 架构图中有两个服务器,服务器支持集群部署,每个服务器也可以作为对方服务器的客户端进行相互注册与复制。图中的三个 Eureka 客户端,其中的两个用于发布服务,另一个用于调用服务;不管是服务器还是客户端,都可以部署多个实例,这样一来,就很容易构建高可用的服务集群。

三、服务器端

       对于注册到服务器端的服务注解,Eureka 服务器并没有提供后台的存储,这些注册的服务实例被保存到内存的注册中心,它们通过心跳来保持其最新状态,这些操作都可以在内存中完成。客户端存在着相同的机制,同样在内存中保存了注册表信息,这样的机制提升了 Eureka 组件的性能,每次服务的请求都不必经过服务器端的注册中心。

四、服务提供者

       作为 Eureka 客户端存在的服务提供者,主要进行以下工作:

              第一,向服务器注册服务;

              第二,发送心跳给服务器;

              第三,从服务器端获取注册列表;

       当客户端注册到服务器时,它将会提供一些关于自己的信息给服务器端,例如自己的主机、端口号、健康检测连接等。

五、服务调用者

       对于发布到 Eureka 服务器的服务,服务调用者可对其进行服务查找与调用,服务调用者也是作为客户端存在的,但其职责主要是发现与调用服务。在实际情况中,有可能出现本身既是服务提供者、又是服务消费者的情况,例如在传统的企业应用三层架构中,服务层会调用数据访问层的接口进行数据操作,它本身也会提供服务给控制层使用。

六、实践案例

1. 创建Maven项目:crazyspringcloud-firsteureka-server,作为 Eureka 服务注册中心:

    (1)  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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sztxtech.creazyspringcloud</groupId>
    <artifactId>crazyspringcloud-firsteureka-server</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>crazyspringcloud-firsteureka-server</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

        说明:pom中引入 spring-cloud-starter-eureka-server 依赖,将会自动引入spring-cloud-starter-web、spring-cloud-starter-ribbon,因此只要加入此依赖,项目就具有了 Web 容器的功能及负载均衡能力。spring-cloud-starter-eureka-server 的依赖关系如下图所示:

    (2)  启动类代码内容:

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

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

        说明:①  @SpringBootApplication:SpringBoot注解,包含了 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解;

                   ② @EnableEurekaServer:通过该注解声明这是一个Eureka服务器;

    (3)  项目主配置文件 application.yml 内容:

server:
  port: 8761

eureka:
  client:
#    配置是否将自己的信息注册到Eureka服务器,默认值是true
    register-with-eureka: false
#    配置是否到Eureka服务器中获取信息,默认值是true
    fetch-registry: false

        说明:服务器注册开关:

        ① eureka.client.register-with-eureka: false ==> 是否将自己的信息注册到Eureka服务器,默认值是true;

        ① eureka.client.fetch-registry: false ==> 是否到Eureka服务器中获取信息,默认值是true;

        若设置为 true,或者不对注册开关进行设置,默认是打开的 (默认值都是true) ,在启动时会报错两个异常:

com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect
    ...
    at com.netflix.discovery.DiscoveryClient.getAndStoreFullRegistry(DiscoveryClient.java:1013)     [eureka-client-1.6.2.jar:1.6.2]
	at com.netflix.discovery.DiscoveryClient.fetchRegistry(DiscoveryClient.java:927) [eureka-client-1.6.2.jar:1.6.2]
	at com.netflix.discovery.DiscoveryClient.<init>(DiscoveryClient.java:408) [eureka-client-1.6.2.jar:1.6.2]
	at com.netflix.discovery.DiscoveryClient.<init>(DiscoveryClient.java:266) [eureka-client-1.6.2.jar:1.6.2]
	at com.netflix.discovery.DiscoveryClient.<init>(DiscoveryClient.java:262) [eureka-client-1.6.2.jar:1.6.2]
    ...
Caused by: java.net.ConnectException: Connection refused: connect
    ...

        并且即便是报异常了,但还是保持启动,并没有因异常而关闭。这是由于在服务器启动时,服务器会把自己当作一个客户端去注册到 Eureka 服务器,并且会到 Eureka 服务器上获取注册信息,它本身只是一个服务器,而不是服务的提供者 (客户端) 。

2. 创建Maven项目:crazyspringcloud-firsteureka-server-provider,作为服务提供者:

    (1)  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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sztxtech.creazyspringcloud</groupId>
    <artifactId>crazyspringcloud-firsteureka-server-provider</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>crazyspringcloud-firsteureka-server-provider</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <!-- 分布式配置中心组件 -->
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

    (2)  项目主配置文件 application.yml 内容:

server:
  port: 9001

spring:
  application:
    name: firsteureka-server-provider

eureka:
  instance:
    hostname: localhost
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

    (3)  创建Controller类,并提供简单的 REST 服务:

import com.sztxtech.creazyspringcloud.entity.Person;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FirstController {
    @RequestMapping(value = "/person/{personId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Person findPerson(@PathVariable("personId") Integer personId) {
        Person person = new Person();
        person.setId(1032295);
        person.setName("侨星然");
        person.setAge(26);

        return person;
    }
}

    (4)  启动类代码内容:

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

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

        说明:@EnableEurekaClient 注解用于声明该应用是一个 Eureka 客户端;

    (5) 运行、测试:

启动服务器 crazyspringcloud-firsteureka-server 确认运行正常后启动客户端 “服务提供者” ,若正常启动,在服务器项目的控制台可以看到注册服务的信息:

2020-06-06 19:41:33.066  INFO 4188 --- [nio-8761-exec-6] c.n.e.registry.AbstractInstanceRegistry  : Registered instance FIRSTEUREKA-SERVER-PROVIDER/DESKTOP-GavinLee:firsteureka-server-provider:9001 with status UP (replication=false)
2020-06-06 19:41:33.687  INFO 4188 --- [nio-8761-exec-8] c.n.e.registry.AbstractInstanceRegistry  : Registered instance FIRSTEUREKA-SERVER-PROVIDER/DESKTOP-GavinLee:firsteureka-server-provider:9001 with status UP (replication=true)

打开浏览器访问 Eureka 控制台:http://localhost:8761 可在页面看到服务注册信息如下:

3. 创建Maven项目:crazyspringcloud-firsteureka-server-invoker,作为服务消费者:

    (1)  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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sztxtech.creazyspringcloud</groupId>
    <artifactId>crazyspringcloud-firsteureka-server-invoker</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>crazyspringcloud-firsteureka-server-invoker</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

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

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

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

    (2)  配置文件 application.yml 内容:

server:
  port: 9050

spring:
  application:
    name: firsteureka-server-invoker

eureka:
  instance:
    hostname: localhost
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

         说明:该服务消费者本身也可以对外提供服务,与提供者一样,使用 Eureka 的配置将该调用者注册到 crazyspringcloud-firsteureka-server 上面。

    (3)  控制器代码:

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@Configuration
public class InvokerControllor {
    
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

    @RequestMapping(value = "/router", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public String router(){
        RestTemplate restTemplate = getRestTemplate();

        // 通过应用名称调用服务
        String json = restTemplate.getForObject("http://FIRSTEUREKA-SERVER-PROVIDER/person/1032295", String.class);
        return json;
    }
}

         说明:① 在控制器中,配置了 RestTemplate 的 Bean,RestTemplate 原是 Spring-web 模块下的来,主要用来调用 REST 服务;其本身并不具备调用分布式服务的能力,但是 RestTemplate 的 Bean 被 @LoadBalanced 注解修饰后,这个 RestTemplate 实例就具备了访问分布式服务的能力了;

                  ② router() 测试方法用来对外发布 REST 服务,该方法只起到路由的作用,实际上是使用 RestTemplate 来调用 crazyspringcloud-firsteureka-server-provider (服务提供者) 的服务;

                  ③ 需要注意的是,这里的服务调用是仅使用服务名称来进行调用的;

    (4)  启动类代码:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication 
@EnableDiscoveryClient 
public class FirstEurekaServerInvoker {
    public static void main(String[] args) {
//        SpringApplication.run(FirstEurekaServerInvoker.class, args);
        new SpringApplicationBuilder(FirstEurekaServerInvoker.class).run(args);
    }
}

         说明:① 在该启动类中使用了 @EnableDiscoveryClient 注解,它使该服务调用者具有了去 Eureka 注册中心发现服务的能力;

                  ② @EnableEurekaClient 注解中包含了 @EnableDiscoveryClient 注解,也就是说,一个Eureka 客户端,本身就具有发现服务的能力;

    (5)  测试运行结果:

        依次按顺序启动服务注册中心、服务提供者、服务消费者,确认全部正常启动之后:

        ① 访问 Eureka 控制台:

        ② 访问服务消费者:http://localhost:9050/router

从以上对消费者的访问结果可看出,实际上调用了服务提供者的 “/person/{personId}” 服务。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值