Spring Cloud Netflix和Eureka简介

x33g5p2x  于2022-09-16 转载在 Spring  
字(17.5k)|赞(0)|评价(0)|浏览(283)

在这篇文章中,我们将了解 Spring Cloud Netflix Eureka服务器和Spring Cloud Netflix Eureka客户端 。我们将开发Eureka服务器Eureka客户端。Eureka客户端将使用Eureka服务器服务发现调用其他客户端。

介绍

在本教程中,我们将开发Spring Cloud Netflix Eureka服务器和Spring Cloud Netflix Client,为了简单起见,我们将在本文中把它们称为Eureka服务器和Eureka客户端。为了展示它是如何工作的,我们将建立一个Eureka服务器和几个Eureka客户端,并使用Eureka服务器展示这些Eureka客户端应用程序之间的通信。我们将使用postman应用程序来展示实际的演示。

1. 什么是Eureka服务器和客户端

Eureka服务器是一个应用程序,也被称为服务发现。它持有所有在它那里注册的Eureka客户端应用程序的详细信息。Eureka服务器将知道所有注册到它的Eureka客户端应用程序(微服务)的IP地址和端口等所有细节。它将帮助Eureka客户端应用程序之间进行通信。

Eureka客户端只不过是一个微服务,我们使用***@EnableEurekaClient@EnableDiscoveryClient***使其成为Eureka客户端,并在属性中加入Eureka服务器URL,它将向Eureka服务器注册自己。Eureka客户端是在Spring Cloud中的。

application.properties文件中,我们还可以设置客户端向服务器发送心跳的时间,如果客户端在该时间段内未能发送心跳,也可以设置过期的时间。

2. Eureka服务器应用设置

让我们先来设置Eureka服务器。我们将使用可视化界面Spring Initializer来使用生成初始应用结构。如果你喜欢,你可以使用IDE来构建模块(大多数IDE都与Initializr集成)。

我们使用的是Java 8;Spring Boot,我们只添加了一个依赖关系,即Eureka服务器(Spring Cloud Discovery)。客户端 "GENERATE",Spring Initializer将创建一个带有依赖关系的项目的初始结构。一旦生成,请解压缩文件夹并在你最喜欢的IDE中创建一个新项目。这里我们使用的是IntelliJ IDE。我们将看到以下项目结构。

下面是我们的模块在IntelliJ中的样子。

3. 尤里卡服务器应用程序概述

让我们来看看这个应用程序和它的重要方面。这是我们的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 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.2.6.RELEASE</version>
      <relativePath />
      <!-- lookup parent from repository -->
   </parent>
   <groupId>com.example</groupId>
   <artifactId>eurekaserver</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>eurekaserver</name>
   <description>Eureka Server Application</description>
   <properties>
      <java.version>1.8</java.version>
      <spring-cloud.version>Hoxton.SR4</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>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>
3.1. application.properties:
spring.application.name=eurekaserver
server.port=9090
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

让我们看一下上面的属性 

  • 服务器端口-Eureka服务器将运行的端口。
  • register-with-eureka-它将是假的,因为它是服务器本身,它不需要自己注册。
  • fetch-registry-这也是针对客户端的,因此它将是假的。客户端用它来从服务器上获取注册表信息,并在本地进行缓存。
  • serviceUrl-这是eureka服务器的一个URL,客户端将使用这个URL向服务器注册。
3.2. Eureka服务器主类

让我们来定义主类,它将引导服务器。

package com.example.eurekaserver;

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

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

@EnableEurekaServer注解帮助spring boot应用程序作为Eureka服务器运行。

4. Eureka客户端1设置

我们完成了Eureka服务器的基本设置,让我们来创建Eureka客户端应用程序。我们将使用可视化界面Spring Initializer来使用生成初始应用结构。

我们使用的是Java 8;Spring Boot 2.2.6,我们只添加一个依赖关系,即Eureka服务器(Spring Cloud Discovery)。客户端 "GENERATE "和Spring Initializer将创建一个带有依赖关系的项目的初始结构。一旦生成,请解压缩文件夹并在你喜欢的IDE中创建一个新项目,这里我们使用IntelliJ IDE。我们将看到以下项目结构。

项目结构:

5. Eureka Client1应用程序概述

下面是对第一个Eureka客户端pom.xml文件的完整介绍。我们已经添加了Netflix Eureka客户端作为我们应用程序的依赖项。下面是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 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.2.6.RELEASE</version>
      <relativePath />
      <!-- lookup parent from repository -->
   </parent>
   <groupId>com.example</groupId>
   <artifactId>eurekaclient1</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>eurekaclient1</name>
   <description>Eureka Client 1</description>
   <properties>
      <java.version>1.8</java.version>
      <spring-cloud.version>Hoxton.SR4</spring-cloud.version>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
      <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>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>

5.1. application.properties文件:

spring.application.name=eurekaclient1
server.port=8081
eureka.client.service-url.defaultZone=http://localhost:9090/eureka/

*服务器端口-客户端应用程序的唯一端口。

  • 租用-更新-间隔-秒-它是客户端将向服务器发送心跳的间隔时间。
  • 租期-到期-持续时间-秒-eureka服务器将等待来自客户端的心跳,否则它将从注册表中删除该客户端。
  • service-url-服务器的URL。
5.2.  Eureka客户端应用程序主类
package com.example.eurekaclient1;

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

@EnableDiscoveryClient
@SpringBootApplication
public class Eurekaclient1Application {

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

}

@EnableDiscoveryClient注解激活了Netflix发现客户端。

5.3. 控制器类

让我们为我们的Eureka客户端定义一个控制器类。这是一个简单的Spring Boot REST控制器,并定义几个端点来为调用的客户端提供产品信息。

package com.javadevjournal.eurekaclient1.controller;

import com.javadevjournal.eurekaclient1.model.Product;
import com.sun.jersey.core.header.MediaTypes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.UUID;

@RestController
public class Eurekaclient1Controller {
    @Autowired
    private LoadBalancerClient loadBalancerClient;
    private RestTemplate restTemplate = new RestTemplate();

    @GetMapping("/calleurekaclient1")
    public ResponseEntity callEurekaClient1(){
        return new ResponseEntity("Hello From Client 1 ", HttpStatus.OK);
    }

    @GetMapping("/callEurekaClient2viaClient1")
    public ResponseEntity callClient2(){
        try {
            return new ResponseEntity(
                    restTemplate.getForObject(getEurkaClient2BaseUri() + "/calleurekaclient2", String.class), HttpStatus.OK);
        }catch (Exception exp) {
            return new ResponseEntity(
                    restTemplate.getForObject(getEurkaClient2BaseUri() + "/calleurekaclient2", String.class), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping(value = "/getallproducts")
    public ResponseEntity getAllProductsFromClient2(){
        try {
            return new ResponseEntity(
                    restTemplate.getForObject(getEurkaClient2BaseUri() + "/allproducts", String.class), HttpStatus.OK);
        }catch (Exception exp) {
            return new ResponseEntity(
                    restTemplate.getForObject(getEurkaClient2BaseUri() + "/allproducts", String.class), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }


    @GetMapping(value = "/getproductbyid/{id}")
    public ResponseEntity getProducByIDFromClient2(@PathVariable UUID id){
        try {
            return new ResponseEntity(
                    restTemplate.getForObject(getEurkaClient2BaseUri() + "/product/"+id, String.class), HttpStatus.OK);
        }catch (Exception exp) {
            return new ResponseEntity(
                    restTemplate.getForObject(getEurkaClient2BaseUri() + "/product/"+id, String.class), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @DeleteMapping("/deleteproductbyid/{id}")
    public void deleteProductByIDFromClient2(@PathVariable UUID id){
        try {
            restTemplate.delete(getEurkaClient2BaseUri() + "/product/delete/"+id);
        }catch (Exception exp) {
            //log the error
        }
    }

    @PostMapping(value = "/updteproduct/")
    public ResponseEntity updateProductFromClient2(){
        try {
            return new ResponseEntity(
                    restTemplate.postForObject(getEurkaClient2BaseUri() + "/product/update/",new Product(UUID.randomUUID(), "Soap" , 99.99, "Body"),Product.class ), HttpStatus.OK);
        }catch (Exception exp) {
            return new ResponseEntity(
                    restTemplate.postForObject(getEurkaClient2BaseUri() + "/product/update/",new Product(UUID.randomUUID(), "Soap" , 99.99, "Body"),Product.class ), HttpStatus.OK);
        }
    }


    private String getEurkaClient2BaseUri(){
        ServiceInstance serviceInstance =  loadBalancerClient.choose("EUREKACLIENT2");
        return serviceInstance.getUri().toString();
    }
}

让我们来看看其他一些重要的要点。

LocalBalanceClient - 它是一个客户端的负载平衡器。
ServiceInstance - 这代表了像Eureka Server这样的发现服务中的一个服务实例。
ReposnseEntity - 它是状态代码、头信息和实际响应体的组合。

  • @RestController - 它是@Controller@ResponseBody的组合 - 它帮助映射资源,也以XML和JSON格式发回响应。

6. Eureka客户端2设置

让我们来定义我们的第二个Eureka客户端。我们将使用可视化界面Spring Initializer来使用生成初始应用结构。

我们使用的是Java 8;Spring Boot 2.2.6,我们只添加一个依赖项,即Eureka服务器(Spring Cloud Discovery)。客户端 "GENERATE "和Spring Initializer将创建一个带有依赖项的项目初始结构。一旦生成,请解压缩文件夹并在你喜欢的IDE中创建一个新项目,这里我们使用IntelliJ IDE。我们将看到以下项目结构。

项目结构:

7. Eureka Client2应用程序概述

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 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.2.6.RELEASE</version>
      <relativePath />
      <!-- lookup parent from repository -->
   </parent>
   <groupId>com.example</groupId>
   <artifactId>eurekaclient2</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>eurekaclient2</name>
   <description>Eureka Client 2</description>
   <properties>
      <java.version>1.8</java.version>
      <spring-cloud.version>Hoxton.SR4</spring-cloud.version>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
      <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>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>
7.1. 应用程序.属性
spring.application.name=eurekaclient2
server.port=8085
eureka.client.service-url.defaultZone=http://localhost:9090/eureka/
7.2. 主类
package com.example.eurekaclient2;

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

@EnableEurekaClient
@SpringBootApplication
public class Eurekaclient2Application {

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

}
7.3. 客户端2(产品服务)控制器
package com.javadevjournal.eurekaclient2.controller;

import com.javadevjournal.eurekaclient2.model.Product;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@RestController
public class Eurekaclient2Controller {
    private static List productList = new ArrayList<>();
    static{
        productList = new ArrayList<>();
        Product p1 = new Product(UUID.randomUUID(), "Guitar" , 99.99, "Music");
        Product p2 = new Product(UUID.randomUUID(), "AWS Book" , 29.99, "Books");
        Product p3 = new Product(UUID.randomUUID(), "Bread" , 9.99, "Food");
        Product p4 = new Product(UUID.randomUUID(), "Soap" , 99.99, "Body");
        Product p5 = new Product(UUID.randomUUID(), "Milk" , 3.99, "Food");
        Product p6 = new Product(UUID.randomUUID(), "Pant" , 17.99, " Cloth");
        Product p7 = new Product(UUID.randomUUID(), "Tyre" , 39.99, "Auto");
        productList.add(p1);
        productList.add(p2);
        productList.add(p3);
        productList.add(p4);
        productList.add(p5);
        productList.add(p6);
        productList.add(p7);
    }

    @GetMapping("/calleurekaclient2")
    public ResponseEntity callEurekaClient2(){
        return new ResponseEntity("Hello From Client 2", HttpStatus.OK);
    }

    @GetMapping(value = "/allproducts", produces = MediaType.APPLICATION_JSON_VALUE)
    public List list() {
        return Eurekaclient2Controller.productList;
    }

    @GetMapping(value = "/product/{id}" , produces = MediaType.APPLICATION_JSON_VALUE)
    public Product showProduct(@PathVariable UUID id) {
        return new Product(id, "Guitar" , 99.99, "Music");
    }

    @PostMapping(value = "/product/update")
    public String saveProduct(@RequestBody Product product) {
        return "Product with product id: "+ product.getProductId() +" and product name:"+product.getProductName()+" has been saved successfully!";
    }

    @DeleteMapping(value = "/product/delete/{id}")
    public void delete(@PathVariable UUID id) {
        //log "Product "+ id +" has been deleted successfully!";
    }
}

8. 服务发现

我们将首先启动**Eureka Server应用程序***,一旦它启动并运行,我们将使用http://localhost:9090/访问Eureka Server*。我们在本地机器上运行它。我们可以看到我们没有列出任何客户(检查应用程序)。

一旦服务器启动:

现在我们将逐一启动所有的客户端,一旦它们全部启动并运行,我们将再次进入Eureka服务器,我们的客户端将被列在应用程序下,并有它们的IP地址和端口。

一旦所有的客户端启动:

现在,我们将使用postman应用程序测试我们的服务器和客户端。

调用客户端1 - 这是一个简单的HTTP获取调用

调用客户端2 - 这是一个简单的HTTP获取调用

通过客户端1调用客户端2(产品服务)--这里我们将使用LoadBalancerClientServiceInstance库,在客户端1内获取客户端2的应用细节,并调用客户端2的方法。

GetProductById: 通过客户端1调用客户端2(产品服务),就像上面的调用一样,但这次客户端2将按id返回产品。这是一个HTTP获取调用。

GetAllProducts。通过客户端1调用客户端2(产品服务),它就像上面的调用,但这次客户端2将返回所有产品的列表。这是一个HTTP获取调用。

DeleteProductById: 通过客户端1调用客户端2(产品服务),和上面的调用一样,但这次客户端2将根据id从产品列表中删除产品。这是一个HTTP DELETE调用。

9. 什么是Feign Client?

Feign客户端是spring cloud bundle中的一个声明性Web服务客户端。它为抽象的rest-calls提供注解,并帮助rest客户端之间进行通信,而不需要编写详细的rest-client代码。我们需要使用@EnableFeignClients注解来标记我们的spring boot应用程序为Feign客户端。

请看下面。

package com.example.feignclient.contrller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.cloud.openfeign.FeignClient;

@FeignClient(name= "greetings")
public interface IFeignClient {
    @GetMapping(value= "/greet/welcome/{message}")
    public String getGreetings(@PathVariable(name= "message") String langCode);
}

总结

在这篇文章中,我们讨论了***Spring Cloud Netflix Eureka Server和Spring Cloud Netflix Eureka Client。****下面是对这篇文章中讨论的项目的快速总结。

  • 什么是Eureka服务器和Eureka客户端?
  • 我们已经为Eureka服务器客户端设置了应用程序。
  • 了解了Spring Cloud下的各种库。
  • 看到了使用Postman进行服务发现的工作。

这个应用程序的源代码可以在GitHub上找到。

相关文章