SpringCloud Gateway 新一代网关

一、前言

        接下来是开展一系列的 SpringCloud 的学习之旅,从传统的模块之间调用,一步步的升级为 SpringCloud 模块之间的调用,此篇文章为第六篇,即介绍 Gateway 新一代网关。

二、概述

2.1 Gateway 是什么

        Gateway 是在 Spring 生态系统之上构建的 API 网关服务,基于 Spring 5Spring Boot 2 和  Project Reactor 等技术。

        Gateway 旨在提供一种简单而有效的方式来对 API 进行路由,以及提供一些强大的过滤器功能, 例如:熔断、限流、重试等。

        SpringCloud Gateway Spring Cloud 的一个全新项目,基于 Spring 5.0+Spring Boot 2.0 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。

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

        Spring Cloud Gateway 的目标提供统一的路由方式且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

2.2 Gateway 总结

        SpringCloud Gateway 使用的 Webflux 中的 reactor-netty 响应式编程组件,底层使用了 Netty 通讯框架。

2.3 Gateway 用途

        1、反向代理

        2、鉴权

        3、流量控制

        4、熔断

        5、日志监控

2.4 网关位置

        在微服务架构中网关在哪里?如下图:

2.5 Gateway 和 zuul 对比

2.5.1 为什么选择 Gateway

         一方面因为 Zuul1.0 已经进入了维护阶段,而且 Gateway SpringCloud 团队研发的,是亲儿子产品,值得信赖。而且很多功能 Zuul 都没有用起来。

        Gateway 是基于异步非阻塞模型上进行开发的,性能方面不需要担心。虽然 Netflix 早就发布了最新的 Zuul 2.x,但 Spring Cloud 貌似没有整合计划。而且 Netflix 相关组件都宣布进入维护期;不知前景如何。多方面综合考虑 Gateway 是很理想的网关选择。

2.5.2 Gateway 特性

        1、基于 Spring Framework 5Project Reactor Spring Boot 2.0 进行构建

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

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

        4、集成 Hystrix 的断路器功能

        5、集成 Spring Cloud 服务发现功能

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

        7、请求限流功能

        8、支持路径重写

2.5.3 Gateway 和 Zuul 区别

        在 SpringCloud Finchley 正式版之前,Spring Cloud 推荐的网关是 Netflix 提供的 Zuul

        1、Zuul 1.x,是一个基于阻塞 I/ OAPI Gateway

        2、Zuul 1.x 基于 Servlet 2. 5 使用阻塞架构,它不支持任何长连接(如 WebSocket),Zuul 的设计模式和 Nginx 较像,每次 I/ O 操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是 Nginx C++ 实现,Zuul Java 实现,而 JVM 本身会有第一次加载较慢的情况,使得 Zuul 的性能相对较差。

        3、Zuul 2.x 理念更先进,想基于 Netty 非阻塞和支持长连接,但 SpringCloud 目前还没有整合。 Zuul 2.x 的性能较 Zuul 1.x 有较大提升。在性能方面,根据官方提供的基准测试, Spring Cloud GatewayRPS(每秒请求数)是 Zuul 1.6 倍。

        4、Spring Cloud Gateway 建立在 Spring Framework 5 Project Reactor Spring Boot 2 之上, 使用非阻塞 API

        5、Spring Cloud Gateway 还支持 WebSocket, 并且与 Spring 紧密集成拥有更好的开发体验。

2.6 Zuul1.x 模型

        Spring Cloud 中所集成的 Zuul 版本,采用的是 Tomca t容器,使用的是传统的 Servlet IO 处理模型。

        servlet servlet container 进行生命周期管理。container 启动时构造 servlet 对象并调用servlet init() 进行初始化;container 运行时接受请求,并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用 service()container 关闭时调用 servlet destory() 销毁 servlet

        上述模式的缺点:servlet 是一个简单的网络 IO 模型,当请求进入 servlet container 时,servlet container 就会为其绑定一个线程,在并发不高的场景下这种模型是适用的。但是一旦高并发(比如用 jemeter 压),线程数量就会上涨,而线程资源代价是昂贵的(上线文切换,内存消耗大)严重影响请求的处理时间。在一些简单业务场景下,不希望为每个 request 分配一个线程,只需要 1 个或几个线程就能应对极大并发的请求,这种业务场景下 servlet 模型没有优势。

        所以 Zuul 1.X 是基于 servlet 之上的一个阻塞式处理模型,即 spring 实现了处理所有 request 请求的一个 servletDispatcherServlet)并由该 servlet 阻塞式处理处理。所以 Springcloud Zuul 无法摆脱 servlet 模型的弊端。

2.7 Gateway 模型

        传统的 Web 框架,比如说:struts2springMvc 等都是基于 Servlet API Servlet 容器基础之上运行的。

        但是在 Servlet3.1 之后有了异步非阻塞的支持。而 WebFlux 是一个典型非阻塞异步的框架,它的核心是基于 Reactor 的相关 API 实现的。相对于传统的 web 框架来说,它可以运行在诸如 NettyUndertow 及支持 Servlet3.1 的容器上。非阻塞式+函数式编程(Spring5 必须让你使用 java8 )。

        Spring WebFlux Spring 5.0 引入的新的响应式框架,区别于 Spring MVC,它不需要依赖 Servlet API,它是完全异步非阻塞的,并且基于 Reactor 来实现响应式流规范。

三、三大核心概念

3.1 Route 路由

        路由是构建网关的基本模块,它由 ID,目标 URI,一系列的断言和过滤器组成,如果断言为 true 则匹配该路由。

3.2 Predicate 断言

        参考的是 Java8 java.util.function.Predicate,开发人员可以匹配 HTTP 请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由。

3.3 Filter 过滤

        指的是 Spring 框架中 GatewayFilter 的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

3.4 总体

        web 请求通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。

        predicate 就是我们的匹配条件。

        filter 可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标 uri,就可以实现一个具体的路由了。

四、Gateway 工作流程

4.1 官网总结

        1、客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler

        2、Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。

        3、Filter “pre” 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在 “post” 类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

4.2 核心逻辑

        路由转发+执行过滤器链。

五、入门配置

5.1 新建工程

        新建一个 cloud-gateway-gateway9527 模块,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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.springcloud</groupId>
        <artifactId>SpringCloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>cloud-gateway-gateway9527</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--一般基础配置类-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

        applicaiton.yml 内容如下所示:

server:
  port: 9527

spring:
  application:
    name: cloud-gateway

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

        主启动类的代码如下所示:

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

        思考一个问题?新建的这个网关工程如何做路由配置。

5.2 通过 yml 配置网关

        在 application.yml 中新增网关的配置,代码如下:

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #payment_route    # 路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          # 匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    # 路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          # 匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

        分别启动 cloud-eureka-server7001cloud-provider-payment8001 和 cloud-gateway-gateway9527 模块。

        添加网关前,我们的访问路径为:http://localhost:8001/payment/get/1,如下图:

        添加网关后,我们的访问路径为:http://localhost:9527/payment/get/1,如下图:

 

5.3 通过配置类配置网关

        我们还可以通过配置类的方式进行网关的配置,假如现在有一个业务需求:通过 9527 网关访问到外网的网站。

        在 cloud-gateway-gateway9527 模块新建一个配置类  GateWayConfig,代码如下:

@Configuration
public class GateWayConfig {

    /**
     * 配置了一个id为route-name的路由规则,
     * 当访问地址 http://localhost:9527/bd 时会自动转发到地址:https://www.baidu.com/
     * @param builder
     * @return
     */
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder)
    {
        RouteLocatorBuilder.Builder routes = builder.routes();

        routes.route("path_route", r -> r.path("/bd").uri("https://www.baidu.com")).build();

        return routes.build();

    }
    @Bean
    public RouteLocator customRouteLocator2(RouteLocatorBuilder builder)
    {
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route("path_route2", r -> r.path("/sina").uri("https://news.sina.com.cn/china")).build();
        return routes.build();
    }

}

        再次分别启动 cloud-eureka-server7001cloud-provider-payment8001 和 cloud-gateway-gateway9527 模块。进行测试即可。

六、通过微服务名实现动态路由

        默认情况下 Gateway 会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。

        什么意思呢?cloud-gateway-gateway9527 模块的 application.yml 内容如下所示:

        这个地方的 url 是写死的,是无法实现负载均衡的,只能调用一个地方的地址,这个是不合理的,而 Gateway 是支持以注册中心微服务名为路径创建动态路由进行转发的,咋配置呢?如下所示:

        需要注意的是:uri 的协议为 lb,表示启用 Gateway 的负载均衡功能。

        lb://serviceName spring cloud gateway 在微服务中自动为我们创建的负载均衡 uri

        分别启动 cloud-eureka-server7001cloud-provider-payment8001、cloud-provider-payment8002 和 cloud-gateway-gateway9527 ​​​​​​​模块进行测试。

        访问 ​http://localhost:9527/payment/lb,不断的进行刷新测试,如下图,可以看到实现了负载均衡

七、Predicate 的使用

7.1 Predicate 是什么

        打开我们 cloud-gateway-gateway9527 ​​​​​​​模块的控制台信息,如下图,那么这个 Route Predicate Factories 是个什么东西呢?

        Spring Cloud Gateway 将路由匹配作为 Spring WebFlux HandlerMapping 基础架构的一部分。

        Spring Cloud Gateway 包括许多内置的 Route Predicate 工厂。所有这些 Predicate 都与 HTTP 请求的不同属性匹配。多个 Route Predicate 工厂可以进行组合。

        Spring Cloud Gateway 创建 Route 对象时, 使用 RoutePredicateFactory 创建 Predicate 对象,Predicate 对象可以赋值给 RouteSpring Cloud Gateway 包含许多内置的 Route Predicate Factories

        所有这些谓词都匹配 HTTP 请求的不同属性。多种谓词工厂可以组合,并通过逻辑 and。

7.2 常用的 Route Predicate

7.2.1 After Route Predicate

        这个断言的意思:匹配这个路由的任何请求必须在 after 之后的时间才可以生效。

        上面的时间是美国的时间,获取我们现在的时间的代码如下:

import java.time.ZoneId;
import java.time.ZonedDateTime;

public class T2 {

    public static void main(String[] args) {

        // 默认时区
        ZonedDateTime zbj = ZonedDateTime.now();
        System.out.println(zbj);
        // 2024-03-13T10:49:52.186+08:00[Asia/Shanghai]

        // 用指定时区获取当前时间
        ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York"));
        System.out.println(zny);
        // 2024-03-12T22:49:52.189-04:00[America/New_York]

    }
}

        在我们 cloud-gateway-gateway9527 ​​​​​​​模块的 application.yml 中配置上述 after 标签,如下:

        启动工程进行测试,如下,可以看到,当前的服务是不可用的。

7.2.2 Before Route Predicate

        这个断言的意思:匹配这个路由的任何请求必须在 before 之后的时间才可以生效。

         在我们 cloud-gateway-gateway9527 模块的 application.yml 中配置上述 before 标签,如下:

        启动工程进行测试,如下,可以看到,当前的服务是可用的。

7.2.3 Between Route Predicate

        这个断言的意思:匹配这个路由的任何请求必须在指定的时间范围内才可以生效。

        在我们 cloud-gateway-gateway9527 模块的 application.yml 中配置上述 between 标签,如下:

        启动工程进行测试,如下,可以看到,当前的服务是可用的。

7.2.4 Cookie Route Predicate

        这个断言的意思:匹配这个路由的任何请求必须携带 cookie 参数才可以生效。

        Cookie Route Predicate 需要两个参数,一个是 Cookie name ,一个是正则表达式。路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行

         在我们 cloud-gateway-gateway9527 模块的 application.yml 中配置上述 cookie 标签,如下:

        首先进行不带 Cookie 参数进行测试,在 cmd 中执行 curl http://localhost:9527/payment/lb,可以看到调用出错了。

        接下来进行带 Cookie 参数进行测试,在 cmd 中执行 curl http://localhost:9527/payment/lb --cookie "username=zzyy",可以看到调用没有任何问题。

7.2.5 Header Route Predicate

        这个断言的意思:匹配这个路由的任何请求必须携带 header 参数才可以生效。

        它一共有两个参数:一个是属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。

          在我们 cloud-gateway-gateway9527 模块的 application.yml 中配置上述 header 标签,如下:

        在 cmd 中执行 curl http://localhost:9527/payment/lb -H "X-Request-Id:123",可以看到调用没有任何问题。

        在 cmd 中执行 curl http://localhost:9527/payment/lb -H "X-Request-Id:-123",可以看到调用出错了,负数的校验未通过。

7.2.6 Host Route Predicate

        这个断言的意思:匹配这个路由的任何请求必须指定主机名称才可以生效。

        Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板,用.号作为分隔符。它通过参数中的主机地址作为匹配规则。

           在我们 cloud-gateway-gateway9527 模块的 application.yml 中配置上述 Host 标签,如下:

        在 cmd 中执行 curl http://localhost:9527/payment/lb -H "Host: www.laotie.com",可以看到调用没有任何问题。

        在 cmd 中执行 curl http://localhost:9527/payment/lb -H "Host: www.laotie.net",可以看到调用出错了。

7.2.7 Method Route Predicate

        这个断言的意思:匹配这个路由的任何请求必须使用 get 请求才可以生效。

            在我们 cloud-gateway-gateway9527 模块的 application.yml 中配置上述 Method 标签,如下:

        在 cmd 中执行 curl http://localhost:9527/payment/lb,可以看到调用没有任何问题。

        在 cmd 中执行 curl -X -POST http://localhost:9527/payment/lb,可以看到调用出错了。

7.2.8 Path Route Predicate

        这个断言的意思:匹配这个路由的任何请求必须指定地址请求才可以生效。

        在我们 cloud-gateway-gateway9527 模块的 application.yml 中配置上述 Path 标签,如下:

        访问 http://localhost:9527/payment/lb,可以看到调用没有任何问题。

7.2.9 Query Route Predicate

        这个断言的意思:匹配这个路由的任何请求必须要有指定参数才可以生效。

        支持传入两个参数,一个是属性名,一个为属性值,属性值可以是正则表达式。

         在我们 cloud-gateway-gateway9527 模块的 application.yml 中配置上述 Query 标签,如下:

        访问 http://localhost:9527/payment/lb?username=31,可以看到调用没有任何问题。

        访问 http://localhost:9527/payment/lb?username=-31,可以看到调用报错了。

7.2.10 小总结

        说白了,Predicate 就是为了实现一组匹配规则,让请求过来找到对应的 Route 进行处理。

八、Filter 的使用

8.1 Filter 是什么

        Filter 是路由过滤器,可用于修改进入的 HTTP 请求和返回的 HTTP 响应,路由过滤器只能指定路由进行使用。

        Spring Cloud Gateway 内置了多种路由过滤器,他们都由 GatewayFilter 的工厂类来产生。

8.2 Filter 生命周期

        生命周期只有两个,一个是业务逻辑之前(pre),一个是业务逻辑之后(post)。类似于 Spring 的前置通知和后置通知。

8.3 Filter 种类

        种类分为两种,GatewayFilter 单一的和 GlobalFilter 全局的两种。

8.3.1 GatewayFilter

        从官网可以看出,单一的这种路由过滤器有 31 种之多,如下图:

8.3.2 GlobalFilter

        从官网可以看出,全局的这种路由过滤器有 10 种左右,如下图:

8.3.3 常用的 GatewayFilter

        这里面举个简单的例子,如下图,

        在浏览器中访问  http://localhost:9527/payment/lb 就等同于访问 curl http://localhost:9527/payment/lb -H "X-Request-Id:1024",它会自动的给你的请求加一个请求头的信息。

8.4 自定义过滤器

8.4.1 作用

        自定义全局的过滤器可以实现全局日志记录、统一网关鉴权等功能。

8.4.2 案例

        接下来我们自定义一个全局的过滤器 GlobalFilter,在  cloud-gateway-gateway9527 模块新建一个全局的过滤器类,代码如下,

        全局过滤器需要实现 GlobalFilter 和 Ordered 接口,并重写两个方法,其中 getOrder() 方法指定过滤器的加载顺序,数字越小加载顺序越早。而 filter() 方法则指定全局的规则,即所有的请求必须携带 uname 参数,如果携带该参数,则交由下一个处理链进行处理。如果未携带该参数,则直接返回错误信息。

package com.springcloud;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Date;

@Component
public class MyLogGateWayFilter implements GlobalFilter, Ordered
{
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
    {
        System.out.println("time:"+new Date()+"\t 执行了自定义的全局过滤器: "+"MyLogGateWayFilter"+"hello");

        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if (uname == null) {
            System.out.println("****用户名为null,无法登录");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

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

8.4.3 测试

        启动工程,输入 http://localhost:9527/payment/lb?uname=z3 进行测试,如下图,可以正常访问。

        输入 http://localhost:9527/payment/lb,未添加 uname 参数,不可以正常访问。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在域控的Users目录下批量创建用户组,名称来自Excel

对于CSV文件&#xff0c;PowerShell可以直接读取并处理&#xff0c;无需额外安装模块。假设你的CSV文件中&#xff0c;用户组名称在第一列&#xff0c;文件名为"groups.csv"&#xff0c;可以使用以下PowerShell脚本来批量创建&#xff1a; # 读取CSV文件中的数据 $g…

学生时期学习资源同步-1 第一学期结业考试题2

原创作者&#xff1a;田超凡&#xff08;程序员田宝宝&#xff09; 版权所有&#xff0c;引用请注明原作者&#xff0c;严禁复制转载

【Python】科研代码学习:十 evaluate (metrics,Evaluator)

【Python】科研代码学习&#xff1a;十 evaluate Evaluate评估类型简单使用教程如何寻找想要的 metric使用 Evaluator与 transformers.trainer 配合使用疑问与下节预告 Evaluate 【HF官网-Doc-Evaluate&#xff1a;API】 看名字就可以知道&#xff0c;Evaluate 是 HF 提供的便…

中国湿地沼泽分类分布数据集

数据下载链接&#xff1a;百度云下载链接 引言 随着经济社会的快速发展和城市化进程的加速推进&#xff0c;农业发生功能性转变&#xff0c;从单一生产功能向生产、生活、生态多功能服务首都经济社会发展转变。湿地与农田、草地、森林三大生态系统整合形成完整的现代农业生态服…

Linux环境(Ubuntu)上搭建MQTT服务器(EMQX )

目录 概述 1 认识EMQX 1.1 EMQX 简介 1.2 EMQX 版本类型 2 Ubuntu搭建EMQX 平台 2.1 下载和安装 2.1.1 下载 2.1.2 安装 2.2 查看运行端口 3 运行Dashboard 管理控制台 3.1 查看Ubuntu上的防火墙 3.2 运行Dashboard 管理控制台 概述 本文主要介绍EMQX 的一些内容&a…

云计算 3月12号 (PEX)

什么是PXE&#xff1f; PXE&#xff0c;全名Pre-boot Execution Environment&#xff0c;预启动执行环境&#xff1b; 通过网络接口启动计算机&#xff0c;不依赖本地存储设备&#xff08;如硬盘&#xff09;或本地已安装的操作系统&#xff1b; 由Intel和Systemsoft公司于199…

游戏数据处理

游戏行业关键数据指标 ~ 总激活码发放量、总激活量、总登录账号数 激活率、激活登录率 激活率 激活量 / 安装量 激活率 激活量 / 激活码发放量 激活且登录率 激活且登录量 / 激活码激活量 激活且登录率应用场景 激活且登录率是非常常用的转化率指标之一&#xff0c;广泛…

今天我们来学习一下关于MySQL数据库

目录 前言: 1.MySQL定义&#xff1a; 1.1基础概念&#xff1a; 1.1.1数据库&#xff08;Database&#xff09;&#xff1a; 1.1.2表&#xff08;Table&#xff09;&#xff1a; 1.1.3记录&#xff08;Record&#xff09;与字段&#xff08;Field&#xff09;&#xff1a; …

C语言strcmp函数讲解

strcmp函数介绍 在cplusplus官网上是这样介绍strcmp函数的 这里的意思是假如我们输入两个字符串一个是abcdef另一个也是abcdef他们两个字符的每个元素的ascii码值进行比较如果两个元素的ascii码值都相等就移动到下一个元素a与a进行比较b与b进行比较直到遇到\0为止&#xff0c…

数据结构:7、队列

一、队列的概念与结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(First In First Out) 入队列&#xff1a;进行插入操作的一端称为队尾 出队列&#xff1a;进行删除操作的一端称为队头…

功能测试--APP性能测试

功能测试--APP性能测试 内存数据查看内存测试 CPU数据查看CPU测试 流量和电量的消耗流量测试流量优化方法电量测试电量测试场景&#xff08;大&#xff09; 获取启动时间启动测试--安卓 流畅度流畅度测试 稳定性稳定性测试 内存数据查看 内存泄露:内存的曲线持续增长(增的远比减…

码头船只出行和货柜管理系统的设计与实现

针对于码头船只货柜信息管理方面的不规范&#xff0c;容错率低&#xff0c;管理人员处理数据费工费时&#xff0c;采用新开发的码头船只货柜管理系统可以从根源上规范整个数据处理流程。 码头船只货柜管理系统能够实现货柜管理&#xff0c;路线管理&#xff0c;新闻管理&#…

【MMDetection3D实战(3)】: KITTI 数据集介绍

文章目录 1. 数据集介绍2 数据下载及准备2.1 下载并整理数据集2.2 传感器及坐标定义2.3 数据的标注3 MMDet3D 中的坐标系规范4 数据的处理及可视化4.1 数据处理4.2 点云读取和可视化4.2.1 点云的读取4.2.2 点云的可视化1. 数据集介绍 KITTI数据集是3D目标检测中比较基础和常用…

【LeetCode】升级打怪之路 Day 17:二叉树题型 —— 二叉树的序列化与反序列化

今日题目&#xff1a; 297. 二叉树的序列化与反序列化652. 寻找重复的子树 目录 LC 297. 二叉树的序列化与反序列化 【classic】 ⭐⭐⭐⭐⭐1&#xff09;序列化逻辑2&#xff09;反序列化逻辑 LC 652. 寻找重复的子树 【稍有难度】 今天主要学习了二叉树的序列化和反序列化相关…

数字逻辑-时序逻辑电路一

一、实验目的 &#xff08;1&#xff09;熟悉触发器的逻辑功能及特性。 &#xff08;2&#xff09;掌握集成D和JK触发器的应用。 &#xff08;3&#xff09;掌握时序逻辑电路的分析和设计方法。 二、实验仪器及材料 三、实验内容及步骤 1、用D触发器&#xff08;74LS74&am…

使用Docker在windows上安装IBM MQ

第一步、安装wsl 详见我另一篇安装wsl文章。 第二步、安装centos 这里推荐两种方式&#xff0c;一种是从微软商城安装&#xff0c;一种是使用提前准备好的镜像安装&#xff0c;详见我另一篇windos下安装centos教程。 第三步、安装windows下的Docker desktop 详见我另一篇wind…

TQ15EG开发板教程:运行MPSOC+AD9361

目录 1&#xff0c;下载工程需要使用的文件 2&#xff0c;编译以及修改工程 3&#xff0c;获取生成BOOT.BIN所需要的3个文件 3.1生成bit文件 3.2生成elf文件 3.3生成fsbl文件 4&#xff0c;生成boot.bin文件 5&#xff0c;上板测试 6&#xff0c;切换FMC接口 7&#…

自适应窗口图片轮播HTML代码

自适应窗口图片轮播HTML代码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 代码下载地址 自适应窗口图片轮播HTML代码

分享 | 计算机组成与设计学习资料+CPU设计源码+实验报告

1.引言 百度网盘资源链接&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1Ww6u_l1L6DMXofC2HxfETw?pwdyqd6 提取码&#xff1a;yqd6 2.学习资源预览 2.1 包含学习手册四本&#xff1a; - 计算机原理与设计&#xff1a;Verilog HDL版 - 计算机组成与设…

开源分子对接程序rDock使用方法(2)-高通量虚拟筛选HTVS

欢迎浏览我的CSND博客&#xff01; Blockbuater_drug …点击进入 文章目录 前言一、rDock用于高通量虚拟筛选HTVSMulti-Step Protocol HTVS步骤及注意事项 二、rDock中Multi-Step Protocol用于HTVS的用法Step 1. Exhaustive dockingStep 2. sdreport summaryStep 3. 运行rbhtfi…