Spring Cloud Consul 基础使用介绍

1.概述

Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案,Consul的方案更“一站式”,内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等)。

Consul是一个工具,提供解决微服务架构中一些最常见挑战的组件:

  • 服务发现 - 自动注册和取消注册服务实例的网络位置
  • 运行状况检查 - 检测服务实例何时启动并运行
  • 分布式配置 - 确保所有服务实例使用相同的配置

Spring Cloud Consul 项目提供Spring Boot 集成 Consul的非常轻松的方法。在本文中,我们将了解如何配置Spring Boot应用程序来使用Consul。

2.先决条件

首先,建议您快速查看Consul及其所有功能。

在本文中,我们将使用在localhost:8500上运行的Consul代理。有关如何安装Consul和运行代理的更多详细信息,请参阅此链接

在windows下安装Consul,
去官网下载:https://www.consul.io/downloads.html

解压到某个目录下。cmd启动:

consul agent -dev

3.引入依赖

首先,我们需要在我们的pom.xml中添加spring-cloud-starter-consul-all依赖项:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-all</artifactId>
    <version>1.3.0.RELEASE</version>
</dependency>

4.服务发现

4.1 服务注册

让我们编写我们的第一个Spring Boot应用程序并与正在运行的Consul代理连接:

@SpringBootApplication
public class ServiceDiscoveryApplication {
    public static void main(String[] args) {
        new SpringApplicationBuilder(ServiceDiscoveryApplication.class).web(true).run(args);
    }
}

默认情况下,Spring Boot将尝试连接到localhost:8500上的Consul代理。要使用其他设置,我们需要更新application.yml文件:

spring:
  application:
    name: myApp
  cloud:
    consul:
      host: localhost
      port: 8500

然后,我们在浏览器 http://localhost:8500 访问Consul代理的站点,我们将看到我们的应用程序在Consul中正确注册。

要想自定义显示的标识符,我们需要使用另一个表达式更新属性spring.cloud.discovery.instanceId:

spring:
  application:
    name: myApp
  cloud:
    consul:
      discovery:
        instanceId: ${spring.application.name}:${random.value}

如果我们再次运行此应用程序,我们将看到它是使用标识符“MyApp”加上随机值注册的。使用random.value是想在本地机器上运行应用程序的多个实例。

如果想要禁用Service Discovery,我们可以将属性spring.cloud.consul.discovery.enabled设置为false。

4.2 寻找服务

我们已经在Consul中注册了我们的应用程序,但客户如何找到服务端点呢?我们需要一个客户端服务来从Consul中获取运行和可用的服务。

Spring 为此提供了DiscoveryClient API,我们可以使用@EnableDiscoveryClient注释启用它:

@SpringBootApplication
@EnableDiscoveryClient
public class DiscoveryClientApplication {
    public static void main(String[] args) {
        new SpringApplicationBuilder(DiscoveryClientApplication.class).web(true).run(args);
    }
}

然后,我们可以将DiscoveryClient bean注入到我们的controller控制器:

@RestController
public class DiscoveryClientController {
  
    @Autowired
    private DiscoveryClient discoveryClient;
 
    public Optional<URI> serviceUrl() {
        return discoveryClient.getInstances("myApp")
          .stream()
          .map(si -> si.getUri());
          .findFirst()
    }
}

最后,我们将定义我们的应用程序端点:

@GetMapping("/discoveryClient")
    public String discoveryPing() throws RestClientException, ServiceUnavailableException {
    URI service = serviceUrl().map(s -> s.resolve("/ping")).orElseThrow(ServiceUnavailableException::new);
    return restTemplate.getForEntity(service, String.class).getBody();
}

@GetMapping("/ping")
public String ping() {
    return "Client ping";
}

其中“myApp/ping”的路径是Spring应用程序的名称与服务端点。Consul将提供名为“myApp”的所有可用应用程序。

5.健康检查

Consul会定期检查服务端点的运行状况。

默认情况下,如果应用程序启动,Spring会访问运行状况端点以返回200 OK来判断服务是正常的。如果我们想要自定义端点,我们必须更新application.yml:

spring:
  cloud:
    consul:
      discovery:
        healthCheckPath: /my-health-check
        healthCheckInterval: 20s

Consul将每20秒轮询一次“/my-health-check”端点。

假设我们故意将自定义的运行状态检查服务返回FORBIDDEN状态:

@GetMapping("/my-health-check")
public ResponseEntity<String> myCustomCheck() {
    String message = "Testing my healh check function";
    return new ResponseEntity<>(message, HttpStatus.FORBIDDEN);
}

如果我们去Consul代理网站查看,我们会看到我们的应用程序健康检测是失败的。要解决此问题,“/my-health-check”服务应返回HTTP 200 OK状态代码。

Consul代理网站截图


Consul代理网站截图

健康检测详情


健康检测详情

6.分布式配置

此功能允许在所有服务之间同步配置。Consul将监视任何配置更改,然后触发所有服务的更新。

首先,我们需要将spring-cloud-starter-consul-config依赖项添加到我们的pom.xml:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-config</artifactId>
    <version>1.3.0.RELEASE</version>
</dependency>

我们还需要将Consul和Spring应用程序的设置从application.yml文件移动到Spring首先加载的bootstrap.yml文件中。

然后,我们需要启用Spring Cloud Consul Config:

spring:
  application:
    name: myPro
  cloud:
    consul:
      host: localhost
      port: 8500
      config:
        enabled: true
server:
  port: 8509

Spring Cloud Consul Config将在“/config/myPro”中查找Consul中的属性。因此,如果我们有一个名为“my.prop”的属性,我们需要在Consul代理站点中创建此属性。

我们可以通过访问“KEY/VALUE”界面来创建属性,然后在“Create Key”表单中输入“/config/myPro/my/prop”,填入“Hello World”作为值。最后保存此值。

现在,让我们看看带有注入属性的控制器是什么样的:

@RestController
public class DistributedPropertiesController {
    @Value("${my.prop}")
    String value;

    @Autowired
    private MyProperties properties;

    @GetMapping("/getConfigFromValue")
    public String getConfigFromValue() {
        return value;
    }

    @GetMapping("/getConfigFromProperty")
    public String getConfigFromProperty() {
        return properties.getProp();
    }
}

MyProperties类:

@RefreshScope
@Configuration
@ConfigurationProperties("my")
public class MyProperties {
    private String prop;

    public String getProp() {
        return prop;
    }

    public void setProp(String prop) {
        this.prop = prop;
    }
}

如果我们运行应用程序,则通过字段值和属性来取值都会获得“Hello World”值。

6.1 更新配置

如何在不重新启动Spring Boot应用程序的情况下更新配置?

我们返回Consul代理站点并使用“New Hello World”更新属性“/config/myPro/my/prop ”,而其他不变。则字段属性将更新为预期的那样:“New Hello World”。

这是因为字段属性是MyProperties类具有@RefreshScope注释。使用@RefreshScope注释注释的所有bean 将在配置更改后刷新。

在实际应用场景中我们不应该直接在Consul中设置属性,我们应该将它们永久存储在某个地方。我们可以使用一个Config Server来完成此操作。

7. 结论

在本文中,我们已经了解了如何设置Spring Boot应用程序以与Consul一起使用以进行服务发现,自定义运行状况检查规则和共享分布式配置。

像往常一样,可以在GitHub上找到消息来源。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容