Spring Cloud Gateway服务网关的部署与使用(结合nacos)

news2025/1/20 3:47:15

一、微服务网关

1.什么是微服务网关

在传统的单体架构中,我们只需要开放一个服务给客户端调用即可。

但是微服务架构中是将一个系统拆分成多个微服务,不同的微服务一般会有不同的网络地址,客户端在访问这些微服务时必须记住几十甚至百个地址,这对于客户端方来说太复杂也难以维护,而且一不小心就会出错,这在开发测试中深有体会。然而有了网关就不一样了:网关作为系统的唯一流量入口,所有请求都必须先经过网关,由网关将请求路由到合适的微服务。网关有以下几点好处:

  • 交互更简单:减少了客户端与各个微服务之间的交互次数

  • 授权认证:在网关上进行认证,再将请求转发到后端的微服务,而无须在每个微服务中进行认证。

  • 安全 :只有网关系统对外进行暴露,微服务可以隐藏在内网,通过防火墙保护。

2.服务网关的基本功能

3.微服务架构中网关的位置

二、gateway概述

  1. 官网:spring-cloud-gateway

  1. gateway历史背景?(了解)

Spring Cloud全家桶中有一个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关。但是在2.x版本中,Zuul的升级一直跳票,迟迟不发布,Spring Cloud最后自己研发了一个网关替代Zuul,就是Gateway。

SpringCloud Gateway 是 Spring Cloud 的一个全新项目,基于 Spring 5.0+Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在提供统一的路由方式且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,限流。

SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。

  1. gateway特性?

  • 基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 进行构建

  • 动态路由:能够匹配任何请求属性

  • 可以对路由指定 Predicate(断言)和 Filter(过滤器)

  • 集成Hystrix的断路器功能

  • 集成 Spring Cloud 服务发现功能

  • 易于编写的 Predicate(断言)和 Filter(过滤器)

  • 请求限流功能

  • 支持路径重写

  1. 为什么选择gateway作为网关?

从商业方面来说,一方面因为Zuul1.0已经进入了维护阶段,而且Gateway是SpringCloud团队研发的,是亲儿子产品,值得信赖。另一方面虽然Netflix早就发布了最新的 Zuul 2.x,但 Spring Cloud 貌似没有整合计划。而且Netflix相关组件都宣布进入维护期,不知前景如何?

从技术层面来说,Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心。而且很多功能Zuul都没有用起来,而gateway用起来非常的简单便捷。

多方面综合考虑Gateway是很理想的网关选择。

  1. gateway工作原理

客户端向 Spring Cloud Gateway 发出请求。 如果网关处理程序映射确定请求与路由匹配,则将其发送到网关 Web 处理程序。 此处理程序通过特定于请求的过滤器链运行请求。 过滤器用虚线划分的原因是过滤器可以在发送代理请求之前和之后运行逻辑。 执行所有“预”过滤器逻辑。 然后发出代理请求。 发出代理请求后,将运行“发布”过滤器逻辑。

三、gateway三大配置项

1.Route(路由)

路由是构建网关的基本模块,它由ID,目标URI,断言集合和过滤器集合组成,如果断言为true,则转发到该路由。

  • id:路由标识,要求唯一,名称任意(建议配合服务名)

  • uri:请求最终被转发到的目标地址

  • order: 路由优先级,数字越小,优先级越高

  • predicates:断言数组(判断条件),路径相匹配的进行路由

  • filters:过滤器数组,可以在返回请求之前或之后时修改请求和响应的内容。

2.Predicate(断言)

断言(Predicate)是基于Spring WebFlux的HandlerMapping实现的。Gateway包含了很多路由断言工厂(spring-cloud-gateway内置的断言),并且这些工厂对应着HTTP请求的很多属性进行了处理,当客户端发送HTTP请求时,HandlerMapping会获取请求参数,并与Gateway中配置的Predicates进行比对,若满足规则就按规则约定进行路由放行,否则拒绝访问或报404错误。

上述断言的种类有十一种,这里以其中几种为例介绍一下如何配置使用:

spring:
  cloud:
    gateway:
      routes:  # 路由数组,当请求满足什么样的断言时,转发到哪个微服务上
        - id: payment_route1     #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后被转发的路由地址
          # 设置断言
          predicates:    
            # Path Route Predicate Factory 断言,满足/payment/get/** 路径的请求都会被路由到 http://localhost:8001 这个uri中
            - Path=/payment/get/**

        - id: payment_route2     #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后被转发的路由地址
          # 设置断言
          predicates:
             - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
             - After=2023-01-08T15:10:03.685+08:00[Asia/Shanghai]         # 断言,路径相匹配的进行路由
spring:
  cloud:
    gateway:
      routes:  # 路由数组,当请求满足什么样的断言时,转发到哪个微服务上
        - id: gateway-provider_1   #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001   #匹配后被转发的路由地址
          # 设置断言
          predicates:
            # Path Route Predicate Factory 断言,满足 /gateway/provider/** 路径的请求都会被路由到 http://localhost:8001 这个uri中
            - Path=/gateway/provider/**
            # Weight Route Predicate Factory 断言,同一分组按照权重进行分配流量,这里分配了80%
            # 第一个group1是分组名,第二个参数是权重
            - Weight=group1, 8        
            
        - id: gateway-provider_2
          uri: http://localhost:8002
          predicates:
            - Path=/gateway/provider/**
            # Weight Route Predicate Factory,同一分组按照权重进行分配流量,这里分配了20%
            - Weight=group1, 2         

经过上面的一系列配置我们可以发现Spring Cloud Gateway 中的断言命名有这样一个公式:“xxx + RoutePredicateFactory”,比如“请求时间满足配置时间之后”断言 AfterRoutePredicateFactory,那么配置时直接取前面的 “After”。

如果路由转发匹配到了两个或以上,则是的按照配置先后顺序转发,上面都配置了路径:“ Path=/gateway/provider/** ”,如果没有配置权重,则肯定是先转发到 “http://localhost:8001”,但是如果在相同分组内设置了权重,则按照权重比例进行流量分配。

3.Filter(过滤)

路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。Spring-Cloud-Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生,下面介绍一下常用路由过滤器的用法:

官网:Spring-Cloud-Gateway中内置GatewayFilter

(1)Filter 过滤器的生命周期:

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

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

(2)Filter 从作用的范围一般分为两种:

  • 局部过滤器 GatewayFilter:应用到单个路由或者一个分组的路由上(需要在配置文件中配置)

  • 全局过滤器 GlobalFilter:应用到所有的路由上(无需配置,全局生效)

(3)过滤器命名规则:xxx + GatewayFilterFactory

(4)局部过滤器 GatewayFilter

AddResponseHeaderGatewayFilterFactory ,在响应头中添加一个键值对

spring:
  cloud:
    gateway:
      routes:
        - id: gateway-provider_1
          uri: http://localhost:8001
          predicates:
            - Path=/gateway/provider/**
          # 配置局部过滤器
          filters:
            - AddResponseHeader=X-Response-Foo, Bar 

StripPrefixGatewayFilterFactory,对指定数量的路径前缀进行去除的过滤器

spring:
  cloud:
    gateway:
      routes:
      - id: strip_prefix_route
        uri: http://localhost:8201
        predicates:
        - Path=/user-service/**
        filters:
        - StripPrefix=2

以上配置会把以/user-service/开头的请求的路径去除两位,通过curl工具使用以下命令进行测试:

原始请求:curl http://localhost:9201/user-service/a/user/1

变为:curl http://localhost:8201/user/1

PrefixPath GatewayFilter,对原有路径进行增加操作的过滤器。

spring:
  cloud:
    gateway:
      routes:
      - id: prefix_path_route
        uri: http://localhost:8201
        predicates:
        - Method=GET
        filters:
        - PrefixPath=/user

以上配置会对所有GET请求添加/user路径前缀,通过curl工具使用以下命令进行测试。

原有请求:curl http://localhost:9201/1

变为:curl http://localhost:8201/user/1

Hystrix GatewayFilter,开启断路器功能,并提供服务降级处理

Hystrix 过滤器允许你将断路器功能添加到网关路由中,使你的服务免受级联故障的影响,并提供服务降级处理。

  • 要开启断路器功能,我们需要在pom.xml中添加Hystrix的相关依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  • 添加相关服务降级的处理类:

@RestController
public class FallbackController {

    @GetMapping("/fallback")
    public Object fallback() {
        Map<String,Object> result = new HashMap<>();
        result.put("data",null);
        result.put("message","Get request fallback!");
        result.put("code",500);
        return result;
    }
}
  • 在配置文件中添加相关配置,当路由出错时会转发到服务降级处理的控制器上:

spring:
  cloud:
    gateway:
      routes:
        - id: hystrix_route
          uri: http://localhost:8201
          predicates:
            - Method=GET
          filters:
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback
  • 关闭user-service,调用该地址进行测试:http://localhost:9201/user/1 ,发现已经返回了服务降级的处理信息。

AddRequestParameter GatewayFilter,给请求添加参数的过滤器

spring:
  cloud:
    gateway:
      routes:
        - id: add_request_parameter_route
          uri: http://localhost:8201
          filters:
            - AddRequestParameter=username, macro
          predicates:
            - Method=GET

以上配置会对GET请求添加username=macro的请求参数,相当于发起该请求:

curl http://localhost:8201/user/getByUsername?username=macro

添加默认过滤器

要添加过滤器并将其应用于所有路由,您可以使用spring.cloud.gateway.default-filters. 此属性采用过滤器列表。以下清单定义了一组默认过滤器:

spring:
  cloud:
    gateway:
      default-filters:
      - AddResponseHeader=X-Response-Default-Red, Default-Blue
      - PrefixPath=/httpbin

(6)GlobalFilter 全局过滤器:

全局过滤器应用全部路由上,无需开发者配置,Spring Cloud Gateway 也内置了一些全局过滤器(spring-cloud-gateway内置的global-filters):

GlobalFilter 的功能其实和 GatewayFilter 是相同的,只是 GlobalFilter 的作用域是所有的路由配置,而不是绑定在指定的路由配置上。多个 GlobalFilter 可以通过 @Order 或者 getOrder() 方法指定执行顺序,order值越小,执行的优先级越高。

注意:由于过滤器有 pre 和 post 两种类型,pre 类型过滤器如果 order 值越小,那么它就应该在pre过滤器链的顶层,post 类型过滤器如果 order 值越小,那么它就应该在 post 过滤器链的底层。示意图如下:

自定义全局过滤器

当请求与路由匹配时,过滤 Web 处理程序会将所有实例GlobalFilter和所有特定路由的实例添加GatewayFilter到过滤器链中。这个组合的过滤器链是按org.springframework.core.Ordered接口排序的,可以通过实现getOrder()方法来设置。

由于 Spring Cloud Gateway 区分过滤器逻辑执行的“前”和“后”阶段,具有最高优先级的过滤器是“前”阶段的第一个和“后”阶段的最后一个阶段。

@Component
@Log4j2
public class MyGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String username = exchange.getRequest().getQueryParams().getFirst("username");
        if (username == null) {
            log.error("用户名为null,非法用户");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    /**
     * 得到权重,order越小,优先级越高
     *
     * @return int
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

当不带username参数时网关会路由失败:

四、nacos整合Gateway 实现关联服务名的动态路由

service-url:
  user-service: http://localhost:8081
spring:
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: ${service-url.user-service}/user/get/{id}
          predicates:
            - Path=/user/get/{id}

这里存在一个问题,在微服务集群部署中一个服务可能会有多台主机,我们这样配置路由不够灵活,每更改一次服务的主机信息都要重新编写一次配制文件,然后还需要重启Gateway服务器。我们要知道,在真正的项目中重启服务是很耗时的,我们应该尽量避免这种情况

同时网关服务gateway需要知道所有服务的域名或IP地址以及端口,另外,一旦服务的域名或IP地址发生修改,路由配置中的 uri 就必须修改。

此外在服务集群中无法实现负载均衡。

当出现这些问题时,我们可以集成到注册中心,使得网关能够从注册中心自动获取uri,并实现负载均衡,同时Spring Cloud Gateway提供了lb//服务名的方式来动态的配置路由,网关会根据注册中心的服务名动态获取服务的URL,这样即便该服务的某一台主机地址改变或者挂掉,网关都不必再跟着改变:

(1)pom 文件中主要依赖:

由于 Netflix Ribbon 进入停更维护阶段,因此 SpringCloud 2020.0.1 版本之后 删除了eureka中的ribbon,替代ribbon的是spring cloud自带的LoadBalancer,默认使用的是轮询的方式 。新版本的 Nacos discovery 都已经移除了 Ribbon ,此时我们需要引入 loadbalancer 代替,才能调用服务提供者提供的服务。

<!--nacos注册与发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <exclusions>
        <!-- 将ribbon排除 -->
        <exclusion>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
         </exclusion>
    </exclusions>
</dependency>
<!--配置中心-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--负载均衡-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--Spring Cloud Gateway网关-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

(2)启动类添加注解开启注册中心功能

 @EnableDiscoveryClient  //开启服务注册和发现

(3)编写对应的配置文件

  • bootstrap.yml,主要是对Nacos配置中心的一些设置

spring:
  application:
    name: gateway-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos地址
      config:
        server-addr: localhost:8848 #Nacos地址
        file-extension: yaml #由于在nacos配置中心创建的配置是yaml格式的,所以在此指定
  • application.yml,启用对应环境

server:
  port: 80
spring:
  profiles:
    active: dev
  • 在Nacos后台编写对应的配制文件,dataId为gateway-service.yaml

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      default-filters:
        # 保留唯一的,出现重复的属性值,会保留一个。例如有两个my:bbb的属性,最后会留一个。
        - DedupeResponseHeader=Access-Control-Allow-Origin, RETAIN_UNIQUE
      globalcors:
        cors-configurations:
          '[/**]':
            allowedHeaders: '*'
            allowedMethods: '*'
            allowedOrigins: '*'
      routes:
        - id: path_route
          uri: lb://user-service
          predicates:
            - Path=/user/get/{id}
            
  ##################省略数据库,redis等其他配置#########################
  • 在Nacos配置中心添加新的路由

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      default-filters:
        - DedupeResponseHeader=Access-Control-Allow-Origin, RETAIN_UNIQUE
      globalcors:
        cors-configurations:
          '[/**]':
            allowedHeaders: '*'
            allowedMethods: '*'
            allowedOrigins: '*'
      routes:
        - id: path_route
          uri: lb://user-service
          predicates:
            - Path=/user/get/{id}
            
        - id: userservice_route
          uri: http://localhost:8080
          predicates:
            - Path=/user/test
##################省略数据库,redis等其他配置#########################

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

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

相关文章

springboot多项目结构

微服务的目录结构一般分为如下几个模块&#xff1a; 当我们做的项目稍微大一点之后&#xff0c;就会经常遇到需要把不同的模块分离出来的时候&#xff0c;比如微信的朋友圈、微信支付、聊天服务等模块&#xff0c;像这种微服务项目一般都会把base、common、前端抽离出来。 com…

DP8403国产3W双通道无滤波器D类立体声音频放大器兼容替代CS8403

目标DP8403简介功能框图&#xff1a;DP8403主要特性DP8403简介 DP8403是3W双通道无滤波器D类立体声音频功率放大器芯片&#xff0c;能够以D类放大器的效率提供AB类功率放大器的性能。采用D类结构&#xff0c;DP8403 能够在 4Ω负载和 5V 电源条件下&#xff0c;提供高达 3W 输…

MySQL (五)------数据库三范式、外键约束、多表间关系、多表关联查询、子查询

数据库三范式 好的数据库设计对数据的存储性能和后期的程序开发&#xff0c;都会产生重要的影响。建立科学的&#xff0c;规范的数据库就需要满足一些规则来优化数据的设计和存储&#xff0c;这些规则就称为范式。 1.1 第一范式: 确保每列保持原子性 第一范式是最基本的范式…

深入理解java反射原理

系列文章目录 文章目录系列文章目录前言一、 如何获取反射中的Class对象&#xff1f;二、反射的步骤三、详细解答1. 获取对象类的实例2、newInstance() 的实现方式3、获取Method对象4. 调用invoke()方法。总结前言 反射是在运行状态中&#xff0c;对于任意一个类&#xff0c;都…

C 程序设计教程(10)—— 数据输入函数(scanf)用法详解

C 程序设计教程&#xff08;10&#xff09;—— 数据输入函数&#xff08;scanf&#xff09;用法详解 该专栏主要介绍 C 语言的基本语法&#xff0c;作为《程序设计语言》课程的课件与参考资料&#xff0c;用于《程序设计语言》课程的教学&#xff0c;供入门级用户阅读。 目录…

Ubuntu安装PyTango步骤

继续上一篇&#xff1a; https://blog.csdn.net/woshigaowei5146/article/details/128443892?spm1001.2014.3001.5502 环境 虚拟机&#xff1a;VMware Ubuntun&#xff1a;20.04LTS Tango&#xff1a;9.3.5 安装 PyTango作为官方debian/ubuntu包在linux上可用: for Python…

195:vue+openlayers 加载json格式热力图,调节半径大小和模糊程度

第195个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers中加载JSON格式的数据,呈现热力图。这里可以调节热力图的半径大小和模糊程度。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例代码(共100行)headDa…

【JavaGuide面试总结】Java高级特性基础篇·上

【JavaGuide面试总结】Java高级特性基础篇上1.为什么 Java 中只有值传递&#xff1f;2.static 关键字使用场景3.Exception 和 Error 有什么区别&#xff1f;4.Checked Exception 和 Unchecked Exception 有什么区别&#xff1f;5.Throwable 类常用方法有哪些&#xff1f;6.fina…

【Linux】缓冲区理解

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《学会Linux》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;缓冲区&am…

深入理解ECAPA-TDNN——兼谈Res2Net、ASP统计池化、SENet、Batch Normalization

概述 ECAPA-TDNN是说话人识别中基于TDNN的神经网络&#xff0c;是目前最好的单体模型之一关于TDNN&#xff0c;可以参考深入理解TDNN&#xff08;Time Delay Neural Network&#xff09;——兼谈x-vector网络结构 ECAPA-TDNN TDNN本质上是1维卷积&#xff0c;而且常常是1维膨…

【Django项目开发】角色管理模块的开发(八)

文章目录一、序列化器设计1、嵌套的序列化器设计2、普通的序列化类支持&#xff1a;新增、修改角色名、删除、查询3、用于给某一个角色批量授权的序列化4、用于给某一个角色单一授权&#xff0c;包括取消单一授权二、视图类设计1、包含的接口有哪些2、set_permission_to_role方…

听说……国产的领航辅助驾驶系统都很卷?

什么是城市NOA功能&#xff1f; 基于国产芯片的城市NOA功能有看点吗&#xff1f; 国产芯片发展到了什么阶段&#xff1f; 车上配的激光雷达是不是越多越好&#xff1f; 车企常吹的“数据驱动”、“中央计算” 究竟是真是假&#xff1f; ……最近&#xff0c;两家中国公司组CP 推…

基于ros将文件夹中的图像转换为bag包(c++版本)

一、前期工作创建工作空间 二、创建工作包 创建完成后&#xff0c;文件夹的格式为&#xff1a; 三、准备编译文件和代码 3.1 更换编译文件中的内容 将上图中的&#xff0c;CMakeLists.txt文件中的内容&#xff0c;替换为下面的内容 cmake_minimum_required(VERSION 3.0.2) p…

【漏洞复现】Yapi接口管理平台RCE漏洞汇总

文章目录前言YApi接口管理平台远程代码执行漏洞一、漏洞描述二、影响版本三、FOFA语句四、漏洞复现五、修复建议YApi NoSQL注入导致远程命令执行漏洞一、YApi介绍二、漏洞描述三、漏洞分析四、漏洞详情五、影响版本六、漏洞复现七、修复建议前言 本篇文章主要归纳总结YApi各版…

南邮数据结构

md文档网址&#xff1a;https://gitee.com/infiniteStars/wang-dao-408-notes/blob/master/408/数据结构.md 1 绪论 1.1算法的基本概念 程序与算法的区别和联系 联系&#xff1a;程序是计算机指令的有序集合&#xff0c;是算法用某种程序设计语言的表述&#xff0c;是算法在…

2023年如何搭建最小可行性的产品文档/产品手册?

在推出并击败竞争对手进入市场的竞赛中&#xff0c;很容易将“不必要的”任务&#xff08;如文档&#xff09;放在次要位置。但根据 Write the Docs 纪录片社区的说法&#xff0c;文档应该既是先导性的&#xff0c;也是参与性的。这意味着您应该在开始开发之前开始记录&#xf…

吊打高斯模糊的stackBlur加入OpenCV

stackBlur介绍 stackBlur 最近才加入到OpenCV中&#xff0c;将在下一个Relase版本&#xff08;4.7&#xff09;中出现。C用户可以尝试从源码编译OpenCV体验一下。Python 用户可以尝试用pip安装rolling版本的OpenCV&#xff1a; pip install opencv-python-rolling4.6.0.202210…

新手教程 | 常见的爬虫类型有哪些?

程序猿圈流传着一个神话级别的事&#xff1a;全公司仅靠1个人&#xff0c;每年就能转上1400多万美元。听起来天方夜谭一样&#xff0c;那他是如何做到的呢&#xff1f;看报道就会发现&#xff0c;他利用的是爬虫技术。 随着互联网的发展&#xff0c;从海量的互联网数据中&…

不可错过,Java程序员必备珍藏书单

不要因为迷茫&#xff0c;而停止了脚下的路。给大家推荐一份Java程序员必看的书单&#xff0c;豆瓣评分都挺不错的&#xff0c;往下看&#xff01; 一、Java 基础篇书单 《Java编程思想》&#xff1a;从Java的基础语法到最高级特性&#xff08;深入的面向对象概念、多线程、自…

煤矿智能化相关50项团体标准征求意见

智能化煤矿总体架构 原文地址&#xff1a;https://chinacs.scimall.org.cn/a3651.html 由煤矿智能化创新联盟等单位提出&#xff0c;中国煤炭学会归口&#xff0c;中煤科工集团常州研究院有限公司等单位起草的《煤矿通信接口与协议通用技术要求》50项团体标准已完成征求意见稿的…