网关简介
大家都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用 这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用。
这样的架构,会存在着诸多的问题:
- 客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性
- 认证复杂,每个服务都需要独立认证。
- 存在跨域请求,在一定场景下处理相对复杂。
上面的这些问题可以借助API网关来解决。
所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、路由转发等等。 添加上API网关之后,系统的架构图变成了如下所示:
Gateway快速入门
要求: 通过浏览器访问api网关,然后通过网关将请求转发到商品微服务
第1步:创建一个api-gateway 的模块,导入相关依赖
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--nacos客户端--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--限流--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-spring-cloud-gateway-adapter</artifactId></dependency></dependencies>
第2步: 创建主类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication
@EnableDiscoveryClient
public class ApiGatewayApplication {public static void main(String[] args) {SpringApplication.run(ApiGatewayApplication.class);}
}
第3步: 添加配置文件
server:port: 7000
spring:application:name: api-gatewaycloud:nacos:discovery:server-addr: localhost:8848 # 将gateway注册到nacosgateway:discovery:locator:enabled: true # 让gateway从nacos中获取服务信息
第4步:启动项目,并通过网关去访问微服务
localhost:7000/service-product/product/1
解释:
- localhost:7000 网关服务地址
- service-product 微服务name
- product/1 接口地址
这时候,就发现只要按照网关地址/微服务/接口的格式去访问,就可以得到成功响应。
自定义全局过滤器(鉴权)
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;//自定义全局过滤器(作用: 统一鉴权)需要实现GlobalFilter和Ordered接口
@Slf4j
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {//完成判断逻辑@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String token = exchange.getRequest().getQueryParams().getFirst("token");if (!StringUtils.equals(token, "admin")) {log.info("鉴权失败");exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}//调用chain.filter继续向下游执行return chain.filter(exchange);}//顺序,数值越小,优先级越高@Overridepublic int getOrder() {return 0;}
}
不加token认证不通过,返回401
加token=admin认证通过