spring cloud 注册cloud怎么注册同一个服务多个实例

2161人阅读
spring boot(1)
本案例来自于spring官网:
JDK要求1.8或以上版本。
首先创建两个项目,eureka-service和eureka-client。
eureka-server作为eureka的服务端,提供注册服务,eureka-client作为eureka的客户端,属于一个应用,注册到eureka注册中心。
eureka-service的配置文件pom.xml如下:
&?xml version="1.0" encoding="UTF-8"?&
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"&
&com.example&
&eureka-service&
&0.0.1-SNAPSHOT&
&org.springframework.boot&
&spring-boot-starter-parent&
&1.3.5.RELEASE&
&org.springframework.cloud&
&spring-cloud-starter-eureka-server&
&org.springframework.boot&
&spring-boot-starter-test&
&org.springframework.cloud&
&spring-cloud-starter-parent&
&Brixton.SR3&
&org.springframework.boot&
&spring-boot-maven-plugin&
eureka-service项目中创建包,自定,本例为:com.spring
在该包下创建类用于启动服务EurekaServiceApplication.java
package com.
import org.springframework.boot.SpringA
import org.springframework.boot.autoconfigure.SpringBootA
import org.springframework.cloud.netflix.eureka.server.EnableEurekaS
@EnableEurekaServer
@SpringBootApplication
public class EurekaServiceApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServiceApplication.class, args);
关于eureka-service的配置文件 applicaiton.yml 或者使用application.properties,两者格式不同。
application.yml
port: 8761
#指定服务端口
registerWithEureka: false
#是否将eureka自身作为应用注册到eureka注册中心
fetchRegistry: false
#为true时,可以启动,但报异常:Cannot execute request on any known server
简单的eureka-service就写好了,运行下EurekaServiceApplication.java
关于eureks-client 的pom.xml文件如下,因为不提供其他服务,这里基本与eureka-service一样:
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"&
&com.huawei.it&
&eureka-client&
&0.0.1-SNAPSHOT&
&org.springframework.boot&
&spring-boot-starter-parent&
&1.3.5.RELEASE&
&org.springframework.cloud&
&spring-cloud-starter-parent&
&Brixton.SR3&
&org.springframework.cloud&
&spring-cloud-starter-eureka&
&org.springframework.boot&
&spring-boot-starter-test&
&org.springframework.boot&
&spring-boot-maven-plugin&
同样创建入口类EurekaClientApplication.java
package com.spring
import java.util.List
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.cloud.client.ServiceInstance
import org.springframework.cloud.client.discovery.DiscoveryClient
import org.springframework.cloud.client.discovery.EnableDiscoveryClient
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@EnableDiscoveryClient
//通过该注解,实现服务发现,注册
@SpringBootApplication
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args)
@RestController
class ServiceInstanceRestController {
@Autowired
private DiscoveryClient discoveryClient
@RequestMapping("/service-instances/{applicationName}")
public List&ServiceInstance& serviceInstancesByApplicationName(
@PathVariable String applicationName) {
return this.discoveryClient.getInstances(applicationName)
@RequestMapping("/")
public String sayhello() {
return "hello"
关于eureka-client的配置文件bootstrap.yml和application.yml,
bootstrap.yml先于application.yml加载,一般不变的东西卸载bootstrap里,使用一样:
application.yml
port: 7070
application:
name: cloud-client
#为你的应用起个名字,该名字将注册到eureka注册中心
好了,现在启动eureka-client,再次访问,可能需要等一会
,这里我把应用名改了
会出现关于应用的信息:
这里因为两个都部署在同一台机器上,所以可以直接发现服务,并注册,如果在不同的机器上不部署,application.yml配置中需要加上eureka的地址如,多个eureka服务地址,可以用,号隔开:
serviceUrl:
defaultZone: http:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2298次
排名:千里之外
(1)(1)(1)(1)spring cloud(8)
近期因工作原因减缓了更新频率,同时为了把搭建起来也费了不少时间,几乎每天都在挤牙膏般的凑时间出来做一些有意义的事。未能按原计划更新博文,在此对持续关注我博客的朋友们深表歉意。
之前在写Spring Cloud系列文章的时候,列过一个较粗的计划,现在由于收到不少反馈和问题,因此准备做一些调整,先将一些大家关注较为集中的点拉出来写一些内容。
今天这篇主要就说说Eureka Server的高可用问题。
在系列文章的开始,我们就介绍了,其中,主要演示了如何构建和启动服务注册中心Eureka
Server,以及如何将服务注册到Eureka Server中,但是在之前的示例中,这个服务注册中心是单点的,显然这并不适合应用于线上生产环境,那么下面在前文的基础上,我们来看看该如何构建高可用的Eureka Server集群。
单点Eureka Server的样例:
Server的高可用
Eureka Server除了单点运行之外,还可以通过运行多个实例,并进行互相注册的方式来实现高可用的部署,所以我们只需要将Eureke Server配置其他可用的serviceUrl就能实现高可用部署。
下面以中的eureka-server为基础,对其改造,构建双节点的服务注册中心。
创建application-peer1.properties,作为peer1服务中心的配置,并将serviceUrl指向peer2
spring.application.name=eureka-serverserver.port=1111eureka.instance.hostname=peer1eureka.client.serviceUrl.defaultZone=http://peer2:1112/eureka/
创建application-peer2.properties,作为peer2服务中心的配置,并将serviceUrl指向peer1
spring.application.name=eureka-serverserver.port=1112eureka.instance.hostname=peer2eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/
在/etc/hosts文件中添加对peer1和peer2的转换
127.0.0.1 peer1127.0.0.1 peer2
通过spring.profiles.active属性来分别启动peer1和peer2
java -jar eureka-server-1.0.0.jar --spring.profiles.active=peer1java -jar eureka-server-1.0.0.jar --spring.profiles.active=peer2
此时访问peer1的注册中心:http://localhost:1111/,如下图所示,我们可以看到registered-replicas中已经有peer2节点的eureka-server了。同样地,访问peer2的注册中心:http://localhost:1112/,能看到registered-replicas中已经有peer1节点,并且这些节点在可用分片(available-replicase)之中。我们也可以尝试关闭peer1,刷新http://localhost:1112/,可以看到peer1的节点变为了不可用分片(unavailable-replicas)。
服务注册与发现
在设置了多节点的服务注册中心之后,我们主需要简单需求服务配置,就能将服务注册到Eureka Server集群中。我们以中的compute-service为基础,修改application.properties配置文件:
spring.application.name=compute-serviceserver.port=2222eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/
上面的配置主要对eureka.client.serviceUrl.defaultZone属性做了改动,将注册中心指向了之前我们搭建的peer1与peer2。
下面,我们启动该服务,通过访问http://localhost:1111/和http://localhost:1112/,可以观察到compute-service同时被注册到了peer1和peer2上。若此时断开peer1,由于compute-service同时也向peer2注册,因此在peer2上其他服务依然能访问到compute-service,从而实现了高可用的服务注册中心。
虽然上面我们以双节点作为例子,但是实际上因负载等原因,我们往往可能需要在生产环境构建多于两个的Eureka Server节点。那么对于如何配置serviceUrl来让集群中的服务进行同步,需要我们更深入的理解节点间的同步机制来做出决策。
Eureka Server的同步遵循着一个非常简单的原则:只要有一条边将节点连接,就可以进行信息传播与同步。什么意思呢?不妨我们通过下面的实验来看看会发生什么。
场景一:假设我们有3个注册中心,我们将peer1、peer2、peer3各自都将serviceUrl指向另外两个节点。换言之,peer1、peer2、peer3是两两互相注册的。启动三个服务注册中心,并将compute-service的serviceUrl指向peer1并启动,可以获得如下图所示的集群效果。
访问http://localhost:1112/,可以看到3个注册中心组成了集群,compute-service服务通过peer1同步给了与之互相注册的peer2和peer3。
场景二:依然假设我们有3个注册中心,我们将peer1的serviceUrl指向peer2,peer2的指向peer3,peer3的指向peer1,此时peer1、peer2、peer3通过单向边形成环。分别启动peer1、peer2、peer3,并访问信息页面,我们可以找到下面的规律,peer1成为了peer2的分片节点,peer2成为了peer3的分片节点,peer3则成为了peer1的分片节点,再将compute-service的serviceUrl指向peer1并启动。放别访问peer1、peer2、peer3的信息页面,可以发现compute-service均被peer2和peer3同步过去了,所以单向边也能进行服务的传播与同步。此时,我们断开peer2,可以看到peer3中的compute-service消失了。重新开启peer2并断开peer3,可以看到peer2依然能同步到compute-service。所以我们可以得出结论,Eureka
Server的传播与同步是具备方向性的。
通过上面的实验,我们可以得出下面的两点结论来指导我们搭建服务注册中心的高可用集群:
两两注册的方式可以实现集群中节点完全对等的效果,实现最高可用性集群,任何一台注册中心故障都不会影响服务的注册与发现
Eureka Server具备单方面有指向的服务传播与同步机制,在一些对服务发现有限制的情况下,可以利用这样的机制进行服务注册与发现的的单向控制
更多讨论可前往:
本文完整示例可参考
【转载请注明出处】:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:29968次
排名:千里之外
原创:13篇
转载:57篇
(9)(8)(1)(4)(49)966,690 一月 独立访问用户
语言 & 开发
架构 & 设计
文化 & 方法
您目前处于:
使用Spring Cloud连接不同服务
使用Spring Cloud连接不同服务
日. 估计阅读时间:
欲知区块链、VR、TensorFlow等潮流技术和框架,请锁定
假设打算通过一系列微服务实现一个应用程序,可以使用与单层系统类似的连接选项。依存项的地址可硬编码到程序中,借此将服务紧密连接在一起。或者也可以将所依赖的服务地址外化,并在部署或运行的时候提供这些服务。本文将介绍在微服务应用程序的构建过程中,如何通过Spring Boot和Spring Cloud实现这些选项。
我们假设了下图所示的一个名为repmax的简单微服务系统:
相关厂商内容
Repmax系统
Repmax应用程序可以记录追踪用户的举重成绩,并用每次举重前五名选手的成绩生成排行榜。其中logbook服务负责通过UI收集每次练习的数据并存储每位用户的完整历史信息。当用户在练习完毕录入成绩后,logbook会将此次举重的详细信息发送至leaderboard服务。
从图中可以看到,logbook服务需要依赖leaderboard服务。从最佳实践的角度考虑,我们将这个依存项抽象为LeaderBoardApi接口:public interface LeaderBoardApi {
void recordLift(Lift lift);
由于这是个Spring应用程序,需要使用RestTemplate处理logbook和leaderboard服务之间通信的细节:abstract class AbstractLeaderBoardApi implements LeaderBoardApi {
private final RestTemplate restT
public AbstractLeaderBoardApi() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
this.restTemplate = restT
public final void recordLift(Lifter lifter, Lift lift) {
URI url = URI.create(String.format("%s/lifts", getLeaderBoardAddress()));
MultiValueMap&String, String& params = new LinkedMultiValueMap&&();
params.set("exerciseName", lift.getDescription());
params.set("lifterName", lifter.getFullName());
params.set("reps", Integer.toString(lift.getReps()));
params.set("weight", Double.toString(lift.getWeight()));
this.restTemplate.postForLocation(url, params);
protected abstract String getLeaderBoardAddress();
AbstractLeaderBoardApi类可以捕获针对leaderboard服务创建POST请求的全部逻辑,并可通过子类指定leaderboard服务的准确地址。
将多个微服务相互连接最简单的方法可能就是将每个服务需要的依存项地址硬编码到程序中。这相当于在单层系统的世界中通过硬编码的方式实现依赖项的具现化(Instantiation)。这一点可以在StaticWiredLeaderBoardApi类中轻松实现:public class StaticWiredLeaderBoardApi extends AbstractLeaderBoardApi {
protected String getLeaderBoardAddress() {
return "http://localhost:8082";
硬编码方式指定的服务地址使得我们能够快速上手,但在现实环境中这样做有些不太实际。服务的每个不同部署需要自定义编译,这一做法很快会变得充满痛苦并且容易出错。
如果要部署的是单层系统,并且希望对应用程序进行重构以消除硬编码的地址,首先需要将地址信息外化至配置文件。微服务应用程序也可以使用相似的方法:将地址信息推送至配置文件,并让所实现的API从配置中读取地址。
Spring Boot使得配置参数的定义和注入工作变得更简单。只要将地址参数加入application.properties文件即可:leaderboard.url=http://localhost:8082
随后可以使用@Value标注(Annotation)将这个参数注入ConfigurableLeaderBoardApi:public class ConfigurableLeaderBoardApi extends AbstractLeaderBoardApi {
private final String leaderBoardA
@Autowired
public ConfigurableLeaderBoardApi(@Value("${leaderboard.url}") String leaderBoardAddress) {
this.leaderBoardAddress = leaderBoardA
protected String getLeaderBoardAddress() {
return this.leaderBoardA
Spring Boot对的支持使得我们不仅可以通过修改配置文件更改leaderboard.url的值,而且可以在启动应用程序时指定环境变量:LEADERBOARD_URL=/leaderboard java -jar repmax-logbook-1.0.0-RELEASE.jar
随后即可在不更改代码的情况下将logbook服务实例指向任何一个leaderboard服务实例。如果系统符合原则,环境中很可能已经包含了连接信息,因此可通过简单的工作将其直接映射至应用程序。
诸如和等平台即服务(PaaS)系统会将数据库和消息系统等托管服务的连接信息暴露到环境中,这样即可用完全相同的方式连接这些依赖项。实际上,将两个服务连接在一起,以及将一个服务与相应的数据存储连接在一起,这两种做法并没有什么本质差异,都只是将两个分布式系统连接在一起。
超越点对点连接
对于比较简单的应用程序,为依存项的地址使用外部配置就已足够。然而对于任何规模的应用程序,我们需要的可能不仅仅是简单的点对点连接,可能还希望实现某种形式的负载平衡。
如果每个服务都直接依赖某一下游服务实例,下游出现的任何故障都可能造成最终用户遇到严重问题。同理,如果下游服务超载,用户将会面临响应时间延长的问题。此时我们需要的是负载平衡。
与其直接依赖一个下游实例,我们更希望通过一组下游服务实例分摊负载。如果这些实例中有一个故障或超载,其他实例可以接手处理任务。为这种体系结构实现负载平衡的最简单方法是使用负载平衡代理。下图展示了在Amazon Web Services部署中使用Elastic Load Balancing实现这种方式的具体做法:
为排行榜应用ELB
这种情况下无需让logbook服务直接与leaderboard服务通信,而是可以使用ELB对每个请求进行路由。ELB会将每个请求路由至某一后端leaderboard服务。通过让ELB充当中介,可将负载分摊到多个leaderboard实例,这有助于减少每个实例的负担。
ELB的负载平衡是动态的,运行过程中可以给后端添加新的实例,因此如果传入流量激增,即可启动更多leaderboard实例加以应对。
Spring Boot应用程序可使用暴露供ELB定期监控的/health端点。能够响应此类运行状况检查操作的实例会保留在ELB的活跃集(Active set)中,如果多次检查均未响应,相应的实例会从服务中移除。
在我们的系统中,leaderboard服务不是唯一能通过负载平衡获益的服务。logbook服务以及前端UI均能借助负载平衡机制实现更好的可扩展性和弹性。
动态重配置
无论使用、,或者使用HAProxy或NGINX自行搭建负载平衡代理,都需要将服务与负载平衡器相互连接。
此时一种方法是为每个负载平衡器提供一个「众所周知」的DNS名称,例如leaderboard.repmax.local,并使用上文提到的静态连接方式将其硬编码至应用程序中。由于DNS系统本身的灵活性,这种方法已经可以做到相当灵活。然而使用硬编码的名称意味着要在运行服务的每个环境中配置一台DNS服务器。在开发过程中,由于需要为多种多样的操作系统提供支持,提供定制化DNS的操作就显得尤为麻烦。此时更好的做法是使用类似上文leaderboard.url的例子那样,将负载平衡器的地址自然地注入服务。
在AWS和GCP等云环境中,负载平衡器(及其地址)会频繁变动。当负载平衡器被删除并重建后,通常会使用一个新的地址。如果将负载平衡器的地址硬编码到程序中,为了应对地址的变化,必须在每次改变后重新编译代码。但通过使用外化的配置,只需更改配置文件并重启动服务即可。
为了应对负载平衡器地址不断变化这一本质,DNS是一种很方便的做法。每个负载平衡器都可分配一个固定的DNS名称,并将这个名称注入所调用的服务。在重建负载平衡器时,其DNS名称可重映射至负载平衡器的新地址。如果准备在环境中运行DNS服务器,就很适合使用这种基于DNS的方法。如果不想运行DNS,但依然希望对负载平衡器进行动态重配置,此时可以考虑使用。
Spring Cloud Config会运行一个名为Config Server的小巧服务,并通过REST API提供可集中访问的配置数据。默认情况下配置数据存储在一个Git仓库中,并可通过标准的PropertySource抽象暴露给Spring Boot服务。使用PropertySource可将本地属性文件中包含的配置与Config Server中存储的配置无缝结合在一起。对于本地开发,可以使用来自本地属性文件的配置,并只在将应用程序部署在现实环境时才覆盖这些配置信息。
为使用Spring Cloud Config取代ConfigurableLeaderBoardApi,首先可以用所需配置初始化一个Git代码库:mkdir -p ~/dev/repmax-config-repo
cd ~/dev/repmax-config-repo
echo 'leaderboard.lb.url=http://some.lb.address' && repmax.properties
git add repmax.properties
git commit -m 'LB config for the leaderboard service'
repmax.properties文件中包含repmax应用程序default配置文件的设置。如果希望将配置加入其他配置文件,例如加入development,此时只需要提交另一个名为repmax-development.properties的文件即可。
若要运行Config Server,可以运行spring-cloud-config-server项目提供的默认Config Server,或自行创建一个简单的Spring Boot项目并承载下列Config Server:@SpringBootApplication
@EnableConfigServer
public class RepmaxConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(RepmaxConfigServerApplication.class, args);
其中@EnableConfigServer标注可用于通过小巧的Spring Boot应用程序启动Config Server。随后可以用spring.cloud.config.server.git.uri属性将Config Server指向Git代码库。对于本地测试工作,可将其加入Config Server应用程序的application.properties文件:spring.cloud.config.server.git.uri=file://${user.home}/dev/repmax-config-repo
通过这种方式,团队中的每位开发者都可以在自己的计算机上启动Config Server,并通过本地Git代码库进行测试。若要验证repmax应用程序的属性是否已通过Config Server暴露,可在Config Server运行后使用浏览器访问http://localhost:8888/repmax/default:
在Config Server中浏览配置信息
从图中可以看到,leaderboard.lb.url属性已通过repmax.properties文件暴露,其值为http://localhost:8083。JSONT载荷的version属性显示了加载配置时所用的Git版本。
在生产环境中,可以充分借助PropertySource抽象将Git代码库的名称以环境变量的方式提供:SPRING_CLOUD_CONFIG_SERVER_GIT_URI=/rdh/repmax-config-repo java -jar repmax-config-server-1.0.0-RELEASE.jar
Spring Cloud Config Client
修改logbook服务使其从新增的Config Server中读取配置,这一过程只需要几个简单的步骤。首先在build.gradle文件中为spring-cloud-starter-config`增加一个依存项;compile("org.springframework.cloud:spring-cloud-starter-config:1.1.1.BUILD-SNAPSHOT")
随后提供Config Client所需的基本自举配置。考虑到Config Server会通过一个名为repmax.properties的文件暴露配置,此时要向Config Client提供应用程序的名称。此类自举配置位于logbook服务的bootstrap.properties文件中:spring.application.name=repmax
默认情况下,Config Client会通过http://localhost:8888查找Config Server。若要修改这个地址,可在启动客户端应用程序时指定SPRING_CLOUD_CONFIG_URI环境。
一旦客户端,即本例中的logbook启动后,即可访问http://localhost:8081/env以确认来自Config Server的配置是否正确加载:
确认Config Client可以访问Config Server
将logbook服务配置为使用Config Client后,可修改ConfigurableLeaderBoardApi以从Config Server暴露的leaderboard.lb.url属性中获取负载平衡器的地址。
启用动态刷新
通过将配置信息集中存储在一个位置,可以轻松更改repmax配置,使其能够被所有服务直接使用。然而为了应用这些配置依然需要重启动服务。实际上可以通过更好的方式实现。可以借助Spring Boot提供的@ConfigurationProperties标注将配置直接映射给JavaBeans。Spring Cloud Config更进一步为每个客户端服务暴露了一个/refresh端点。带有@ConfigurationProperties标注的Bean可在通过/refresh端点触发刷新后更新自己的属性。
任何Bean均可添加@ConfigurationProperties标注,但是有必要对刷新操作进行限制,只应用于包含配置数据的Bean。为此可以用一个专门用于保存leaderboard地址的LeaderboardConfig Bean:@ConfigurationProperties("leaderboard.lb")
public class LeaderboardConfig {
private volatile S
public String getUrl() {
return this.
public void setUrl(String url) {
this.url =
@ConfigurationProperties标注的值实际上是希望映射至Bean的配置值的前缀。随后每个值可使用标准的JavaBean命名规则进行映射。这种情况下,url Bean属性可映射至配置中的leaderboard.lb.url。
随后要修改ConfigurableLeaderBoardApi以接受LeaderboardConfig实例,而非原始的leaderboard地址:public class ConfigurableLeaderBoardApi extends AbstractLeaderBoardApi {
private final LeaderboardC
@Autowired
public ConfigurableLeaderBoardApi(LeaderboardConfig config) {
this.config =
protected String getLeaderBoardAddress() {
return this.config.getLeaderboardAddress();
为了触发配置刷新操作,可向logbook服务的/refresh端点发送一个HTTP POST请求:curl -X POST http://localhost:8081/refresh
有关服务发现
通过使用Spring Cloud Config,并在logbook和leaderboard服务之间使用负载平衡代理,应用程序已经基本完成了。然而还需要进行一定的完善。
如果在AWS或GCP中部署,可以充分利用这些环境中提供的高弹性负载平衡器,但如果使用诸如HAProxy或NGINX之类的市售负载平衡代理产品,此时必须自行处理服务的发现和注册工作。leaderboard的每个新增实例,以及每个因为故障要从代理中移除的实例,都必须在代理中进行配置。我们真正需要的是动态发现技术,每个服务实例都需要能自行注册以供发现和使用。
使用负载平衡代理的情况下还存在另一个潜在问题:可靠性。由于所有流量需要通过代理进行路由,因此整个系统的可靠性都受制于代理本身的可靠性。代理停机同时会导致整个系统停机。此外还需要考虑客户端和代理之间,以及代理和服务器之间通信所产生的开销。
为解决这些问题Netflix开发了Eureka。Eureka是一种用于提供服务注册和发现能力的客户端-服务器系统。服务实例启动后,可将自己与Eureka服务器进行注册。诸如logbook等客户端服务可以联系Eureka服务器以获取可用服务列表。客户端和服务器之间采用了点对点的通信方式。
Eureka使得我们不再需要代理,这样可以改善整个系统的可靠性。如果leaderboard代理故障,logbook服务将完全无法联系leaderboard服务。通过使用Eureka,logbook可以知道所有可用leaderboard实例,就算一个实例故障,logbook也只需要联系下一个leaderboard实例并重试。
那么在整个系统体系结构中,Eureka服务器本身是否会成为一个故障点?抛开为Eureka服务器创建集群这种做法不谈,每个Eureka客户端都可以在本地缓存服务的运行状态。只要在Eureka服务器上运行了服务监视器,例如systemd,就可以顺利应对偶尔出现的崩溃等问题。
与Config Server类似,Eureka服务器也可以作为一个小巧的Spring Boot应用程序来运行:@SpringBootApplication
@EnableEurekaServer
public class RepmaxEurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(RepmaxEurekaServerApplication.class, args);
在应用程序启动时,@EnableEurekaServer标注会通知Spring Boot启动Eureka。出于高可用目的,默认情况下服务器会尝试联系其他服务器。在独立安装的情况下可以考虑在application.yml中关闭该功能:server:
port: 8761
hostname: localhost
registerWithEureka: false
fetchRegistry: false
请注意,按照惯例可在8761端口运行Eureka服务器。访问http://localhost:8761可以查看Eureka仪表板。由于目前尚未注册任何服务,可用实例列表中什么也没显示:
空白的Eureka仪表板
若要将leaderboard服务注册至Eureka,可为该应用程序类添加一个@EnableEurekaClient标注。随后通过application.properties告诉Eureka客户端在哪里可以找到服务器,以及应用程序在服务器上注册时所用的名称:spring.application.name=repmax-leaderboard
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka
leaderboard服务启动时,Spring Boot会检测到@EnableEurekaClient标注并启动Eureka客户端,随后该客户端会将leaderboard服务注册至Eureka服务器。Eureka仪表板将会显示出新注册的服务:
服务注册后Eureka仪表板显示的内容
logbook服务可以通过与leaderboard服务相同的方式配置为Eureka客户端,需要添加@EnableEurekaClient标注并配置Eureka服务URL。
通过在logbook服务中启用Eureka客户端,Spring Cloud会暴露一个用于查询服务实例的DiscoveryClient Bean:@Component
public class DiscoveryLeaderBoardApi extends AbstractLeaderBoardApi {
public DiscoveryLeaderBoardApi(DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryC
private final DiscoveryClient discoveryC
protected String getLeaderBoardAddress() {
List&ServiceInstance& instances = this.discoveryClient.getInstances("repmax-leaderboard");
if(instances != null && !instances.isEmpty()) {
ServiceInstance serviceInstance = instances.get(0);
return String.format("http://%s:%d", serviceInstance.getHost(), serviceInstance.getPort());
throw new IllegalStateException("Unable to locate a leaderboard service");
调用DiscoveryClient.getInstances可获得ServiceInstances列表,列表中每一项均对应了一个注册到Eureka服务器的leaderboard服务。从简化的角度考虑,可以从列表中选择第一项服务用于远程调用。
客户端的负载平衡
Eureka就位后,不同服务将能以动态的方式相互发现,并能直接相互通信,借此可避免负载平衡器代理所产生的开销以及可能的故障点。当然这里也需要进行权衡,因为我们将有关负载平衡的复杂性转嫁到了代码中。
在这里可以看到,DiscoveryLeaderBoardApi.getLeaderBoardAddress方法在每次远程调用过程中,会直接选择找到的第一个ServiceInstance。借助这种方法可以方便地将负载分散到所有可用实例。此外本例中还可以通过Netflix Cloud的另一个组件处理客户端的负载平衡:。
将Ribbon与Spring Cloud以及现有的Eureka环境配合使用的方法很简单。只需要在logbook服务中添加针对spring-cloud-starter-ribbon的依赖关系,并改为使用LoadBalancerClient取代DiscoveryClient即可:public class RibbonLeaderBoardApi extends AbstractLeaderBoardApi {
private final LoadBalancerClient loadBalancerC
@Autowired
public RibbonLeaderBoardApi(LoadBalancerClient loadBalancerClient) {
this.loadBalancerClient = loadBalancerC
protected String getLeaderBoardAddress() {
ServiceInstance serviceInstance = this.loadBalancerClient.choose("repmax-leaderboard");
if (serviceInstance != null) {
return String.format("http://%s:%d", serviceInstance.getHost(), serviceInstance.getPort());
throw new IllegalStateException("Unable to locate a leaderboard service");
至此选择ServiceInstance的任务将由Ribbon负责,该功能可以智能地监控端点运行状况,并通过内建机制实现负载平衡。
本文介绍了各种将微服务连接在一起的方法。其中最简单的方法可能就是将服务所需的每个依存项的地址硬编码到程序中。这种方法可以帮助我们快速上手,但在现实环境中实用性很低。
对于现实世界中最基本的应用程序,通过外部配置使用application.properties文件指定依存项地址这种做法已经足够了。诸如Cloud Foundry和Heroku等平台即服务(PaaS)系统通过暴露连接信息,使得我们能够用完全相同的方式连接这些依赖项。
然而更大规模的应用程序不仅需要简单的点对点连接,还需要使用某种形式的负载平衡。Spring Cloud Config与负载平衡代理的紧密结合是一种解决方案,但如果使用诸如HAProxy或NGINX等市售的负载平衡代理,就只能自行处理服务的发现和注册过程,代理也有可能成为所有流量的一个故障点。通过使用Netflix的Eureka和Ribbon组件,应用程序中的服务将能以动态的方式互相查找,并能将有关负载平衡的决策从专门的负载平衡器代理交由客户端服务来处理。
由于无法控制中间层微服务之间通信产生的传入流量,诸如AWS ELB等负载平衡解决方案在系统边缘可能依然占有一席之地,Ribbon提供了一种不依赖具体的云供应商,可靠性和性能更为出色的解决方案。
Rob Harrop是Skipjaq公司CTO,该公司致力于通过机器学习技术解决绩效管理方面遇到的问题。在加入Skipjaq前,Rob以SpringSource共同创始人的身份广为人知,这家软件公司开发了大获成功的Spring框架。在SpringSource任职期间,他是Spring框架的核心贡献者,并领导了dm Server(现名为Eclipse Virgo)的开发团队。在加入SpringSource前,(当时仅19岁的)Rob是英国曼彻斯特顾问公司Cake Solutions的共同创始人兼CTO。作为广受敬重的作者、演讲人和讲师,Rob经常撰写和探讨有关大规模系统、云体系结构,以及功能编程(Functional programming)的话题。他出版的著作包括极受欢迎的Spring框架参考书《Pro Spring》。
Author Contacted
告诉我们您的想法
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
赞助商链接
InfoQ每周精要
通过个性化定制的新闻邮件、RSS Feeds和InfoQ业界邮件通知,保持您对感兴趣的社区内容的时刻关注。
架构 & 设计
文化 & 方法
<及所有内容,版权所有 &#169;
C4Media Inc.
服务器由 提供, 我们最信赖的ISP伙伴。
北京创新网媒广告有限公司
京ICP备号-7
注意:如果要修改您的邮箱,我们将会发送确认邮件到您原来的邮箱。
使用现有的公司名称
修改公司名称为:
公司性质:
使用现有的公司性质
修改公司性质为:
使用现有的公司规模
修改公司规模为:
使用现在的国家
使用现在的省份
Subscribe to our newsletter?
Subscribe to our industry email notices?
我们发现您在使用ad blocker。
我们理解您使用ad blocker的初衷,但为了保证InfoQ能够继续以免费方式为您服务,我们需要您的支持。InfoQ绝不会在未经您许可的情况下将您的数据提供给第三方。我们仅将其用于向读者发送相关广告内容。请您将InfoQ添加至白名单,感谢您的理解与支持。

我要回帖

更多关于 spring cloud注册中心 的文章

 

随机推荐