Spring cloud eureka feign

一、简介
在微服务架构中服务发现是一个非常核心的功能。在spring cloud中可以很方便集成Netflix Service Discovery组件eureka。Eureka包含server和client,其中server端能够以群集的形式提供,各个sever又可以通过同步其他server中注册的service状态来实现高可用性。
当一个Eureka client向server注册时,会提供自身的元数据信息,包括host、port、health check URI等信息,Eureka server通过侦听同一个service的不同实例的心跳信息来确定当前实例是否正常,如果心跳信息失败,就会自动将该实例移除。

调用注册到Eureka中的服务,可以不直接采用EurekaClient,利用声明式的rest client :feign,或者Spring RestTemplate可以更加方便的调用注册在Eureka总的服务。

二、例子
  • 1. Eureka server
  • 核心是在正常的Spring boot程序中加入spring-cloud-starter-eureka-server依赖,在启动类中加入@EnableEurekaServer 注解
  • 代码结构:


  • 启动类
  • package hello;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @EnableEurekaServer
    @SpringBootApplication
    public class EurekaServiceApplication {
        
        public static void main(String[] args) {
            SpringApplication.run(EurekaServiceApplication.class, args);
        }
    }
    
    

  • 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>
    
    	<groupId>com.example</groupId>
    	<artifactId>eureka-service</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>1.5.1.RELEASE</version>
    		<relativePath/> <!-- lookup parent from repository -->
    	</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-test</artifactId>
    			<scope>test</scope>
    		</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>
    
    	<repositories>
    		<repository>
    			<id>spring-snapshots</id>
    			<name>Spring Snapshots</name>
    			<url>https://repo.spring.io/libs-snapshot</url>
    			<snapshots>
    				<enabled>true</enabled>
    			</snapshots>
    		</repository>
    	</repositories>
    
    </project>
    
    

  • 应用配置信息
  • server.port=8761
    
    eureka.client.register-with-eureka=false
    eureka.client.fetch-registry=false
    
    logging.level.com.netflix.eureka=OFF
    logging.level.com.netflix.discovery=OFF
    

  • 2.Eureka client(即user server端)
  • 核心是在正常的Spring boot程序中加入spring-cloud-starter-eureka依赖,在启动类中加入@EnableDiscoveryClient注解
  • 代码结构:

  • 启动类
  • package demo;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Random;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @author Spencer Gibb
     */
    @SpringBootApplication
    @EnableDiscoveryClient
    @RestController
    public class HelloServerApplication {
    
    	@RequestMapping("/greeting")
    	public String hello() {
    		List<String> greeting = Arrays.asList("Hi there","Greetings","Salutations");
    		Random rand = new Random();
    		int randomNum = rand.nextInt(greeting.size());
    		return greeting.get(randomNum);
    	}
    
    	public static void main(String[] args) {
    		SpringApplication.run(HelloServerApplication.class, args);
    	}
    }
    
    

  • 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>
    
    	<groupId>org.test</groupId>
    	<artifactId>feign-eureka-hello-server</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<name>feign-eureka-hello-server</name>
    	<description>Demo project for Spring Cloud</description>
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>1.5.1.RELEASE</version>
    		<relativePath /> <!-- lookup parent from repository -->
    	</parent>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<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>
    
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-actuator</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-feign</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-eureka</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    
    </project>
    
    

  • 应用配置信息
  • spring:
      application:
        name: HelloServer
    
    server:
      port: 7111
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
      instance:
        leaseRenewalIntervalInSeconds: 10
        metadataMap:
          instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${server.port}}}
    

  • 3.User client(调用注册到Eureka server中的Eureka client)
  • 核心是在正常的Spring boot程序中加入spring-cloud-starter-eureka、spring-cloud-starter-feign依赖,在启动类中加入@EnableFeignClients注解
  • 代码结构:


  • 启动类
  • package demo;
    
    import static org.springframework.web.bind.annotation.RequestMethod.GET;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.feign.EnableFeignClients;
    import org.springframework.cloud.netflix.feign.FeignClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @author Spencer Gibb
     */
    @SpringBootApplication
    @RestController
    @EnableFeignClients
    public class HelloClientApplication {
    	@Autowired
    	HelloClient client;
    
    	@RequestMapping("/greeting")
    	public String hello() {
    		return client.hello();
    	}
    
    	public static void main(String[] args) {
    		SpringApplication.run(HelloClientApplication.class, args);
    	}
    
    	@FeignClient("HelloServer")
    	interface HelloClient {
    		@RequestMapping(value = "/greeting", method = GET)
    		String hello();
    	}
    }
    
    


    FeignClient中的service id要和User server配置信息中的spring.application.name的值保持一致

  • 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>
    
    	<groupId>org.test</groupId>
    	<artifactId>feign-eureka-hello-client</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<name>feign-eureka-hello-client</name>
    	<description>Demo project for Spring Cloud</description>
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>1.5.1.RELEASE</version>
    		<relativePath /> <!-- lookup parent from repository -->
    	</parent>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<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>
    
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-actuator</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-feign</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-eureka</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    
    </project>
    
    

  • 应用配置信息
  • spring:
      application:
        name: HelloClient
    
    server:
      port: 7211
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
      instance:
        leaseRenewalIntervalInSeconds: 10
        metadataMap:
          instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${server.port}}}
    
    
    endpoints:
      restart:
        enabled: true
      shutdown:
        enabled: true
      health:
        sensitive: false
    



    三、启动
    按下面的顺序启动
    Eureka server ->user server -> user client
    等所有应用都启动后通过界面访问http://localhost:7211/greeting,可以正常访问user-server中的方法返回值,整个流程是 界面访问 user client 工程中的hello方法,user client通过@FeignClient中指定的service id从Eureka server中获取到注册的 HelloServer instance,即 user server,然后调用user server中的hello方法,返回调用结果给 user client,最终返回界面



    四、Eureka 集群



    1.修改Eureka-server对应的配置文件

    spring:
      application:
        name: eureka-server-clustered
      profiles: primary
    server:
      port: 8011
    eureka:
      instance:
        hostname: eureka-primary
      client:
        registerWithEureka: false
        fetchRegistry: false
        serviceUrl:
          defaultZone: http://eureka-secondary:8012/eureka/,http://eureka-tertiary:8013/eureka/
    
    ---
    spring:
      application:
        name: eureka-server-clustered
      profiles: secondary
    server:
      port: 8012
    eureka:
      instance:
        hostname: eureka-secondary
      client:
        registerWithEureka: false
        fetchRegistry: false
        serviceUrl:
          defaultZone: http://eureka-tertiary:8013/eureka/,http://eureka-primary:8011/eureka/
    
    ---
    spring:
      application:
        name: eureka-server-clustered
      profiles: tertiary
    server:
      port: 8013
    eureka:
      instance:
        hostname: eureka-tertiary
      client:
        registerWithEureka: false
        fetchRegistry: false
        serviceUrl:
          defaultZone: http://eureka-primary:8011/eureka/,http://eureka-secondary:8012/eureka/
    



    2.修改user-server对应的配置文件
    spring:
      application:
        name: UserServer
    
    server:
      port: 7111
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://eureka-secondary:8012/eureka/
      instance:
        leaseRenewalIntervalInSeconds: 10
        metadataMap:
          instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${server.port}}}
    


    注意:application.name 修改过,feignclient对应的serviceid也需要修改

    3.修改user-client对应的配置文件

    spring:
      application:
        name: UserClient
    
    server:
      port: 7211
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://eureka-primary:8011/eureka/,http://eureka-secondary:8012/eureka/,http://eureka-tertiary:8013/eureka/
      instance:
        leaseRenewalIntervalInSeconds: 10
        metadataMap:
          instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${server.port}}}
    
    
    endpoints:
      restart:
        enabled: true
      shutdown:
        enabled: true
      health:
        sensitive: false
    


    3.如果在同一台机器上,修改hosts
    #	127.0.0.1       localhost
    #	::1	localhost
    127.0.0.1       localhost
    127.0.0.1       eureka-primary
    127.0.0.1       eureka-secondary
    127.0.0.1       eureka-tertiary
    


    依次启动 Eureka-server user-server user-client,其中启动Eureka-server时用
    java -jar eureka-server-clustered-0.0.1-SNAPSHOT.jar --spring.profiles.active=primary
    java -jar eureka-server-clustered-0.0.1-SNAPSHOT.jar --spring.profiles.active=secondary
    java -jar eureka-server-clustered-0.0.1-SNAPSHOT.jar --spring.profiles.active=tertiary
    

    启动三次,此时Eureka-server以集群形式提供服务,可以关闭任意一个或两个来测试Eureka的高可用性
  • primary


  • secondary

  • tertiary

  • 猜你喜欢

    转载自fengyilin.iteye.com/blog/2356629