当前位置: 移动技术网 > IT编程>开发语言>Java > 带你入门SpringCloud服务发现 | Eurka搭建和使用

带你入门SpringCloud服务发现 | Eurka搭建和使用

2019年09月01日  | 移动技术网IT编程  | 我要评论

前言

服务注册与发现是微服务中最为基础的环节,而 eureka 就是一个可以帮助你实现服务注册与发现的选择之一。如果你对 eureka 和服务发现了解甚少,那么该篇博客将会帮助到你。文中通过具体操作带你了解如下内容:

  1. 什么是服务注册与发现
  2. 什么是 eureka
  3. springcloud eureka 单台环境搭建
  4. springcloud eureka 高可用环境搭建
  5. springcloud eureka + resttemplate + ribbion 的使用
  6. springcloud feign + springcloud eureka 的使用

阅读本文需要你熟悉springboot项目的基本使用即可,还有一点需要注意的是在操作过程中尽量和我本地环境一致,因为环境不一致可能会带来一些问题。我本地环境如下:

springboot version: 2.1.0.release
springcloud version: greenwich.release
apache maven version: 3.6.0
java version: 1.8.0_144
idea:spring tools suite (sts)

服务注册与发现介绍

上面讲到服务发现是微服务中最为基础的环节,什么是服务发现呢 ?我们可以从单体架构说起,单体架构各个服务都在一起,是不需要被发现的。但是在微服务的架构中会出现很多的服务。服务与服务之间怎么获取调用地址url 呢 ?例如 一个商城网站有商品服务和订单服务。查询订单服务时需要从商品服务中获取商品的信息。

如果有1个订单服务和1 个商品服务,订单服务服务在配置文件中将商品服务的 url 配置在配置文件中即可。如果出现 2个商品服务,你可能会想到将2个商品服务url 配置到订单服务中。如果出现上千个服务呢?你可能发现这种方式不是一个好的方案。同时还有一个问题就是:商品服务宕机后。如何将宕机的服务从配置文件中剔除。

我们可以将商品服务的 url 地址信息都注册到统一的服务上,在调用时拉取所有商品服务的 url 信息。订单服务可以自定义负载均衡策略来选取一个 url 地址进行调用,如果注册中心发现某个商品服务已经宕机,可以将其从注册中心剔除。而今天的主角 eureka 就是通过这种机制来完成服务发现的。

接下来就正式开始今天的主角 eureka 的详细介绍!

eureka 是什么 ?

在介绍操作前,首先来了解一下 eureka 是什么?eureka 是 netflix 公司开源的一个基于 rest 服务的服务发现框架,主要用于aws云,用于定位服务,以实现中间层服务器的负载平衡和故障转移。springcloud 对 netflix 众多的开源框架都封装到其子项目spring-cloud-netflix 中,而 eureka 就是其中的一个。springcloud 可以通过 eureka 来完成微服务的服务注册与发现,当然你也可以使用其他的服务发现框架在 springcloud 中。

具体使用和介绍可以访问 eureka 的 github wiki 进行查看
https://github.com/netflix/eureka/wiki/
https://github.com/netflix/eureka/wiki/eureka-at-a-glance

闲话少说,开始我们的 eureka 环境搭建!

springcloud eureka 单台环境搭建

eureka server 端搭建

按下图所示打开springboot starter构建的窗口 file--new--spring starter project

file

勾选 eureka server

file

如果不勾选 eureka server 也可以在springboot项目中引入 spring-cloud-starter-netflix-eureka-server 依赖即可。代码如下:

        <dependency>
            <groupid>org.springframework.cloud</groupid>
            <artifactid>spring-cloud-starter-netflix-eureka-server</artifactid>
        </dependency>

在 springboot application上声明 @enableeurekaserver

file

在 application.properties 添加配置信息

server.port=8761
spring.application.name=eurekaserver
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultzone= http://localhost:8761/eureka/
eureka.server.enable-self-preservation=false

server.port: 配置服务端的端口号。
spring.application.name: 配置服务端应用名称.。
eureka.client.register-with-eureka: 是否将自己注册到服务端,eureka 服务端需要配置成false 默认是 true
eureka.client.fetch-registry:是否从其他eureka服务端获取注册信息,默认为true。如过是单台服务器可以设置为false。

eureka.server.enable-self-preservation:开启自我保护模式,默认为 true 表示为开启。开发中为了方便可以将其设置为false。
eureka.client.service-url.defaultzone:设置 eureka 服务端的地址,如果是单体服务就配置该 eureka 单台服务的 ip+端口号+/eureka。需要注意的是 /eureka 一定要加上。

自我保护模式介绍:

默认情况下,如果eureka server在一定时间内(默认90秒)没有接收到某个微服务实例的心跳,eureka server将会移除该实例。但是当网络分区故障发生时,微服务与eureka server之间无法正常通信,而微服务本身是正常运行的,此时不应该移除这个微服务,所以引入了自我保护机制。

自我保护机制的工作机制是如果在15分钟内超过85%的客户端节点都没有正常的心跳,那么eureka就认为客户端与注册中心出现了网络故障,eureka server自动进入自我保护机制,此时会出现以下几种情况:

1、eureka server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。 2、eureka server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用。 3、当网络稳定时,当前eureka server新的注册信息会被同步到其它节点中。

自我保护介绍内容摘抄自 —— java技术栈的博客: spring cloud eureka 自我保护机制 https://segmentfault.com/a/1190000015349644

如果 eureka.client.register-with-eureka=true 或者不配置该信息会,eureka 服务端本身也注册到服务端如下图所示:

file

eureka client 端搭建

首先在 springboot starter 构建的窗口 勾选 eureka discovery clientspring web starter 如下图所示:
file

需要注意的是如果没有勾选 spring web starter 客户端注册是注册不到服务端的。

如果不勾选,也可以直接在springboot项目中引入下面2个依赖来完成。

            <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-web</artifactid>
        </dependency>
        <dependency>
            <groupid>org.springframework.cloud</groupid>
            <artifactid>spring-cloud-starter-netflix-eureka-client</artifactid>
        </dependency>

然后在 springboot application 上声明 @enablediscoveryclient 如下图所示:
file

最后在 application.properties 配置如下信息:

server.port=8760
spring.application.name=eurekaclient
eureka.client.service-url.defaultzone= http://localhost:8762/eureka/

客户端的 eureka.client.service-url.defaultzone 配置和eureka server(eureka注册中心)配置一样。

访问 eureka server(eureka注册中心)端如下图所示中instances currently registered with eureka中查看注册的客户端。

file

如果你按照上述方式搭建并未成功,可以请参考我在github 项目 spring-cloud-get-started 仓库中模块名为: spring-cloud-eureka-single-service(eureka server)和 spring-cloud-eureka-single-service-client( eureka client)进行对比查看是否配置有误。

spring-cloud-get-started 项目地址:https://github.com/zhuoqianmingyue/spring-cloud-get-started

搭建高可用的 eureka 服务端

在生产环境中为保证 eureka 服务的高可用,我们需要搭建多台 eureka server(eureka注册中心)。eureka server(eureka注册中心)搭建集群还是比较简单的,只需要让各个服务端互相注册即可。官网搭建集群框架图如下:

file

我来举个例子,假如你有2台 eureka server 服务,名称分别为 eureka1、eureka2。

eureka1的配置: 需要将 eureka.client.service-url.defaultzone 配置成 eureka2 的服务地址。配置代码如下:
eureka.client.service-url.defaultzone=http://eureka2:8762/eureka/

eureka2 的配置 需要将 eureka.client.service-url.defaultzone 配置成 eureka1 的服务地址。配置代码如下:
eureka.client.service-url.defaultzone=http://eureka1:8761/eureka/

假如你有3台 eureka 服务名称分别为 eureka1、eureka2、eureka3。
eureka1的配置: 需要将 eureka.client.service-url.defaultzone 配置上 eureka2 和 eureka3的服务地址并用逗号分隔。
eureka.client.service-url.defaultzone=http://eureka2:8762/eureka/,http://eureka3:8763/eureka/
eureka2的配置: 需要将 eureka.client.service-url.defaultzone 配置上 eureka1 和 eureka3的服务地址并用逗号分隔。
eureka.client.service-url.defaultzone=http://eureka1:8761/eureka/,http://eureka3:8763/eureka/
eureka3的配置: 需要将 eureka.client.service-url.defaultzone 配置上 eureka1 和 eureka2的服务地址并用逗号分隔。
eureka.client.service-url.defaultzone=http://eureka1:8761/eureka/,http://eureka2:8762/eureka/

需要注意的是如果配置了 eureka.client.fetch-registry 需要将其改为 true,如果没有配置可以忽略。eureka.client.fetch-registry 表示可以从其他 eureka server 获取注册信息。
还有一点需要注意的是,eureka.client.serviceurl.defaultzone 配置不能使用 localhost。
如果你使用的是windows 系统,并且只有一台机器的情况下,需要在 hosts 中配置三个域名信息。
file
file

我本地代码服务端和客户端搭建具体配置:

客户端和服务端引入依赖和添加@enablexxx的注解比较简单,我这里就不在详细说明了。可以参考 springcloud eureka 单台环境搭建 中的介绍。

主要需要注意的是 application.properties 中的配置,以下是我本地服务端和客户端配置详细信息:

eureka服务1的配置

server.port=8761
spring.application.name=multiserviceeurekaserver1
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=true
eureka.client.service-url.defaultzone=http://multiserviceeurekaserver2:8762/eureka/,http://multiserviceeurekaserver3:8763/eureka/
eureka.server.enable-self-preservation=falses

eureka服务2的配置

server.port=8762
spring.application.name=multiserviceeurekaserver2
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=true
eureka.client.service-url.defaultzone=http://multiserviceeurekaserver1:8761/eureka/,http://multiserviceeurekaserver3:8763/eureka/
eureka.server.enable-self-preservation=false

eureka服务3的配置

server.port=8763
spring.application.name=multiserviceeurekaserver3
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=true
eureka.client.service-url.defaultzone=http://multiserviceeurekaserver1:8761/eureka/,http://multiserviceeurekaserver2:8762/eureka/
eureka.server.enable-self-preservation=false

客户端的配置

server.port=8760
spring.application.name=multiserviceeurekaclient
eureka.client.service-url.defaultzone=http://www.lhsxpumps.com/_multiserviceeurekaserver1:8761/eureka/,http://multiserviceeurekaserver2:8762/eureka/,http://multiserviceeurekaserver3:8763/eureka/

eureka服务1 控制台界面信息:
file

eureka服务2 控制台界面信息:
file

eureka服务3 控制台界面信息:
file

如果你按照上述方式搭建并未成功,可以参考我在 github 项目 spring-cloud-get-started 仓库中模块名为:
spring-cloud-eureka-multi-service-server1(multiserviceeurekaserver1)
spring-cloud-eureka-multi-service-server2(multiserviceeurekaserver2)
spring-cloud-eureka-multi-service-server3(multiserviceeurekaserver3)
spring-cloud-eureka-multi-service-client(multiserviceeurekaclient)
进行对比查看是否配置有误。

spring-cloud-get-started 项目地址:https://github.com/zhuoqianmingyue/spring-cloud-get-started

springcloud eureka + resttemplate + ribbion 使用

上面我们介绍如何搭建单机版和高可用版的 eureka 环境,接下来我们来介绍如果通过 resttemplate + ribbion 从 eureka server 调用我们的 eureka 客户端服务的 api 接口。

调用的流程是:消费端从 eureka server 获取我们要调用具体服务生产者(eureka 客户端)的所有 url 地址信息,然后通过 ribbion 的负载策略选取一个服务地址。最后通过resttemplate 进行调用具体服务 api 接口。

我通过一台 eureka server( eureka注册中心服务)端 和 2个商品服务(eureka客户端),外加一个服务消费者订单服务(eureka客户端)。通过订单服务从 eureka 注册中心服务获取2个商品服务(eureka客户端)地址url并通过 ribbion 负载策略选取其中一个商品服务url 进行服务的调用。

** eureka server 注册中心服务的搭建:**

添加 spring-cloud-starter-netflix-eureka-server 依赖,然后再 springboot application 上声明 @enableeurekaserver,最后在 application.properties 中添加相关配置信息。

spring-cloud-starter-netflix-eureka-server 依赖配置如下:

        <dependency>
            <groupid>org.springframework.cloud</groupid>
            <artifactid>spring-cloud-starter-netflix-eureka-server</artifactid>
        </dependency>

application.properties 具体配置信息如下:

server.port=8761
spring.application.name=eurekaserver
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultzone=http://localhost:8761/eureka/
eureka.server.enable-self-preservation=false

** 2个 商品服务 (eureka 客户端)搭建:**

添加 spring-cloud-starter-netflix-eureka-client 依赖,然后再 springboot application 上声明 @enablediscoveryclient ,最后在 application.properties 中添加相关配置信息。

分别在商品服务1 和商品服务2 中定义一样的 restful 接口,并通过返回不同的商品名称以示区分。

spring-cloud-starter-netflix-eureka-client 依赖配置如下:

            <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-web</artifactid>
        </dependency>
        <dependency>
            <groupid>org.springframework.cloud</groupid>
            <artifactid>spring-cloud-starter-netflix-eureka-client</artifactid>
        </dependency>

商品服务1 配置信息:

server.port=8760
spring.application.name=productserver
eureka.client.service-url.defaultzone=http://localhost:8761/eureka/

商品服务1 api 接口代码如下:

@restcontroller
public class productcontroller {
    
    @getmapping("/product/{id}")
    public product productinfo(@pathvariable(name="id")long productid) {
        product product = new product();
        product.setid(productid);
        product.setname("product 1:"+"苹果");
        product.setprice(12d);
        return product;
    }
}

商品服务 2 配置信息:

server.port=8770
spring.application.name=productserver
eureka.client.service-url.defaultzone=http://localhost:8761/eureka/

商品服务 2 api 接口代码如下:

@restcontroller
public class productcontroller {
    
    @getmapping("/product/{id}")
    public product productinfo(@pathvariable(name="id")long productid) {
        product product = new product();
        product.setid(productid);
        product.setname("product 2:"+"苹果");
        product.setprice(12d);
        return product;
    }
}

商品类的代码如下

public class product {
    
    private long id;
    private string name;
    private double price;
    //省略 getter 和 setter
}

订单服务(eureka客户端)搭建:

添加 spring-cloud-starter-netflix-eureka-client 依赖,然后再 springboot application 上声明 @enablediscoveryclient ,最后在 application.properties 中添加相关配置信息。

server.port=8762
spring.application.name=orderservice
eureka.client.service-url.defaultzone=http://localhost:8761/eureka/

商品服务的调用需要使用到 resttemplate,所以需要配置 resttemplate 到spring的上下文中。具体代码如下:

@configuration
public class resttemplateconfig {
    @bean
    public resttemplate buildresttemplate() {
        return new resttemplate();
    }
}

通过 loadbalancerclient 的 choose 方法来获取 serviceinstance,serviceinstance 就是2个 商品服务(productserver)其中一个服务信息,loadbalancerclient 是 springcloud 获取服务的抽象。具体实现是通过 spring-cloud-netflix-ribbon 项目中 ribbonloadbalancerclient 来实现的。通过 serviceinstance 获取商品服务(productserver)的服务地址 url。然后通过 resttemplate 调用 api 接口。具体代码如下:

@restcontroller
public class productcontroller {
    
    @autowired
    private loadbalancerclient loadbalancerclient;
    @autowired
    private resttemplate resttemplate;
    
    @requestmapping("/product/{id}")
    public string productinfo(@pathvariable(name="id")long productid) {
        
        serviceinstance serviceinstance = loadbalancerclient.choose("productserver");
        uri uri = serviceinstance.geturi();
        string url = uri.tostring()+"/product/"+productid;
        responseentity<string> forentity = resttemplate.getforentity(url, string.class);
        string message = forentity.getbody();
        
        return message;
    }
}

我们也可以通过使用 @loadbalanced 注解来完成上述操作,使用@loadbalanced注解的方式相对上面使用 loadbalancerclient 代码简洁了不少。具体操作如下:

在 resttemplateconfig 构建方法上添加 @loadbalanced 注解。具体代码如下:

@configuration
public class resttemplateconfig {
    @bean
    @loadbalanced
    public resttemplate buildresttemplate() {
        return new resttemplate();
    }
}

在productcontroller 中无需在注入 loadbalancerclient,直接使用 resttemplate 调用即可。具体代码如下:

@restcontroller
public class productcontroller {
    
    @autowired
    private resttemplate resttemplate;
    
    @requestmapping("/product/{id}")
    public string productinfo(@pathvariable(name="id")long productid) {
        
        string url = "http://productserver/product/"+productid;
        responseentity<string> forentity = resttemplate.getforentity(url, string.class);
        string message = forentity.getbody();
        
        return message;
    }
}

测试:

整个测试过程需要启动 一台 注册中心服务、2台商品服务、1台订单服务,个人建议注册中心服务和商品服务通过java -jar的方式启动,而订单服务通过 idea 来启动。当然你可以可以都在idea 中进行启动所有的服务。

启动 eureka 注册中心服务:
进入 eureka 注册中心服务目录执行打包命令 mvn clean package -dmaven.test.skip=true。会生成一个可执行的 jar 包如下图所示:
file
然后进入 target目录 执行 java -jar jar包的名称,如下图所示:
file
如下图所示:eureka 注册服务启动成功!
file

启动商品服务:
进入商品服务项目的目录,打包并且通过 java -jar 启动商品服务1项目。具体操作如下图所示:
file
file
商品 2服务操作和上述一致,这里就不再进行演示

最后访问服务注册服务,查看商品1和商品2服务是否注册到注册中心服务中,如下图所示表示注册成功!
file

启动订单服务:
通过下图的方式启动订单服务:
file
file
访问 http://www.lhsxpumps.com/_localhost:8762/product/1 从订单服务中获取商品服务的信息,如下图所示它会以轮询的方式调用商品服务1 和商品服务2。
file
file

如果你按照上述方式搭建并未成功,可以参考我在github 项目 spring-cloud-get-started 仓库中模块名为:
spring-cloud-eureka-ribbion-service ( eureka server 服务注册中心 eurekaserver )
spring-cloud-eureka-ribbion-product (商品服务1)
spring-cloud-eureka-ribbion-product2(商品服务2)
spring-cloud-eureka-ribbion-service-order-consume(订单服务)
spring-cloud-eureka-ribbion-service-order-consume-annotation(订单服务注解版)
进行对比查看是否配置有误。

spring-cloud-get-started 项目地址:https://github.com/zhuoqianmingyue/spring-cloud-get-started

springcloud feign + springcloud eureka 使用

调用 eureka 客户端服务还可以通过 springcloud feign 来进行操作。feign的底层还是使用ribbion。

接下来我们开始 springcloud feign 是用操作流程介绍,看到这里你有没有发springcloud 使用的套路。这个套路拢共分三步:
1.引入组件 starter依赖。
2.application 上添加@enablexxx注解。
3.appcation.properties上进行添加相关配置信息。

springcloud feign也绕不开这个套路,第一步及先在订单服务添加 feign starter。具体依赖代码如下:

html <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-netflix-eureka-client</artifactid> </dependency> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-openfeign</artifactid> </dependency>

第二步是在 springboot application上声明 @enablefeignclients 如下图所示:

file

第三步是在application.properties中配置 eureka客户端的配置,具体配置信息如下:

html server.port=8762 spring.application.name=orderservice eureka.client.service-url.defaultzone=http://localhost:8761/eureka/

第四步是在 resttemplateconfig 构建方法上声明 @loadbalanced

@configuration
public class resttemplateconfig {
    @bean
    @loadbalanced
    public resttemplate buildresttemplate() {
        return new resttemplate();
    }
}

第五步是创建调用接口,并在接口上声明 @feignclient(name="productserver") 其中name的值是调用服务的名称。在声明调用的方法 @requestmapping()中配置 url 和商品服务 api 接口一样即可。

@feignclient(name="productserver")
public interface productclient {
    @getmapping("/product/{id}")
    public product productinfo(@pathvariable(name="id")long productid);
}

第六步开始编写调用的测试类,在productcontroller 中引入 personclient 然后调用productclient 调用方法即可。

@restcontroller
public class productcontroller {
    
    @autowired
    private productclient personclient;
    
    @requestmapping("/product/{id}")
    public product productinfo(@pathvariable(name="id")long productid) {
        product product = personclient.productinfo(productid);
        return product;
    }
}

测试:

feign 使用 和 ribbion 使用是一样的服务注册中心和商品服务,启动方式请参考上面feign 使用操作介绍。

访问 http://www.lhsxpumps.com/_localhost:8762/product/1 调用订单服务,和使用ribbion方式效果一致。具体访问结果如下:

file

file

springcloud feign + springcloud eureka 使用springcloud eureka + resttemplate + ribbion 使用 共用 eureka 服务端和服务生产者的项目,如果搭建过程中遇到问题可以参考我在github 项目 spring-cloud-get-started 仓库中模块名为: spring-cloud-eureka-feign-service-order-consume 进行对比即可。

spring-cloud-get-started 项目地址:https://github.com/zhuoqianmingyue/spring-cloud-get-started

小结

springcloud eureka 搭建和使用只要你掌握了搭建三步法:1.引入组件 starter依赖、2.application 上添加@enablexxx注解、3.appcation.properties上进行添加相关配置信息。关于具体的配置可以结合 spring 官网文档进行查阅。

参考文献

https://spring.io/guides/gs/service-registration-and-discovery/
https://cloud.spring.io/spring-cloud-netflix/reference/html/
https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-ribbon.html
http://seymours.cn/articles/2018/09/19/1537338458105.html

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网