SpringCloud GateWay与Nacos使用

news2024/10/7 15:29:49

网关就相当于一个内网与外网的出入口,起着 安全、验证的功能,如果没有网关,那么如果需要实现验证的功能,除非

SpringCloud GateWay 作为微服务的网关,起着如下作用

① 作为所有API接口服务请求的接入点

② 作为所有后端业务服务的聚合点,所有业务服务都可以在这里被调用

③ 实现安全、验证、路由、过滤、流控等策略,进行一些必要的中介处理

④ 统一管理: 提供配置管理工具,对所有API服务的调用生命周期和相应的中介策略进行统一的管理

(当然 由于多了一次中间转发,所以 QPS 就会下降)

下面就总结一下 SpringCloud GateWay 与 Nacos 的整合与使用

一、基础项目搭建

① 启动nacos 服务,这里是以单击的形式启动(nacos 下载地址可以自己百度)

  其默认端口为8848  账户名为nacos  密码为nacos 

 ② 创建项目

       父项目 (定义SpringCloud 版本 以及 SpringBoot 版本 以及公共 依赖)

       gateway-service (  子项目,实现Nacos 服务发现以及 权限过滤)

      user-service  (子项目,实现Nacos 服务注册以及充当服务提供者的功能)

   其结构图如下

父项目 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>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>test_cloud_gateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>test_cloud_gateway</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>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <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>
                <version>${spring.boot.version}</version>
            </plugin>
        </plugins>
    </build>

</project>

( 吐槽一下:  SpringCloud 以及 SpringCloug Alibaba  的组件的版本之间有点坑,稍不注意就有可能导致 类缺少或者其他的问题)  

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.example</groupId>
        <artifactId>test_cloud_gateway</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>gateway-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>gateway-service</description>
    <properties>
        <java.version>17</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>
    </dependencies>

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

</project>

application.yml 文件

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848  # 注册中心地址
        username: nacos
        password: nacos
        locator:
          enabled: true # gateway 可以从nacos 中发现微服务
  application:
    name: gateway-service

server:
  port: 9091

 (因为在bootstrap.yml文件中声明了配置中心以及文件的后缀格式,这时候项目启动就会自动获取nacos 上的gate-way-service.yaml 文件作为其启动配置项)

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.example</groupId>
        <artifactId>test_cloud_gateway</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </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>
        </dependency>

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

application.yml

server:
  port: 8099
dubbo:
  application:
    name: ${spring.application.name}
    qos-enable: false
  registry:
    address: nacos://127.0.0.1:8848
    use-as-metadata-center: false
    use-as-config-center: false
    parameters:
      register-mode: instance

请求类:

package com.example.userservice.controller;

import com.example.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 zhangyang
 * @version 1.0
 * @Date 2023/4/9 15:44
 * @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);
    }
}
package com.example.userservice.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * @author zhangyang
 * @version 1.0
 * @Date 2023/4/9 15:46
 * @Description
 */
@AllArgsConstructor
@Data
public class User {

    private Integer id;


    private String name;
}

③ 启动项目

 当我们启动项目后,就会在nacos 上看到注册的gateway-service 服务、user-service 服务

二、Springcloud Gateway  配置说明

  Gateway  本质上就是相当于 将请求封装成一个对象,然后去匹配设置的路由信息,

然后去通过filter 处理,然后调用微服务。

1、路由服务

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848  # 注册中心地址
        username: nacos
        password: nacos
        locator:
          enabled: true # gateway 可以从nacos 中发现微服务
    gateway:
      routes:
        - id: user-service-route # 路由的id,要保证其唯一性
          uri: lb://user-service # lb 表示 从nacos 中按照名称获取微服务,并遵循负载均衡策略, user-service 即微服务注册名
          predicates:
            - Path=/user-api/**  # 使用断言
          filters:
            - StripPrefix=1 # 使用过滤器

  application:
    name: gateway-service


server:
  port: 9091

        其中

   id:  路由标识符,用于区分其他route

   uri:    路由指向目的地uri,即客户端请求最终转发到微服务

  predicate:  断言,用于条件判断,只有断言都返回真,才会真正的执行路由  

  filter : 过滤器由于修改请求和响应信息

重新服务后,在地址栏上访问

 

 就会通过gateway 服务查询查询到对应的user-service 服务

全局过滤器

 全局过滤器作用域所有路由,无需配置,通过全局过滤器可以实现对权限的统一校验,安全性验证等功能

package com.example.demo.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;

/**
 * @author zhangyang
 * @version 1.0
 * @Date 2023/4/10 10:53
 * @Description
 */
@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;
    }
}

这里是通过 网关的GlobalFilter 拦截请求头上的的token 字符串,然后用于获取token  如果不符合条件则直接异常信息

 

转发规则

  假设: uri 都设定为 http://localhost:9023****

规则实例说明
Path- Path=/gate/,/rule/ 当请求的路径为gate、rule开头的时,转发到http:9023服务器上
before- Before=2017-01-20T17:42:47.789-07:00[America/Denver]在某个时间之前的请求才会被转发到http://localhost:9023服务器上
After- After=2017-01-20T17:42:47.789-07:00[America/Denver]在某个时间之后请求才会被转发
Beteween- Between=2017-01-20T17:42:47.789-07:00[America/Denver],2017-01-21T17:42:47.789-07:00[America/Denver]在某个时间段之间的才会被转发
Cookie- Cookie=chocolate, ch.p名为chocolate的表单或者满足正则ch.p的表单才会被匹配到进行请求转发
Method- Method=GET只有GET方法才会匹配转发请求,还可以限定POST、PUT等请求方式

过滤器规则(Filter)

过滤器规则实例说明
PrefixPath- PrefixPath=/app在请求路径前加上app
RewritePath- RewritePath=/test, /app/test访问localhost:9092/test,请求会转发到localhost:8001/app/test
SetPathSetPath=/app/{path}通过模板设置路径,转发的规则时会在路径前增加app,{path} 表示原请求路径

 

路由失败处理

  当请求路由地址不匹配或者断言为false 的时候,GateWay 会默认返回Whitelabel ErrorPage 错误页面,这种错误提示不符合我们的业务需求。

我们可以自定义返回一个较为友好的错误提示,需要创建一个类继承DefaultErrorWebExceptionHandler 类,重写其方法

   

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;
    }
}

配置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;
    }
}

重启Gateway项目后,访问一个不符合条件的断言

 

跨域访问

修改配置文件

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848  # 注册中心地址
        username: nacos
        password: nacos
        locator:
          enabled: true # gateway 可以从nacos 中发现微服务
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods: "*"
            alloedHeaders: "*"
      routes:
        - id: user-service-route # 路由的id,要保证其唯一性
          uri: lb://user-service # lb 表示 从nacos 中按照名称获取微服务,并遵循负载均衡策略, user-service 即微服务注册名
          predicates:
            - Path=/user-api/**  # 使用断言
          filters:
            - StripPrefix=1 # 使用过滤器

  application:
    name: gateway-service


server:
  port: 9091

整合Setinel 进行限流

 添加对应的依赖

<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: localhost:8081

配置对应的SentinelFilter 实例

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

然后重启网关,登录Sentinel 控制台查看

 

 

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/417892.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot 整合 RabbitMQ (四十一)

二八佳人体似酥&#xff0c;腰间仗剑斩愚夫。虽然不见人头落&#xff0c;暗里教君骨髓枯。 上一章简单介绍了SpringBoot 实现 Web 版本控制 (四十),如果没有看过,请观看上一章 关于消息中间件 RabbitMQ, 可以看老蝴蝶之前的文章: https://blog.csdn.net/yjltx1234csdn/categor…

还不懂如何与AI高效交流?保姆级且全面的chatGPT提示词工程教程来啦!(一)基础篇

还不懂如何与chatGPT高效交流&#xff1f;保姆级且全面的chatGPT提示词工程教程来啦&#xff01;&#xff08;一&#xff09;基础篇 文章目录还不懂如何与chatGPT高效交流&#xff1f;保姆级且全面的chatGPT提示词工程教程来啦&#xff01;&#xff08;一&#xff09;基础篇一&…

CDH6.3.2大数据集群生产环境安装(七)之PHOENIX组件安装

添加phoenix组件 27.1. 准备安装资源包 27.2. 拷贝资源包到相应位置 拷贝PHOENIX-1.0.jar到/opt/cloudera/csd/ 拷贝PHOENIX-5.0.0-cdh6.2.0.p0.1308267-el7.parcel.sha、PHOENIX-5.0.0-cdh6.2.0.p0.1308267-el7.parcel到/opt/cloudera/parcel-repo 27.3. 进入cm页面进行分发、…

【AIGC】9、BLIP-2 | 使用 Q-Former 连接冻结的图像和语言模型 实现高效图文预训练

文章目录一、背景二、方法2.1 模型结构2.2 从 frozen image encoder 中自主学习 Vision-Language Representation2.3 使用 Frozen LLM 来自主学习 Vision-to-Language 生成2.4 Model pre-training三、效果四、局限性论文&#xff1a;BLIP-2: Bootstrapping Language-Image Pre-…

unity 序列化那些事,支持Dictionary序列化

目录 一、普通类型和UnityEngine空间类型序列化 二、数组、list的序列化 三、自定义类的序列化支持 四、自定义asset 五、在inspector面板中支持Dictionary序列化 1、在MonoBehaviour中实现Dictionary序列化 2、自定义property&#xff0c;让其在inpsector能够显示 3、Mo…

【从零开始学Skynet】实战篇《球球大作战》(七):gateway代码设计(下)

1、确认登录接口 在完成了登录流程后&#xff0c;login会通知gateway&#xff08;第⑧阶段&#xff09;&#xff0c;让它把客户端连接和新agent&#xff08;第⑨阶段&#xff09;关联起来。 sure_agent代码如下所示&#xff1a; s.resp.sure_agent function(source, fd, play…

[Gitops--1]GitOps环境准备

GitOps环境准备 1. 主机规划 序号主机名主机ip主机功能软件1dev192.168.31.1开发者 项目代码 apidemogit,golang,goland2gitlab192.168.31.14代码仓库,CI操作git-lab,git,golang,docker,gitlab-runner3harbor192.168.31.104管理和存储镜像docker,docker-compose,harbor4k8s-m…

基础排序算法【计数排序】非比较排序

基础排序算法【计数排序】非比较排序⏰【计数排序】&#x1f550;计数&#x1f566;排序&#x1f553;测试⏰总结&#xff1a;⏰【计数排序】 计数排序又称为鸽巢原理&#xff0c;是对哈希直接定址法的变形应用 > 基本思路&#xff1a; 1.统计数据出现的次数 2.根据统计的结…

并行分布式计算 并行算法与并行计算模型

文章目录并行分布式计算 并行算法与并行计算模型基础知识定义与描述复杂性度量同步和通讯并行计算模型PRAM 模型异步 PRAM 模型 &#xff08;APRAM&#xff09;BSP 模型LogP 模型层次存储模型分层并行计算模型并行分布式计算 并行算法与并行计算模型 基础知识 定义与描述 并…

15个最适合初创公司创始人使用的生产力工具

创业是一段激动人心且收获颇丰的旅程&#xff0c;同时也伴随着一些挑战。创始人往往要面对长时间的工作、紧迫的期限和大量的压力时刻。因此&#xff0c;初创公司创始人必须最大限度地利用他们的时间并利用他们可用的生产力工具——不仅是为了发展他们的业务&#xff0c;而且是…

Cron表达式简单介绍 + Springboot定时任务的应用

前言 表达式是一个字符串&#xff0c;主要分成6或7个域&#xff0c;但至少需要6个域组成&#xff0c;且每个域之间以空格符隔开。 以7个域组成的&#xff0c;从右往左是【年 星期 月份 日期 小时 分钟 秒钟】 秒 分 时 日 月 星期 年 以6个域组成的&#xff0c;从右往左是【星…

【精华】表格识别技术-MI

表格识别是指将图片中的表格结构和文字信息识别成计算机可以理解的数据格式&#xff0c;在办公、商务、教育等场景中有着广泛的实用价值&#xff0c;也一直是文档分析研究中的热点问题。围绕这个问题&#xff0c;我们研发了一套表格识别算法&#xff0c;该算法高效准确地提取图…

RabbitMq 的消息可靠性问题(二)---MQ的消息丢失和consumer消费问题

前言 RabbitMq 消息可靠性问题(一) — publisher发送时丢失 前面我们从publisher的方向出发解决了发送时丢失的问题&#xff0c;那么我们在发送消息到exchange, 再由exchange转存到queue的过程中。如果MQ宕机了&#xff0c;那么我们的消息是如何确保可靠性的呢&#xff1f;当消…

SQL的函数

文章目录一、SQL MIN() Function二、SQL SUM() 函数三、SQL GROUP BY 语句四、SQL HAVING 子句五、SQL EXISTS 运算符六、SQL UCASE() 函数总结一、SQL MIN() Function MIN() 函数返回指定列的最小值。 SQL MIN() 语法 SELECT MIN(column_name) FROM table_name;演示数据库 …

Numba witch makes Python code fast

一. 前言&#xff1a;numba&#xff0c;让python速度提升百倍 python由于它动态解释性语言的特性&#xff0c;跑起代码来相比java、c要慢很多&#xff0c;尤其在做科学计算的时候&#xff0c;十亿百亿级别的运算&#xff0c;让python的这种劣势更加凸显。 办法永远比困难多&a…

ASP.NET Core MVC 从入门到精通之接化发(二)

随着技术的发展&#xff0c;ASP.NET Core MVC也推出了好长时间&#xff0c;经过不断的版本更新迭代&#xff0c;已经越来越完善&#xff0c;本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容&#xff0c;适用于初学者&#xff0c;在校毕业生&#xff0c…

4.13实验 加测试题目

今天是个好日子,要搞栈的实验 没啥就是链栈和顺序栈 和出栈入栈,强大都是从最基本开始的 来和我一起写写吧 //顺序栈 typedef struct node{int *base;int *top;int sizer; }shed;//链栈 typedef struct Node{ int data; struct Node* next; }*stact,link; //顺序栈的初始化…

《绝对坦率》速读笔记

文章目录书籍信息概览&#xff08;第一部分 一种新的管理哲学&#xff09;建立坦率的关系给予并鼓励指导了解团队中每个人的动机协同创造成果&#xff08;第二部分 工具和技巧&#xff09;关系指导团队结果书籍信息 书名&#xff1a;《绝对坦率&#xff1a;一种新的管理哲学》…

北邮22信通:(12)二叉树的遍历书上代码完整版

北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 上一篇文章&#xff1a; 下一篇文章&#xff1a; 目录 一.储存最简单数据类型的二叉树 代码部分&#xff1a; 代码效果&#xff1a; 运行结果&#xff1a…

解决JD-GUI-1.6.6 中文乱码

一、背景 在window环境下使用中遇到了乱码问题。 问题有两个&#xff1a; 一、从反编译代码的界面 CTRLC 复制是如果选中内容包含中文&#xff0c;贴到其他编辑器时&#xff0c;中文丢失。 二、打开xml文件、properties文件等包含中文时。中文在反编译界面中显示乱码。用其他工…