SpringCloud:注册中心——Eureka

一,SpringCloud注册中心

    1, SpringCloud支持三种注册中心:Eureka,Zookeeper,Consul。本篇对Eureka进行演示

    2,Eureka注册中心分为三个部分实现服务间发现和调用:Eureka注册中心服务端,Eureka注册中心客户端_生产者,Eureka注册中心客户端_消费者。如下图所示,Eureka服务通过两台服务构建集群,集群间信息复制,实现Eureka注册中心的服务高可用;三个客户端服务可以互为生产者和消费者,在Eureka注册中心注册自身服务或获取服务路径实现服务调用。

二,代码变现

    1,服务结构

        * 两个Eureka服务端项目,实现集群效果

        * 两个Member项目为客户端生产者,实现负载均衡(SpringCloud默认通过Ribbon实现负载均衡)

        * Order项目为客户端消费者,实现服务调用

    2,Eureka服务端

        a,Maven依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
  </parent>
  <!-- 管理依赖 -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Finchley.M7</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <dependencies>
    <!--SpringCloud eureka-server -->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
  </dependencies>
  <!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
  <repositories>
    <repository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/libs-milestone</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

        b,配置文件

            * server_1配置信息

###服务端口号
server:
  port: 8000
###eureka 基本信息配置
eureka:
  instance:
    ###注册到eureka ip地址
    hostname: 127.0.0.1
  client:
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:7900/eureka/
    ###注册自身到其他Server服务器,单点为false
    register-with-eureka: true
    fetch-registry: true

            * server_2配置信息

###服务端口号
server:
  port: 7900
###eureka 基本信息配置
eureka:
  instance:
    ###注册到eureka ip地址
    hostname: 127.0.0.1
  client:
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:8000/eureka/
    ###注册自身到其他Server服务器,单点为false
    register-with-eureka: true
    fetch-registry: true

       c,启动Main函数

package com.gupao;

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

/**
 * @author pj_zhang
 * @create 2019-01-08 21:23
 **/
// 开启Eureka服务
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApp {

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

        d,启动效果

              * ERROR:com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server;该问题是因为集群服务互相注册,单服务启动有先后顺序,先启动服务不能注册到未启动服务,服务未发现,稍等即可,无需处理!

            * 启动后,直接访问服务,页面效果如下

    3,Eureka客户端_生产者

        a,生产者为Member_1、Member_2两个,用来演示SpringCloud默认支持的Ribbon负载均衡

        b,Maven依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
  </parent>
  <!-- 管理依赖 -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Finchley.M7</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <dependencies>
    <!-- SpringBoot整合Web组件 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- SpringBoot整合eureka客户端, eureka-client -->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

  </dependencies>
  <!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
  <repositories>
    <repository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/libs-milestone</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

        c,Member_1配置信息

###服务启动端口号
server:
  port: 8200
###服务名称(服务注册到eureka名称)
spring:
    application:
        name: app-itmayiedu-member
###服务注册到eureka地址, 因为是集群, 注册到两个注册中心, 用逗号隔开
eureka:
  client:
    service-url:
           defaultZone: http://localhost:8000/eureka,http://localhost:7900/eureka

    ###因为该应用为注册中心,不会注册自己
    register-with-eureka: true
    ###是否需要从eureka上获取注册信息
    fetch-registry: true

        d,Member_2配置信息

###服务启动端口号
server:
  port: 8300
###服务名称(服务注册到eureka名称)
spring:
    application:
        name: app-itmayiedu-member
###服务注册到eureka地址
eureka:
  client:
    service-url:
           defaultZone: http://localhost:8000/eureka,http://localhost:7900/eureka

    ###因为该应用为注册中心,不会注册自己
    register-with-eureka: true
    ###是否需要从eureka上获取注册信息
    fetch-registry: true

        e,生产者服务接口

package com.gupao.springcloud.test.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author pj_zhang
 * @create 2019-01-08 21:52
 **/
@RestController
public class MemberController {

    @Value("${server.port}")
    private Integer port;

    // RestTemplate方式进行调用
    @RequestMapping("/sendMessage")
    public String sendMessage() {
        return "MemberController sendMessage, port : " + port;
    }

    // Feign客户端方式调用
    @RequestMapping("/getMemberByFeign")
    public String getMemberByFeign() {
        return "MemberController getMemberByFeign, port : " + port;
    }

}

        f,启动Main函数

package com.gupao;

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

/**
 * @author pj_zhang
 * @create 2019-01-08 21:49
 **/
// Eureka客户端
@EnableEurekaClient
@SpringBootApplication
public class MemberApp {
    public static void main(String[] args) {
        SpringApplication.run(MemberApp.class, args);
    }
}

        g,启动效果

             * 此时在8000端口服务上存在服务注册信息,而7900端口服务上不存在;这是因为注册中心服务的主从关系,如果8000服务宕机,则会复制信息到7900端口服务上;注册信息复制可能存在30S的时差

            * 直接通过SpringBoot方式访问接口;如图,生产者服务启动成功

    4,Eureka客户端_消费者

        a,消费者服务可以通过两种方式进行服务访问:RestTemplate方式和声明式Feign方式,此处会分别进行演示

        b,Maven依赖

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>
    <!-- 管理依赖 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M7</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- SpringBoot整合eureka客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 声明式feign方式进行服务调用 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
    <!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/libs-milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

        c,配置文件

###服务启动端口号
server:
  port: 8100
###服务名称(服务注册到eureka名称)
spring:
    application:
        name: app-itmayiedu-order
###服务注册到eureka地址

eureka:
  client:
    service-url:
           defaultZone: http://localhost:8000/eureka,http://localhost:7900/eureka

    ###因为该应用为注册中心,不会注册自己
    register-with-eureka: true
    ###是否需要从eureka上获取注册信息
    fetch-registry: true

        d,RestTemplate方式访问

              * 服务接口调用

package com.gupao.springcloud.test.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author pj_zhang
 * @create 2019-01-08 21:46
 **/
@RestController
public class OrderController {

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/orderToMember")
    public String orderToMember() {
        // 获取所有服务, 此处只是展示
        System.out.println(discoveryClient.getServices());
        String result = restTemplate.getForObject("http://app-itmayiedu-member/sendMessage", String.class);
        return result;
    }

}

              * 启动Main函数

package com.gupao;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * @author pj_zhang
 * @create 2019-01-08 21:45
 **/
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients
public class OrderApp {

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

    /**
     * 服务调用如果通过ip:port进行调用, 该步骤可省略
     * 服务调用如果通过application_name进行调用,如当前演示,则必须手动添加RestTemplate的Bean实现
     * 并添加@LoadBalanced注解:此处以为,使用application_name进行服务发现后,
     * 可能存在服务名称对应下的多个服务节点,添加该注解用来实现负载均衡
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

               * 启动效果如下

        e,Feign客户端访问

            * 项目结构如下;Maven依赖已经在上一步引入,可以回头查看

           * 声明式feign接口

package com.gupao.springcloud.test.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author pj_zhang
 * @create 2019-01-09 22:20
 **/
// 需要调用的目标服务服务名称
@FeignClient(name = "app-itmayiedu-member")
public interface MemberFeign {

    // 目标服务服务路径, 该路径需要与服务端路径统一, 用来实现路由处理
    @RequestMapping("/getMemberByFeign")
    String getMemberByFeign();

}

            * 服务调用接口

package com.gupao.springcloud.test.controller;

import com.gupao.springcloud.test.feign.MemberFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author pj_zhang
 * @create 2019-01-09 22:29
 **/
@RestController
public class OrderFeignController {

    @Value("${server.port}")
    private Integer serverPort;


    // 注入声明式Feign接口
    @Autowired
    private MemberFeign memberFeign;

    @RequestMapping("/getMemberByFeign")
    public String feignGetMember() {
        // 通过注入的Feign接口直接调用服务, 底层会进行服务访问路径拼接并访问服务
        return memberFeign.getMemberByFeign();
    }

}

           * 启动Main函数

package com.gupao;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * @author pj_zhang
 * @create 2019-01-08 21:45
 **/
@EnableEurekaClient
@SpringBootApplication
// 允许通过声明式Feign客户端启动
@EnableFeignClients
public class OrderApp {

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


}

           * 启动效果如下

猜你喜欢

转载自blog.csdn.net/u011976388/article/details/86498810