基于SpringCloudGateway实现微服务网关的方式

目录
  • (一)什么是微服务网关
  • (二)Spring Cloud Gateway网关
    • 2.1 核心概念:
    • 2.2 搭建环境:
  • (三) 路由配置详解
    • 3.1 自定义断言配置
    • 3.2 断言不匹配404页面自定义
  • (四)Spring Cloud Gateway过滤器
  • (五) 网关限流
    • 5.1 常见的一些限流算法:
    • 5.2 集成Sentinel进行限流
    • 5.3 网关实现跨域
  • (六)总结

(一)什么是微服务网关

后端写完所有的微服务之后,最终是要交给前端去调用。我们都知道每个微服务都有各自的端口号,如果前端直接通过IP加端口的方式去调用微服务会很麻烦。如果想对请求增加限制也会变得十分困难。这个时候微服务网关就出现了。

微服务网关又成为API网关,它是系统对外的唯一入口。APl网关封装了系统内部架构,为每个客户端提供一个定制的APl。API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。

听起来有些抽象,下面就做一张图给大家展示一下:前端的请求统一由微服务网关进行管理,微服务网关可以调用各个微服务,同时自身还有多种功能。

API网关的职责有身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理,最重要的功能是和外界联系。

常见的API网关实现方式有Zuul,traefix,Spring Cloud Gateway等等。目前主流的微服务网关是Spring Cloud Gateway。

(二)Spring Cloud Gateway网关

Spring Cloud Gateway是Spring 官方基于Spring 5.0,Spring Boot 2.0和Project Reactor 等技术开发的网关,旨在为微服务架构提供一种简单而有效的统一的API路由管理方式,统一访问接口。Spring Cloud Gateway作为Spring Cloud 生态系中的网关,目标是替代Netflix ZUUL,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。

2.1 核心概念:

路由(route):路由是网关最基础的部分,路由信息由一个ID,一个目的URL,一组断言工厂和一组Filter组成。

断言(predicates):java8中的断言函数,Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自Http Request中的任何信息。当断言为真时,则匹配路由。

过滤器(filter):对请求和响应进行过滤

下面通过实践来操作微服务网关,本项目有依赖于Nacos与Sentinel,如果不需要这部分的内容可以在配置文件中去除。

2.2 搭建环境:

1、引入工程导入依赖

创建api_gateway_server工程,在工程中的pom.xml中导入依赖,项目全局依赖如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.javayz</groupId>
    <artifactId>nacos-discovery-spring-cloud-gateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>nacos-discovery-spring-cloud-gateway</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <projec.build.sourceEncoding>UTF-8</projec.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.0.RELEASE</spring-boot.version>
        <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</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>

        <!--springcloudgateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
            <version>1.7.2</version>
        </dependency>
    </dependencies>

    <!--当前项目继承的依赖-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2、配置启动类

创建GatewayApplication类

@EnableDiscoveryClient
@SpringBootApplication
public class NacosDiscoverySpringCloudGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(NacosDiscoverySpringCloudGatewayApplication.class, args);
    }
}

3、编写配置文件

这里对配置文件的编写使用.yml格式的配置文件,在resource文件夹下创建applicaiion.yml。这里需要注意的是gateway下routes的配置,首先用id自定义网关;接着定义uri,意思是当访问的是9090端口(即访问的是网关时),就自动把ip和端口号变成该uri;最后写断言predicates,这里的Path=/index/** 指得是自动匹配 /index/**的路径。当请求地址为http://localhost:9090/index/1时,微服务网关会去访问http://nacos-discovery-consumer/index/1,这就是微服务网关调用微服务的功能。

server:
  port: 9090
spring:
  application:
    name: nacos-discovery-spring-cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #启用discoveryClient网关集成,实现服务发现
      routes:
        - id: route1
          uri: lb://nacos-discovery-consumer  #lb://表示负载均衡
          predicates:  #判断条件
            - Path=/test,/index/**

(三) 路由配置详解

路由断言中有许多匹配规则,之前只介绍了Path,其实还有许多匹配规则

predicates:
    #匹配一个时间,在这个时间之后发生的请求才能访问(格式是ZonedDateTime)
    - After=2021-03-14T11:31:08.377+08:00[Asia/Shanghai]
    #匹配一个时间,在这个时间之前发生的请求才能访问(ZonedDateTime)
    - Before=2021-03-14T11:31:08.377+08:00[Asia/Shanghai]
    #匹配两个时间,在这个时间之间才能访问
    - Between=2021-03-14T11:31:08.377+08:00[Asia/Shanghai],2021-03-14T12:31:08.377+08:00[Asia/Shanghai] #路由断言之间
    #路由断言Cookie匹配,匹配给定名称(如master)或者正则表达式,如下面配置,请求的cookie中必须有token=master才能访问
    - Cookie=token,master
    #根据请求头信息匹配,使用方式和cookie类似
    - Header=XXX,XXX
    #根据host地址匹配
    - Host=**.somehost.org
    #根据请求方法匹配
    - Method=GET
    #根据请求路径进行匹配
    - Path=***
    #根据参数匹配,如果配置为token,则所有的请求必须要带上token=XXX
   - Query=token
   #根据远程IP匹配
   - RemoteAddr=192.168.1.1/24
   #权重,第一个参数是组名,第二个参数是权重,两个route下配置不同权重,会根据权重负载访问
   - Weight=group1,8

定义请求路径时,我们还可以据微服务名称拉取请求路径,下面是两种不同方法定义uri,实现同样的功能。

uri: http://127.0.0.1:9001  #当访问9090端口时,自动把ip和端口替换为此uri
uri: lb://userservice #根据微服务名称拉取请求路径

总体的配置:

server:
  port: 9090
spring:
  application:
    name: nacos-discovery-spring-cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #启用discoveryClient网关集成,实现服务发现
      routes:
        - id: route1
          uri: lb://nacos-discovery-consumer  #lb://表示负载均衡
          predicates:  #判断条件
            - Path=/test,/index/**,/**

    nacos:
      discovery:
        server-addr: 192.168.78.128:8848
      username: nacos
      password: nacos

    sentinel:
      eager: true
      transport:
        dashboard: localhost:8080

3.1 自定义断言配置

自定义断言的实现分为两步,假设我们现在要实现一个自定义的过滤器,规则是必须携带一个token,并且token要等于指定的值。

1、定义配置类:这里包含在配置文件要传入的对象值

@Data
public class TokenConfig {
    private String token;
}

2、定义路由断言工厂:首先是命名必须是XXXRoutePredicateFactory,继承 AbstractRoutePredicateFactory

@Slf4j
@Component
public class TokenRoutePredicateFactory extends AbstractRoutePredicateFactory<TokenConfig> {
    public TokenRoutePredicateFactory(){
        super(TokenConfig.class);
    }
    //用来把配置中的值变成一个集合
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("token");
    }
    //通过jdk1.8的断言接口来返回true或者false,如果是true表示过滤器不拦截
    @Override
    public Predicate<ServerWebExchange> apply(TokenConfig config) {
        return exchange ->{
            //获取request请求参数
            MultiValueMap<String,String> valueMap=exchange.getRequest().getQueryParams();
            boolean flag=false;
            List<String> list=new ArrayList<>();
            //将request请求的value保存到集合里
            valueMap.forEach((k,v)->{
                list.addAll(v);
            });
            //判断有没有和配置文件中相同的值
            for (String s:list){
                log.info("Token"+s);
                if (StringUtils.equalsIgnoreCase(s,config.getToken())){
                    flag=true;
                    break;
                }
            }
            return flag;
        };
    }
}

最后在断言处写上我们自定义的内容:

predicates:  #判断条件
  - Path=/test,/index/**,/**
  - Token=javayz

只有链接是http://localhost:9090/sentinel/test1?token=javayz带上token=javayz的请求才能访问。

3.2 断言不匹配404页面自定义

SpringCloudGateway默认给出的404页面是

这样的页面实在不友好,我们可以通过自定义的方式让他返回一个JSON字符串

public class MyErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {

    public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }

    /**
     * 指定响应处理方法为JSON处理
     * @param errorAttributes
     * @return
     */
    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(),this::renderErrorResponse);
    }

    /**
     * 根据code获取对应的HttpStatus
     * @param errorAttributes
     * @return
     */
    @Override
    protected int getHttpStatus(Map<String, Object> errorAttributes) {
        return (int) errorAttributes.get("status");
    }

    /**
     * 构建异常信息
     * @param request
     * @param ex
     * @return
     */
    private String buildMessage(ServerRequest request,Throwable ex){
        StringBuilder builder = new StringBuilder("Failed to handle request:");
        builder.append(request.methodName());
        builder.append(" ");
        builder.append(request.uri());
        if (ex!=null){
            builder.append(ex.getMessage());
        }
        return builder.toString();
    }

    /**
     * 返回的json数据
     * @param status
     * @param errorMsg
     * @param data
     * @return
     */
    public static Map<String,Object> response(int status,String errorMsg,Object data){
        Map<String,Object> map=new HashMap<>();
        map.put("code",status);
        map.put("message",errorMsg);
        map.put("data",data);
        return map;
    }
}

新建一个类叫做MyErrorWebExceptionHandler:

再编写一个配置类,将自定义的异常页面代码注入到Bean容器中:

@Configuration
public class GatewayConfiguration {
    private final ServerProperties serverProperties;
    private final ApplicationContext applicationContext;
    private final ResourceProperties resourceProperties;
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfiguration(ServerProperties serverProperties, ApplicationContext applicationContext, ResourceProperties resourceProperties, ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) {
        this.serverProperties = serverProperties;
        this.applicationContext = applicationContext;
        this.resourceProperties = resourceProperties;
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    @Bean("myErrorWebExceptionHandler")
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public ErrorWebExceptionHandler myErrorWebExceptionHandler(ErrorAttributes errorAttributes){
        MyErrorWebExceptionHandler exceptionHandler=new MyErrorWebExceptionHandler(
                errorAttributes,
                this.resourceProperties,
                this.serverProperties.getError(),
                this.applicationContext
        );
        exceptionHandler.setViewResolvers(this.viewResolvers);
        exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
        exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
        return exceptionHandler;
    }
}

最后访问到404就会以JSON的格式返回,方便调用方做处理。

(四)Spring Cloud Gateway过滤器

Spring Cloud Gateway除了具有请求路由功能之外,也支持对请求的过滤。

生命周期:

过滤器有两种生命周期,PRE和POST:

PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。

POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。

过滤器类型:

GatewayFilter:应用到单个路由或者一个分组的路由上

GlobalFilter:应用到所有的路由上

局部过滤器可以使用Spring Cloud Gateway内置的方法,在官网中(docs.spring.io/spring-clou…

官方过滤器:

这里简单介绍几个:

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red, blue

添加AddRequestHeader过滤器后,每次请求转发给微服务后都会在header种增加一个X-Request-red。

- AddRequestParameter=red, blue

添加Request参数,每次请求转发给微服务后都会增加一个请求参数。

自定义全局过滤器: 创建一个Filter包,在包下新建GatewayFilter类,自定义全局过滤器需要继承GlobalFilter, Ordered接口,并重写接口的两个方法

@Component
public class GatewayFilter implements GlobalFilter, Ordered {
    //在里面写过滤器的逻辑
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("进入了过滤器");
        //表示继续向下执行
        return chain.filter(exchange);
    }
    //过滤器的优先级,数值越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

通过访问可以看到控制台上出现了打印的信息。

模拟用户认证过程:

全局过滤器可以实现对全局的用户验证。修改gatewayFilter,编写失败的逻辑,如果获取到的request请求中第一个属性不是access-token或为空,则返回HttpStatus.UNAUTHORIZED的报错

@Component
public class GatewayFilter implements GlobalFilter, Ordered {
    //在里面写过滤器的逻辑
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("进入了过滤器");
        String token = exchange.getRequest().getQueryParams().getFirst("access-token");
        if (token==null){
            //如果不存在,认证失败
            System.out.println("没有登陆");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }
    //过滤器的优先级,数值越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

在浏览器中输入:http://localhost:9090/sentinel/test1,出现报错,因为没有access-token

在浏览器中输入:http://localhost:9090/sentinel/test1?access-token=1,获取正确结果。

(五) 网关限流

在实际环境中会遇到这样的问题,同一时间会有许多请求去调用微服务,大量请求的进入很有可能导致微服务被破环,因此限流就变得很重要。

5.1 常见的一些限流算法:

计数器算法:设定一个单位时间内的计数值,如果单位时间内访问的请求大于这个设定的值,则之后的请求都拒绝。直到单位时间内的值低于这个值才继续接收。

漏桶算法:我们可以把漏桶算法想象成一个漏斗。请求进来时先到漏斗中,然后按设定好的输出速率分配到微服务上。当一下子有很多请求进来时,只能在漏斗上等着。为了控制流量,需要设置两个变量:一个是桶的大小,另一个是漏斗流出的速率。

令牌桶算法:令牌桶算法是对漏桶算法的一种改进,相比于漏桶算法,令牌桶算法能允许一定程度的突发调用。令牌桶算法的原理:在令牌桶算法中,存在一个桶,用来存放固定数量的令牌,令牌会以一定速率放到桶中,桶中的令牌满了之后就不会再放令牌。当一个请求来临时,要先在令牌桶中拿到一个令牌,才能去调用微服务,当令牌桶中没有令牌的时候,后来到的请求就需要等待。令牌桶算法除了可以限流,还允许一定程度的突发调用:比如一个令牌桶的容量是100,在没有请求的时候,令牌桶中的令牌数量是满的。此时如果突然来了100个请求,那么这100个请求都能被立刻执行。

5.2 集成Sentinel进行限流

添加依赖

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
    <version>1.7.2</version>
</dependency>

添加Sentinel配置:

spring:
  cloud:
    sentinel:
      eager: true
      transport:
        dashboard: localhost:8080

将Sentinel过滤器注入到Bean容器中

@Bean
@Order(-1)
public GlobalFilter sentinelGatewayFilter(){
    return new SentinelGatewayFilter();
}

这样就可以用Sentinel的方式对网关进行限流了。

对于限流后的错误提示,我们可以修改默认错误提示方式,改成自定义或者跳转到错误页面:

@Configuration
public class GatewayConfiguration {
    private final ServerProperties serverProperties;
    private final ApplicationContext applicationContext;
    private final ResourceProperties resourceProperties;
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfiguration(ServerProperties serverProperties, ApplicationContext applicationContext, ResourceProperties resourceProperties, ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) {
        this.serverProperties = serverProperties;
        this.applicationContext = applicationContext;
        this.resourceProperties = resourceProperties;
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    //自定义一个错误处理
    @Bean(name = "myBlockRequestHandler")
    public BlockRequestHandler myBlockRequestHandler(){
        BlockRequestHandler blockRequestHandler=new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                return ServerResponse.status(HttpStatus.BAD_GATEWAY)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(BodyInserters.fromValue("服务被限流了"));
            }
        };
        return blockRequestHandler;
    }

    //用自定义的handler替换掉默认的,或者重定向
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(BlockRequestHandler myBlockRequestHandler){
        //自定义Block处理
        GatewayCallbackManager.setBlockHandler(myBlockRequestHandler);

        //重定向block处理
        //GatewayCallbackManager.setBlockHandler(new RedirectBlockRequestHandler("http://www.baidu.com"));
        return new SentinelGatewayBlockExceptionHandler(viewResolvers,serverCodecConfigurer);
    }

    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter(){
        return new SentinelGatewayFilter();
    }
}

5.3 网关实现跨域

这个和SpringBoot中解决跨域的思路类似,配置CorsConfig

@Configuration
public class CorsConfig {

    @Bean
    public CorsWebFilter corsWebFilter(){
        CorsConfiguration configuration=new CorsConfiguration();
        configuration.addAllowedHeader("*");
        configuration.addAllowedMethod("*");
        configuration.addAllowedOrigin("*");

        UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/*",configuration);
        return new CorsWebFilter(source);
    }
}

(六)总结

本章内容比较多,但是把SpringCloudGateway基本会遇到的内容都讲解了一遍,希望对你有帮助。

到此这篇关于基于SpringCloudGateway实现微服务网关的文章就介绍到这了,更多相关SpringCloudGateway 微服务网关内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解spring cloud构建微服务架构的网关(API GateWay)

    前言 在我们前面的博客中讲到,当服务A需要调用服务B的时候,只需要从Eureka中获取B服务的注册实例,然后使用Feign来调用B的服务,使用Ribbon来实现负载均衡,但是,当我们同时向客户端暴漏多个服务的时候,客户端怎么调用我们暴漏的服务了,如果我们还想加入安全认证,权限控制,过滤器以及动态路由等特性了,那么就需要使用Zuul来实现API GateWay了,下面,我们先来看下Zuul怎么使用. 一.加入Zuul的依赖 <dependency> <groupId>org.spri

  • Spring Cloud Gateway编码实现任意地址跳转的示例

    目录 本篇概览 一般路由规则 特殊规则 设计 源码下载 编码 配置 开发和启动后台服务,模拟生产和测试环境 验证 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 作为<Spring Cloud Gateway实战>系列的第十四篇,本文会继续发掘Spring Cloud Gateway的潜力,通过编码体验操控网关的乐趣,开发出一个实用的功能:让Spring Cloud Gateway应用在收到请求后,可以按照业务的

  • SpringCloud中Gateway实现鉴权的方法

    目录 一.JWT 实现微服务鉴权 1 什么是微服务鉴权 2.代码实现 一.JWT 实现微服务鉴权 JWT一般用于实现单点登录.单点登录:如腾讯下的游戏有很多,包括lol,飞车等,在qq游戏对战平台上登录一次,然后这些不同的平台都可以直接登陆进去了,这就是单点登录的使用场景.JWT就是实现单点登录的一种技术,其他的还有oath2等. 1 什么是微服务鉴权 我们之前已经搭建过了网关,使用网关在网关系统中比较适合进行权限校验. 那么我们可以采用JWT的方式来实现鉴权校验. 2.代码实现 思路分析 1.

  • 聊聊Spring Cloud Gateway过滤器精确控制异常返回问题

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览在<Spring Cloud Gateway修改请求和响应body的内容>一文中,咱们通过filter成功修改请求body的内容,当时留下个问题:在filter中如果发生异常(例如请求参数不合法),抛出异常信息的时候,调用方收到的返回码和body都是Spring Cloud Gateway框架处理后的,调用方无法根据这些内容知道真正的错误原因

  • 基于SpringCloudGateway实现微服务网关的方式

    目录 (一)什么是微服务网关 (二)Spring Cloud Gateway网关 2.1 核心概念: 2.2 搭建环境: (三) 路由配置详解 3.1 自定义断言配置 3.2 断言不匹配404页面自定义 (四)Spring Cloud Gateway过滤器 (五) 网关限流 5.1 常见的一些限流算法: 5.2 集成Sentinel进行限流 5.3 网关实现跨域 (六)总结 (一)什么是微服务网关 后端写完所有的微服务之后,最终是要交给前端去调用.我们都知道每个微服务都有各自的端口号,如果前端直

  • Go微服务网关的实现

    目录 Go微服务网关 网络基础大纲 OSI七层网络协议 三次握手 与 四次挥手 为啥会出现大量的close_wait TCP 为啥需要拥塞控制 TCP 拥塞控制 为啥会出现粘包,拆包,如何处理 产生tcp粘包和拆包的原因 如何解决拆包粘包 如何获取完整应用数据报文 基于golang 实现TCP,UDP,Http服务端与客户端 Go微服务网关 从核心原理理解网关的本质 网关具备的基本功能: 支持多种协议代理:tcp/http/ websocket/grpc 支持多种负载均衡策略:轮询,权重轮询,h

  • SpringCloud超详细讲解微服务网关Gateway

    目录 前言 微服务网关GateWay介绍 GateWay特性介绍 Gateway 中的相关术语 Gateway实战 1.创建项目gateway 2.创建启动类 3.新增配置文件 4.编程方式实现路由 5.启动验证 总结 前言 上一篇:微服务网关Zuul 上文中,我们介绍了微服务网关Zuul,Zuul 是 Netflix 公司开源的产品,被称为第一代网关,也是 Spring Cloud 前几个版本默认使用的一款提供动态路由微服务网关组件,但是随着 Netflix 公司一系列的停更事件,在最新的 S

  • .Net Core微服务网关Ocelot基础介绍及集成

    网关是什么 简单来说,网关就是暴露给外部的请求入口.就和门卫一样,外面的人想要进来,必须要经过门卫.当然,网关并不一定是必须的,后端服务通过http也可以很好的向客户端提供服务.但是对于业务复杂.规模庞大的项目来说,使用网关有很多无法舍弃的好处,比如可以进行统一的请求聚合来节省流量.降低耦合度,可以赋予项目熔断限流的能力提高可用性等等. ocelot是什么 ocelot是.net core实现的开源的api网关项目,开源地址:https://github.com/ThreeMammals/Oce

  • SpringCloud超详细讲解微服务网关Zuul

    目录 网关的作用 Spring Cloud 网关组件Zuul介绍 Zuul网关实战 1.创建服务 2.创建配置文件 3.创建Zuul过滤器 4.编写启动类 5.启动验证 总结 网关的作用 微服务架构中,服务实例的地址可能经常会发生变化,所以我们不能直接将服务的地址暴露出来.如果每一个微服务都直接暴露接口,会导致一系列的问题,比如调用过于复杂,涉及到账户.权限不能统一处理等.另外基于高内聚低耦合的设计准则来讲,我们也应该将内部系统和外部系统做切割. 因此,这时就需要有一个独立的组件来处理外部的请求

  • .Net Core微服务网关Ocelot集成Consul

    有consul基础的都知道,consul可以发现新增的服务,剔除掉无效的服务,赋予应用自动伸缩的能力.而ocelot如果集成了consul,那ocelot也能拥有这些能力,还可以自主选择负载均衡策略,灵活性更强. (建议看完前一篇文章再来实践这一篇,不然可能有难度) 上干货. 首先打开上一篇新建好的项目,继续添加nuget包: 然后注册相关服务: public void ConfigureServices(IServiceCollection services) { services.AddOc

  • .Net Core微服务网关Ocelot集成Consul

    有consul基础的都知道,consul可以发现新增的服务,剔除掉无效的服务,赋予应用自动伸缩的能力.而ocelot如果集成了consul,那ocelot也能拥有这些能力,还可以自主选择负载均衡策略,灵活性更强. (建议看完前一篇文章再来实践这一篇,不然可能有难度) 上干货. 首先打开上一篇新建好的项目,继续添加nuget包: 然后注册相关服务: public void ConfigureServices(IServiceCollection services) { services.AddOc

  • 基于.net core微服务的另一种实现方法

    前言 基于.net core 的微服务,网上很多介绍都是千篇一律基于类似webapi,通过http请求形式进行访问,但这并不符合大家使用习惯.如何像形如[ GetService<IOrderService>().SaveOrder(orderInfo)]的方式, 调用远程的服务,如果你正在为此苦恼, 本文或许是一种参考. 背景 原项目基于传统三层模式组织代码逻辑,随着时间的推移,项目内各模块逻辑互相交织,互相依赖,维护起来较为困难.为此我们需要引入一种新的机制来尝试改变这个现状,在考察了 Ja

  • .Net Core微服务网关Ocelot超时、熔断、限流

    基本概念 超时.熔断.限流听起来好像很远,但实际上用在方方面面.很多人可能还搞不懂熔断是做什么,其实可以把熔断理解为一种防护措施.做个假设,在微服务体系下,某个下游服务响应很慢,然后随着时间推移,会有越来越多的请求堆积,从而会导致各种严重后果,单说连接池大量被占用就很要命.更不用说服务之间还要相互调用,你等我10秒,我等你5秒,不仅毫无体验感,高可用也就成了空谈.不如换个思路:与其等10秒返回一个请求失败,不如马上就返回请求失败.这样一来,请求堆不起来,资源也有时间释放或者恢复.这个动作就叫熔断

  • SpringCloud 微服务最佳开发实践

    现在基于SpringCloud的微服务开发日益流行,网上各种开源项目层出不穷.我们在实际工作中可以参考开源项目实现很多开箱即用的功能,但是必须要遵守一定的约定和规范. 本文结合我们实际的开发中遇到的一些问题整理出了一份微服务开发的实践规范,欢迎各位大佬拍砖指点. Maven规范 1.所有项目必须要有一个统一的parent模块 所有微服务工程都依赖这个parent,parent用于管理依赖版本,maven仓库,jar版本的统一升级维护 在parent下层可以有 core,starter,rate-

随机推荐