ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Java框架 SpringCloud 快速入门: 搭建 Gateway 网关实现请求路由

Java框架 SpringCloud 快速入门: 搭建 Gateway 网关实现请求路由 概述微服务拆成十几个服务后前端不可能挨个记它们的 IP 和端口这层统一入口就该由网关来兜底。本文用 cloud-demo 项目里的 gateway 模块把 SpringCloud Gateway 从零搭起来跑通第一条路由。纲要为什么需要网关没有网关时客户端直连微服务的问题网关的三大职责路由转发、权限校验、限流客户端 → gateway(10010) → user-service / order-service 的架构图网关技术选型对比Zuul / Gateway / NginxGateway 快速入门四步走新建 gateway 模块引入依赖含不能引 spring-boot-starter-web 的坑启动类代码application.yml 路由配置id、uri、predicates启动测试与预期输出断言Predicate与过滤器Filter的关系网关路由的完整处理流程实战坑清单web 依赖冲突、lb:// 写错 503、无注册中心时的 uri 写法、yml 缩进导致 404为什么需要网关cloud-demo 里已经有 user-service8081、order-service8082两个服务后续再加商品、支付、登录……如果让前端直接调客户端就得维护一张不断膨胀的服务地址表服务一迁移全部跟着改。这些地址、鉴权、限流的横切逻辑收拢到一个统一入口处处理就是网关的位置。Gateway 网关是所有微服务的统一入口核心做三件事路由转发请求先到网关网关不处理业务按规则把请求转发到对应微服务。目标服务有多个实例时还要做负载均衡。权限校验作为入口先判断用户有没有请求资格没资格直接拦截不让请求进到业务服务。限流流量高峰时按下游微服务能承受的速度放行请求避免把服务压垮。对应到 cloud-demo 的整体架构/user/**/user/**/order/**注册注册注册服务发现客户端gateway 网关:10010user-service:8081user-service:8082order-service:8083Nacos 注册中心:8848网关本身不写任何业务逻辑——它只负责把请求送到对的地方。所以后面验证时你会发现网关服务里一行业务代码都没有访问http://localhost:10010/user/1却能查到用户数据。网关技术选型SpringCloud 里能当网关的不止一家选型前先把差异摆清楚技术方案实现基础编程模型定位与特点Zuul 1.xServlet阻塞式 IOSpringCloud 老牌网关每个请求占用一个线程高并发下线程开销大Zuul 2.xNetty响应式官方没纳入 SpringCloud 集成社区支持弱SpringCloud GatewayWebFlux Reactor响应式非阻塞SpringCloud 官方推荐少量线程扛大量请求性能优于 ZuulNginxC事件驱动反向代理偏向流量入口、静态资源和负载均衡写业务逻辑不方便一句话结论业务网关选 Gateway跟 SpringCloud 生态无缝集成过滤器里能直接写 Java 业务逻辑Nginx 更适合放在 Gateway 前面做流量入口和静态资源分发两者是配合关系不是二选一。Gateway 快速入门搭建步骤四步新建模块引入依赖 → 编写启动类 → 配置路由规则 → 启动测试。新建 gateway 模块在 cloud-demo 父工程下新建一个 module命名为 gateway。模块结构cloud-demo ├── eureka-server # 注册中心演示工程 ├── gateway # 本次新建的网关模块 │ ├── pom.xml │ └── src/main │ ├── java/cn/itcast/gateway │ │ └── GatewayApplication.java │ └── resources │ └── application.yml ├── order-service # 订单服务 └── user-service # 用户服务这里有个必讲的坑gateway 模块绝对不能引入spring-boot-starter-web。Gateway 基于 WebFlux响应式而 spring-boot-starter-web 基于 Spring MVC阻塞式 Servlet两者同时存在时 Spring Boot 启动报错*************************** APPLICATION FAILED TO START *************************** Description: Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway. Action: Please remove spring-boot-starter-web dependency.按报错提示把 web 依赖移除即可网关只暴露路由和过滤能力不需要 MVC 那一套。同理spring-boot-starter-webflux也不要手动引gateway starter 自己会带。引入依赖gateway 的 pom.xml 只需要两个依赖网关 starter 提供路由、断言、过滤器等全部网关能力nacos 服务发现依赖是因为网关本身也是微服务要把自己注册到 Nacos也要从 Nacos 拉取下游服务列表做负载均衡?xml version1.0 encodingUTF-8?projectxmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdcloud-demo/artifactIdgroupIdcn.itcast.demo/groupIdversion1.0/version/parentmodelVersion4.0.0/modelVersionartifactIdgateway/artifactIdpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.target/propertiesdependencies!--nacos服务注册发现依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency!--网关gateway依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependency/dependenciesbuildfinalNameapp/finalNamepluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build/project两个依赖的引入顺序无所谓先引谁都行。编写启动类packagecn.itcast.gateway;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplicationpublicclassGatewayApplication{publicstaticvoidmain(String[]args){SpringApplication.run(GatewayApplication.class,args);}}就是个普通 Spring Boot 启动类没有任何网关专属注解——网关的能力全靠自动装配starter 在类路径下就会生效。编写路由配置请求路由通过 application.yml 配置实现。先配服务端口、服务名、Nacos 地址让网关能注册到 Nacos 并发现其他服务然后才是核心的spring.cloud.gateway.routesserver:port:10010# 网关端口spring:application:name:gateway# 服务名称cloud:nacos:server-addr:localhost:8848# nacos地址gateway:routes:# 网关路由配置加了s说明是数组可以配多条规则-id:user-service# 路由id自定义保证唯一即可# uri: http://127.0.0.1:8081 # 路由的目标地址http开头就是固定地址写死了uri:lb://userservice# 路由的目标地址lb是负载均衡load balance后面跟服务名称predicates:# 路由断言判断请求是否符合路由规则-Path/user/**# 路径断言只要路径以/user/开头就符合-id:order-serviceuri:lb://orderservicepredicates:-Path/order/**一条路由规则由三部分组成id路由的唯一标识只要不重复可以随便起这里直接叫 user-service。uri路由目标地址有两种写法。http://127.0.0.1:8081是把地址写死服务一扩容或迁移就要改配置一般不用推荐lb://服务名lb是 load balance 的缩写意思是转发时做负载均衡——网关拿服务名去 Nacos 拉服务列表再从中挑一个实例发请求。predicates断言判断请求是否符合规则。Path/user/**表示路径以/user/开头的请求符合这条路由会被代理到 userservice不符合的请求去找别的路由都不匹配就返回 404。这里的 Path 断言由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory这个类解析处理配置文件里写的只是一串字符串字符串会被对应的断言工厂读取并转成路由判断条件。启动测试依次启动 Nacos、user-service、order-service 和 gateway然后对比直连与走网关两种访问方式。不走网关直接访问用户服务curlhttp://localhost:8081/user/1走网关访问网关端口curlhttp://localhost:10010/user/1两者的响应完全一致{id:1,userName:itcast,address:北京}访问/order/101同理被 order-service 那条路由规则接住。注意此时网关服务里没有一行业务代码能查到数据就是因为请求被路由转发到了 user-service——网关只是个转发员。断言与过滤器的关系路由配置里还有第四个可选项 filters路由过滤器本节先建立概念框架后续文章展开。一次请求经过网关的处理顺序符合规则不符合全部不匹配请求到达网关predicates 断言判断命中路由filters 过滤器加工请求/响应转发到 uri 目标服务尝试下一条路由规则返回 404两者的分工用一句话概括断言决定请求走哪条路由过滤器决定请求/响应在转发前后被怎么加工。断言是路由的匹配条件如路径、请求方式、请求头过滤器是转发链路上的加工环节如给请求加头、修改响应。路由里还支持 default-filters 配置全局默认过滤器对每条路由都生效。网关路由的完整流程把前面所有环节串起来一次http://localhost:10010/user/1请求的完整旅程user-service:8081Nacos注册中心gateway:10010客户端user-service:8081Nacos注册中心gateway:10010客户端注册服务信息GET /user/1predicates判断/user/** 命中 user-service 路由根据服务名 userservice 拉取服务列表返回实例列表 [8081, 8082]负载均衡挑一个实例如8082转发 GET /user/1用户数据JSON响应结果关键点请求进入网关后网关按路由规则顺序做断言匹配命中user-service这条后因为 uri 写的是lb://userservice网关会拿服务名去 Nacos 查地址列表负载均衡选中一个实例比如 8082再把请求发过去。服务端扩缩容时网关配置一行都不用改这就是 lb 写法比写死 http 地址好的根本原因。实战坑清单这几个坑都真实踩过排障时按现象对号入座现象原因解决方式启动报错 Spring MVC found on classpathgateway 模块引了 spring-boot-starter-web与 WebFlux 冲突移除 web 依赖父工程统一管理依赖时单独 exclusion返回 503 Service Unavailableuri 写成lb://user-service但注册中心里服务名实际是userservice或 lb 前缀写成lb:/、lb//lb 后面的服务名必须与spring.application.name完全一致注意大小写启动即失败 No instances available没有启动注册中心或目标服务未注册却用了lb://前缀先起 Nacos 并注册目标服务没有注册中心时 uri 必须写http://具体IP:端口请求返回 404路由像没生效yml 缩进错误routes 下每一项是数组元素- id前面的短横线缩进层级不对或 predicates 下的- Path/user/**缩进错了对照上面的完整 yml 逐层检查缩进开启 debug 日志logging.level.cn.itcast: debug观察路由匹配过程路由不生效且报 404但 yml 看着没问题服务名大小写不一致如配置写lb://Userservice而注册的是userservice统一使用小写服务名排查路由问题最快的手段是看启动日志Gateway 启动时会加载routes配置多少条路由、每条的 id 和 uri 都打在日志里请求进来后再结合 debug 级别日志看断言匹配能定位九成问题。API 速览配置项 / 概念位置说明spring.cloud.gateway.routesapplication.yml路由配置数组网关核心配置idroutes 数组元素路由唯一标识自定义不可重复uriroutes 数组元素目标地址http://固定地址lb://服务名负载均衡predicatesroutes 数组元素断言列表全部满足才命中路由Path/xxx/**predicates 数组路径断言按路径前缀匹配filtersroutes 数组元素路由过滤器对请求/响应做加工default-filtersspring.cloud.gateway 下全局默认过滤器对所有路由生效官方文档Spring Cloud Gateway 官方文档Spring Cloud Alibaba Nacos Discovery总结网关是微服务的统一入口负责路由转发、权限校验、限流三件事Gateway 基于 WebFlux 响应式实现性能优于 Servlet 阻塞式的 Zuul。搭建网关两步走引 nacos 服务发现 gateway 两个依赖yml 里配服务信息加 routes 路由规则。一条路由 id唯一标识 uri目标地址推荐lb://服务名 predicates断言匹配可选 filters 做请求加工。高频坑都在依赖冲突web 与 gateway 互斥和配置细节服务名大小写、yml 缩进、lb 前缀上报错信息基本能直接定位。
返回列表