目录
1、微服务
2、特点
3、组件
3.1、Nacos
1. 注册中心原理
2. 核心特性
3. 使用原因
4. 部署方式
3.2、配置中心
3.3、gateway
1、基本功能:
2、gateway核心概念
3.4、feign
1、介绍
2、核心组件
3、Feign优化点
5、Feign的日志级别
3.5、hystrix
4、跨域问题
前言
1. 微服务架构的兴起
-
单体应用的痛点:
2010 年代初期,企业应用多采用单体架构(Monolithic),随着业务复杂度增加,单体应用面临以下问题:-
维护困难:代码臃肿,牵一发而动全身。
-
扩展性差:无法针对单个功能模块独立扩展。
-
技术栈僵化:难以引入新语言或框架。
-
-
微服务的解决方案:
-
Netflix、Amazon 等公司率先实践微服务架构(将应用拆分为小型、松耦合的服务),但随之而来的是分布式系统的复杂性:-
服务如何通信?
-
如何实现服务发现、负载均衡?
-
如何保证容错和一致性?
Spring Cloud 的目标:提供一套标准化工具链,简化微服务的开发和治理。
-
1、微服务
对于一个微服务的项目架构,通常会有网关服务、接口服务、微服务组件、中间件服务、数据存储组成。如下图所示:
而对于springcloud,它主要提供了以下几点:
基于 Spring 生态的微服务全家桶,提供一站式分布式系统解决方案。目前整合了 Netflix、Hystrix、rabbion、feign、gateway、Seata 等组件,涵盖服务发现、配置中心、熔断、网关、链路追踪和事务Seata。
云原生技术的前奏:
Spring Cloud 的部分设计理念(如配置中心、服务网格的雏形)为后来的 Kubernetes 和 Service Mesh 奠定了基础。例如:
-
Spring Cloud Config → Kubernetes ConfigMap
-
Spring Cloud Gateway → Istio Ingress
2、特点
通过对流量的流向,可以得出微服务在项目开发过程中的结论:
特点:
通常基于 HTTP/REST 或 OpenFeign(声明式 HTTP 客户端),文本传输(如 JSON),跨语言友好。目前 HTTP 协议头开销较大,性能低于 Dubbo,适合对吞吐量要求不高的场景。
通过 Spring Cloud Netflix 或 Spring Cloud Alibaba 、 Spring Boot 无缝集成。
3、组件
3.1、Nacos
1. 注册中心原理
常用的nacos(aliyun维护)或者eureka(netflix已经停更),关于注册中心还有zk(雅虎开发)
目前nacos的的特性包括:
Nacos = Spring Cloud Eureka + Spring Cloud Config
Nacos 可以与 Spring, Spring Boot, Spring Cloud 集成,并能代替 Spring Cloud Eureka, Spring Cloud Config。
如下图所示为nacos的界面,需要手动安装服务端https://github.com/alibaba/nacos/releases。
安装完成后,启动,并在浏览器上访问相应的端口。
2. 核心特性
配置管理:
Nacos提供了统一的配置管理平台,可以帮助用户集中管理不同环境的配置信息。用户可以通过Nacos的控制台或API进行配置的新增、修改、删除等操作,并且支持配置的版本管理。
服务发现和注册:
Nacos提供了服务注册和发现的功能,可以帮助用户快速发现和访问服务。服务提供者在启动时将服务的元数据注册到Nacos,服务消费者通过Nacos获取服务提供者的地址信息,并进行调用。
动态配置:
Nacos支持动态配置,可以在不停机的情况下动态修改配置信息。例如,可以通过Nacos修改数据库连接池的最大连接数,而不需要重启应用。
健康检查:
Nacos提供了健康检查的功能,可以检测服务的可用性。当服务不可用时,Nacos会自动将该服务从服务列表中剔除。
路由策略:
Nacos支持多种路由策略,可以根据不同的规则将请求路由到不同的服务提供者。
3. 使用原因
易⽤:
简单的数据模型, 标准的 restfulAPI, 易用的控制台, 丰富的使用文档。
稳定:
99.9% 高可用, 脱胎于历经阿里巴巴 10 年生产验证的内部产品, 支持具有数百万服务的大规模场景, 具备企业级 SLA 的开源产品。
实时:
数据变更毫秒级推送生效; 1w 级, SLA 承诺 1w 实例上下线 1s, 99.9% 推送完成; 10w级, SLA 承诺 1w 实例上下线 3s, 99.9% 推送完成; 100w 级别, SLA 承诺 1w 实例上下线 9s,99.9% 推送完成。
规模:
十万级服务/配置, 百万级连接, 具备强大扩展性。
4. 部署方式
主要分为 单机模式、集群模式 和 多集群模式,同时支持与 Kubernetes 等云原生平台集成。
1、单机模式
适用场景:开发测试环境或资源有限的小型生产环境。
特点:
-
使用内置的 Derby 数据库(默认),数据不持久化,重启后丢失。
-
轻量级启动,无需额外依赖。
操作方式示例:
1.解压安装
wget https://github.com/alibaba/nacos/releases/download/2.2.0/nacos-server-2.2.0.tar.gz
tar -zxvf nacos-server-2.2.0.tar.gz
cd nacos/bin
2.启动
# Linux/Unix
sh startup.sh -m standalone
# Windows
startup.cmd -m standalone
3.访问控制台:
http://<IP>:8848/nacos
(默认账号/密码:nacos/nacos
)。
注意:
若需持久化数据,可切换至 MySQL 数据库(修改 conf/application.properties
):
spring.datasource.platform=mysql
db.url.0=jdbc:mysql://<MySQL_IP>:3306/nacos?characterEncoding=utf8
db.user=nacos
db.password=nacos
2.集群模式
适用场景:生产环境,保证高可用和负载均衡。
特点:
-
至少 3 个节点(避免脑裂问题)。
-
需依赖外部数据库(如 MySQL)共享数据。
-
通过 VIP(虚拟 IP) 或 SLB 对外提供统一入口。
部署步骤:
1. 准备数据库:
1.执行 conf/nacos-mysql.sql
初始化数据库表结构。
2. 修改配置文件
编辑 conf/application.properties
配置 MySQL 数据源(同单机模式)。
编辑 conf/cluster.conf
,列出所有节点 IP 和端口:
192.168.1.101:8848
192.168.1.102:8848
192.168.1.103:8848
3. 启动集群:
-
在每个节点执行启动命令(无需
-m standalone
参数):
sh startup.sh
4. 验证集群状态:
-
访问任意节点的控制台,在「集群管理」中查看节点列表。
3. 多集群模式(多数据中心)
适用场景:跨地域或跨可用区部署,实现容灾和多活。
特点:
-
每个集群独立部署,通过 Nacos Sync 组件同步数据。
-
依赖全局统一的命名空间(Namespace)和服务分组(Group)。
部署要点:
-
每个数据中心的 Nacos 独立集群部署(参考集群模式)。
-
使用 Nacos Sync 同步服务注册信息和配置:
# 示例同步配置(从集群A同步到集群B)
sync:clusters:from:cluster-name: ClusterAserver-addr: 192.168.1.101:8848to:cluster-name: ClusterBserver-addr: 192.168.2.101:8848
3.2、配置中心
使用nacos作为配置中心使用时,如下图所示:
参数说明:
命名空间:
Nacos 基于Namespace 帮助用户逻辑隔离多个命名空间,这可以帮助用户更好的管理测试、预发、生产等多环境服务和配置,让每个环境的同一个配置(如数据库数据源)可以定义不同的值。
Data ID:配置的唯一标识,用于查找配置文件。
Group:配置分组,用于设置小组信息。
3.3、gateway
由路由转发 + 执行过滤器链组成。
根据以下视图展示,可以清楚知道网关在服务中的定位及作用。
可以看到网关服务主要为下游微服务的路由,而nginx#属于对下游网关组件的负载。
下面可以来看下为什么需要网关及特点:
1、基本功能:
- 统一入口:暴露出网关地址,作为请求唯一入口,隔离内部微服务,保障了后台服务的安全性
- 鉴权校验:识别每个请求的权限,拒绝不符合要求的请求
- 动态路由:动态的将请求路由到不同的后端集群中
- 限流:通常结合redis进行。
2、gateway核心概念
以下为网关的作用:
1、路由(Route):
由一个ID,一个目标URI(最终路由到的url地址),一组断言(匹配条件判断)和一组过滤器定义。如果断言为真,则路由匹配。
代码示例:
spring:cloud:gateway:routes:- id: manager # 路由唯一标识uri: lb://manager_server # 路由指向目的地URL或服务名,客户端请求最终被转发到的微服务predicates:- Path=/manager/** # 断言:以manager开头的请求都负载到manager_server服务filters:- RewritePath=/manager/(?<segment>.*), /$\{segment} # 过滤器:过滤掉url里的manager,例如http://ip:port/manager/test -> http://ip:port/testorder: 5 # 用于多个Route之间的排序,数值越小越靠前,匹配优先级越高
2、断言(Predicate):
通过断言匹配http请求中的任何内容(请求头、请求参数等),如果匹配成功,则匹配断言所在路由。
代码示例:
spring:cloud:gateway:routes:- id: manageruri: https://manager_serverpredicates:- After=2017-01-20T17:42:47.789-07:00[America/Denver] # 时间点后匹配- Before=2017-01-20T17:42:47.789-07:00[America/Denver] # 时间点前匹配- Between=2017-01-20T17:42:47.789-07:00[America/Denver],2017-01-21T17:42:47.789-07:00[America/Denver] # 时间区间匹配- Cookie=chocolate, ch.p # 指定cookie正则匹配- Header=X-Request-Id, \d+ # 指定Header正则匹配- Host=**.somehost.org,**.anotherhost.org # 请求Host匹配- Method=GET,POST # 请求Method匹配指定请求方式- Path=/red/{segment},/blue/{segment} # 请求路径正则匹配- Query=green # 请求包含某参数- Query=red, gree. # 请求包含某参数并且参数值匹配正则表达式(匹配red;green,greet,gree...)- RemoteAddr=192.168.1.1/24 # 远程地址匹配# 设置分组和权重,按照路由权重选择同一个分组中的路由- id: preManager1uri: https://preManager1predicates:- Weight=group1, 2- id: preManager2uri: https://preManager2predicates:- Weight=group1, 8
3、过滤器(Filter):
在请求前后执行业务逻辑,比如鉴权、日志监控、流量控制、修改请求头、修改响应等。
1.按生命周期分类
前置(pre)过滤器:
在请求被路由之前调用:在chain.filter(exchange)前编写过滤器逻辑。
后置(post)过滤器:
在路由到微服务之后调用:通过chain.filter(exchange).then(Mono.fromRunnable(() -> {过滤器逻辑})实现。
2.按类型分类
- 局部(GatewayFilter)过滤器:作用在某一个路由上,使用时需要关联指定的路由
- 全局(GlobalFilter)过滤器:作用在所有路由上,不需要在配置文件中配置
关于自定义全局过滤器:
创建自定义全局过滤器类 ,实现GlobalFilter和Ordered两个接口。
- GlobalFilter:全局过滤拦截器
- Ordered:拦截器的顺序,数字越低,优先级越高
模拟登录校验
在过滤器中检查请求中是否携带token请求头。如果token请求头存在则放行;如果token为空或者不存在则返回认证失败状态码。
@Component
public class MyGlobalFilter implements GlobalFilter,Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {boolean token = exchange.getRequest().getHeaders().containsKey("token");System.out.println("----全局过滤器token----"+token);if (!token){exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);ServerHttpResponse response = exchange.getResponse();return response.setComplete();}return chain.filter(exchange);}@Overridepublic int getOrder() {return 1;}
}
以下为通过全局过滤器设置登录权限的管控代码示例:
@Order(-1)
@Component
public class Authorizes implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1.获取请求参数ServerHttpRequest request = exchange.getRequest();MultiValueMap<String, String> queryParams = request.getQueryParams();//2.获取参数中的authorization参数String authorization = queryParams.getFirst("authorization");//3.判断参数值是否等于adminif ("admin".equals(authorization)){//4.放行return chain.filter(exchange);}//5.拦截//5.1 设置状态码exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}
}
4、执行顺序:
小结:
网关,旨在为微服务架构提供一种简单有效的统一的API路由管理方式。同时,基于Filter链的方式提供了网关的基本功能,比如:鉴权、流量控制、熔断、路径重写、黑白名单、日志监控等。
3.4、feign
feign在服务调用的链路图如下所示:
Feign作为声明式的Web服务客户端,可以简化服务调用过程,提供一种更加优雅的方式去调用远程HTTP API。
Feign整合了Ribbon和Hystrix等Netflix开源组件只需通过注解的方式就能够直接调用服务,从而提高了开发效率和程序的可读性。
1、介绍
Feign是一个声明式的HTTP客户端,在内部使用到了动态代理的机制。
当定义一个接口,并使用 @FeignClient 注解标注之后,Feign会根据这个接口生成一个代理类。这个代理类在运行时会被实例化,并在调用接口方法时发起HTTP请求。
当FeignClient创建时,Ribbon会自动介入,根据服务实例的健康状况和配置的负载均衡策略,决定将请求发送到哪个实例。
以下为自定义负载机制:
@FeignClient(name = "example-service", configuration = ExampleConfiguration.class)
public interface ExampleServiceClient {// ...
}public class ExampleConfiguration {@Beanpublic IRule ribbonRule() {// 自定义负载均衡策略return new BestAvailableRule();}
}
2、核心组件
feign底层在远程进行接口调用的时候,常用各个组件的原理图如下所示:
默认的客户端:
-
JDK 原生的
HttpURLConnection
-
通过
Client.Default
实现
可以使用带连接池的httpclient
// 使用OkHttp的配置示例
@Bean
public Client feignClient() {return new OkHttpClient();
}
平常开发中,会将feign配合hystrix和负载均衡进行一起使用。
feign---->hystrix(判断实例是否可yong)------>reblance------>httpclient----->response
目前feign的底层原理里面常用的组件如下:
3、Feign优化点
Feign性能主要包括:
- 使用带连接池的http请求替代默认的URLConnection
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId>
</dependency>
- 日志级别,用打印最少的(basic或者none)
feign:client:config:default: #这里用default就是全局配置,如果写服务名称,则是针对某个微服务的配置loggerLevel: BASIChttpclient:enabled: true #开启feign对httpClient的支持max-connections: 200 #最大的连接数max-connections-per-route: 50 #每个路径的最大连接数
5、Feign的日志级别
Feign的日志级别分为四种:
NONE:不记录任何日志信息,这是默认值。
BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据
关于feign的实操,可以参考Feign介绍_feign loggerlevel-CSDN博客
3.5、hystrix
持续更新
总结:
-
Spring Cloud 是“微服务标准生态”,适合需要快速构建完整分布式系统的团队。
-
Dubbo 是“高性能 RPC 框架”,适合内部服务间的高效调用。
-
混合使用:实际项目中,可结合两者(如 Dubbo 用于内部服务调用,Spring Cloud 提供网关和配置管理)。
4、跨域问题
跨域:域名不一致就是跨域,主要包括:.
域名不同:
www.taobao.com 和 www.taobao.org 和www.jd.com 和 miaosha.jd.com。
域名相同,端口不同:
localhost:8080和localhost8081。
跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题。
可以参考以下设置进行解决:
spring:cloud:gateway:globalcors: # 全局的跨域处理add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题corsConfigurations:'[/**]':allowedOrigins: # 允许哪些网站的跨域请求 allowedOrigins: “*” 允许所有网站- "http://localhost:8090"allowedMethods: # 允许的跨域ajax的请求方式- "GET"- "POST"- "DELETE"- "PUT"- "OPTIONS"allowedHeaders: "*" # 允许在请求中携带的头信息allowCredentials: true # 是否允许携带cookiemaxAge: 360000 # 这次跨域检测的有效期
总结:
Spring Cloud 的核心使命
本质是通过 Spring 的编程模型和生态整合能力,将分布式系统的复杂性封装成简单、一致的 API,使开发者能够:
-
快速构建微服务:基于 Spring Boot 的“约定优于配置”。
-
无缝集成分布式组件:如注册中心、熔断器等。
-
适应云环境:为后续云原生演进铺路。
随着云原生技术的发展,Spring Cloud 也在持续进化(如支持 Kubernetes 原生服务发现),但其核心目标始终是降低分布式系统的开发复杂度。
参考文章:
1、Nacos的简介及安装和使用-CSDN博客
2、gateway基本配置-CSDN博客