
2.3 【实例】创建第一个微服务分布式项目
2.3.1 实例背景
2.2节简要介绍了Consul的部分基本操作,本实例将创建cloud_01工程,并以Consul集群搭建/部署过程的形式详解如何组建Consul集群。通过Spring Cloud Consul框架整合Consul注册中心集群,最后在Consul注册中心管理页面中查看相关的Spring Boot微服务工程。
2.3.2 搭建Consul集群
Consul集群是指在相同的Consul数据中心中,同时运行多台Consul注册中心,让Consul共享存储的微服务信息,保证高并发下的注册中心运行效果。
1.准备服务器
本实例将使用4台虚拟服务器进行搭建,准备的服务器如表2-3所示。
表2-3 为了搭建Consul集群准备的虚拟服务器列表

2.下载及部署
将Consul应用程序分别传输到不同的服务器上,如图2-2(Windows)和图2-3(Linux)所示。

图2-2

图2-3
在Linux系统中使用unzip命令可将ZIP文件解压,解压之后即可直接使用./consul命令启动。其他启动Consul的方式如下。
(1)更改/etc/profile文件,更改相应的环境变量。
(2)将Consul文件传输到/usr/local/bin文件夹中。
(3)配置快捷启动。
(4)编写启动脚本。
3.逐个启动Consul注册中心
192.168.138.144的Server端Consul节点启动命令如下。

其他Consul节点只需依次更改命令中的-bind参数为当前需要配置的IP地址,即可启动其他Consul节点。192.168.138.140/192.168.138.147等Linux系统的Client端Consul节点启动命令如下。

在-server生产级别启动注册中心,至少含有3台-server服务器。若只进行测试,则可以只有一台-server服务器,与-dev命令效果相同,如图2-4所示。

图2-4
此时已经成功搭建了一个Consul集群。每个Consul都可以给n个微服务进行注册,视项目大小可酌情添加Consul的Client节点,但不宜过多,以免管理维护困难。另外,也可以把node参数中的Value都换成Consul所在服务器的IP,也容易区分各Consul节点。
4.利用配置文件启动注册中心并修改端口号
如果在启动192.168.138.147服务器的注册中心时端口被占用,可以通过命令修改端口号并进行启动。如果命令过长不方便输入,可以编写一个json配置文件,在json配置文件中输入端口号等相关配置信息,一次性更改所有配置。json配置文件代码如下。

修改json配置文件可以更改配置信息,并且相关命令参数也都可以写入文件中。Consul注册中心的默认端口号如表2-4所示。
表2-4 Consul注册中心的默认端口号

在扫描配置文件时,通过-config-file命令可以扫描配置文件。
5.集群搭建后的效果
当前集群下的Server端UI展示效果如图2-5所示。

图2-5
当前集群下的命令行展示效果如图2-6所示。

图2-6
2.3.3 创建微服务工程编写相应依赖文件
搭建Consul集群后,需将Spring Boot微服务工程注册到Consul注册中心上,使Consul注册中心获得微服务工程的相关信息,微服务依赖Spring Boot微服务相关的文件、Consul整合文件等,pom.xml文件依赖代码如下。


本书中Spring Cloud版本是Finchley.RELEASE,Spring Cloud版本的名字都用英文命名,因为Spring Cloud每个版本中会集成Spring Boot的相关插件和Spring Cloud的相关组件。
而Spring Cloud因为集成的插件、组件过多,如Spring Cloud Config,Spring Cloud Netflix,Spring Cloud Bus,所以经常发生版本不兼容的情况。
2.3.4 Spring Cloud和Spring Boot的版本对应关系
Spring Cloud与Spring Boot的版本对应关系如表2-5所示,如果Spring Cloud与Spring Boot不兼容,会导致程序出现大量未知异常。
表2-5 Spring Cloud与Spring Boot的版本对应关系

Spring Boot 2.0以下版本,功能较少。如Spring Data MongoDB,在Spring Boot 1.5版本只提供MongoRepository仓库映射的方式进行CURD,在Spring Boot 2.0版本更新了MongoTemplate模板,以方便管理MongoDB数据库。
2.3.5 编写微服务YAML资源配置文件
Spring Cloud Consul初步整合Consul注册中心的application.yml资源配置文件,代码如下。

spring.cloud.consul.host和spring.cloud.consul.port代表要去注册的注册中心地址,而spring.cloud.consul.discovery.hostname代表当前应用程序运行的地址。
spring.application.name是Spring Boot微服务设定的名称,在Consul的Web UI管理页面中也会显示微服务工程的名字。
spring.cloud.consul.discovery.instance-id是在Consul中注册的名字。instanceId可省略,Consul将显示${spring.application.name}。注意,spring.cloud.consul.discovery.instance-id的名字必须唯一,默认情况下Consul使用SpringApplicationContext ID中的ID进行注册。Spring应用程序上下文ID为${spring.application.name}:comma,separated,profiles:${server.port},代码如下。

spring.consul.discovery.healthCheckPath为Consul注册中心检查应用程序是否健康的接口路径,默认路径为/health。该路径必须返回200,否则Consul会认为微服务处于无法正常运行的状态。为避免应用程序接口重复,也可以写成如下代码。

spring.cloud.discovery.healthCheckInterval为Consul注册中心检查应用程序是否健康的间隔时间,可设置为1分钟。
在YAML或properties文件中书写${}相关内容都是Spring Boot整合SpringEL所提供的EL表达式能力,可以获取Spring容器中的相关参数。例如,在YAML文件中编写port:${server.port},代表从Spring容器的上下文中获得了server.port参数,并以此赋值给port参数。
2.3.6 编写微服务启动类注册到Consul上
Spring Cloud集成Eureka时使用@EnableEurekaClient注解连接Eureka注册中心,而集成Consul或Zookeeper等其他注册中心时使用@EnableDiscoveryClient注解。@EnableEurekaClient注解与@EnableDiscoveryClient注解的用法基本相同,@Enable-DiscoveryClient也可以用于注册到Eureka上。@EnableDiscoveryClient注解基于spring-cloud-commons包,@EnableEurekaClient注解基于spring-cloud-netflix包。
Spring Boot微服务整合Consul创建微服务分布式项目的启动类ApplicationMain.java,代码如下。

如果不编写health()函数,Consul注册中心的Web UI界面会报错,告诉用户这个微服务无法正常连接。health()函数在YAML资源配置文件中配置,告诉Consul注册中心调用该函数检测微服务是否正在正常运行。
2.3.7 当前项目结构
如图2-7所示,利用Spring Cloud集成Consul注册中心,只需要一个启动类和一个资源配置文件即可,除健康检查Health()接口和@EnableDiscoveryClient启动注册中心接口外,不需要其他任何Java代码。

图2-7
2.3.8 运行结果
启动Spring Boot应用程序后,可以在Consul的UI界面中观察应用程序,如图2-8所示。

图2-8
Serf Health Status:表示当前Consul节点正在良好地运行(或其他状态)。
Service'cloud01-application'check:其下方文字表示cloud01-application的健康检查正在良好运行。
如果复制cloud-01工程,并更改其端口号和工程名称等相关参数,再次注册到Consul中的效果如图2-9所示。

图2-9
从图中可以看到,两个应用程序都在良好运行,此时第一个分布式应用程序已经搭建成功。除了在192.168.138.144的Consul服务器上可以看到相关信息,在其他服务器上也可以看到相关信息。在Consul的server集群中,每个server的数据都是共享的,如图2-10和图2-11所示。

图2-10

图2-11
2.3.9 实例易错点
1.Consul无法正常检测到健康接口
如图2-12所示,Consul检测到cloud033-application应用程序的健康接口失效,报错时只能检查资源配置文件中的spring.consul.discovery.healthCheckPath健康接口路径编写是否正确,并且是否正常返回200。

图2-12
2.实例化失败
如果含有creating bean等相关报错信息,通常都由配置信息不全所产生。可优先尝试用静态书写相关内容,确认无误后再更改为配置文件的动态形态。
注意,不要遗忘参数spring.application.name。spring.application.name是Spring Boot对当前应用程序命名的参数,Consul也以此开始对整个应用程序进行实例化;是分布式最重要的参数之一。实例化失败报错信息如下。

3.@SpringCloudApplication注解报错
注意,启动程序的启动类使用的依旧是@SpringBootApplication注解,若写成@SpringCloudApplication注解,则会报错。
Spring Cloud认为每个微服务分布式的应用程序,都应含有Spring Boot相关启动注解、注册中心相关注解和熔断器注解,并以此推出@SpringCloudApplication注解整合分布式上述3个注解。但是应用程序目前没有集成其他分布式框架,所以使用@SpringCloudApplication注解会让Spring Cloud检测不到一些应该编写的配置文件,从而引发报错,错误信息如下。
