MyException - 我的异常网
当前位置:我的异常网» 云计算 » SpringCloud(3): 服务注册与发现,服务注册中心

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

www.MyException.Cn  网友分享于:2013-12-24  浏览:0次
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  

 

文章评论

漫画:程序员的工作
漫画:程序员的工作
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
 程序员的样子
程序员的样子
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
Java程序员必看电影
Java程序员必看电影
为什么程序员都是夜猫子
为什么程序员都是夜猫子
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
程序员应该关注的一些事儿
程序员应该关注的一些事儿
中美印日四国程序员比较
中美印日四国程序员比较
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
程序员都该阅读的书
程序员都该阅读的书
一个程序员的时间管理
一个程序员的时间管理
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
我是如何打败拖延症的
我是如何打败拖延症的
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
每天工作4小时的程序员
每天工作4小时的程序员
程序员必看的十大电影
程序员必看的十大电影
如何成为一名黑客
如何成为一名黑客
老程序员的下场
老程序员的下场
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
旅行,写作,编程
旅行,写作,编程
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
编程语言是女人
编程语言是女人
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
程序员的鄙视链
程序员的鄙视链
那些争议最大的编程观点
那些争议最大的编程观点
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
程序员和编码员之间的区别
程序员和编码员之间的区别
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有