当前位置: 首页 > news >正文

SpringCloud GateWay网关

1、网关介绍

        微服务网关(Microservices Gateway)是微服务架构中的核心组件,充当所有客户端请求的统一入口,负责请求的路由、过滤和聚合等操作。它是微服务与外部系统(如Web、移动端)之间的中间层,简化了客户端的调用复杂度,并提供了统一的治理能力。

2、网关的作用

        网关的作用有:统一入口、请求路由、负载均衡、流量控制、身份认证、协议转换、系统监控、安全防护。  

1、统一入口

        统一入口,也叫路由转发。将客户端请求动态路由到对应的微服务实例(如 /order 请求转发到订单服务)。并且支持路径重写、负载均衡。前端不需要知道每一个后端服务的地址,只要知道网关地址就行了。在企业系统中,会统一通过api网关对外暴露接口,屏蔽内部服务拆分带来的复杂性。比如对于财务模块,接口都是以/api/fc/xxx的形式。有/fc/AAA,/fc/BBB,/fc/CCC,这些接口可能部署在不同的服务器上,那么对应的ip地址也不一样。有了网关的话,就不用记住那么多ip地址了。都走网关就行了。确保前端只与网关通信,无需感知后端服务地址。

2、请求路由

        根据请求特征(如URL路径、HTTP头、参数)将请求精准分发至对应后端服务,支持动态路由策略。静态路由通常是预定义以硬编码的形式写在配置文件yml中的。项目启动后,静态路由就生效了,如果想要修改的话,需要重启项目。而动态路由是运行时加载,可以写在数据库中,或者配置中心apollo,运行的时候读取配置。

3、负载均衡

        通过算法(如轮询、加权轮询、最少连接)将流量分发到多个服务器实例,避免单点过载,提升系统可用性。在一些高并发的场景中,通过网关将请求分散至多台服务器,防止单台服务器宕机。

4、流量控制

        通过限流(Rate Limiting)、熔断(Circuit Breaking)和降级(Degrade)策略,防止系统过载导致服务中断,保障核心服务稳定。

        限流:可以通过控制请求速率防止服务过载。比如,可以使用网关内置限流,使用Redis+Lua脚本实现分布式限流。Redis作为分布式计数器存储,确保多节点限流一致性。Lua脚本保证检查+更新计数的原子性操作。

        熔断:当下游服务响应超时或报错时,快速失败避免资源耗尽。防止一个服务的故障扩撒到整个系统,产生雪崩效应。可以使用Hystrix实现服务熔断。Hystrix实现服务熔断其实就是有点类似于java里面的异常处理机制。

        降级:一旦程序发生异常则直接将当前服务熔断,并把发生异常的服务降级(前提是要有次级服务)。一级降二级,二级降三级......依次类推。通常会采用多级降级策略:

        一级降级(轻度):

        场景:服务器资源使用率达到70%

        动作:关闭一些非核心任务:日志分析、数据备份、广告推送等。

        降低服务质量:降低图片视频的清晰度。

        启用本地缓存:一些页面读取本地缓存信息,而不是直接读取远程的信息。

        二级降级(中度):

        场景:服务器资源使用率达到90%

        动作:关闭非核心API,简化业务流程,同步改异步(实时性改为非实时性,延迟写入数据

        库,先存内存队列)。

        三级降级(重度):

        场景:服务器资源耗尽

        动作:仅保留核心功能,如电商系统仅保留下单、支付功能。商品详情页仅返回静态HTML

        (无实时数据),用户信息返回预 设默认值(如匿名用户头像)。进入安全模式,拒绝所有

        的写操作,关闭第三方服务调用(短信通知),启用本地事 务日志。

        实现服务熔断、降级,可以引入Hystrix,在相应的接口上加上:@HystrixCommand(fallbackMethod = "AAA")。

        如以下三个服务:AAA、BBB、CCC。AAA发生故障,会进行熔断并降级到BBB,如果BBB再发生故障,会熔断并降级到CCC。

@GetMapping("/AAA")
@ResponseBody
@HystrixCommand(fallbackMethod = "BBB")
public float AAA() {......
}@HystrixCommand(fallbackMethod = "CCC")
public float BBB() {......
}public float CCC() {......
}

 

5、身份认证

        在企业内网中,用户通过网关输入账号密码去访问内部的OA系统。在调用内部服务API时,也会经过网关,网关校验token,确保调用方权限。

6、协议转换

        在不同协议间转换数据格式,如Http转Https、WebSocket、Modbus转OPC UA,实现异构系统互联。

        Http:超文本传输协议,主要用于Web/移动端/微服务,是明文传输,通常用于测试环境,默认端口是80。

        Https:在Http的基础上进行了加密,即:Http+SSL/TLS,SSL(安全套接层协议)是用于网络通信中数据加密身份验证。数据传输时通过SSL进行加密,并通过数字证书验证服务器身份,确保用户访问的是真实网站,而非假冒伪劣网站。SSL通常是由权威机构CA签发的。默认端口443。

        WebSocket:全双工长连接。实时双向通信。主要用于:实时聊天、在线协作、网游中多玩家。WS默认端口80,WSS默认端口443。

        Modbus:该协议用于工业设备,如PCL控制。

        OPC UA:该协议是一种面向服务的工业通信框架。

7、系统监控

        收集请求日志,实时监控系统状态,辅助故障排查与优化。

8、安全防护

        网关可以提供访问控制、流量过滤、加密通信等安全功能。

3、实现一个网关

        我使用的是Spring Cloud Gateway。不过也可以用Nginx作为网关。因为SpringCloudGateway是java写的,运行在JVM上,因此对于基于SpringCloud框架的微服务来说,SpringCloudGateway更适用。

        对于非SpringCloud框架的服务来说,使用Nginx更适合了。Nginx是基于C语言开发的,性能比SpringCloud更好。Nginx支持反向代理,所谓反向代理就是代理服务端去接收客户端的请求,并分发给对应的内部服务。网关起的就是一个反向代理的作用。隐藏服务细节,客户端无需感知后端服务地址。Nginx通常会用于高并发的场景,Nginx作为入口网关,处理静态资源请求,并将动态请求转发到后端应用服务器(如Tomcat、Node.js),同时实现SSL终止、缓存、负载均衡等功能。

        正向代理就是代理客户端向服务端发起请求。通常用于各种VPN。

3.1、创建一个Eureka注册中心

        Step1、引入eureka依赖 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><groupId>org.example</groupId><artifactId>eureka-center</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><springframework.version>1.5.4.RELEASE</springframework.version><springframework.version1>1.3.5.RELEASE</springframework.version1></properties><dependencies><!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka-server</artifactId><version>${springframework.version1}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>${springframework.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>${springframework.version}</version><scope>test</scope></dependency></dependencies></project>

        Step2、application.yml

server:port: 8001#Eureka配置
eureka:instance:hostname: localhost  #Eureka服务端的实例名称client:register-with-eureka: false  #是否向eureka注册中心注册自己,因为这里本身就是eureka服务端,所以无需向eureka注册自己fetch-registry: false #fetch-registry为false,则表示自己为注册中心service-url:   #监控页面defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

        Step3、启动类

package com.eureka;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;/*** @author: Wulc* @createTime: 2025-05-02* @description:* @version: 1.0*/@SpringBootApplication
@EnableEurekaServer  //使eureka服务端可以工作
public class SpringcloudEurekaApplication {public static void main(String[] args) {SpringApplication.run(SpringcloudEurekaApplication.class, args);}
}

        项目启动成功后,浏览器输入:http://localhost:8001/ 一个Eureka注册中心就已经好了。

 

3.2、创建一个网关服务

        Step1、引入gateway依赖 ​​​​​ 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><groupId>org.example</groupId><artifactId>my-gateway</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.3</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>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></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><exclusions><!-- 排除可能引入的Spring MVC依赖 -->
<!--                Spring Cloud Gateway基于WebFlux响应式框架(非阻塞式),而Spring MVC是传统的Servlet-based框架(阻塞式)。-->
<!--                当两者同时存在于classpath时,Spring Boot无法决定使用哪种Web服务器(Tomcat vs Netty),导致启动失败。--><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></exclusion></exclusions></dependency><!--        loadbalancer是负载均衡,对应yml中的lb--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency></dependencies><!--    使用dependencyManagement统一管理SpringCloud组件,集中定义所有SpringCloud相关组件的兼容版本,避免手动指定每个依赖的版本号,--><!--    解决版本冲突问题。我这里使用了2021.0.3,对应的是Springboot2.6.x--><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>2021.0.3</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>

         Step2、编写yml文件 application.yml

server:port: 80spring:main:web-application-type: reactive  # 强制使用WebFluxapplication:name: my-gateway-serviceprofiles:include: route  #使用application-route.yml里面的配置eureka:client:service-url:defaultZone: http://localhost:8001/eureka/  # Eureka注册中心地址register-with-eureka: truefetch-registry: trueinstance:prefer-ip-address: trueinstance-id: ${spring.application.name}:${server.port}

        application-route.yml

spring:cloud:gateway:discovery:locator:enabled: true  # 开启从注册中心动态创建路由lower-case-service-id: true  # 服务名小写routes:- id: route1uri: lb://wulc-test-consumer-server  # lb表示负载均衡 loadbalancepredicates: #断定,遵守哪些规则,就把请求转发给wulc-test-consumer-server这个服务- Path=/api/wulc/**- id: route2uri: lb://wulc-test-serverpredicates:- Path=/api/test/**filters:#StripPrefix=1表示移除请求路径中的第1个路径,#即:如果前端的请求是/api/test/getMsg,那么gateway网关转发时就会找/test/getMsg- StripPrefix=1		order: 0

        Step3、启动类

package com.gateway;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;/*** @author Wulc* @date 2025/5/4 13:56* @description*/
@SpringBootApplication
@EnableDiscoveryClient
public class ApplicationStarter {public static void main(String[] args) {SpringApplication.run(ApplicationStarter.class, args);}
}

        启动成功后,在eureka上服务注册成功了。

3.3、创建一个普通服务

        Step1、引入相关依赖 pom.xml

<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><groupId>org.example</groupId><artifactId>wulc-test</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><name>wulc-test</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><springframework.version>1.5.4.RELEASE</springframework.version><springframework.version1>1.3.5.RELEASE</springframework.version1></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${springframework.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>${springframework.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>${springframework.version}</version></dependency><!--        eureka--><!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId><version>${springframework.version1}</version></dependency></dependencies></project>

        Step2、yml文件 application.yml

server:port: 8084spring:application:name: wulc-test-server#eureka配置,服务注册到哪?
eureka:client:service-url:defaultZone: http://localhost:8001/eureka/instance:#修改eureka上默认描述信息instance-id: ${spring.application.name}:${server.port}

        Step3、controller

package com.test.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author: Wulc* @createTime: 2025-05-01* @description:* @version: 1.0*/@RestController
@RequestMapping("/test")
public class MsgController {@GetMapping("/getMsg")public String getMsg(){System.out.println("成功获取信息");return "成功获取信息";}
}

        Step4、启动类

package com.test;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;/*** @author: Wulc* @createTime: 2025-05-01* @description:* @version: 1.0*/
@EnableDiscoveryClient
//@EnableEurekaClient
@SpringBootApplication
public class ApplicationStarter {public static void main(String[] args) {SpringApplication.run(ApplicationStarter.class, args);}
}

        注意:@EnableDiscoveryClient和@EnableEurekaClient都是用于将微服务注册到服务注册中心的注解。但@EnableEurekaClient仅支持Eureka,而@EnableDiscoveryClient同时支持:Eureka、Consul、Zookeeper、Nacos 等。

        启动成功后,在Eureka上注册了该服务。

  

        通过网关,成功转发到了wulc-test-server服务上的/test/getMsg接口。

        我们可以分别用8085、8086端口号再启动两个服务,作为集群,来验证负载均衡。

 

         使用postman访问网关接口:http://localhost:80/api/test/getMsg 33次。可以看到gateway网关,将33次请求转发到了wulc-test-server:8084、wulc-test-server:8085、wulc-test-server:8086三个服务上面,起到了一个负载均衡的作用。

 

4、网关跨域

        所谓跨域,是指不同源的客户端/服务端,在没有对方授权的情况下是不允许发送/接收对方的数据资源的,会产生“跨域”情况。“跨域”是浏览器的一种保护机制,是由同源策略所导致的限制。所谓同源策略指的是:只有当两个url协议、域名和端口完全一致时,才认为是同源,否则就是跨域。跨域一般是在前端访问后端接口时产生的。在前端服务器上可以ping通相应的后端服务器,但是由于前后端服务器不同源,因此产生跨域无法访问。

 

        常见的跨域解决方法有,在Springboot控制类或者方法上加@CrossOrigin注解。

        @CrossOrigin注解有:value、origins、allowedHeaders、exposedHeaders、methods、allowCredentials、maxAge这些属性。

(1)value和origins是等价的,用于指定允许访问资源的来源,例:

// 允许单个源
@CrossOrigin(origins = "http://localhost:3000")// 允许多个源
@CrossOrigin(origins = {"http://site1.com", "https://site2.com"})// 允许所有源(慎用,生产环境不推荐)
@CrossOrigin(origins = "*")

(2)allowedHeaders,定义客户端可以在请求中携带的 HTTP 头字段(如 `Authorization`、`Content-Type`)。默认仅允许简单头(`Accept`、`Accept-Language`、`Content-Language`、`Content-Type`)。例:

// 允许自定义头
@CrossOrigin(allowedHeaders = {"X-Custom-Header", "Authorization"})// 允许所有头(开放权限,慎用)
@CrossOrigin(allowedHeaders = "*")

(3)exposedHeaders,指定哪些响应头可以被浏览器访问(默认只能读取简单响应头)。例:

// 暴露自定义头
@CrossOrigin(exposedHeaders = "X-Total-Count")// 暴露多个头
@CrossOrigin(exposedHeaders = {"X-Header1", "X-Header2"})

 (4)methods,限制允许的http方法,如get、post。例:

// 只允许 GET 和 POST
@CrossOrigin(methods = {RequestMethod.GET, RequestMethod.POST})// 允许所有方法(开放权限,慎用)
@CrossOrigin(methods = "*")

(5)allowCredentials,是否允许凭据,用于控制是否允许浏览器发送凭据(如 CookieAuthorization 头)。默认 false(不允许),设为 true 时需配合 origins 明确指定来源(不能为 *)。例:

// 允许携带 Cookie
@CrossOrigin(allowCredentials = "true", origins = "http://trusted-site.com")
fetch("http://your-api.com/data", {credentials: "include"  // 发送 Cookie
});

(6)maxAge,预检请求缓存时间。所谓缓存预检是浏览器在有效时间内,不会重复对同一跨域请求进行检查,直接发送真实的请求。即,在第一次发送跨域访问时,浏览器会检查跨域请求的合法性。如果合法的话,那么在设置的maxAge时间内,如果是同一请求方再次发起跨域访问,浏览器直接跳过跨域合法性检查阶段。从而提升性能。例:

@CrossOrigin(origins = "http://xxx.com", maxAge = 3600)		maxAge单位为秒,即3600秒

        当然因为在实际中,前后端交互会涉及很多的服务和接口。如果一个服务一个服务,一个接口一个接口,一个控制类一个控制类的,去加@CrossOrigin,去各种配置,写CorsConfiguration类的话,会很麻烦,不便于统一管理。因此,我们可以统一在网关这层进行全局跨域规则配置。统一管理所有后端服务的跨域配置。

        我这里给一个简单的网关跨域yml配置。详细的配置方法可以参考一下文档:Spring Cloud Gateway 中文文档 或者问一下AI。

spring:cloud:gateway:globalcors:cors-configurations:'[/**]':allowed-origin-patterns: '*'  #允许所有的跨域allowed-headers: '*'  #允许所有的头allowed-methods: '*'  #允许所有的请求方式

5、总结

        其实SpringCloud Gateway网关的核心就是:路由、断言、过滤器。路由就是告诉网关该转发到哪个对应的后端服务上,断言就是转发规则,过滤器就是对请求api的过滤,比如前端调用后端接口,都会加一个/api前缀用于区分接口的类型(普通接口、feign接口)。但是在写后端接口时,通常不会在Controller里面@RequestMapping上加上/api,因此需要配置过滤器,网关转发请求时,把前缀去掉。网关通常可以用于身份认证。利用网关进行身份认证有两种方式:一种是在网关层直接校验token,另一种是网关将认证请求转发到专门的鉴权服务,由专门的鉴权服务校验token,并把校验结果返回网关,如果有权限,则网关再转发到相应的后端服务上。

        网关直接校验token(推荐使用这种)

 

        网关转发给鉴权服务校验token(比较复杂)

 

        微服务之间的调用,默认是不经过网关的。直接去注册中心,找到要调用的服务在哪里就行了,通过feign调用。

        微服务之间的调用,也是可以经过网关的。虽然从技术上可以实现微服务之间调用经过网关,但是实际中不建议经过网关,网关是对接前端的,后端之间的微服务调用,直接调用就行了,使用feign调用。这样还省了一层路径。除非外部后端系统要调用你这个服务的接口,最好加一层网关,进行身份认证。

        在典型的微服务架构中,无论是前端的请求,还是后端对前端请求的响应,都必须经过网关。

         为什么不能绕过网关?

6、参考资料

63、Gateway - 总结哔哩哔哩bilibili

基于Eureka的网关服务(gateway)配置-CSDN博客

SpringCloud微服务中gateway网关的使用(一)——(介绍+gateway与zuul的区别+gateway实现的两种方式)_SpringCloud-CSDN专栏

springcloud-eureka与gateway简易搭建_gateway注册到eureka-CSDN博客

网关 GateWay 的使用详解、路由、过滤器、跨域配置_gateway配置路由转发-CSDN博客

注解@CrossOrigin解决跨域问题 - 淼淼之森 - 博客园

文心一言

DeepSeek - 探索未至之境

 

相关文章:

SpringCloud GateWay网关

1、网关介绍 微服务网关&#xff08;Microservices Gateway&#xff09;是微服务架构中的核心组件&#xff0c;充当所有客户端请求的统一入口&#xff0c;负责请求的路由、过滤和聚合等操作。它是微服务与外部系统&#xff08;如Web、移动端&#xff09;之间的中间层&#xff0…...

可视化大屏开发全攻略:技术与实践指南

引言 在数字化浪潮席卷全球的当下&#xff0c;数据已成为企业乃至整个社会发展的核心驱动力。从繁华都市的交通管控中心&#xff0c;到大型企业的数据运营中枢&#xff0c;可视化大屏无处不在&#xff0c;以直观、震撼的方式展示着数据的魅力与价值。它就像是一扇通往数据世界…...

如何设计一个为QStackWidget的界面切换动画?

目录 前言 接口考虑 实现的思路 前言 笔者这段时间沉迷于给我的下位机I.MX6ULL做桌面&#xff0c;这里抽空更新一下QT的东西。这篇文章是跟随CCMoveWidget一样的文章&#xff0c;尝试分享自己如何书写这份代码的思考的过程 接口考虑 笔者不太想使用继承的方式重新写我们的…...

LeetCode 0790.多米诺和托米诺平铺:难想条件的简单动态规划

【LetMeFly】790.多米诺和托米诺平铺&#xff1a;难想条件的简单动态规划 力扣题目链接&#xff1a;https://leetcode.cn/problems/domino-and-tromino-tiling/ 有两种形状的瓷砖&#xff1a;一种是 2 x 1 的多米诺形&#xff0c;另一种是形如 "L" 的托米诺形。两种…...

模拟芯片设计中数字信号处理一些常用概念(一)

模拟芯片设计中经常用时域场景思考来解决问题,但实际上很多地方如果采用频域角度思考,解决问题更快更方便。 时域和频域的对照关系如下: a、如果时域信号是周期的,那么它的频谱就是离散的。 b、如果时域信号是非周期的,那么它的频谱就是连续的。 c、如果时域信号是离散的…...

c++进阶——AVL树主要功能的模拟实现(附带旋转操作讲解)

文章目录 AVL树的实现AVL树的概念及引入AVL树调整问题AVL树的实现AVL树的结构AVL树的插入插入的流程更新平衡因子的原则实现插入的基本框架(插入 调整平衡因子)旋转操作右单旋左单旋左右双旋右左双旋 合并旋转代码 测试部分平衡检测接口测试用例 对于其他接口的说明 AVL树的实…...

一个电商场景串联23种设计模式:创建型、结构型和行为型

理解了&#xff01;你希望有一个具体的项目案例&#xff0c;能够涵盖所有23种设计模式&#xff0c;并且将它们分类为创建型、结构型和行为型。这个需求非常好&#xff0c;能够帮助你从实际的应用场景理解每种设计模式的用法。 为了实现这个目标&#xff0c;我将为你设计一个电…...

浅拷贝和深拷贝的区别

Person p1 new Person(10);Person p2 p1;p2.age 20;System.out.println(p1p2); // trueSystem.out.println(p1.age); // 20 这种做法只是复制了对象的地址&#xff0c;即两个变量现在是指向了同一个对象&#xff0c;任意一个变量&#xff0c;操作了对象的属性&#xff0c;都…...

Java开发者面试实录:微服务架构与Spring Cloud的应用

面试场景 面试官: 请介绍一下你的基本情况。 程序员: 大家好&#xff0c;我叫张小明&#xff0c;今年27岁&#xff0c;硕士学历&#xff0c;拥有5年的Java后端开发经验。主要负责基于Spring Boot开发企业级应用&#xff0c;以及微服务架构的设计和实现。 面试官: 好的&#…...

在Ubuntu系统中安装桌面环境

在 Ubuntu 系统中安装桌面环境可以通过包管理器 apt 或工具 tasksel 实现。以下是详细的安装方法和常见桌面环境的选择&#xff1a; --- ### **1. 准备系统更新** 在安装前&#xff0c;建议更新软件源和系统包&#xff1a; bash sudo apt update && sudo apt upgrade…...

多语言笔记系列:Polyglot Notebooks 中使用 xUnit 单元测试

Polyglot Notebooks 中使用 xUnit 单元测试 本文目录 Polyglot Notebooks 中使用 xUnit 单元测试[TOC](本文目录)Polgylot Notebooks 并没有直接支持单元测试框架。不能像VS里那样方便的进行单元测试。简单远行的话&#xff0c;可以使用下面的方案&#xff01;1、引入必要的NuG…...

Cisco Packet Tracer 选项卡的使用

目录 设备Config选项卡的使用 Realtime and Simulation模式&#xff08;数据包跟踪与分析&#xff09; 设备Desktop选项卡的使用 设备Config选项卡的使用 Hostname NVRAM Startup Config----Load 加载 INTERFACE 点击on Save 如果&#xff0c;不把Running Config保存为Sta…...

杨校老师竞赛课之C++备战蓝桥杯初级组省赛

目录 1. 灯塔 题目描述 输入描述 输出描述 输入样例1 输出样例1 输入样例2 输出样例2 数据说明 2. 子区间 题目描述 输入描述 输出描述 输入样例 输出样例 数据说明 3. 染色 题目描述 输入描述 输出描述 输入样例1 输出样例1 输入样例2 输出样例2 数据…...

gcc/g++用法摘记

链接静态库 gcc main.o -L/path/to/libs -lmylib -o myprogram 【待续】...

kotlin 扩展函数

Kotlin 扩展函数的定义与使用 定义扩展函数 Kotlin 的扩展函数是一种强大的机制&#xff0c;允许开发者为已有的类添加额外的功能&#xff0c;而无需继承该类或对其进行任何修改。这种特性极大地提高了代码的灵活性和可读性。 扩展函数可以通过在函数名称前指定目标类型的接…...

机器人强化学习入门学习笔记

(1)物理引擎 物理引擎就是模拟真实世界物理规律的软件工具。它会根据你给定的物体、质量、形状、力等信息,计算这些物体在时间上的运动和相互作用。如果你设计了一个机器人,那物理引擎就是“虚拟现实世界”,让机器人在里面“活起来”,模拟它走路、抓东西、摔倒等动作。而…...

《RESTful API版本控制的哲学思辨:稳定性与创新性的终极平衡》

有效的版本控制&#xff0c;就如同精密仪器中的校准装置&#xff0c;确保API在不断升级的过程中&#xff0c;依然能与旧有系统无缝对接&#xff0c;维持整个生态的平稳运行。 不同的客户端对API的依赖程度和使用方式各不相同。有些客户端可能因为各种原因&#xff0c;无法及时…...

spring中spring-boot-configuration-processor的使用

spring-boot-configuration-processor 是 Spring Boot 提供的注解处理器&#xff0c;用于在编译阶段生成配置元数据文件&#xff08;spring-configuration-metadata.json&#xff09;&#xff0c;从而优化开发体验。以下是其核心功能和使用指南&#xff1a; 一、核心功能 IDE 智…...

30天开发操作系统 第27天 -- LDT与库

前言 大家早上好&#xff0c;我们今天的第一个任务就是修复昨天晚上的那个bug。是个什么bug来着&#xff1f;就是用nsct命令运行的应用程序&#xff0c;无论是按ShiftF1还是点击窗口的“x”按钮都没有反应的那个bug啦。 我们得先来找到出问题的原因&#xff0c;然后才能采取对…...

std::move()详解

一、std::move()的作用和原理 本质&#xff1a; std::move()并不像字面意思“搬走”那些对象&#xff0c;而是&#xff1a; 将传入的对象“强制转化”为右值引用类型&#xff0c;从而开启“移动语义”。 在源码层面&#xff1a; 复制代码 template<typename T> std::…...

linux系统基本操作命令

文件和目录操作 ls&#xff1a;列出目录内容。 例如&#xff1a;ls -l 显示详细信息&#xff0c;ls -a 显示包括隐藏文件在内的所有文件。 cd&#xff1a;改变当前目录。 例如&#xff1a;cd /home/username 切换到指定目录。 pwd&#xff1a;显示当前目录的完整路径。 mk…...

python打卡day16

NumPy 数组基础 因为前天说了shap&#xff0c;这里涉及到数据形状尺寸问题&#xff0c;所以需要在这一节说清楚&#xff0c;后续的神经网络我们将要和他天天打交道。 知识点&#xff1a; numpy数组的创建&#xff1a;简单创建、随机创建、遍历、运算numpy数组的索引&#xff1a…...

架构进阶:什么是数据架构,如何理解数据架构?(华为)

数据架构是企业架构的重要组成部分,DAMA、IBM 及国内大厂对其定义各有侧重。它包含数据资产目录、数据标准、数据模型和数据分布四个组件。数据资产目录可梳理企业数据资产,数据标准统一数据含义和规则,数据模型反映业务对象关联关系,数据分布呈现数据流动情况。数据架构是…...

基于EFISH-SCB-RK3576工控机/SAIL-RK3576核心板的KTV点歌主机技术方案‌(国产化替代J1900的全场景技术解析)

‌一、硬件架构设计‌ ‌多媒体处理模块‌ ‌超高清解码‌&#xff1a; RK3576 NPUGPU协同解码&#xff0c;支持4K60fps H.265硬解&#xff08;功耗<5W&#xff09;&#xff0c;支持8路1080P视频同步预览对比J1900需外接VPU解码芯片&#xff0c;硬件成本降低40%&#xff0c;…...

Java面试深度解密:Spring Boot、Redis、日志优化、JUnit5及Kafka事务核心技术解析

模拟面试实战 面试官&#xff1a;请解释Spring Boot的自动配置原理&#xff1f;哪些关键注解参与了这一过程&#xff1f; xbhog&#xff1a;Spring Boot通过AutoConfiguration标记核心配置类&#xff0c;通过ConditonalOnClass和ConditionalOnMissingBean判断依赖是否存在并自…...

内存碎片深度剖析

目录 什么是内存碎片 内部碎片的解决 malloc STL二级空间配置器 外部碎片的解决 伙伴系统算法 slab分配器 什么是内存碎片 内存碎片是指在内存中存在的一些不连续的、较小的空闲内存块&#xff0c;这些小块内存由于太小而无法被有效地分配给程序使用&#xff0c;从而导…...

飞帆网页中使用 i 评论插件

https://fvi.cn/786...

DeepSeek成本控制的三重奏

知识蒸馏 使用规则引擎筛选合成数据&#xff0c;来替代90%的人工标注 动态精度切换&#xff1a;“节能模式” 根据任务复杂度自动切换FP16/INT8精度&#xff0c;单位token能耗低至0.0028瓦时&#xff0c;推理电费成本降低82% 极致压缩训练 通过以上的技术&#xff0c;降低训练…...

五一の自言自语 2025/5/5

今天开学了&#xff0c;感觉还没玩够。 假期做了很多事&#xff0c;弄了好几天的路由器、监控、录像机&#xff0c;然后不停的出现问题&#xff0c;然后问ai&#xff0c;然后解决问题。这次假期的实践&#xff0c;更像是计算机网络的实验&#xff0c;把那些交换机&#xff0c;…...

效整理文件信息!一键生成文件夹目录的工具

一、软件介绍 大家好&#xff0c;今天给大家推荐一款实用的文件夹目录生成工具&#xff0c;它能快速提取文件夹内的文件信息&#xff0c;并整理成Excel表格&#xff0c;包含文件名、路径、类型、创建/修改时间、大小等关键数据。 为什么需要这个工具&#xff1f; 之前我想整理…...

关闭ollama开机自启动

不同操作系统关闭Ollama开机自启动的方法有所不同&#xff0c;以下是常见操作系统的具体方法&#xff1a; Windows系统 通过任务管理器&#xff1a;按Ctrl Shift Esc打开任务管理器&#xff0c;切换到“启动”选项卡&#xff0c;在列表中找到Ollama&#xff08;或相关条目&a…...

2025 年最新树莓派 Pico 连接 ESP8266 模块实现 WiFi 通信、搭建 TCP 服务器实现数据交互详细教程

AT 指令基本结构概述 AT 指令最初由 Hayes 公司为其调制解调器&#xff08;modem&#xff09;开发&#xff0c;目的是提供一种标准化的方式来控制通信设备。最早的 Hayes Smartmodem 300 调制解调器&#xff08;1981年&#xff09;引入了这一指令集&#xff0c;因此 AT 指令也…...

java类=null的回收

在Java&#xff08;或类似使用垃圾回收的语言&#xff09;中&#xff0c;当你执行 a null 后&#xff0c;对象 B() 是否会被回收取决于是否还有其他引用指向它。具体分析如下&#xff1a; 关键点&#xff1a; 引用链分析&#xff1a; 初始时&#xff1a;a 引用了 A 实例&#…...

2025系统架构师---论面向对象的软件设计

摘要 自“软件危机”出现过后&#xff0c;工程化软件开发方法不断发展&#xff0c;采用什么方法对大 规模软件进行设计并保证软件的质量。在这样背景下&#xff0c;人们开始从面向数据流过 程开发法中不断思考&#xff0c;进而引入对象的概念。对象是数据与行为的封装&#…...

如何判断node节点是否启用cgroup?

要判断 Linux 节点是否启用了 cgroup&#xff08;Control Groups&#xff09;&#xff0c;可以通过以下方法验证&#xff1a; 方法 1&#xff1a;检查 /proc/cgroups 文件 查看内核支持的 cgroup 子系统列表&#xff1a; cat /proc/cgroups 输出说明&#xff1a; 若文件不存…...

学习黑客Nmap 实战

金丹期第三重 — Debian 12 实战&#xff1a;Nmap 全流程探秘 testhtml5.vulnweb.com 晋阶宣言 本章彻底补完前面“只扫到 80/443 却没识别 nginx 版本”的缺憾。 道友将依次完成 快速侦查 → 深度洞察 → NSE 弱点扫描 三连招&#xff0c;并学会用 -sV、-Pn、--script-trace 等…...

AD创建元件符号

在创建好工程文档之后打开SCH Library 创建工程的方法&#xff1a;AD创建一个工程文档-CSDN博客 这里以创建一个电容符号为例子&#xff0c;先创建引脚&#xff0c;画引脚的时候要把网格尺寸设置为100mil AD原理图怎么改网格尺寸-CSDN博客 放置好引脚之后绘制元素&#xff0…...

第六章:6.1 ESP32教学:多任务处理与FreeRTOS实战

一、FreeRTOS简介 ESP32内置了FreeRTOS实时操作系统内核&#xff0c;这是一个专为嵌入式系统设计的开源实时操作系统。它支持&#xff1a; 多任务并行处理 任务优先级管理 内存管理 任务间通信 定时器管理 二、任务创建与管理 1. 任务创建&#xff08;xTaskCreate&…...

Python生活手册-正则表达式:从快递单到咖啡订单的文本魔法

一、快递单号识别术&#xff08;基础匹配&#xff09; 1. 数字猎人&#xff08;\d&#xff09; 想象你有一叠快递单需要自动识别&#xff1a; import re快递单 "【顺丰】单号&#xff1a;SF123456789 签收人&#xff1a;张先生" 单号 re.search(r"SF\d&quo…...

Windows 自带删除缓存

Temp临时文件文件夹手动除 Windows键R 快速打开运行输入%temp%,其下所有文件删除 打开储存感知 打开「设置」→「系统」→「存储」&#xff0c;点击右侧面板中的「配置存储感知或立即运行」。将弹出页拉至最下方&#xff0c;勾选其中的「删除以前版本的 Windows」&#xff0c;再…...

Linux电源管理(6)_Generic PM之挂起功能

原文链接&#xff1a;Linux电源管理&#xff08;6&#xff09;_Generic PM之挂起功能 1.前言 Linux内核提供了三种暂停方式&#xff1a;Freeze&#xff0c;Standby和STR&#xff08;暂停到RAM&#xff09;&#xff0c;在用户空间向” / sys / power / state”文件分别写入“ …...

MCP原理详解及实战案例(动嘴出UI稿、3D建模)

文章目录 MCP 原理介绍架构核心组件协议层传输层连接生命周期MCP与function calling: 互补关系 MCP python SDKMCP的优点 怎么用MCP&#xff1a;天气服务参考应用项目&#xff1a; REF 24年11月份&#xff0c;claude推出了模型上下文协议( MCP),作为一种潜在的解决方案&#xf…...

【Java项目脚手架系列】第二篇:JavaWeb项目脚手架

【Java项目脚手架系列】第二篇&#xff1a;JavaWeb项目脚手架 前言 在Java Web开发中&#xff0c;一个好的项目脚手架可以大大提高开发效率&#xff0c;减少重复工作。本篇文章将介绍一个基于Maven的JavaWeb项目脚手架&#xff0c;它包含了基础的Web开发配置和常用功能。 什…...

【机器学习-线性回归-5】多元线性回归:概念、原理与实现详解

线性回归是机器学习中最基础且广泛应用的算法之一&#xff0c;而多元线性回归则是其重要扩展。本文将全面介绍多元线性回归的核心概念、数学原理及多种实现方式&#xff0c;帮助读者深入理解这一强大的预测工具。 1. 多元线性回归概述 1.1 什么是多元线性回归 多元线性回归(…...

《TCP/IP详解 卷1:协议》之第十章:动态选路协议

目录 一、常见的动态路由协议 二、RIP 1、RIP 版本1&#xff1a; 1.1、报文格式 2、RIP 版本2&#xff1a; 2.1、报文格式 三、OSPF 1、链路状态路由协议 2、工作原理 3、OSPF的特点 四、BGP 五、参考链接 一、常见的动态路由协议 路由协议&#xff08;Routing Pr…...

逆向常见题目—迷宫类题目

逆向常见题目—迷宫类题目 迷宫(maze) 思路&#xff1a; 1.找到地图(字符串) 2.找到方向(上左下右) 3.找到起点到终点 然后将路径输出即可 特征: 标题,hint为maze 或者 看到字符串###等等 整理字符串为图形.py (要是不是正方形需要自己输出行和列) import mathdef arra…...

Redis 数据类型详解(二):Hash 类型全解析

文章目录 一、什么是 Redis 的 Hash 类型&#xff1f;二、Hash为什么在有些时候比String好用三、常见命令1.HSET key field value2.HGET key field3.HMSET4.HMGET5.HGETALL6.HKEYS7.HVALS8.HINCRBY9.HSETNX 四、应用场景五、性能优势六、注意事项总结 提示&#xff1a;以下是本…...

Vite简单介绍

Vite 是一个现代化的前端构建工具&#xff0c;由 Vue.js 的创始人 Evan You 开发&#xff0c;旨在提供更快的开发体验和更高效的构建流程。它的名字来源于法语单词“vite”&#xff0c;意为“快速”&#xff0c;这也反映了它的核心优势——极速的冷启动和热模块替换&#xff08…...

jwt身份验证和基本的利用方式

前言 &#xff1a; 什么是jwt&#xff08;json web token&#xff09;&#xff1f; 看看英文单词的意思就是 json形式的token 他的基本的特征 &#xff1a; 类似于这样的 他有2个点 分割 解码的时候会有三个部分 头部 payload 对称密钥 这个就是对称加密 头部&am…...

基于YOLOv的目标检测训练数据构建方法研究—图像采集、标注、划分与增强一体化流程设计

在目标检测任务中&#xff0c;高质量的训练数据是模型性能提升的关键。本文围绕 YOLOv 系列模型&#xff0c;系统性地研究了目标检测训练数据的构建方法&#xff0c;提出了一套从图像采集、标注、数据集划分到数据增强的一体化流程设计 。通过多源图像采集策略确保样本多样性&a…...