微服务系列详解—Part 3:Spring Cloud Service注册和发现

25 篇文章 0 订阅
本文详细介绍了在微服务架构中,使用Spring Cloud Eureka进行服务注册和发现的重要性。通过示例展示了如何配置和使用Eureka Server创建服务注册表,以及如何将微服务注册为Eureka客户端,实现服务之间的自动发现和调用。同时,讨论了Eureka Server的心跳机制和多实例注册。最后提到了使用@LoadBalanced RestTemplate进行负载均衡调用的实现。
摘要由CSDN通过智能技术生成

了解有关设置服务注册表和发现或你的Spring Cloud和Spring Boot微服务开发的信息。抽丝剥茧 细说架构那些事——【优锐课】

在微服务世界中,服务注册表和发现扮演着重要的角色,因为我们很可能会运行多个服务实例,并且我们需要一种机制来调用其他服务而不用硬编码它们的主机名或端口号。除此之外,在云环境中,服务实例可以随时启动和关闭。因此,我们需要一些自动服务注册和发现机制。Spring Cloud像往常一样提供Service Registry and Discovery功能,并具有多个选项。我们可以使用Netflix Eureka或Consul进行服务注册和发现。在本文中,我们将学习如何使用SpringCloud Netflix Eureka进行服务注册和发现。

使用Spring Boot和Spring Cloud的微服务

在我之前的文章微服务系列详解—Part 2:使用Spring Cloud Config和Vault进行配置管理中,我们学习了如何在配置服务器中外部存储配置参数以及如何在Vault中安全存储机密。

在这篇文章中,我们将学习:
• 什么是服务注册和发现?
• 基于Spring Cloud Netflix Eureka的服务注册表
• 将微服务注册为Eureka客户
• 使用Eureka Client发现其他服务

假设我们有两个微服务目录服务和库存服务,并且我们正在http://localhost:8181/和http://localhost:8282/上运行两个库存服务实例。现在,我们要从目录服务调用一些清单服务REST端点。我们应该打哪个URL?通常,在这些情况下,我们使用负载均衡器来配置这两个要委派的URL,然后在负载均衡器URL上调用REST端点。精细。

但是,如果你想根据负载动态启动新实例呢?即使只运行几个服务器节点,在负载均衡器配置中手动更新服务器节点详细信息也容易出错且乏味。这就是为什么我们需要自动服务注册机制,并且能够使用一些逻辑服务ID而不是使用特定的IP地址和端口号来调用服务的原因。

我们可以使用Netflix Eureka Server创建服务注册表,并将我们的微服务作为Eureka客户端,这样,一旦启动微服务,它将以逻辑服务ID自动在Eureka Server中注册。然后,其他微服务(也是Eureka客户端)可以使用服务ID来调用REST端点。
Spring Cloud使使用负载平衡RestTemplate创建服务注册表和发现其他服务变得非常容易。

让我们使用Netflix Eureka创建一个Service Registry,这不过是带有Eureka Server启动程序的SpringBoot应用程序。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

我们需要添加@EnableEurekaServer批注,以使你的Spring Boot应用程序成为基于Eureka Server的服务注册表。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class ServiceRegistryApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceRegistryApplication.class, args);
    }
}

默认情况下,每个Eureka服务器也是Eureka客户端,并且至少需要一个服务URL来定位对等方。由于我们将有一个Eureka Server节点(独立模式),我们将通过在application.properties文件中配置以下属性来禁用此客户端行为。

application.properties
spring.application.name=service-registry
server.port=8761
eureka.instance.hostname=localhost
eureka.instance.client.registerWithEureka=false
eureka.instance.client.fetchRegistry=false
eureka.instance.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

Netflix Eureka Service提供UI,在这里我们可以查看有关注册服务的所有详细信息。

现在运行ServiceRegistryApplication并访问http://localhost:8761,它将显示类似于以下屏幕截图的UI。

微服务系列详解—Part 2:使用Spring Cloud Config和Vault进行配置管理中,我们创建了商品目录服务。让我们作为Eureka客户端提供此服务并在Eureka服务器中注册。

将Eureka Discovery启动器添加到catalog-service,这将添加以下依赖项。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

使用classpath上的spring-cloud-starter-netflix-eureka-client时,我们只需要在application.properties中配置eureka.client.service-url.defaultZone属性即可自动向Eureka Server注册。

eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

在Eureka Server中注册服务后,它将在特定时间间隔内不断发送心跳。如果Eureka服务器未从任何服务实例接收到心跳,它将假定服务实例已关闭并将其从池中取出。

完成此配置后,启动catalog-service并访问http://localhost:8761。 你应该看到catalog-service已以SERVICE ID注册为CATALOG-SERVICE。你还可以注意到状态为UP(1),这表示服务已启动并正在运行,并且一个catalog-service实例正在运行。

让我们使用以下命令在另一个端口上启动另一个Catalog-service实例。

java -jar -Dserver.port=9797 target/catalog-service-0.0.1-SNAPSHOT-exec.jar

现在,如果你转到http://localhost:8761,你会注意到2个catalog-service实例已注册,并且可以看到它们的主机名:端口详细信息。

在上一节中,我们学习了如何将服务注册为Eureka客户端,并且还尝试了注册同一服务的多个实例。

现在,我们将创建另一个微服务库存服务,该服务公开一个REST端点http:// localhost:8282/api/invenory/{productCode},它将给出当前可用的数量作为响应。

{
    productCode: "P001",
    availableQuantity: 250
}

使用Web,JPA,H2 / MySQL,Actuator,Config Client和Eureka Discovery启动器创建一个清单服务SpringBoot应用程序。
创建REST控制器以返回给定产品代码的库存详细信息。

@RestController
@Slf4j
public class InventoryController {
    private final InventoryItemRepository inventoryItemRepository;
    @Autowired
    public InventoryController(InventoryItemRepository inventoryItemRepository) {
        this.inventoryItemRepository = inventoryItemRepository;
    }
    @GetMapping("/api/inventory/{productCode}")
    public ResponseEntity<InventoryItem> findInventoryByProductCode(@PathVariable("productCode") String productCode) {
        log.info("Finding inventory for product code :"+productCode);
        Optional<InventoryItem> inventoryItem = inventoryItemRepository.findByProductCode(productCode);
        if(inventoryItem.isPresent()) {
            return new ResponseEntity(inventoryItem, HttpStatus.OK);
        } else {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
    }
}

通过在src/main/resources/bootstrap.properties中配置Eureka serviceUrl在Eureka服务器上注册清单服务。

spring.application.name=inventory-service
server.port=8282
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

现在构建清单服务,并通过运行以下命令启动它的2个实例。

java -jar -Dserver.port=9898 target/inventory-service-0.0.1-SNAPSHOT-exec.jar
java -jar -Dserver.port=9999 target/inventory-service-0.0.1-SNAPSHOT-exec.jar

现在,你可以访问Eureka仪表板http://localhost:8761/并查看2个注册的库存服务实例。

假设我们要从目录服务调用库存服务REST端点。我们可以使用RestTemplate调用REST端点,但是有2个实例正在运行。

我们可以使用@LoadBalanced批注将RestTemplate注册为Spring bean。具有@LoadBalanced批注的RestTemplate将在内部使用Ribbon LoadBalancer解析ServiceID并使用可用服务器之一调用REST端点。

@SpringBootApplication
public class CatalogServiceApplication {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(CatalogServiceApplication.class, args);
    }
}

现在,我们可以使用RestTemplate在http://inventory-service/api/inventory/{productCode}.处调用库存服务端点。

@Service
@Transactional
@Slf4j
public class ProductService {
    private final ProductRepository productRepository;
    private final RestTemplate restTemplate;
    @Autowired
    public ProductService(ProductRepository productRepository, RestTemplate restTemplate) {
        this.productRepository = productRepository;
        this.restTemplate = restTemplate;
    }
    public Optional<Product> findProductByCode(String code) {
        Optional<Product> productOptional = productRepository.findByCode(code);
        if(productOptional.isPresent()) {
            log.info("Fetching inventory level for product_code: "+code);
            ResponseEntity<ProductInventoryResponse> itemResponseEntity =
                    restTemplate.getForEntity("http://inventory-service/api/inventory/{code}",
                                                ProductInventoryResponse.class,
                                                code);
            if(itemResponseEntity.getStatusCode() == HttpStatus.OK) {
                Integer quantity = itemResponseEntity.getBody().getAvailableQuantity();
                log.info("Available quantity: "+quantity);
                productOptional.get().setInStock(quantity> 0);
            } else {
                log.error("Unable to get inventory level for product_code: "+code +
                ", StatusCode: "+itemResponseEntity.getStatusCode());
            }
        }
        return productOptional;
    }
}
@Data
public class ProductInventoryResponse {
    private String productCode;
    private int availableQuantity;
}

请注意,我们使用的是http://inventory-service/api/inventory/{code}而不是http://localhost:9898/api/inventory/{code}或http://localhost:9999/api/inventory/{code}直接{code}。

通过这种自动服务注册和发现机制,我们无需担心正在运行多少实例以及它们的主机名和端口等。

在本文中,我们学习了如何使用Spring Cloud Netflix Eureka进行服务注册和发现。

在下一篇文章中,我们将研究使用Netflix Hystrix实现Circuit Breaker模式。微服务系列详解-Part4:使用Netflix Hystrix的Spring Cloud断路器

感谢阅读!
另外还有一些资源分享给各位,需要的可以免费领取~
在这里插入图片描述

课程简介: 课程总计41课时,从什么是事务讲起,直到分布式事务解决方案,很的0基础基础与提升系列课程。对于难以理解的知识点,全部用画图+实战的方式讲解。 第一部分:彻底明白事务的四个特性:原子性、一致性、隔离性、持久性,用场景和事例来讲解。 第二部分:实战讲数据库事务的6中并发异常:回滚丢失、覆盖丢失、脏读、幻读、不可重复读、MVCC精讲。 第三部分:彻底搞清楚4种事务隔离级别:READ_UNCOMMITTED 读未提交隔离级别、READ_COMMITTED 读已提交隔离级别、REPEATABLE_READ 可重复度隔离级别、SERIALIZABLE 序列化隔离级别 第四部分:彻底搞清楚MySQL的各种锁:行锁、表锁、共享锁、排它锁、Next-Key锁、间隙锁、X锁、S锁、IS锁、IX锁、死锁、索引与锁、意向锁等。 第五部分:彻底搞清楚Spring事务的7种传播级别的原理和使用:PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY、PROPAGATION_REQUIRES_NEW、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER、PROPAGATION_NESTED分布式事务的理论基础:RPC定理、BASE理论、XA协议都是什么,原理是什么,有什么关联关系 第六部分:分布式事务的5种解决方案原理和优缺点:2PC两阶段提交法、3PC三阶段提交法、TCC事务补偿、异步确保策略、最大努力通知策略 第七部分:阿里巴巴分布式事务框架Seata:历经多年双十一,微服务分布式事务框架,用一个Nacos+Spring Cloud+Seta+MySql的微服务项目,实战讲解阿里的分布式事务技术,深入理解和学习Seata的AT模式、TCC模式、SAGA模式。 课程资料: 课程附带配套2个项目源码72页高清PDF课件一份阿里巴巴seata-1.1.0源码一份阿里巴巴seata-server安装包一份
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值