使用Spring Cloud Consul的Spring Cloud服务发现
Spring Boot consul是一个用于Spring Boot应用程序的服务发现和配置框架。它是一个轻量级的、可扩展的、易于使用的服务发现和配置框架,采用Spring Boot和Spring Cloud设计。
本教程将创建一个在线应用程序来管理商店。我们将使用微服务架构开发该应用。
我们将有两个服务。
- 产品服务--它将管理系统中所有商店销售的所有产品。
- 商店服务=管理系统中商店的相关信息。
前提条件
- 在你的机器上安装Consul和JDK。
- 有Spring框架和Spring Boot方面的知识。
设置consul
在本教程中,我们需要在我们的开发机上安装consul。
导航到consul网站,为你的操作系统下载最新版本的consul。然后,解压下载的文件,运行consul命令来启动consul代理,如下图所示。
consul agent -server -bootstrap-expect=1 -data-dir=consul-data -ui -bind=<your ip address>
注意:用你的ip地址代替。
上述命令的输出应该如下。
test@DEV-34:/$ sudo /usr/local/bin/consul agent -server -bootstrap-expect=1 -data-dir=consul-data -ui -bind=192.168.1.169
==> Starting Consul agent...
Version: '1.8.4'
Node ID: '2bff16b4-eaf1-540d-1e96-bb168f5fdf74'
Node name: 'DEV-34'
Datacenter: 'dc1' (Segment: '<all>')
Server: true (Bootstrap: true)
Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: -1, DNS: 8600)
Cluster Addr: 192.168.1.169 (LAN: 8301, WAN: 8302)
Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false
==> Log data will now stream in as it occurs:
2022-02-09T13:30:32.813+0300 [WARN] agent: BootstrapExpect is set to 1; this is the same as Bootstrap mode.
现在我们已经在我们的开发机器上安装并运行了consul,我们需要通过在我们的网络浏览器上导航到http://localhost:8500,来验证consul代理是否完全正常。我们可以从浏览器的仪表板上看到我们的开发机器上运行的服务,如下图所示。

设置Spring Boot应用程序
产品服务
在你的网络浏览器上导航到spring initilzr。输入应用程序名称为product-service ,包名称为com.example.productservice 。
添加Actuator,Lombok,Web,Rest repositories和Consul discoveries 作为项目依赖。
点击生成按钮,下载具有所需依赖性配置的模板项目代码。
解压缩下载的压缩文件,并在你喜欢的IDE中打开。导航到src/main/java/com/example/productservice/ 目录并更新ProductServiceApplication.java 文件,如下所示。
@SpringBootApplication
@EnableDiscoveryClient
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
@EnableDiscoveryClient 是用来启用服务发现和配置框架的。这个注解允许服务向consul代理注册自己。
在application.properties 文件中,添加以下配置。
server.port=9090
spring.application.name:product-service
management.security.enabled=false
server.port:服务的端口号。应用程序将在这个端口上启动和运行。spring.application.name:服务的名称。这个名字用于在consul中注册该服务。其他服务也可以通过这个名字发现这个服务。management.security.enabled:禁用执行器所暴露的管理端点的安全性。
在根项目包中,创建一个名为Product 的新的Java类,并用如下所示的代码片断对其进行更新。
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@ToString
public class Product {
String name;
float price;
}
@AllArgsConstructor:该注解用于创建一个具有所有字段的构造函数。@NoArgsConstructor:该注解用于创建一个没有任何字段的构造函数。@Setter:该注解用于为所有字段创建设置器。@Getter:该注解用于为所有字段创建获取器。@ToString:该注解用于为该类创建一个toString方法。
为了向世界展示我们的服务,我们需要创建一个新的Java类,名为ProductController ,它将接受HTTP请求。用下面的代码片段更新它。
@RestController
public class ProductController {
private static final Map<String, List<Product>> productDatabase;
static {
productDatabase = new HashMap<>();
List<Product> products = new ArrayList<>();
Product sugar = new Product("Sugar", 120.0f);
products.add(sugar);
Product salt = new Product("Salt", 30.0f);
products.add(salt);
productDatabase.put("ABC shop", products);
List<Product> items = new ArrayList<>();
Product soap = new Product("Soap", 30.0f);
items.add(soap);
Product cooking = new Product("Cooking", 70.0f);
items.add(cooking);
productDatabase.put("XYZ", items);
}
@RequestMapping(value = "/shopproducts/{shopName}", method = RequestMethod.GET)
public List<Product> getProductPerShop(@PathVariable("shopName") String shopName) {
List<Product> products = productDatabase.get(shopName);
if (products == null) {
products = new ArrayList<>();
Product product = new Product("No product", 0f);
products.add(product);
}
return products;
}
}
@RestController:这个注解是用来创建一个控制器类。- 由于我们没有实现数据库层,我们在静态块中声明了一个产品的静态地图。这将充当我们的数据库层。
getProductPerShop:这个方法用来获取一个给定商店的产品。它根据商店名称过滤产品并返回产品列表。
商店服务
在你的网络浏览器上导航到spring initilzr。输入应用程序名称为shop-service ,包名称为com.example.productservice 。
添加Actuator,Lombok,Web,Rest repositories和Consul discoveries 作为项目依赖。
点击生成按钮,下载具有所需依赖性配置的模板项目代码。
解压缩下载的压缩文件,并在你最喜欢的IDE中打开。导航到src/main/java/com/example/shopservice/ 目录并更新ShopServiceApplication.java 文件,如下所示。
@SpringBootApplication
@EnableDiscoveryClient
public class ShopServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ShopServiceApplication.class, args);
}
}
@EnableDiscoveryClient 是用来启用服务发现和配置框架的。这个注解允许服务向consul代理注册自己。
在根应用程序目录中,创建一个新的Java类,命名为ShopServiceDelegate ,并用下面的代码片断更新它。
@Service
public class ShopServiceDelegate {
@Autowired
RestTemplate template;
public String getDataFromProductService(String shopName) {
String response = template.exchange("http://product-service/shopproducts/{shopName}",
HttpMethod.GET, null, new ParameterizedTypeReference<String>() {
}, shopName).getBody();
System.out.println("Received " + response + " - " + new Date());
return "Shop Name - " + shopName + " ::: Product details " + response + " - " + new Date();
}
@Bean
@LoadBalanced
public RestTemplate template() {
return new RestTemplate();
}
}
@Service:该注解用于创建一个服务类。getDataFromProductService:这个方法用来获取一个给定商店的产品。它根据商店名称过滤产品并返回产品列表。template():这个方法用于创建一个RestTemplate Bean。我们已经将这个Bean标记为@LoadBalanced,以创建一个负载平衡的RestTemplate。当这个服务的许多实例被运行时,一个负载平衡的RestTemplate将被创建。
为了使其他服务能够与商店服务进行通信,我们需要创建一个名为ShopServiceRestController 的新Java类,它将接受HTTP请求。用下面的代码片段更新它。
@RestController
@AllArgsConstructor
public class ShopServiceController {
ShopServiceDelegate shopServiceDelegate;
@RequestMapping(value = "/getshopdetails/{shopName}", method = RequestMethod.GET)
public String getProducts(@PathVariable("shopName") String shopName) {
return shopServiceDelegate.getDataFromProductService(shopName);
}
}
@RestController:该注解用于创建一个控制器类。@AllArgsConstructor:该注解用于创建一个包含所有字段的构造函数。通过这个注解,我们通过构造函数注入ShopServiceDelegate Bean。
测试
运行产品服务,并验证它正在运行,并且可以被Consul仪表盘中的consul代理发现,如下图所示。

现在,产品服务已经成功运行,我们可以运行商店服务。一旦商店服务启动,我们可以从consul仪表板上验证它的运行没有问题,并且可以被consul代理发现,如下图所示。

当我们向http://localhost:8098/getshopdetails/ABC 发出GET请求时,我们会得到一个如下的响应。
[{"name":"Soap","price":30.0},{"name":"Cooking","price":70.0}] - Thu Feb 10 09:15:17 EAT 2022
我们可以向产品服务请求商店服务,而不需要产品服务的URL和端口。我们只能得到带有服务名称和端点的响应。Consul简化了服务发现。
当与Docker一起使用时,我们不需要跟踪IP地址的变化,但服务可以用服务名称进行通信。
总结
在本教程中,我们已经学会了如何在我们的开发机器上有效地部署Consul服务注册表和发现服务器及客户端。
现在你可以尝试使用微服务架构实现一个Spring Boot项目,并使用Spring Cloud consul进行部署。