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

033-从零搭建微服务-日志插件(一)

写在最前

如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。

源码地址(后端):mingyue: 🎉 基于 Spring Boot、Spring Cloud & Alibaba 的分布式微服务架构基础服务中心

源码地址(前端):mingyue-ui: 🎉 基于 Vue3 + TS + Vite + Element plus 等技术,适配 MingYue 后台微服务

文档地址:Wiki - Gitee.com

为什么要日志插件?

在Java应用程序中记录日志是一种良好的实践,它为开发、运维和支持团队提供了很多好处。以下是一些主要的理由:

  1. 故障排除和调试:

    • 日志是定位和解决问题的重要工具。通过在关键代码路径和操作中插入日志语句,开发人员可以追踪应用程序的执行流程,快速定位潜在的错误和异常。

  2. 性能分析:

    • 记录关键操作的执行时间、资源使用情况等信息,有助于性能分析和优化。通过分析日志,可以确定应用程序的瓶颈并改进性能。

  3. 安全审计:

    • 记录关键的安全事件和用户活动,以便进行审计和检测潜在的安全威胁。登录失败、访问敏感信息等事件的记录对于安全监控至关重要。

  4. 系统状态监控:

    • 通过记录系统状态和关键指标,可以实时监控应用程序的运行状况。这有助于及时发现和解决潜在的问题,以提高系统的稳定性和可用性。

  5. 版本追踪和审计:

    • 在代码中记录版本信息、变更历史和代码提交信息,有助于追踪应用程序的演变过程。审计日志还可以用于追溯特定功能或问题的起源。

  6. 用户行为分析:

    • 对于包含用户交互的应用程序,记录用户活动可以帮助了解他们的使用模式、偏好和行为。这对于改进用户体验和调整产品设计非常有帮助。

  7. 合规性和法规要求:

    • 许多行业和法规要求记录关键事件和操作,以确保企业的合规性。通过日志记录,可以满足这些法规的要求,并提供审计证据。

  8. 持久化数据:

    • 将日志存储在持久化介质中,例如文件或数据库,以便在应用程序重新启动后仍然可以访问日志。这有助于在系统故障或应用程序崩溃时还原状态并进行故障排除。

日志设计

日志类型

系统操作日志和用户登录日志是两种不同类型的日志,它们记录了系统中不同方面的活动

  • 系统操作日志:记录系统的各种操作,包括但不限于增删改查、上传与下载文件等。

  • 用户登录日志:记录用户登录和注销的信息。

记录方式

  • 系统操作日志:采用注解(非侵入)方式记录;

  • 用户登录日志:采用显式(侵入)方式记录;

日志插件

添加 mingyue-common-log 插件

<dependencies><dependency><groupId>com.csp.mingyue</groupId><artifactId>mingyue-common-security</artifactId></dependency>
</dependencies>

Log 注解

@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
​/*** 模块*/String module() default "";
​/*** 功能*/BusinessType businessType() default BusinessType.OTHER;
​/*** 操作人类别*/OperatorUserType operatorUserType() default OperatorUserType.MANAGE;
​/*** 是否保存请求的参数*/boolean isSaveRequestData() default true;
​/*** 是否保存响应的参数*/boolean isSaveResponseData() default true;
​/*** 排除指定的请求参数*/String[] excludeParamNames() default {};
​
}

Log 切面

操作日志记录核心类

@Slf4j
@Aspect
@RequiredArgsConstructor
@AutoConfiguration
public class LogAspect {
​private final ServiceInstance serviceInstance;
​/*** 排除敏感属性字段*/public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
​/*** 处理完请求后执行* @param joinPoint 切点*/@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {handleLog(joinPoint, controllerLog, null, jsonResult);}
​/*** 拦截异常操作* @param joinPoint 切点* @param e 异常*/@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {handleLog(joinPoint, controllerLog, e, null);}
​protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {// 日志记录开始时间Long startTime = System.currentTimeMillis();
​// ========数据库日志========OperateLogEvent operateLog = new OperateLogEvent();
​try {// 请求信息String ip = ServletUtils.getClientIP();operateLog.setReqIp(ip);operateLog.setServiceId(serviceInstance.getServiceId());operateLog.setReqAddress(AddressUtils.getRealAddressByIP(ip));operateLog.setReqUrl(StrUtil.sub(Objects.requireNonNull(ServletUtils.getRequest()).getRequestURI(), 0, 255));
​operateLog.setStatus(BusinessStatus.SUCCESS.ordinal());
​// 用户信息LoginUser loginUser = LoginHelper.getLoginUser();operateLog.setUserId(loginUser.getUserId());operateLog.setUserName(loginUser.getUsername());
​if (e != null) {operateLog.setStatus(BusinessStatus.FAIL.ordinal());operateLog.setException(StrUtil.sub(e.getMessage(), 0, 2000));}
​// 设置方法名称String className = joinPoint.getTarget().getClass().getName();String methodName = joinPoint.getSignature().getName();operateLog.setMethod(className + "." + methodName + "()");
​// 设置User-AgentoperateLog.setUserAgent(ServletUtils.getRequest().getHeader(HttpHeaders.USER_AGENT));// 设置请求方式operateLog.setReqMethod(ServletUtils.getRequest().getMethod());// 处理设置注解上的参数getControllerMethodDescription(joinPoint, controllerLog, operateLog, jsonResult);}catch (Exception exp) {// 记录本地异常日志log.error("异常信息:{}", exp.getMessage());}finally {Long endTime = System.currentTimeMillis();operateLog.setDuration(endTime - startTime);// 发布事件保存数据库SpringUtils.context().publishEvent(operateLog);}}
​/*** 获取注解中对方法的描述信息 用于Controller层注解* @param log 日志* @param operateLog 操作日志*/public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperateLogEvent operateLog,Object jsonResult) throws Exception {// 设置标题operateLog.setModule(log.module());// 设置 action 动作operateLog.setBusinessType(log.businessType().ordinal());// 设置操作人类别operateLog.setUserType(log.operatorUserType().ordinal());// 是否需要保存 request,参数和值if (log.isSaveRequestData()) {// 获取参数的信息,传入到数据库中。setRequestValue(joinPoint, operateLog, log.excludeParamNames());}// 是否需要保存 response,参数和值if (log.isSaveResponseData() && ObjectUtil.isNotNull(jsonResult)) {R resp = JSONUtil.toBean(JSONUtil.toJsonStr(jsonResult), R.class);operateLog.setRespMsg(resp.getMsg());operateLog.setRespCode(resp.getCode());operateLog.setRespResult(StrUtil.sub(JSONUtil.toJsonStr(jsonResult), 0, 2000));}}
​/*** 获取请求的参数,放到log中* @param operLog 操作日志* @throws Exception 异常*/private void setRequestValue(JoinPoint joinPoint, OperateLogEvent operLog, String[] excludeParamNames)throws Exception {Map<String, String> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());String requestMethod = operLog.getReqMethod();if (MapUtil.isEmpty(paramsMap) && HttpMethod.PUT.name().equals(requestMethod)|| HttpMethod.POST.name().equals(requestMethod)) {String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);operLog.setReqParams(StrUtil.sub(params, 0, 2000));}else {MapUtil.removeAny(paramsMap, EXCLUDE_PROPERTIES);MapUtil.removeAny(paramsMap, excludeParamNames);operLog.setReqParams(StrUtil.sub(JSONUtil.toJsonStr(paramsMap), 0, 2000));}}
​/*** 参数拼装*/private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames) {StringJoiner params = new StringJoiner(" ");if (ArrayUtil.isEmpty(paramsArray)) {return params.toString();}for (Object o : paramsArray) {if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) {String str = JSONUtil.toJsonStr(o);Dict dict = JsonUtils.parseMap(str);if (MapUtil.isNotEmpty(dict)) {MapUtil.removeAny(dict, EXCLUDE_PROPERTIES);MapUtil.removeAny(dict, excludeParamNames);str = JSONUtil.toJsonStr(dict);}params.add(str);}}return params.toString();}
​/*** 判断是否需要过滤的对象。* @param o 对象信息。* @return 如果是需要过滤的对象,则返回true;否则返回false。*/@SuppressWarnings("rawtypes")public boolean isFilterObject(final Object o) {Class<?> clazz = o.getClass();if (clazz.isArray()) {return clazz.getComponentType().isAssignableFrom(MultipartFile.class);}else if (Collection.class.isAssignableFrom(clazz)) {Collection collection = (Collection) o;for (Object value : collection) {return value instanceof MultipartFile;}}else if (Map.class.isAssignableFrom(clazz)) {Map map = (Map) o;for (Object value : map.values()) {return value instanceof MultipartFile;}}return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse|| o instanceof BindingResult;}
​
}

异步调用日志服务

@Slf4j
@Component
@RequiredArgsConstructor
public class LogEventListener {
​private final RemoteLogService remoteLogService;
​/*** 保存系统日志记录*/@Async@EventListenerpublic void saveLog(OperateLogEvent operateLog) {log.info("保存系统日志记录落库「{}」", JSONUtil.toJsonStr(operateLog));remoteLogService.saveSysOperateLog(BeanUtil.copyProperties(operateLog, SysOperateLog.class));}
​
}

自动注入日志类

org.springframework.boot.autoconfigure.AutoConfiguration.imports

com.csp.mingyue.common.log.event.LogEventListener
com.csp.mingyue.common.log.aspect.LogAspect

系统操作日志表设计

DROP TABLE IF EXISTS sys_operate_log;
CREATE TABLE sys_operate_log (operate_log_id    BIGINT(20)         NOT NULL                 COMMENT '操作日志ID',module            VARCHAR(50)        DEFAULT ''               COMMENT '模块',business_type     INT(2)             DEFAULT 0                COMMENT '业务类型(0其它 1新增 2修改 3删除)',method            VARCHAR(100)       DEFAULT ''               COMMENT '方法名称',service_id        VARCHAR(32)        DEFAULT NULL             COMMENT '服务ID',user_id           BIGINT(20)         NOT NULL                 COMMENT '用户ID',user_name         VARCHAR(50)        NOT NULL                 COMMENT '用户账号',user_type         TINYINT(1)         DEFAULT 0                COMMENT '用户类型(0其它 1系统用户)',user_agent        VARCHAR(1000)      DEFAULT NULL             COMMENT '用户代理',req_ip            VARCHAR(128)       DEFAULT ''               COMMENT '请求IP',req_address       VARCHAR(255)       DEFAULT ''               COMMENT '请求地点',req_url           VARCHAR(255)       DEFAULT ''               COMMENT '请求URL',req_method        VARCHAR(20)        DEFAULT NULL             COMMENT '请求方式',req_params        TEXT               DEFAULT NULL             COMMENT '请求参数',duration          BIGINT             NOT NULL                 COMMENT '执行时长,单位(ms)',resp_code         INT                DEFAULT NULL             COMMENT '结果码',resp_msg          VARCHAR(512)       NULL DEFAULT ''          COMMENT '结果提示',resp_result       VARCHAR(2000)      DEFAULT ''               COMMENT '返回参数',status            CHAR(1)            DEFAULT 0                COMMENT '操作状态(0正常 1异常)',exception         TEXT               DEFAULT NULL             COMMENT '异常信息',operate_time      DATETIME           NOT NULL                 COMMENT '操作时间',is_deleted        CHAR(1)            DEFAULT '0'              COMMENT '删除标志(0正常,1删除)',create_by         VARCHAR(64)        DEFAULT ''               COMMENT '创建者',create_time       DATETIME           DEFAULT NULL             COMMENT '创建时间',update_by         VARCHAR(64)        DEFAULT ''               COMMENT '更新者',update_time       DATETIME           DEFAULT NULL             COMMENT '更新时间',PRIMARY KEY (operate_log_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC COMMENT='系统操作日志';

测试日志注解

使用注解

@Log(module = "用户管理", businessType = BusinessType.DELETE)

@DeleteMapping("{userId}")
@Log(module = "用户管理", businessType = BusinessType.DELETE)
@Operation(summary = "删除用户", parameters = { @Parameter(name = "userId", description = "用户ID", required = true) })
public R<Boolean> delUser(@PathVariable Long userId) {return R.ok(sysUserService.delUser(userId));
}

调用接口

调用完成后查看数据库是否存在该操作记录即可

curl -X 'DELETE'   'http://192.168.63.114:7100/system/sysUser/111111111'   -H 'accept: */*'   -H 'Authorization: UWapduuggQcNSqg1oQZ17ZyfPHDxxt8Q'

相关文章:

033-从零搭建微服务-日志插件(一)

写在最前 如果这个项目让你有所收获&#xff0c;记得 Star 关注哦&#xff0c;这对我是非常不错的鼓励与支持。 源码地址&#xff08;后端&#xff09;&#xff1a;mingyue: &#x1f389; 基于 Spring Boot、Spring Cloud & Alibaba 的分布式微服务架构基础服务中心 源…...

短期经济波动:均衡国民收入决定理论(三)

短期经济波动&#xff1a;国民收入决定理论(三) 文章目录 短期经济波动&#xff1a;国民收入决定理论(三)[toc]1 总需求曲线及其变动1.1 总需求曲线含义1.2 总需求曲线推导1.2.1 代数推导1.2.2 几何推导 1.3 AD曲线及其变动1.3.1 扩张性财政政策1.3.2 扩张性货币政策 2 总供给曲…...

电力感知边缘计算网关产品设计方案-网关软件架构

边缘计算网关采用ARM定制硬件平台架构,包含上位机端(内网)和FPGA网关端(外网)两部分,通过芯片间的高速信号总线实现边缘计算网关工业数据采集、数据实时传输、数据存储、网关状态信息收集等功能。 边缘计算网关上位机端(内网)重点完成工业数据采集、业务软件运算、客户…...

最新AI创作系统ChatGPT系统运营源码/支持最新GPT-4-Turbo模型/支持DALL-E3文生图

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…...

Java使用Redis的几种客户端介绍

Redis是一种高性能的内存数据库&#xff0c;可以提供快速的数据读写操作。在Java中使用Redis&#xff0c;需要使用Redis客户端。目前&#xff0c;Java中常用的Redis客户端有以下几种&#xff1a; Jedis Jedis是Java中最流行的Redis客户端之一&#xff0c;它提供了丰富的API和…...

程序员的护城河

程序员的护城河 算法&#xff0c;一定是过硬的算法&#xff01;&#xff01;&#xff01;举个栗子&#xff1a;算法不硬吃大亏写在最后 算法&#xff0c;一定是过硬的算法&#xff01;&#xff01;&#xff01; 其实会什么技术不重要&#xff0c;掌握多少种编程语言也不重要&a…...

常见面试题-MySQL软删除以及索引结构

为什么 mysql 删了行记录&#xff0c;反而磁盘空间没有减少&#xff1f; 答&#xff1a; 在 mysql 中&#xff0c;当使用 delete 删除数据时&#xff0c;mysql 会将删除的数据标记为已删除&#xff0c;但是并不去磁盘上真正进行删除&#xff0c;而是在需要使用这片存储空间时…...

信号的机制——信号处理函数的注册

在 Linux 操作系统中&#xff0c;为了响应各种各样的事件&#xff0c;也是定义了非常多的信号。我们可以通过 kill -l 命令&#xff0c;查看所有的信号。 # kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) SIGABRT 7) SIGBUS …...

JS-项目实战-鼠标悬浮变手势(鼠标放单价上生效)

1、鼠标悬浮和离开事件.js //当页面加载完成后执行后面的匿名函数 window.onload function () {//get:获取 Element:元素 By:通过...方式//getElementById()根据id值获取某元素let fruitTbl document.getElementById("fruit_tbl");//table.rows:获取这个表格…...

redis运维(十一) python操作redis

一 python操作redis ① 安装pyredis redis常见错误 说明&#xff1a;由于redis服务器是5.0.8的,为了避免出现问题,默认最高版本的即可 --> 适配 ② 操作流程 核心&#xff1a;获取redis数据库连接对象 ③ Python 字符串前面加u,r,b的含义 原因&#xff1a; 字符串在…...

黑马程序员微服务 第五天课程 分布式搜索引擎2

分布式搜索引擎02 在昨天的学习中&#xff0c;我们已经导入了大量数据到elasticsearch中&#xff0c;实现了elasticsearch的数据存储功能。但elasticsearch最擅长的还是搜索和数据分析。 所以今天&#xff0c;我们研究下elasticsearch的数据搜索功能。我们会分别使用DSL和Res…...

什么是UV贴图?

UV 是与几何图形的顶点信息相对应的二维纹理坐标。UV 至关重要&#xff0c;因为它们提供了表面网格与图像纹理如何应用于该表面之间的联系。它们基本上是控制纹理上哪些像素对应于 3D 网格上的哪个顶点的标记点。它们在雕刻中也很重要。 为什么UV映射很重要&#xff1f; 默认情…...

从哪里下载 Oracle database 11g 软件

登入My Oracle Support&#xff0c;选择Patches & Updates 标签页&#xff0c;点击下方的Latest Patchsets链接&#xff1a; 然后单击Oracle Database&#xff0c;就可以下载11g软件了&#xff1a; 安装单实例数据库需要1和2两个zip文件&#xff0c;安装GI需要第3个zip文…...

Ingress安全网关

目录 文章目录 目录本节实战TCP 流量拆分&#x1f6a9; 实战&#xff1a;TCP 流量拆分-2023.11.15(测试成功) Ingress安全网关Kubernetes Ingress&#x1f6a9; 实战&#xff1a;Kubernetes Ingress-2023.11.15(测试成功) Ingress GatewayIngress Gateway&#x1f6a9; 实战&am…...

Jmeter控制RPS

一、前言 ​ RPS (Request Per Second)一般用来衡量服务端的吞吐量&#xff0c;相比于并发模式&#xff0c;更适合用来摸底服务端的性能。我们可以通过使用 JMeter 的常数吞吐量定时器来限制每个线程的RPS。对于RPS&#xff0c;我们可以把他理解为我们的TPS&#xff0c;我们就不…...

【Nginx】转发配置nginx.conf

文章目录 NginxNginx主要作用转发配置相关问题参考推荐阅读 Nginx Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔赛索耶夫为俄罗斯访问量第二的Rambler.ru站点&#xff08;俄文&#xff1a;Рамбл…...

uniapp实现下载图片到本地

uniapp实现下载图片到本地 在uniapp开发中&#xff0c;可以使用uni.downloadFile方法实现下载文件功能&#xff0c;客户端直接发起一个 HTTP GET 请求&#xff0c;返回文件的本地临时路径。 const urlPath http://192.168.0.1:8080/fileApi/logo.png uni.downloadFile({url:…...

spring cloud-注册中心(Eureka)

一、服务注册中心组件(*) 定义&#xff1a;服务注册中心就是在整个微服务架构单独抽取一个服务&#xff0c;该服务不做项目中任何业务功能&#xff0c;仅用来在微服务中记录微服务、对微服务进行健康状态检查&#xff0c;及服务元数据信息存储常用的注册中心&#xff1a;eurek…...

004 OpenCV akaze特征点检测匹配

目录 一、环境 二、akaze特征点算法 2.1、基本原理 2.2、实现过程 2.3、实际应用 2.4、优点与不足 三、代码 3.1、数据准备 3.2、完整代码 一、环境 本文使用环境为&#xff1a; Windows10Python 3.9.17opencv-python 4.8.0.74 二、akaze特征点算法 特征点检测算法…...

openRPA开源项目源码编译

最近接触到了一个新的领域——RPA&#xff0c;RPA全称Robotic Process Automation&#xff0c;中文名为机器人流程自动化。RPA可以视作一个数字机器人&#xff0c;它可以通过程序来模拟人与软件系统的交互过程&#xff0c;代替人工将大量重复、有规则的计算机操作自动化&#x…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...

车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...

海云安高敏捷信创白盒SCAP入选《中国网络安全细分领域产品名录》

近日&#xff0c;嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》&#xff0c;海云安高敏捷信创白盒&#xff08;SCAP&#xff09;成功入选软件供应链安全领域产品名录。 在数字化转型加速的今天&#xff0c;网络安全已成为企业生存与发展的核心基石&#xff0c;为了解…...

高抗扰度汽车光耦合器的特性

晶台光电推出的125℃光耦合器系列产品&#xff08;包括KL357NU、KL3H7U和KL817U&#xff09;&#xff0c;专为高温环境下的汽车应用设计&#xff0c;具备以下核心优势和技术特点&#xff1a; 一、技术特性分析 高温稳定性 采用先进的LED技术和优化的IC设计&#xff0c;确保在…...

raid存储技术

1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划&#xff0c;涵盖存储系统的布局、数据存储策略等&#xff0c;它明确数据如何存储、管理与访问&#xff0c;为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...