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><!-- <!– 系统模块日志级别控制 –>--><!-- <logger name="com.chery.bi.modules.veos" level="warn" />--><!-- <!– Spring日志级别控制 –>--><!-- <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实现数据接入 在数据上行的时候,通过使用车辆唯一标识码(vin)和连接通道绑定 Netty一些配置参数如下: #netty项目使用的端口 server.port8017 #使用启用epoll(在Linux上拥有更好的传输性…...

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

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

计算机三级嵌入式笔记(二)——嵌入式处理器
目录 考点1 嵌入式处理器的结构类型 考点2 嵌入式处理器简介 考点3 ARM处理器概述 考点4 处理器和处理器核 考点5 ARM 处理器的分类 考点6 经典 ARM 处理器 考点7 ARM Cortex 嵌入式处理器 考点8 ARM Cortex实时嵌入式处理器 考点9 ARM Cortex 应用处理器 考点10 AR…...

【GoLang】Golang 快速入门(第一篇)
目录 1.简介: 2.设计初衷: 3.Go语言的 特点 4.应用领域: 5.用go语言的公司: 6. 开发工具介绍以及环境搭建 1.工具介绍: 2.VSCode的安装: 3.安装过程: 4.Windows下搭建Go开发环境--安装和配置SDK 1.搭建Go开发环境 - 安装…...

Linux中的三类读写函数
文件IO和标准IO的区别 遵循标准: 文件IO遵循POSIX标准,主要在类UNIX环境下使用。标准IO遵循ANSI标准,具有更好的可移植性,可以在不同的操作系统上重新编译后运行。可移植性: 文件IO的可移植性相对较差,因为…...

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

找工作准备刷题Day10 回溯算法 (卡尔41期训练营 7.24)
回溯算法今天这几个题目做过,晚上有面试,今天水一水。 第一题:Leetcode77. 组合 题目描述 解题思路 从题目示例来看,k个数是不能重合的,但是题目没有明确说明这一点。 使用回溯算法解决此问题,利用树形…...

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

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

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

测试开发面试题---计算机网络
计算机网络模型 OSI模型:七层模型 物理层:定义电气特征,机械特征等功能规范,传递实际比特流数据链路层:物理地址寻址(MAC),帧的传输,错误检测和纠正网络层:…...

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

【MySQL进阶之路 | 高级篇】显式事务和隐式事务
使用事务有两种方式:显式事务和隐式事务。 1. 显式事务 步骤1: START TRANSACTION或者BEGIN,作用是显式开启一个事务。 START TRANSACTION语句相较于BEGIN特别之处在于,后面能跟几个修饰符。比如: READ ONLY&…...

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

day05 Router、vuex、axios
配置 router和vuex需要在创建vue项目的时候,开始的时候选择Manually select features,于是就可以在下一个创建配置讯问中选择router和vuex。 axios则需要执行命令行: 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调优,包括JVM 11调优参数及其应用。此外,我将提供12个实用的代码示例,每个示例都会结合JVM启动参数和Java代码。 本文已收录于,我的技术网站 java-broke.site,有大厂完整面经&#x…...

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

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

6.乳腺癌良性恶性预测(二分类、逻辑回归、PCA降维、SVD奇异值分解)
乳腺癌良性恶性预测 1. 特征工程1.1 特征筛选1.2 特征降维 PCA1.3 SVD奇异值分解 2. 代码2.1 逻辑回归、二分类问题2.2 特征降维 PCA2.3 SVD奇异值分解 1. 特征工程 专业上:30个人特征来自于临床一线专家,每个特征和都有医学内涵;数据上&…...

Vue3响应式高阶用法之markRaw()
Vue3响应式高阶用法之markRaw() 文章目录 Vue3响应式高阶用法之markRaw()一、简介二、使用场景2.1 避免性能开销2.2 防止意外修改 三、基本使用3.1 标记对象 四、功能详解4.1 markRaw与reactive的区别4.2 markRaw与ref的区别 五、最佳实践及案例5.1 使用大型第三方库对象5.2 静…...

免费SSL证书的安全性与获取指南
SSL证书是一种数字凭证,用于加密用户与网站之间的信息交换,以确保传输的数据不被第三方窃取。它像是一个数字版的密封印章,为数据的传输过程提供了一层保护膜。 免费的SSL证书通常由CA机构提供,它们同样可以提供基础数据的加密服…...

【CN】Argo 持续集成和交付(一)
1.简介 Argo 英 [ˈɑ:ɡəu] 美 [ˈɑrˌɡo] Kubernetes 原生工具,用于运行工作流程、管理集群以及正确执行 GitOps。 Argo 于 2020 年 3 月 26 日被 CNCF 接受为孵化成熟度级别,然后于 2022 年 12 月 6 日转移到毕业成熟度级别。 argoproj.github.i…...

Unity3D 自定义Debug双击溯源问题详解
前言 在Unity3D的开发过程中,经常需要处理各种交互和事件,其中双击事件是常见的需求之一。然而,由于Unity自带的双击检测机制并不完善,开发者往往需要自定义实现以满足特定需求。本文将详细介绍如何在Unity3D中自定义Debug双击溯…...

环境搭建-Docker搭建ClickHouse
Docker搭建ClickHouse 一、前言二、ClickHouse安装2.1 拉取镜像运行ClickHouse服务 三、测试安装3.1 进入clickhouse容器3.2 命令补充说明 四、测试连接五、设置CK的用户名密码 一、前言 本文使用的Docker使用Windows搭建,Linux版本的搭建方式一样。 Windows系统搭…...

深入理解CSS中的变量(概念篇)
CSS变量,也称为自定义属性,是一种在CSS中定义和重用值的方式。它们允许开发者在一个地方定义样式值,然后在整个样式表中引用这些值,从而提高代码的可维护性和可读性。 1、定义和使用CSS变量 CSS变量的定义和使用非常简单。变量名以两个连字符开头,变量值为任何有效的CSS…...

Prometheus 监控Tomcat等java应用的状态
5月应用服务出现问题,当别的小伙伴问我,有没有Tomcat等应用状态的监控的时候,我有点儿尴尬。所以赶紧抽空部署一下。 在配置之前,就当已经会安装jdk和tomcat了。 一、下载jmx_exporter #linux下 cd /usr/local/prometheus wget …...

c++中的斐波那契数列(Fibonacci Sequence)和背包问题(Knapsack Problem)
前言 hello,大家好啊,我是文宇,不是文字,是文宇哦。 斐波那契数列(Fibonacci Sequence) 斐波那契数列(Fibonacci Sequence)是一个经典的数学问题,其中每个数都是前两个…...

connect的非阻塞模式
本文参考:connect 函数在阻塞和非阻塞模式下的行为 一般情况下,在使用connect连接服务端时,需要等待一会儿才会函数才会返回,导致程序阻塞。为了降低阻塞的影响,我们可能会单独开个线程处理connect请求,例…...