网关Gateway学习实践

入门业务

第一步:创建sca-gateway模块,pom.xml文件中加入依赖

 <!--添加api网关依赖,添加此依赖以后不要再添加spring-cloud-starter-web依赖
 否则有冲突-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
  <!--添加服务发现依赖-->
        <dependency>
 			<groupId>com.alibaba.cloud</groupId>
 			<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
		</dependency>
<!--添加限流依赖(以下两个)-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>

第二步:创建application.yml,添加相关配置

server:
  port: 9000
spring:
  application:
    name: sca-gateway
  cloud:
    nacos:                        
      discovery: #服务注册和发现,若不需要注册可不写
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8180
      eager: true #true表示服务启动时,即可在sentinel控制台看到服务信息
    gateway:  #网关配置
      routes: # 路由配置(routes下可以有多个路由,用id做唯一标识)
        - id: route01
          #uri: http://localhost:8081/ #请求转发路径
          uri: lb://sca-provider #lb表示负载均衡,sca-provider为服务注册中心的一个服务名
          predicates: #谓词判断逻辑(定义请求转发条件,谓词所有条件都满足才会执行请求转发)
            - Path=/nacos/provider/echo/**
#            - After=2021-12-10T23:59:59.789+08:00[Asia/Shanghai]
#            - Header=X-Request-Id, \d+
#            - Method=Get
#            - Query=token, \d+
          filters: #局部过滤器,针对于当前路由进行设计,谓词逻辑返回值都为true则执行这里filter
            - StripPrefix=1 #去除前缀过滤器,这里1表示去掉Path中第一层目录

#流程分析: RoutePredicateHandlerMapping-->PathRoutePredicateFactory-->Xxx WebHandler-->Filters()

其中:路由(Route) 是 gateway 中最基本的组件之一,表示一个具体的路由信息载体。主要定义了下面的几个信息:

  • id,路由标识符,区别于其他 Route。
  • uri,路由指向的目的地 uri,即客户端请求最终被转发到的微服务。
  • predicate,断言(谓词)的作用是进行条件判断,只有断言都返回真,才会执行路由。
  • filter,过滤器用于修改请求和响应信息。

第三步:创建项目启动类
第四步:启动sca-provider、sca-gateway服务进行访问测试
(localhost:9000/nacos/provider/echo/***)

负载均衡

第一步:添加服务发现依赖
第二步:修改其配置文件
lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略。同时建议开发阶段打开gateway日志,代码如下:

logging:
  level:
    org.springframework.cloud.gateway: debug

第三步:启动8081、8082的provider端口服务,进行访问测试,并反复刷新分析

全局过滤器设计及实现

package com.jt;

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.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 自定义全局过滤器
 */
//@Component 将过滤器交给spring管理,实验过后,注释掉,否则后续每次请求,都需要传指定参数
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    /**Ordered  优先级,值越小,优先级越高
     * 请求过滤方法
     * @param exchange 基于此对象获取请求和响应对象
     * @param chain 过滤链
     * @return 这里的返回值代表一个Publisher对象(消息的发布者),
     * 可以由此对象帮你进行请求传递。
     */	 
    @Override
    public Mono<Void> filter(ServerWebExchange exchange,
                             GatewayFilterChain chain) {
        //1.获取请求对象
        ServerHttpRequest request = exchange.getRequest();
        //2.获取请求数据
        String username=
        request.getQueryParams().getFirst("username");
        //3.进行认证分析
        //3.1认证失败则拒绝请求继续传递
        if(!"admin".equals(username)){
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        //3.2认证成功继续处理(传递)
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

限流设计

还有最后
第一步:添加依赖
第二步:添加sentinel及路由规则
第三步:启动网关项目,检测sentinel控制台的网关菜单
启动时,添加sentinel的jvm参数,通过此菜单可以让网关服务在sentinel控制台显示不一样的菜单,代码如下。

-Dcsp.sentinel.app.type=1

在这里插入图片描述
第五步:通过url进行访问检测是否实现了限流操作

限流结果自定义

package com.jt;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.fastjson.JSON;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.Map;
网关流控的默认实现是DefaultBlockRequestHandler
@Configuration
public class GatewayConfig {
    public GatewayConfig(){
        GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                Map<String,Object> map=new HashMap<>();
                map.put("status", 429);
                map.put("message","blocked by sentinel ....");
                String jsonStr= JSON.toJSONString(map);
                return ServerResponse.ok()
                        .body(Mono.just(jsonStr),
                                String.class);
            }
        });
    }
}

其中,Mono 是一个发出(emit)0-1个元素的Publisher对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值