Spring Cloud Gateway网关(一)之网关路由
1、gateway相关介绍
在微服务架构中,系统往往由多个微服务组成,而这些服务可能部署在不同机房、不同地区、不同域名下。这种情况下,客户端(例如浏览器、手机、软件工具等)想要直接请求这些服务,就需要知道它们具体的地址信息,例如 IP 地址、端口号等。这种客户端直接请求服务的方式存在很多的复杂问题。如:需要维护大量的服务地址、存在跨域请求的问题、每个微服务需要独立认证等。所以我们可以通过 API 网关(gateway)来解决这些问题。所有客户端请求都发生到网关,由网关统一转发到不同的地址。网关还可以 处理一些非业务功能的逻辑,例如权限验证、监控、缓存等。本篇主要讲解通过网关统一请求转发到不同微服务。
2、创建网关服务
首先创建maven项目新建网关模块:
pom导入网关相关依赖:
<dependencies> <!--Eureka Client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--特别注意:在 gateway 网关服务中不能引入 spring-boot-starter-web 的依赖,否则会报错--> <!-- Spring cloud gateway 网关依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
<!-- LoadBalancer -->
<!-- 引入spring-cloud-loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--ribbon Spring Cloud Ribbon 在高版本移除了 -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>-->
<!-- <version>2.2.5.RELEASE</version>-->
<!-- </dependency>-->
</dependencies>
创建springboot启动类:
@SpringBootApplication @EnableEurekaClient public class GateWayApplication { public static void main(String[] args) { SpringApplication.run(GateWayApplication.class,args); } }
启动类创建成功后,在resources资源目录下创建application.yml文件,用来配置gateway。首先设置服务端口和服务名称:
server: port: 8081 spring: application: name: gateway-server-one
在把网关注册到注册中心:
#客户端注册 eureka: instance: instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} #localhost hostname: localhost client: register-with-eureka: true #是否向注册中心注册自己 默认为true fetch-registry: true #是否需要检索服务 默认为true service-url: defaultZone: http://eternity:1234qwer@localhost:4405/eureka/
配置好之后,可以启动网关。查看网关服务是否可以正常启动以及是否在注册中心注册成功,如果注册成功然后在开始配置网关参数。
可以看到服务启动成功,我们看看注册中心是否成功:
eureka中心已经有了,说明启动成功。
3、配置gateway路由
spring: application: name: gateway-server-one cloud: loadbalancer: ribbon: enabled: false #使用LoadBalancer, Ribbon 在高版本移除了 切换到ReactiveLoadBalancerClientFilter gateway: discovery: locator: #路由访问方式:http://Gateway_HOST:Gateway_PORT/大写的serviceId/**,其中微服务应用名默认大写访问。 enabled: true #开启通过名称找到服务器功能 lower-case-service-id: true #使用小写service-id routes: - id: hibernate-server-one-route #路由的ID,没有固定规则,但要求唯一,建议与服务名对应 uri: http://localhost:8800 #匹配后提供服务的路由地址 predicates: #以下是断言条件,必选全部符合条件 - Path=/admin/user/** #断言,路径相匹配的进行路由 - Method=GET #只能时 GET 请求时,才能访问 - id: xxl-job-server-one-route # uri: http://localhost:8801 #可以设置为服务名 uri: lb://XXL-JOB-SERVER-MODEL #可以设置为服务名 predicates: - Path=/admin/user/** #断言,路径相匹配的进行路由, 注意:Path 中 P 为大写 - After=2022-06-06T03:29:37.318-07:00 # [Asia/Shanghai] # after来进行设置,后面添加一个时间,就是指在什么时间之后这个服务才可以被访问,否则将无法被访问到 # - After=2030-01-20T17:42:47.789-07:00 # [America/Denver]
配置成功后再次启动网关,查看服务器是否转发成功。
通过网关gateway请求路径访问查找用户信息:
http://localhost:8081/admin/user/
通过postman测试接口,查询成功。
4、gateway负载均衡
通过在配置文件中配置路径的uri为注册中心服务器名称,可以实现gateway负载均衡。访问时通过服务名称去查找服务名下面的多个实例,根据配置的策略实现转发到不同实例服务。
uri: lb://XXL-JOB-SERVER-MODEL #可以设置为服务名
在通过服务名称转发的过程中,有可能转发失败。报找不到服务,接口报错:
查看网关控制台发现也报错:
java.net.UnknownHostException: failed to resolve 'xxl-job-server-model' after 4 queries at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final] Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): |_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain] |_ checkpoint ⇢ HTTP POST "/admin/user/" [ExceptionHandlingWebHandler] Stack trace: at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final] at io.netty.resolver.dns.DnsResolveContext.tryToFinishResolve(DnsResolveContext.java:966) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final] at io.netty.resolver.dns.DnsResolveContext.query(DnsResolveContext.java:414) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
没有找到服务名,刚开始以为是设置路由的服务名和注册中心的服务名不一致。经过查找发现是一致。最后查找发现是客户端微服务注册到注册中心的hostname配置错误,需要配置和注册中心一致的hostname。不然网关通过服务名找不到相关地址:
查看eureka服务注册地址:
所以需要配置客户端hostname:
hostname: localhost
再次重新运行系统,发现报错问题已经解决。