Spring Cloud Eureka Service Discovery Client Server Example

摘要: In this tutorial we demonstrate how to create and configure a service discovery client server environment using Netflix Eureka. First, we use spring-cloud to create and configure a Service Discovery Registry Server. This server will listen to new nodes spinning up in our environment. Secondly, we create some Service Discovery Clients that will launch on multiple ports. The service discovery registry will automatically register these clients.

In this tutorial we demonstrate how to create and configure a service discovery client server environment using Netflix Eureka. First, we use spring-cloud to create and configure a Service Discovery Registry Server. This server will listen to new nodes spinning up in our environment. Secondly, we create some Service Discovery Clients that will launch on multiple ports. The service discovery registry will automatically register these clients.

Netflix Eureka

Eureka is a REST (Representational State Transfer) based service that is primarily used in the AWS cloud for locating services for the purpose of load balancing and failover of middle-tier servers.

Service discovery is one of the key tenets of a microservice based architecture. Trying to hand configure each client or some form of convention can be very difficult to do and can be very brittle. Eureka is the Netflix Service Discovery Server and client. The server can be configured and deployed to be highly available, with each server replicating state about the registered services to the others.

Service Discovery: Eureka Server Example

Let’s start by creating the Eureka service discovery registry server.

Project Structure

Our project structure looks like the following.

Maven Dependencies

We use Apache Maven to manage our project dependencies. Make sure the following dependencies reside on the class-path.

<?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.memorynotfound.spring.cloud.eureka.service.discovery</groupId>
    <artifactId>service-registry</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <url>https://memorynotfound.com</url>
    <name>Spring CLOUD - ${project.artifactId}</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Camden.SR5</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>

Configure Eureka Server

We configure the Eureka service discovery registry in a standalone mode. The combination of the two caches (client and server) and the heartbeat makes a standalone Eureka server fairly resilient to failure, as long as there is some sort of monitor or elastic runtime keeping it alive. In standalone mode, you might prefer to switch off the client side behaviour, so it doesn’t keep trying and failing to reach its peers. Here is an example configuration:

server:
  port: ${PORT:8761} # Indicate the default PORT where this service will be started

eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false # telling the server not to register himself in the service
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

logging:
  level:
      - ".=info"
      - "com.memorynotfound=debug"
      - "org.springframework=info"

Stand up a Eureka Service Registry

You can use Spring Cloud’s @EnableEurekaServer annotation to standup a registry that other applications can talk to. This is a regular Spring Boot application with one annotation added to enable the registry. In production environment you’ll typically have multiple service registries for high availability.

package com.memorynotfound.cloud;

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

@EnableEurekaServer
@SpringBootApplication
public class ServiceRegistryApplication {

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

}

Running The Service Registry

You can start the service registry using the following maven command.

mvn spring-boot:run

When the server is started, you can go to the admin panel by using the following url http://localhost:8761/. You’ll receive the following output. Notice that we haven’t started any clients yet, so we have no instances available yet.

Spring Cloud Service Discovery: Eureka Client Example

Now we created the Service Registry, it’s time to create some clients. In the following section we’ll create a simple Eureka Client and deploy it multiple times on different ports.

When a client registers with Eureka, it provides meta-data about itself such as host and port, health indicator URL, home page etc. Eureka receives heartbeat messages from each instance belonging to a service. If the heartbeat fails over a configurable timetable, the instance is normally removed from the registry.

Project Structure

Let’s start by looking at the project structure.

Maven Dependencies

We use Apache Maven to manage our project dependencies. Make sure the following dependencies reside on the class-path.

<?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.memorynotfound.spring.cloud.eureka.service.discovery</groupId>
    <artifactId>bookstore-service</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <url>https://memorynotfound.com</url>
    <name>Spring CLOUD - ${project.artifactId}</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.7</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Camden.SR5</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>

Configuring the Eureka Client

The default application name (service ID), virtual host and non-secure port, taken from the Environment are spring.application.name, spring.application.name and server.port respectively.

The Eureka instance is configured by eureka.instance.* configuration keys, but the defaults will be fine if you ensure that your application has a spring.application.name (this is the default for the Eureka service ID or VIP). The eureka.instance.serviceUrl.defaultZone is a magic string fallback value that provides the service URL for any client that doesn’t express a preference.

server:
  port: ${PORT:8098}

# configure eureka client
eureka:
  instance:
    leaseRenewalIntervalInSeconds: 1
    leaseExpirationDurationInSeconds: 3
  client:
    serviceUrl:
      defaultZone: http://user:[email protected]:8761/eureka/

# custom attribute for the actuator info endpoint
info:
  app:
    name: bookstore-service
    
# give the application a name
spring:
  application:
    name: bookstore-service

# disable actuagor security for endpoints 
management:
  security:
    enabled: false

# custom logging settings
logging:
  level:
      - ".=info"
      - "com.memorynotfound=debug"
      - "org.springframework=info"

Writing a Client Rest Service

To demonstrate the workings of the client we are writing a simple rest service.

package com.memorynotfound.cloud;

import java.math.BigDecimal;

public class Book {

    private Integer id;
    private String name;
    private BigDecimal price;

    public Book() {
    }

    public Book(Integer id, String name, BigDecimal price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

The first service BookController simply returns a List of books.

package com.memorynotfound.cloud;

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

import java.math.BigDecimal;
import java.util.*;

@RestController
public class BookController {

    @GetMapping("books")
    public List<Book> getBooks(){
        return Arrays.asList(
                new Book(1, "Spring Cloud Eureka Service Registry Server", new BigDecimal(0)),
                new Book(2, "Spring Cloud Eureka Service Discovery", new BigDecimal(0)),
                new Book(3, "Spring Cloud Eureka Client", new BigDecimal(0))
        );
    }
}

Using the EurekaClient

Once you have an app that @EnableDiscoveryClient or (@EnableEurekaClient) you can use it to discover service instances form the Eureka Server. One way to do this is to use the native com.netflix.discovery.EurekaClient (as opposed to the Spring Cloud DiscoveryClient). In the following controller we use the EurekaClient to retrieve all the instances from the ‘cluster’.

package com.memorynotfound.cloud;

import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.shared.Applications;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DiscoveryController {

    @Autowired
    private EurekaClient eurekaClient;

    @GetMapping("/applications")
    public Applications getApplications() {
        return eurekaClient.getApplications();
    }
}

Stand up Service Discovery Eureka Client

package com.memorynotfound.cloud;

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

@EnableEurekaClient
@SpringBootApplication
public class BookStoreApplication {

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

}

Running The Eureka Client

We start multiple clients by using the following commands. Make sure you use different ports.

# start the first client
mvn spring-boot:run -Drun.arguments="--PORT=8098"

# start the second client
mvn spring-boot:run -Drun.arguments="--PORT=8099"

Example output

When the clients are booted and you access the admin page again: http://localhost:8761/, you’ll see the service registry discovered 2 instances.

When we access the following URL: http://10.0.63.74:8091/applications. we receive detailed meta-data information about our instances.

When we access the following URL: http://10.0.63.74:8091/books. we receive the following output.

Download

上一篇: Spring Boot Thymeleaf Configuration Example
下一篇: Spring Boot Customize Actuator Info Endpoint Example Configuration
 评论 ( What Do You Think )
名称
邮箱
网址
评论
验证
   
 

 


  • 微信公众号

  • 我的微信

站点声明:

1、一号门博客CMS,由Python, MySQL, Nginx, Wsgi 强力驱动

2、部分文章或者资源来源于互联网, 有时候很难判断是否侵权, 若有侵权, 请联系邮箱:summer@yihaomen.com, 同时欢迎大家注册用户,主动发布无版权争议的 文章/资源.

3、鄂ICP备14001754号-3, 鄂公网安备 42280202422812号