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

Netty实现数据上下行

Netty实现数据上下行

使用LVS+NGinx+Netty实现数据接入
在数据上行的时候,通过使用车辆唯一标识码(vin)和连接通道绑定

Netty一些配置参数如下:

#netty项目使用的端口
server.port=8017
#使用启用epoll(在Linux上拥有更好的传输性能)
netty.server.use-epoll=true
#netty项目监听的两个端口
netty.server.port1=8035
netty.server.port2=8055# 使用plunlog 查看运行日志,需要和plumelog服务端的redis配置一致
plumelog.appName=netty
plumelog.redisHost=xxx.xx.xxx.xx:xxxx
plumelog.redisAuth=
plumelog.redisDb=0#Spring boot admin Client
management.endpoints.web.exposure.include=*:
#这个配置项用于控制哪些Actuator端点应该通过Web接口暴露。*表示暴露所有端点。这包括健康检查、环境信息、度量信息等。在生产环境中,你可能需要根据需要暴露特定的端点,而不是全部暴露,以提高安全性。
management.endpoint.health.show-details=always:
#这个配置项用于控制健康端点(/actuator/health)返回的细节级别。always表示总是显示详细的健康信息,包括所有子系统的健康状态。其他选项包括never(不显示任何细节)和when-authorized(在授权用户请求时显示细节)。这有助于监控和诊断应用的健康状态。
management.health.redis.enabled=false:
#这个配置项用于控制是否将Redis的健康检查包含在应用的整体健康检查中。设置为false表示不将Redis的健康状态作为应用健康状态的一部分。这在你不想或不需要监控Redis服务状态时很有用。
management.server.port=8109:
#这个配置项用于设置管理端点的端口。默认情况下,管理端点(Actuator端点)与主应用共享相同的端口。但你可以通过此配置将它们分离到不同的端口上,以便更好地管理和监控。在这个例子中,管理端点被配置为监听8109端口。
spring.boot.admin.client.url=http://xxx.xx.xxx.xx:xxxx:
#这个配置项用于指定Spring Boot Admin服务器的URL。Spring Boot Admin是一个用于管理和监控Spring Boot应用的工具。通过此配置,你的Spring Boot应用可以注册到Spring Boot Admin服务器,从而允许你通过Web界面监控和管理应用。你需要将xxx.xx.xxx.xx:xxxx替换为实际的Spring Boot Admin服务器地址和端口。
spring.boot.admin.client.instance.prefer-ip=true:
这个配置项用于控制在Spring Boot Admin中注册应用实例时,是否优先使用IP地址而不是主机名。设置为true表示使用IP地址。这有助于在DNS解析可能存在问题或延迟时,确保Spring Boot Admin能够准确地识别和管理应用实例。

1、Handler

Netty的Handler 提供了一系列对数据的处理方法,与登录handle与数据处理handle分开。

在登陆成功后移除登陆handle

            if ("01".equals(logMsg) || "C2".equals(logMsg)) {boolean loginCheck = redisTemplateNew.exists(vinAsc);StringBuilder loginMsg = new StringBuilder(decryptData);if (!loginCheck) {//上报时间;发送登陆失败的kafka消息String dateSend = getDate16();kafkaTemplate.send("sendFailNS", kafkaKey, dateSend + decryptData);log.error(vinAsc + " loginFail");} else {//登陆成功标识loginMsg.replace(6, 8, "01");//把vin码做绑定channelActive(ctx);String clientId = vinAsc.trim();ChannelStore.bind(ctx, clientId);           }//加密回复报文String encryptData = commonUntils1.getEncryptRSA(loginMsg, vinAsc);byte[] odls = ByteBufUtil.decodeHexDump(encryptData);ctx.writeAndFlush(Unpooled.wrappedBuffer(odls));if (!loginCheck) {//关闭连接  `channelInactive(ctx);ctx.channel().close();} else {//移除鉴权ctx.pipeline().remove(this);}//上报时间String dateSend = getDate16();if ("01".equals(logMsg)) {kafkaTemplate.send("sendLAFS", kafkaKey, dateSend + decryptData);} else if ("C2".equals(logMsg)) {kafkaTemplate.send("sendLAFS", kafkaKey, dateSend + decryptData);}}

2、调用下行API

因为Netty服务器是集群,会把客户端的唯一标识符和连接服务器的地址存在数据库里,在平台调用下行命令时,先找到netty连接的服务器。

    /*** 发送消息的控制器方法。** @param downVO 包含消息详情的请求体对象,包括VIN(车辆识别码)、类型(设防、解防、启动指令等)和流水号。* @return 返回一个响应实体,包含消息发送的状态码和描述。* @throws Exception 如果校验失败或发送消息时遇到异常,则抛出异常。*/@PostMapping(value = "/sendMsg")public ResponseEntity<String> sendMSg(@RequestBody DownVO downVO) throws Exception {// 校验VINif (StringUtils.isBlank(downVO.getVin())) {ApiResponse apiResponse = new ApiResponse(400, "VIN参数不合法");return new ResponseEntity(apiResponse, HttpStatus.BAD_REQUEST);}// 校验类型if (StringUtils.isBlank(downVO.getType()) || !"1".equals(downVO.getType()) && !"2".equals(downVO.getType()) && !"3".equals(downVO.getType())) {ApiResponse apiResponse = new ApiResponse(400, "远控类型参数不合法");return new ResponseEntity(apiResponse, HttpStatus.BAD_REQUEST);}// 校验流水号if (StringUtils.isBlank(downVO.getSerialNumber()) || downVO.getSerialNumber().length() != 16) {ApiResponse apiResponse = new ApiResponse(400, "流水号参数不合法");return new ResponseEntity(apiResponse, HttpStatus.BAD_REQUEST);}try {log.info(downVO.getVin() +" 下行命令:" + downVO.getVin() + ", " + downVO.getType() + ", " + downVO.getSerialNumber());String remoteMsg = getRemoteData(downVO.getVin(), downVO.getType(), downVO.getSerialNumber());Channel channel = ChannelStore.getChannel(downVO.getVin());log.info(downVO.getVin() + " 下行通道:" + channel + "  下行组装消息:" + remoteMsg);// 连接状态if ((channel == null) || !channel.isActive()) {log.error(downVO.getVin() +" 555连接已断开:" + redisTemplateNew.get(downVO.getVin()+"_IP"));redisTemplateNew.delete(downVO.getVin()+"_IP");ApiResponse apiResponse = new ApiResponse(555, "连接已断开");return new ResponseEntity(apiResponse, HttpStatus.BAD_REQUEST);}log.error( downVO.getVin() +" 消息发送成功:" +   downVO.getType() + ", " + downVO.getSerialNumber());byte[] odls = ByteBufUtil.decodeHexDump(remoteMsg);channel.writeAndFlush(Unpooled.wrappedBuffer(odls));ApiResponse apiResponse = new ApiResponse(200, "消息发送成功");return new ResponseEntity(apiResponse, HttpStatus.OK);} catch (Exception e) {// 处理异常,返回错误信息String errorMessage = "消息发送失败: " + e.getMessage();log.error(downVO.getVin() +" 消息发送失败:" +  e.getMessage());return new ResponseEntity(new ApiResponse(500, errorMessage), HttpStatus.INTERNAL_SERVER_ERROR);}}

3、任务监控

日志使用pumelog查看

<?xml version="1.0" encoding="UTF-8"?><configuration scan="true" scanPeriod="60 seconds" debug="false">    <!-- 日志存放路径 -->   <property name="log.path" value="logs/bi-veos" />   <!-- 日志输出格式 -->   <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%X{traceId}][%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />    <!-- 控制台输出 -->   <appender name="console" class="ch.qos.logback.core.ConsoleAppender">      <encoder>         <pattern>${log.pattern}</pattern>      </encoder>   </appender>    <!-- 系统日志输出 -->   <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">       <file>${log.path}/info.log</file>        <!-- 循环政策:基于时间创建日志文件 -->      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">            <!-- 日志文件名格式 -->         <fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>         <!-- 日志最大的历史 30天 -->         <maxHistory>30</maxHistory>      </rollingPolicy>      <encoder>         <pattern>${log.pattern}</pattern>      </encoder>      <filter class="ch.qos.logback.classic.filter.LevelFilter">            <!-- 过滤的级别 -->            <level>INFO</level>            <!-- 匹配时的操作:接收(记录) -->            <onMatch>ACCEPT</onMatch>            <!-- 不匹配时的操作:拒绝(不记录) -->            <onMismatch>DENY</onMismatch>        </filter>   </appender>    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">       <file>${log.path}/error.log</file>        <!-- 循环政策:基于时间创建日志文件 -->        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">            <!-- 日志文件名格式 -->            <fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>         <!-- 日志最大的历史 30天 -->         <maxHistory>30</maxHistory>        </rollingPolicy>        <encoder>            <pattern>${log.pattern}</pattern>        </encoder>        <filter class="ch.qos.logback.classic.filter.LevelFilter">            <!-- 过滤的级别 -->            <level>ERROR</level>         <!-- 匹配时的操作:接收(记录) -->            <onMatch>ACCEPT</onMatch>         <!-- 不匹配时的操作:拒绝(不记录) -->            <onMismatch>DENY</onMismatch>        </filter>    </appender>    <!-- 环境配置 -->    <springProperty scope="context" name="plumelog.appName" source="plumelog.appName"/>    <springProperty scope="context" name="plumelog.redisHost" source="plumelog.redisHost"/>    <springProperty scope="context" name="plumelog.redisAuth" source="plumelog.redisAuth"/>    <springProperty scope="context" name="plumelog.redisDb" source="plumelog.redisDb"/>    <springProperty scope="context" name="plumelog.env" source="spring.profiles.active"/>    <!-- plumelog -->    <appender name="plumelog" class="com.plumelog.logback.appender.RedisAppender">        <appName>${plumelog.appName}</appName>        <redisHost>${plumelog.redisHost}</redisHost>        <redisAuth>${plumelog.redisAuth}</redisAuth>        <redisDb>${plumelog.redisDb}</redisDb>        <env>${plumelog.env}</env>    </appender><!--    &lt;!&ndash; 系统模块日志级别控制  &ndash;&gt;--><!--   <logger name="com.chery.bi.modules.veos" level="warn" />--><!--   &lt;!&ndash; Spring日志级别控制  &ndash;&gt;--><!--   <logger name="org.springframework" level="warn" />-->    <!--系统操作日志-->    <root level="info">        <appender-ref ref="console" />        <appender-ref ref="file_info" />        <appender-ref ref="file_error" />        <appender-ref ref="plumelog"/>    </root></configuration>

任务监控 使用springbootadmin查看

只需要在pom中引入依赖,配置如开始所示

   <dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-client</artifactId><version>2.7.3</version></dependency><!-- actuator start--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><artifactId>logback-classic</artifactId><groupId>ch.qos.logback</groupId></exclusion></exclusions></dependency>

新建spring boot server项目 并配置邮件告警
在这里插入图片描述

Spring Boot应用名称和端口
spring.application.name=nettyAdminServer:设置Spring Boot应用的名称为nettyAdminServer,这个名称在Spring Boot Admin或其他服务发现机制中很重要,用于识别和区分不同的服务。
server.port=8110:设置应用监听的端口号为8110。
健康检查细节
management.endpoint.health.show-details=always:配置健康检查端点以总是显示详细信息。这有助于在监控和诊断时获取更多关于应用健康状态的信息。
邮件配置
spring.mail.smtp.auth=true:启用SMTP认证。
spring.mail.properties.mail.smtp.ssl.trust=${spring.mail.host}:设置SMTP SSL/TLS连接的信任主机为spring.mail.host配置的值,即smtp.feishu.cn。这有助于建立安全的邮件连接。
spring.mail.properties.mail.smtp.ssl.enable=true:启用SMTP连接的SSL/TLS加密。
spring.mail.host=smtp..cn:设置SMTP服务器的主机名为smtp..cn,即SMTP服务器。
spring.mail.username和spring.mail.password:分别设置SMTP服务器的登录用户名和密码,用于认证。
spring.mail.port=465:设置SMTP服务器的端口号为465,这是SMTPS(SMTP over SSL)的标准端口。
Spring Boot Admin邮件通知
spring.boot.admin.notify.mail.to和spring.boot.admin.notify.mail.from:分别设置Spring Boot Admin发送邮件通知的收件人和发件人地址
Spring Boot Admin忽略的变更
spring.boot.admin.notify.discord.ignore-changes={"UNKNOWN:UP","OFFLINE:UP"}:这个配置项实际上与Discord通知相关,但配置中提到了spring.boot.admin.notify.discord,而你的配置环境看起来并没有启用Discord通知。不过,这里的意思是配置Spring Boot Admin在哪些状态变更时不发送Discord通知,比如从UNKNOWN到UP或从OFFLINE到UP
spring.application.name=nettyAdminServer
server.port=8110
management.endpoint.health.show-details=alwaysspring.mail.smtp.auth=true
spring.mail.properties.mail.smtp.ssl.trust=${spring.mail.host}
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.host=smtp.cn
spring.mail.username=
spring.mail.password=
spring.mail.port=465
spring.boot.admin.notify.mail.to=
spring.boot.admin.notify.mail.from=
spring.boot.admin.notify.discord.ignore-changes={"UNKNOWN:UP","OFFLINE:UP"}

Spring bootadmin监控界面

在这里插入图片描述

在这里插入图片描述

相关文章:

Netty实现数据上下行

Netty实现数据上下行 使用LVSNGinxNetty实现数据接入 在数据上行的时候&#xff0c;通过使用车辆唯一标识码&#xff08;vin&#xff09;和连接通道绑定 Netty一些配置参数如下: #netty项目使用的端口 server.port8017 #使用启用epoll&#xff08;在Linux上拥有更好的传输性…...

【React】事件绑定:深入解析高效处理用户交互的最佳实践

文章目录 一、什么是事件绑定&#xff1f;二、基本事件绑定三、绑定 this 上下文四、传递参数五、事件对象六、事件委托七、常见事件处理八、优化事件处理 React 是现代前端开发中最受欢迎的框架之一&#xff0c;其组件化和高效的状态管理能力使得构建复杂的用户界面变得更加容…...

SpringCloud:使用OpenFeign优化前面的Nacos实现高效购物车商品信息处理

在现代电商系统中&#xff0c;购物车的性能直接影响用户的购物体验。为了提升系统性能和用户满意度&#xff0c;我们可以使用Spring Cloud的OpenFeign和负载均衡器来高效地处理购物车中的商品信息。本文将详细介绍如何在Spring Cloud中集成这些组件&#xff0c;并实现一个高效的…...

计算机三级嵌入式笔记(二)——嵌入式处理器

目录 考点1 嵌入式处理器的结构类型 考点2 嵌入式处理器简介 考点3 ARM处理器概述 考点4 处理器和处理器核 考点5 ARM 处理器的分类 考点6 经典 ARM 处理器 考点7 ARM Cortex 嵌入式处理器 考点8 ARM Cortex实时嵌入式处理器 考点9 ARM Cortex 应用处理器 考点10 AR…...

【GoLang】Golang 快速入门(第一篇)

目录 1.简介&#xff1a; 2.设计初衷&#xff1a; 3.Go语言的 特点 4.应用领域: 5.用go语言的公司&#xff1a; 6. 开发工具介绍以及环境搭建 1.工具介绍: 2.VSCode的安装: 3.安装过程&#xff1a; 4.Windows下搭建Go开发环境--安装和配置SDK 1.搭建Go开发环境 - 安装…...

Linux中的三类读写函数

文件IO和标准IO的区别 遵循标准&#xff1a; 文件IO遵循POSIX标准&#xff0c;主要在类UNIX环境下使用。标准IO遵循ANSI标准&#xff0c;具有更好的可移植性&#xff0c;可以在不同的操作系统上重新编译后运行。可移植性&#xff1a; 文件IO的可移植性相对较差&#xff0c;因为…...

MATLAB基础应用精讲-【数模应用】二元Probit回归分析

目录 前言 知识储备 二元Logistic模型和Probit模型 Logistic模型的形式 Probit模型 优势比(OR) 准二项分布族 算法原理 数学模型 二元因变量和线性概率模型 probit和logit回归 logit和probit模型的估计和推断 稳健性检验 二元logit回归分析全流程 一、案例数…...

找工作准备刷题Day10 回溯算法 (卡尔41期训练营 7.24)

回溯算法今天这几个题目做过&#xff0c;晚上有面试&#xff0c;今天水一水。 第一题&#xff1a;Leetcode77. 组合 题目描述 解题思路 从题目示例来看&#xff0c;k个数是不能重合的&#xff0c;但是题目没有明确说明这一点。 使用回溯算法解决此问题&#xff0c;利用树形…...

如何有效的进行小程序的优化

如今小程序已经成为了许多开发者开展业务&#xff0c;提供服务的重要平台 。所以如何有效的优化小程序成为了开发者关注的首要问题&#xff0c;以下是一份详细的小程序优化方案&#xff1a; 一、目标设定 明确小程序优化的主要目标&#xff0c;例如提高用户留存率、增加用户活…...

FPGA-ROM IP核的使用(2)

前言 接着昨天的进行一个小的实验验证ROM IP核。 实验效果 读取上一期生成的IP核中的数据&#xff0c;并将其显示在数码管上。 具体流程 ROM IP核存放数据0~255&#xff0c;之后每隔0.2s&#xff0c;从0的地址开始读数据&#xff0c;并显示在数码管上&#xff1b;接着先后…...

Manticore Search(es轻量级替代)

概念&#xff1a; Manticore Search 是一个使用 C 开发的高性能搜索引擎&#xff0c;创建于 2017 年&#xff0c;其前身是 Sphinx Search 。Manticore Search 充分利用了 Sphinx&#xff0c;显着改进了它的功能&#xff0c;修复了数百个错误&#xff0c;几乎完全重写了代码并保…...

测试开发面试题---计算机网络

计算机网络模型 OSI模型&#xff1a;七层模型 物理层&#xff1a;定义电气特征&#xff0c;机械特征等功能规范&#xff0c;传递实际比特流数据链路层&#xff1a;物理地址寻址&#xff08;MAC&#xff09;&#xff0c;帧的传输&#xff0c;错误检测和纠正网络层&#xff1a;…...

Wonder3D 论文学习

论文链接&#xff1a;https://arxiv.org/abs/2310.15008 代码链接&#xff1a;https://github.com/xxlong0/Wonder3D 解决了什么问题&#xff1f; 随着扩散模型的提出&#xff0c;3D 生成领域取得了长足进步。从单张图片重建出 3D 几何是计算机图形学和 3D 视觉的基础任务&am…...

【MySQL进阶之路 | 高级篇】显式事务和隐式事务

使用事务有两种方式&#xff1a;显式事务和隐式事务。 1. 显式事务 步骤1&#xff1a; START TRANSACTION或者BEGIN&#xff0c;作用是显式开启一个事务。 START TRANSACTION语句相较于BEGIN特别之处在于&#xff0c;后面能跟几个修饰符。比如&#xff1a; READ ONLY&…...

Ruby、Python、Java 开发者必备:Codigger之软件项目体检

在编程的广阔天地里&#xff0c;Ruby、Python 和 Java 开发者们各自凭借着独特的语言特性&#xff0c;构建着精彩纷呈的应用世界。然而&#xff0c;无论使用哪种语言&#xff0c;确保项目的高质量始终是至关重要的目标。而 Codigger 项目体检则成为了实现这一目标的得力助手&am…...

day05 Router、vuex、axios

配置 router和vuex需要在创建vue项目的时候&#xff0c;开始的时候选择Manually select features&#xff0c;于是就可以在下一个创建配置讯问中选择router和vuex。 axios则需要执行命令行&#xff1a; npm install axios -S 之后再在需要发送请求的view导入即可。 router…...

yolov5-7在opencv里跑自己的onnx模型

先把模型放在如下目录 运行如下代码 import cv2 import numpy as npclass Onnx_clf:def __init__(self, onnx:strdnn_model1/plane02.onnx, img_size640, classlist:list[plane]) -> None: func: 读取onnx模型,并进行目标识别para onnx:模型路径img_size:输出图片大小,和模…...

JVM 11 的优化指南:如何进行JVM调优,JVM调优参数有哪些

这篇文章将详细介绍如何进行JVM 11调优&#xff0c;包括JVM 11调优参数及其应用。此外&#xff0c;我将提供12个实用的代码示例&#xff0c;每个示例都会结合JVM启动参数和Java代码。 本文已收录于&#xff0c;我的技术网站 java-broke.site&#xff0c;有大厂完整面经&#x…...

nginx的配置和使用

一、nginx支持win和linux版本的下载&#xff0c;选择合适的版本进行安装 二、配置文件注解 重点的几个参数进行注释&#xff1a; 1、listen 要监听的服务的端口&#xff0c;符合这个端口的才会被监听 server_name要监听的服务地址&#xff0c;可能是ip,也可能是域名&#xf…...

mysql面试(六)

前言 本章节详细讲解了一下mysql执行计划相关的属性释义&#xff0c;以及不同sql所出现的不同效果 执行计划 一条查询语句经过mysql查询优化器的各种基于成本和各种规则优化之后&#xff0c;会生成一个所谓的 执行计划&#xff0c;这个执行计划展示了这条查询语句具体查询方…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...

Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程

鸿蒙电脑版操作系统来了&#xff0c;很多小伙伴想体验鸿蒙电脑版操作系统&#xff0c;可惜&#xff0c;鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机&#xff0c;来体验大家心心念念的鸿蒙系统啦&#xff01;注意&#xff1a;虚拟…...

2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案

一、延迟敏感行业面临的DDoS攻击新挑战 2025年&#xff0c;金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征&#xff1a; AI驱动的自适应攻击&#xff1a;攻击流量模拟真实用户行为&#xff0c;差异率低至0.5%&#xff0c;传统规则引…...

Vue 实例的数据对象详解

Vue 实例的数据对象详解 在 Vue 中,数据对象是响应式系统的核心,也是组件状态的载体。理解数据对象的原理和使用方式是成为 Vue 专家的关键一步。我将从多个维度深入剖析 Vue 实例的数据对象。 一、数据对象的定义方式 1. Options API 中的定义 在 Options API 中,使用 …...