nacos、SpringCloud 、GateWay、Setinel整合

一、创建spring boot项目

删除src目录

1.1 创建gateway子项目

1.2 创建应用模块

二 、修改pom.xml

注意:这里springboot和springcloud版本号要相匹配

不清楚可以去官网官网查询
在这里插入图片描述

2.1 修改父模块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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
    </parent>
    <packaging>pom</packaging>
    <groupId>com.lyj</groupId>
    <artifactId>springCloudDemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud</name>
    <description>cloud</description>
    <modules>
        <module>gateway-service</module>
        <module>user-service</module>
    </modules>

    <properties>
        <java.version>8</java.version>
        <spring.boot.version>2.4.2</spring.boot.version>
        <alibaba.cloud.version>2021.1</alibaba.cloud.version>
        <spring.cloud.version>2020.0.1</spring.cloud.version>
        <jackson.verson>2.8.9</jackson.verson>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions> <!-- 去掉springboot自带的日志 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <exclusions> <!-- 去掉springboot自带的日志 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
            <scope>test</scope>
        </dependency>

        <!-- Nacos 配置管理 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!-- Nacos 服务发现 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- 使用log4j2 作为项目日志 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions> <!-- 去掉springboot自带的日志 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <!-- apache.commons begin -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

        <!-- SpringCloud 框架 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
            <version>1.18.20</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>3.1.1</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <!-- spring cloud 依赖 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.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>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${alibaba.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.2 修改gateway-service的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>
    <parent>
        <groupId>com.lyj</groupId>
        <artifactId>springCloudDemo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>gateway-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gateway-service</name>
    <description>gateway-service</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
            <version>3.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            <version>3.0.4</version>  <!-- 版本号是必须要加的 -->
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!--sentinel限流-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

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



    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.3 修改user-service的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>
    <parent>
        <groupId>com.lyj</groupId>
        <artifactId>springCloudDemo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>user-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>user-service</name>
    <description>user-service</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions> <!-- 去掉springboot自带的日志 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <exclusions> <!-- 去掉springboot自带的日志 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring.boot.version}</version>
            <exclusions> <!-- 去掉springboot自带的日志 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

三、 新建nacos命名空间 

四 、创建bootstrap.yml文件

4.1 创建gateway-service的bootstrap.yml文件

spring:
  cloud:
    sentinel:
      transport:
        port: 8719
        dashboard: 192.168.163.157:8858
    nacos:
      server-addr: 192.168.163.157:8848  # 注册中心地址
      username: nacos
      password: nacos
      discovery:
        namespace: ${NACOS_NAMESPACE:8f436e2c-cf33-4607-b174-07f0dafe3ec5}
        locator:
          enabled: true # gateway 可以从nacos 中发现微服务
    gateway:
      globalcors:
        cors-configurations: #跨域访问
          '[/**]':
            allowedOrigins: "*"
            allowedMethods: "*"
            alloedHeaders: "*"
      routes:
        - id: user-service-route # 路由的id,要保证其唯一性
          uri: lb://user # lb 表示 从nacos 中按照名称获取微服务,并遵循负载均衡策略, user-service 即微服务注册名
          predicates:
            - Path=/user-api/**  # 使用断言
          filters:
            - StripPrefix=1 # 使用过滤器

  application:
    name: gateway
server:
  port: 9091

4.2 创建user-service的bootstrap.yml文件


# 应用名称(nacos会将改名称作为服务名称)
spring:
  application:
    name: user
  cloud:
    nacos:
      server-addr: ${NACOS_SERVER_ADDR:192.168.163.157:8848}
      username: ${NACOS_USERNAME:nacos}
      password: ${NACOS_PASSWORD:nacos}
      #配置中心
      config:
        namespace: ${NACOS_NAMESPACE:8f436e2c-cf33-4607-b174-07f0dafe3ec5}
        name: ${NACOS_CONFIG_FILE:application-local}
        file-extension: yaml
      #服务注册
      discovery:
        namespace: ${NACOS_NAMESPACE:8f436e2c-cf33-4607-b174-07f0dafe3ec5}
        register-enabled: ${NACOS_REGISTER_ENABLED:true}
server:
  port: 8099

启动项目

 

服务已注册到nacos

五、测试通过gateway访问user-service接口

user-versice新建测试接口

UserController.java
package com.example.userservice.userservice.controller;

import com.example.userservice.userservice.pojo.User;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 简要描述
 *
 * @Author: lyj
 * @Date: 2024/5/16 17:38
 * @Version: 1.0
 * @Description: 文件作用详细描述....
 */

@RestController
@RequestMapping("/user")
public class UserController {

    private static Map<Integer, User> userMap;

    static {
        userMap = new HashMap<>();
        userMap.put(1, new User(1, "张三"));
        userMap.put(2, new User(2, "李四"));
        userMap.put(3, new User(3, "王五"));
    }

    @RequestMapping("/findById/{id}")
    public User findById(@PathVariable("id") Integer id) {
        // 为了测试方便,用此方式模拟用户查询
        return userMap.get(id);
    }
}
User.java
package com.example.userservice.userservice.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * 简要描述
 *
 * @Author: lyj
 * @Date: 2024/5/16 17:39
 * @Version: 1.0
 * @Description: 文件作用详细描述....
 */
@AllArgsConstructor
@Data
public class User {

    private Integer id;


    private String name;
}

 重启user-service服务

访问:http://localhost:9091/user-api/user/findById/3

网关gateway配置成功

六、gateway配置全局过滤器

TokenGlobalFilter.java
package com.example.gatewayservice.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class TokenGlobalFilter implements GlobalFilter, Ordered {

    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (token == null || token.length() == 0 || !token.equals("123456")) {
            log.error("鉴权失败");
            ServerHttpResponse serverHttpResponse = exchange.getResponse();

            serverHttpResponse.setStatusCode(HttpStatus.OK);
            serverHttpResponse.getHeaders().add("Content-type", "application/json;charset=UTF-8");

            // 鉴权失败,返回的数据结构
            Map<String, Object> map = new HashMap<>();
            map.put("code", HttpStatus.UNAUTHORIZED.value());
            map.put("message", HttpStatus.UNAUTHORIZED.getReasonPhrase());

            DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(new ObjectMapper().writeValueAsBytes(map));
            return serverHttpResponse.writeWith(Flux.just(buffer));
        }
        return chain.filter(exchange);
    }

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

重启gateway-service服务

访问:http://localhost:9091/user-api/user/findById/3

加上token

 访问:http://localhost:9091/user-api/user/findById/3?token=123456

 七、路由失败处理

路由user-api1不存在,报错404 但是这种对前端开发不友好,所以重新处理

GatewayConfiguration.java
package com.example.gatewayservice.exception;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;

import java.util.Collections;
import java.util.List;

/**
 * 简要描述
 *
 * @Author: lyj
 * @Date: 2024/5/16 18:19
 * @Version: 1.0
 * @Description: 文件作用详细描述....
 */
@Configuration(proxyBeanMethods = false)
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;
    }
}
MyErrorWebExceptionHandler.java
package com.example.gatewayservice.exception;

import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.*;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

/**
 * 简要描述
 *
 * @Author: lyj
 * @Date: 2024/5/16 18:19
 * @Version: 1.0
 * @Description: 自定义异常处理
 */
public class MyErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {

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

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    @Override
    protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
        boolean includeStackTrace = isIncludeStackTrace(request, MediaType.ALL);
        Map<String, Object> errorMap = getErrorAttributes(request, includeStackTrace);
        int status = Integer.valueOf(errorMap.get("status").toString());
        Map<String, Object> response = this.response(status, errorMap.get("error").toString(), errorMap);
        return ServerResponse.status(status).contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(response));
    }

    // 我们希望返回的数据结构
    public static Map<String, Object> response(int status, String errorMessage, Map<String, Object> errorMap) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", status);
        map.put("message", errorMessage);
        map.put("data", errorMap);
        return map;
    }
}

 重启gateway-service

返回json前端开发好处理

八、整合Setinel 进行限流

docker安装Setinel

docker pull bladex/sentinel-dashboard:1.8.0

docker run --name sentinel-dashboard -d -p 8858:8858 -d bladex/sentinel-dashboard:1.8.0
docker ps

访问:http://192.168.163.157:8858/#/login

账号和密码都是sentinel

 gateway-service添加对应的依赖(开头已添加过了)

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

修改对应的配置文件,连接Sentinel 控制台:

spring:
  cloud:
    sentinel:
      transport:
        port: 8719
        dashboard: 192.168.163.157:8858

 重启gateway-service服务,访问接口

由于Sentinel是懒加载,如果没有加载出来就先访问一下对应服务的随便一个接口后再刷新试试

  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值