微服务环境搭建
在【在线教育平台-快乐学习】项目中,我们团队使用了Spring Cloud Gateway作为网关,网关在请求路由时需要知道每个微服务实例的地址,接着项目使用Nacos作用服务发现中心和配置中心,并使用Feign远程调用。
这里,对所用技术进行简单的回顾梳理。
流程如下:
1、微服务启动,将自己注册到Nacos,Nacos记录了各微服务实例的地址。
2、网关从Nacos读取服务列表,包括服务名称、服务地址等。
3、请求到达网关,网关将请求路由到具体的微服务。
要使用网关首先搭建Nacos,Nacos有两个作用:
1、服务发现中心
微服务将自身注册至Nacos,网关从Nacos获取微服务列表。
2、配置中心
微服务众多,它们的配置信息也非常复杂,为了提供系统的可维护性,微服务的配置信息统一在Nacos配置。
Nacos
统一配置管理
Spring Cloud :一套规范Spring Cloud alibaba: nacos服务注册中心,配置中心。
Nacos 作为配置中心功能是基于 Raft 算法来实现的。
补充:Spring Cloud:是基于 Spring Boot 的扩展,专门用于构建和管理 分布式系统,包括微服务架构中的服务发现、负载均衡、熔断、配置管理等功能。适合构建复杂的企业级微服务系统。
首先搭建Nacos服务发现中心。
在搭建Nacos服务发现中心之前需要搞清楚两个概念:namespace和group
namespace:用于区分环境、比如:开发环境、测试环境、生产环境。
group:用于区分项目,比如:xuecheng-plus项目、xuecheng2.0项目
首先在nacos配置namespace:
登录Centos,启动Naocs,使用sh /data/soft/restart.sh将自动启动Nacos。
访问:http://192.168.101.65:8848/nacos/
账号密码:nacos/nacos
登录成功,点击左侧菜单“命名空间”进入命名空间管理界面,
点击“新建命名空间”,填写命名空间的相关信息。如下图:
使用相同的方法再创建“测试环境”、"生产环境"的命名空间。
创建成功,如下图:
拉取配置文件
1)引入nacos-config依赖
首先,在user-service服务中,引入nacos-config的客户端依赖:
1 | <dependency> |
2)添加bootstrap.yaml
然后,在user-service中添加一个bootstrap.yaml文件,内容如下:
1 | spring: |
这里会根据spring.cloud.nacos.server-addr获取nacos地址,再根据
${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
作为文件id,来读取配置。
本例中,就是去读取userservice-dev.yaml
:
配置3要素
先将项目中的配置文件分分类:
1、每个项目特有的配置
是指该配置只在有些项目中需要配置,或者该配置在每个项目中配置的值不同。
比如:spring.application.name每个项目都需要配置但值不一样,以及有些项目需要连接数据库而有些项目不需要,有些项目需要配置消息队列而有些项目不需要。
2、项目所公用的配置
是指在若干项目中配置内容相同的配置。比如:redis的配置,很多项目用的同一套redis服务所以配置也一样。
另外还需要知道nacos如何去定位一个具体的配置文件,即:namespace、group、dataid.
1、通过namespace、group找到具体的环境和具体的项目。
2、通过dataid找到具体的配置文件,dataid有三部分组成
比如:content-service-dev.yaml配置文件 由(content-service)-(dev). (yaml)三部分组成
content-service:第一部分,它是在application.yaml中配置的应用名,即spring.application.name的值。
dev:第二部分,它是环境名,通过spring.profiles.active指定,
Yaml: 第三部分,它是配置文件 的后缀,目前nacos支持properties、yaml等格式类型,本项目选择yaml格式类型。
所以,如果我们要配置content-service工程的配置文件:
在开发环境中配置content-service-dev.yaml
在测试环境中配置content-service-test.yaml
在生产环境中配置content-service-prod.yaml
我们启动项目中传入spring.profiles.active的参数决定引用哪个环境的配置文件,例如:传入spring.profiles.active=dev表示使用dev环境的配置文件即content-service-dev.yaml。
3)读取nacos配置
这部分参考:
热配置
为了实现 Nacos 配置的热更新,使得微服务在不重启的情况下能够动态生效,可以使用两种方式:
- 方式一:使用
@RefreshScope
注解@Value
注解通常用于直接从配置文件注入单个属性值。如果要实现配置变更后的热更新,可以在注入了@Value
的类上使用@RefreshScope
注解。- 当 Nacos 中的配置发生变化时,Spring Cloud 会自动刷新带有
@RefreshScope
的 Bean,更新其内部的配置值。
- 方式二:使用
@ConfigurationProperties
注解@ConfigurationProperties
注解用于将一组属性自动映射到一个类中,适合读取多项配置。- 与
@Value
不同,@ConfigurationProperties
允许更灵活的配置结构,并且在 Nacos 配置变更时无需手动刷新。 - 这种方式更推荐,因为它更符合 Spring Boot 配置管理的最佳实践。
1. 创建配置类 PatternProperties
- 通过
@ConfigurationProperties
注解,绑定pattern.dateformat
属性,方便在其他类中使用:
1 | package cn.itcast.user.config; |
- 作用:该类会自动读取 Nacos 配置中
pattern.dateformat
的值,将其绑定到dateformat
属性中。
2. 修改 UserController
使用 PatternProperties
- 在控制器中,使用
PatternProperties
读取dateformat
属性,而不再使用@Value
注解。
1 | package tech.wangkay.user.web; |
- 作用:通过
PatternProperties
类读取pattern.dateformat
配置属性,当 Nacos 中的配置发生变化时,PatternProperties
会自动更新。
3. 热更新方式的选择
- 使用
@RefreshScope
注解时,需要确保类的生命周期是“刷新作用域”下的。这意味着类中的配置在 Nacos 更新后会重新加载。 - 使用
@ConfigurationProperties
注解时,无需额外的@RefreshScope
注解,Spring Cloud Config 会自动刷新配置类中的属性。
配置共享
nacos提供了shared-configs可以引入公用配置。
在content-api中配置了swagger,所有的接口工程 都需要配置swagger,这里就可以将swagger的配置定义为一个公用配置,哪个项目用引入即可。
单独在xuecheng-plus-common分组下创建xuecheng-plus的公用配置,进入nacos的开发环境,添加swagger-dev.yaml公用配置
删除接口工程中对swagger的配置。
项目使用shared-configs可以引入公用配置。在接口工程的本地配置文件 中引入公用配置,如下:
1 | spring: |
再以相同 的方法配置日志的公用配置。
在接口工程和业务工程,引入loggin-dev.yaml公用配置文件
配置完成,重启content-api接口工程,访问http://localhost:63040/content/swagger-ui.html 查看swagger接口文档是否可以正常访问,查看控制台log4j2日志输出是否正常。
面试
了解哪些注册中心
工具 | 特点 | 主要功能 | 使用场景 |
---|---|---|---|
Zookeeper | 最早流行的开源分布式协调服务框架之一,需要用户自行实现分布式配置功能。 | 提供分布式配置中心功能,高可用、可靠性高,但配置功能需自行开发。 | 适用于需要强一致性和高可用性的分布式系统,且用户有能力开发分布式配置功能。 |
Nacos | 阿里巴巴开源的服务注册中心和配置中心,集成了配置管理工具。 | 提供服务注册、发现、配置管理和可视化工具,目标是云原生服务平台。 | 适用于云原生架构的微服务系统,尤其是需要统一配置管理的场景。 |
Eureka | Netflix 开源的服务注册中心,广泛应用于 Spring Cloud 微服务架构。 | 提供 REST API 和 Web 界面,支持 Region 和 Zone 的服务分组与负载均衡。 | 适用于 Spring Cloud 微服务架构,提供便捷的服务注册与发现。 |
Consul | HashiCorp 开源的服务注册中心,拥有丰富的功能,如健康检查和 KV 存储。 | 提供服务注册、发现、健康检查、KV 数据存储、API 和 Web UI 管理,支持健康检查和复杂路由。 | 适用于需要健康检查、动态路由及配置管理的微服务系统。 |
Nacos作用
功能 | 描述 |
---|---|
配置管理 | 将应用程序的配置信息存储在 Nacos 的配置中心,通过动态配置管理和灰度发布,实现微服务的动态热更新和配置。 |
服务发现与注册 | 将服务注册到 Nacos 注册中心,Nacos 会自动发现服务并进行负载均衡,实现服务的高可用性和伸缩性。 |
服务治理 | 提供健康检查、故障转移、服务限流、熔断降级等治理能力,提升服务的可靠性和稳定性。 |
事件监听和推送 | 实现配置变更、服务注册、注销等事件的监听和推送,支持应用程序的自动化部署和管理。 |
Nacos配置变化客户端感知
Nacos 是一个用于服务注册、发现和配置管理的平台,支持配置热更新、服务治理、健康检查等功能。它通过动态配置和服务负载均衡,提升了微服务的高可用性和可靠性。Nacos 的核心功能还包括事件监听,支持配置变更的实时推送。
长轮询 (Long Polling) 讲解
- 概念:长轮询是一种介于推送和轮询之间的机制。客户端发起请求后,服务器不会立即返回结果,而是“hold”住请求,直到有数据更新或超时再返回。如果有数据更新,服务器立即返回响应;如果没有更新,服务器则等待一段时间后返回,再由客户端重新发起下一次请求。
- 优点:
- 实时性强:一旦有配置或数据变更,客户端可以快速感知到更新。
- 资源消耗较低:相比于传统的短轮询,长轮询减少了不必要的频繁请求,降低了服务器压力。
- Nacos 的使用:
- Nacos 1.x 版本采用长轮询模式,客户端定期发起请求,服务器保持连接直到有更新。
- Nacos 2.x 则使用基于 gRPC 的长连接,进一步提高了实时性和性能。
Feign远程调用
我们在不同服务之前需要相互调用,在项目中,我们是使用Feign远程调用的。
Feign 是 Spring Cloud 提供的一种 声明式 HTTP 客户端,用于简化微服务之间的 远程调用。它允许开发者通过 接口 来调用远程服务,就像调用本地方法一样,无需编写大量的 HTTP 请求代码。
Feign 使用示例
定义 Feign 客户端接口:
1 | import org.springframework.cloud.openfeign.FeignClient; |
使用 Feign 调用远程服务:
1 | import org.springframework.beans.factory.annotation.Autowired; |
Feign 的优点
- 声明式调用:通过接口和注解的方式,简化了远程服务的调用过程。
- 简洁的代码:开发者不再需要手动编写 HTTP 请求代码,减少了重复代码。
- 与 Spring Cloud 生态的良好集成:支持与 Ribbon、Hystrix 等组件无缝结合,提供了负载均衡和容错机制。
还有哪些微服务之间调用方法呢?
调用方式 | 描述 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|
Feign | 声明式 HTTP 客户端,简化了微服务之间的 HTTP 调用,支持负载均衡和熔断。 | 简洁、直观,集成 Ribbon 和 Hystrix,支持负载均衡与容错。 | 仅支持 HTTP 协议,性能相比其他方式稍逊。 | 微服务之间通过 HTTP/REST 接口通信的场景,适用于 Spring Cloud 生态。 |
RestTemplate | Spring 提供的同步 HTTP 客户端,用于调用 RESTful API,配置灵活。 | 使用灵活,可自定义请求头、参数、超时等。 | 需要手动处理请求构建、响应解析,代码较为冗长。 | 同样用于 HTTP 通信,适合需要高度自定义的 HTTP 请求场景。 |
WebClient | Spring 5 中引入的异步非阻塞的 HTTP 客户端,支持响应式编程。 | 支持异步和响应式编程,性能优于 RestTemplate,适合高并发场景。 | 相比 RestTemplate 和 Feign,代码编写相对复杂。 | 适用于高并发、响应式编程场景,如对性能和资源利用率要求较高的系统。 |
gRPC | 基于 HTTP/2 和 Protobuf 的高效 RPC 框架,支持多语言微服务之间的通信。 | 高效、轻量,支持双向流、负载均衡、服务发现和认证,跨语言支持良好。 | 需要学习和配置 Protobuf,HTTP/2 相比 HTTP/1.1 复杂度高,调试难度大。 | 对性能要求高,跨语言微服务调用场景,如音视频处理、实时通信等。 |
Dubbo | 阿里巴巴开源的高性能 RPC 框架,支持多种协议与序列化方式,支持负载均衡和服务治理。 | 高性能,支持多种传输协议(如 Dubbo 协议、HTTP),提供丰富的服务治理功能,支持扩展性强。 | 生态体系主要集中在 Java,跨语言能力弱于 gRPC。 | 适用于对性能要求高的内部系统,尤其是需要服务治理、负载均衡等功能的场景。 |
Spring Cloud Gateway | Spring Cloud 提供的 API 网关,支持路由、负载均衡、安全认证等功能,适合前端和后端服务的调用。 | 提供强大的路由功能,具有负载均衡、限流、熔断和安全认证等能力。 | 主要用于服务的路由和过滤,复杂业务逻辑不适合。 | 适用于前端请求统一网关调度后端服务的场景,尤其是需要请求路由、过滤、限流等能力的场景。 |
消息队列 | 通过中间件(如 Kafka、RabbitMQ、ActiveMQ 等)进行异步消息通信,实现微服务之间的松耦合。 | 实现异步通信,解耦服务,支持事件驱动架构,适合高并发和高可用场景。 | 增加了系统复杂性,消息的时效性和可靠性需要额外考虑。 | 适用于事件驱动架构、异步处理、跨服务事务管理等场景,尤其是需要解耦的场景。 |
HTTP 调用 | 使用标准的 HTTP 请求(如使用 OkHttp、Apache HttpClient 之类的库)进行服务直接调用。 | 灵活性高,适合定制化需求,几乎所有编程语言都支持 HTTP 调用。 | 需要手动处理请求和响应,缺乏自动化的负载均衡、容错等功能。 | 适合简单的服务间通信或者需要跨语言调用的场景。 |
Thrift | Apache 开发的跨语言 RPC 框架,支持多种传输协议和序列化方式,性能较高。 | 序列化效率高,支持多语言,适合跨语言调用,性能优异。 | 需要学习和配置 Thrift IDL,调试较复杂,生态不如 gRPC 丰富。 | 适用于跨语言微服务调用且对性能要求较高的场景。 |
Gateway服务网关
Spring Cloud Gateway 是 Spring Cloud 生态系统中的一个 API 网关 框架,旨在为微服务架构中的请求提供统一的路由、过滤和管理功能。它是 Spring Cloud 的官方网关解决方案,替代了早期的 Zuul 网关。
功能 | 描述 |
---|---|
请求路由 | 路由是网关的基本功能,用于将客户端的请求转发到不同的微服务或后端系统。支持根据路径、方法、头信息等条件进行路由。 |
过滤器 | 过滤器用于在请求被路由之前或之后进行处理。内置过滤器支持修改请求头、添加响应头、限流、重定向等操作,支持自定义过滤器以满足更复杂的需求。 |
负载均衡 | 与 Spring Cloud LoadBalancer 集成,实现对后端服务的负载均衡。在多个服务实例之间分发请求,提升系统的可用性和性能。 |
安全认证与授权 | 支持与 Spring Security 集成,实现身份认证和权限控制。可以通过 JWT 验证用户身份,并根据角色对请求进行授权。 |
限流和熔断 | 与 Resilience4j 或 Hystrix 集成,实现请求的熔断和限流功能,防止后端服务过载或故障影响系统的稳定性。 |
路径重写 | 支持请求路径重写,例如将 /api/service1/** 重写为 /service1/** ,从而简化后端服务的路径管理。 |
WebSocket 支持 | 支持 WebSocket 通信,能够处理 WebSocket 请求并将其转发到后端服务,实现实时双向通信。 |
监控与可视化 | 可以与 Spring Boot Actuator 集成,提供路由、过滤器、限流等功能的监控数据,帮助管理员实时掌握网关的运行状态和性能。 |
核心功能:
- 请求路由
- 权限控制
- 限流
Gateway快速入门
- 创建SpringBoot工程gateway,引入网关依赖
- 编写启动类
- 编写基础配置和路由规则
- 启动网关服务进行测试.
引入网关依赖
1 | <!--网关--> |
编写启动类
1 | package cn.itcast.gateway; |
编写基础配置和路由规则
1 | server: |
我们将符合Path
规则的一切请求,都代理到 uri
参数指定的地址。
本例中,我们将 /user/**
开头的请求,代理到lb://userservice
,lb是负载均衡,根据服务名拉取服务列表,实现负载均衡。
整个访问的流程如下:
有意思的问题:网关如果挂了还能正常运行吗?
如果网关挂掉了,通常情况下系统**将无法正常运行。**原因如下:
网关是系统的“单点入口”
- 在微服务架构中,网关通常是整个系统的唯一入口,所有请求都通过网关转发到后端服务。如果网关挂掉了,客户端的请求将无法到达后端服务。
- 这意味着系统的所有服务对外部的暴露将被阻断,整个系统可能会变得不可用。
参考自:微服务Day3y