SpringCloud(三): 服务注册与发现,服务注册中心—Eureka

 

(编写不易,转载请注明:http://shihlei.iteye.com/blog/2400190)

 一 服务注册与发现

(1)概述

服务调用基本两端:

服务提供者(Service Provider)、服务消费者(Service Client)

调用方式:

a)简单版:

直接调用

优点:

简单,快速完成

缺点:

服务消费者感知服务端IP、Port,任何这二者修改,都可能引起客户端都需要修改,极端可能需要重新发布上线。

不利于服务HA。



 

 

 

(b)反向代理版:

在中间增加反向代理,服务消费者依赖反向代理服务器,屏蔽服务提供者后端物理架构。

特点:

客户端,服务器端无入侵性

传统反向代理定位HA和负载均衡,不具备自动注册新服务,添加服务新机能力,可以通过扩展反向代理服务器解决。



 

 

(c)服务注册中心版:

服务注册到中心中,服务消费者从中心获取服务IP、Port,再进行请求。

特点:

将核心的服务注册发现能力,已独立中间件形式提供。其实和反向代理的解决方案差不多。

 

 

 

 

(2)服务注册中心定位 

解决:

服务物理设备变动(ip,端口变动),造成客户端需要修改的问题。

目前业界大部分使用基于Docker云架构,提供弹性扩展能力,服务提供者IP,Port无法在发布时就给定,引入服务注册中心,可以适应这种变化。

 

主要提供功能:

1)服务注册发现

2)心跳同步

3)负载均衡

 

二 服务注册中心:Eureka

(1)概述:

Eureka:Netflix公司开发的服务发现中间件,用于服务的负载均衡和服务故障转移 

SpringCloud 集成了EurekaSever,让我们通过简单配置即可启动

git:https://github.com/Netflix/eureka

wiki:https://github.com/Netflix/eureka/wiki

架构:

(2)基于SpringCloud搭建EurekaServer:

搭建过程重用了《 SpringCloud(一): SpringBoot 创建简单的微服务》中的项目,项目环境可点击查看。

 

第一步:创建项目,添加依赖:见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>

    <artifactId>spring-cloud-eureka-server</artifactId>
    <packaging>jar</packaging>

    <name>spring-cloud-eureka-server</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>x.demo.springcloud</groupId>
        <artifactId>spring-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../../pom.xml</relativePath>
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 

第二步:创建SpringCloud启动类,添加@EnableEurekaServer

package x.demo.springcloud.eureka.server;

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

@SpringBootApplication
@EnableEurekaServer
public class SpringCloudEurekaServerApplication {

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

 

第三步:配置EurekaServer相关信息:application.yml

spring:
  profiles: Standalone
  application:
    name: eureka-server-standalone
server:
  port: 8761
eureka:
  # 每个EurekaServer 都包含一个EurekaClient,用于请求其他节同步
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
    # 单机版不注册到Eureka
    registerWithEureka: false
    fetchRegistry: false
  instance:
    # 指定实例名称,默认:${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}}
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}

 

第四步:访问查看是否成功

 

 

 

 

(3)Eureka Server集群搭建

Eureka Server 集群主要是各个实例通过EurekaClieint 注册到其他实例(对等体Pear)中,保证服务注册表冗余。

注意:由于要操作必须在所有对等体上生效,服务修改才生效,所以有时候会慢。

规划:启动三个实例,互相注册对等体

Peer1:5001

Peer2:5002

Peer3:5003

第一步:项目如上

第二步:修改application.yml指定各个Peer配置,主要是端口及对等体

特别注意:我将多个Profile写在同一个文件中,咋样yml中约定“---”标识一个Profile

---
#HA 版: 通过运行多个实例并请求他们相互注册, 通过defaultZone 注定本实例要注册到哪些其他的节点
spring:
  profiles: Peer1
  application:
    name: eureka-server
server:
  port: 50001
eureka:
  client:
    service-url:
      defaultZone: http://localhost:50002/eureka/,http://localhost:50003/eureka/
  instance:
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}

---
spring:
  profiles: Peer2
  application:
    name: eureka-server
server:
  port: 50002
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:50001/eureka/,http://localhost:50003/eureka/
  instance:
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}

---
spring:
  profiles: Peer3
  application:
    name: eureka-server
server:
  port: 50003
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:50001/eureka/,http://localhost:50002/eureka/
  instance:
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}

 

第三步:配置启动,idea添加启动操作,以Peer1为例,Peer2,Peer3同

注:第一个Peer启动的时候注册对等体报错正常,因为其他对等体还没启动

异常:com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused


 

第四步:访问页面验证


 

 

三 服务提供者,服务消费者集成EurekaClient

重用前面的项目:见《 SpringCloud(一): SpringBoot 创建简单的微服务》《SpringCloud(二):声明式RestClient—Feign》

1)spring-cloud-microservice:微服务项目,实现获取当前时间服务
2)spring-cloud-webfront:前端项目,根据业务调用各种微服务,这里只是获取时间。

 

(1)服务提供者

第一步:依赖

<?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>

    <artifactId>spring-cloud-microservice</artifactId>
    <packaging>jar</packaging>

    <name>spring-cloud-microservice</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>x.demo.springcloud</groupId>
        <artifactId>spring-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../../pom.xml</relativePath>
    </parent>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- utils -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 

第二步:application.yml 配置 EurekaClient,做服务注册

server:
  port: 10001

# 服务名称
spring:
  application:
    name: microservice-time
eureka:
  client:
    service-url:
      defaultZone: http://localhost:50001/eureka/,http://localhost:50002/eureka/,http://localhost:50003/eureka/
  instance:
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    prefer-ip-address: true

 

第三步:启动集成@EnableDiscoveryClient (可以用@EnableEurekaClient 替代)

package x.demo.springcloud.microservice;

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


@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudServiceApplication {

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

 第四步:页面查看注册 

 

   

 

(2)服务消费者

第一步:依赖

<?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>

    <artifactId>spring-cloud-webfront</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-cloud-webfront</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>x.demo.springcloud</groupId>
        <artifactId>spring-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../../pom.xml</relativePath>
    </parent>

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

    <dependencies>
        <!-- test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- spring -->
        <!-- spring boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--rest client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>

        <!-- utils -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

 

第二步:application.yml 配置 EurekaClient,做服务发现

server:
  port: 20001
spring:
  application:
    name: webfront
eureka:
  client:
    service-url:
      defaultZone: http://localhost:50001/eureka/,http://localhost:50002/eureka/,http://localhost:50003/eureka/
  instance:
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    prefer-ip-address: true

 

 第三步:基于Feign的服务Client

package x.demo.springcloud.webfront.service.impl.feign;

import org.springframework.cloud.netflix.feign.FeignClient;
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.RequestParam;
import x.demo.springcloud.webfront.service.impl.ProtocolResult;

//name为服务提供者应用名称
@FeignClient(name = "microservice-time")
public interface TimeV1MicroServiceDiscoveryClient {

    @RequestMapping(method = RequestMethod.GET, value = "/time/v1/now", consumes = MediaType.APPLICATION_JSON_VALUE)
    ProtocolResult<String> now(@RequestParam(name = "format", required = false) String format);
}

第四步:Service,Controller

package x.demo.springcloud.webfront.service;

public interface TimeService {
    /**
     * 获取当前时间
     * @return 当前时间,格式:yyyy-MM-dd HH:mm:ss
     */
    String now();
}

 

@Service("timeV1FeignImpl")
public class TimeV1FeignImpl implements TimeService {

    @Resource
    private TimeV1MicroServiceDiscoveryClient timeV1MicroServiceDiscoveryClient;

    /**
     * 获取当前时间
     *
     * @return 当前时间,格式:yyyy-MM-dd HH:mm:ss
     */
    @Override
    public String now() {
        ProtocolResult<String> result = timeV1MicroServiceDiscoveryClient.now(null);
        return result.getBody();
    }
}

  

package x.demo.springcloud.webfront.web;

import javax.annotation.Resource;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import x.demo.springcloud.webfront.service.TimeService;

@RestController
@RequestMapping("/time")
public class TimeController {

    @Resource(name = "timeV1FeignImpl")
    private TimeService timeService;

    @GetMapping("/now")
    public String now() {
        return timeService.now();
    }
}

 

 第五步:启动集成@EnableDiscoveryClient (可以用@EnableEurekaClient 替代)

package x.demo.springcloud.webfront;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class SpringCloudWebfrontApplication {

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

 

第六步:验证


 

 

四 参考

https://springcloud.cc/spring-cloud-dalston.html  

 

猜你喜欢

转载自shihlei.iteye.com/blog/2400190