1. 项目概述:当工业数据平台遇上关系型数据库
在工业自动化和物联网项目中,我们常常会遇到一个典型的场景:生产现场的设备数据通过PLC、传感器等实时采集,经由OPC服务器(如KEPServerEX)汇聚,形成一个实时数据池。与此同时,企业的生产管理、质量追溯、设备维护等业务逻辑又重度依赖存储在MySQL这类关系型数据库中的历史数据、配方参数、工单信息等。如何让KEPServerEX这个强大的实时数据网关,也能“读懂”并“搬运”MySQL里的数据,实现实时数据与业务数据的无缝融合,就成了一个非常实际且高频的需求。
这个需求的核心价值在于打破数据孤岛。想象一下,你可以在上位机SCADA画面中,不仅看到设备的实时温度、压力,还能直接关联显示当前正在生产的产品型号、工艺标准阈值(这些信息来自MySQL),甚至根据数据库中的质量判定规则,对实时数据进行动态报警。或者,你可以将MySQL中计算好的生产排程计划,作为设定值下发到KEPServerEX,进而控制生产线启停。KEPServerEX读取MySQL数据,正是实现这类“IT/OT融合”场景的关键桥梁。
KEPServerEX本身是一个工业连接平台,它擅长与各种工业协议(如OPC UA、Modbus、Siemens S7等)打交道。而让它读取MySQL,本质上是扩展了它的数据源边界,使其从一个纯粹的“实时数据采集器”升级为一个“混合数据聚合器”。无论是工艺工程师、系统集成商还是软件开发人员,掌握这项技能,都能极大地提升数据应用的灵活性和系统集成的深度。
2. 核心方案选型与设计思路拆解
要实现KEPServerEX读取MySQL,我们并非只有一条路可走。根据项目复杂度、性能要求和开发资源,主要有三种主流思路,每种都有其适用的场景和背后的技术考量。
2.1 方案一:使用KEPServerEX Advanced Tags(高级标签)与ODBC驱动
这是最直接、官方支持度较高的方式。KEPServerEX提供了“Advanced Tags”功能,允许通过ODBC(开放式数据库连接)接口访问外部数据库。你需要做的是:
- 在运行KEPServerEX的服务器上,配置MySQL的ODBC数据源(DSN)。
- 在KEPServerEX的通道(Channel)或设备(Device)下,创建“Advanced Tags”。
- 在标签属性中,编写SQL查询语句,并配置轮询间隔。
为什么选择这个方案?它的最大优势是“开箱即用”,无需额外开发,所有配置都在KEPServerEX管理界面(KEPServerEX Configuration)中完成。对于简单的、周期性的数据查询(例如每分钟读取一次最新的工艺参数表),这个方案非常合适。它把数据库查询直接映射成了一个OPC标签,客户端(如SCADA、MES)可以像访问一个普通设备点一样访问这个“数据库点”。
设计考量与局限:这个方案的性能完全依赖于轮询机制。如果你的应用需要低延迟(秒级以下)或基于事件触发(如数据库记录新增时立即读取),轮询会带来不必要的开销和延迟。此外,复杂的多表关联查询或需要大量计算才能得出的结果,可能会加重数据库负担,不适合在此处直接执行。它的定位是轻量级、周期性的数据拉取。
2.2 方案二:开发自定义KEPServerEX Client Application(客户端应用)
这是功能最强大、最灵活的方案。其核心思路是“主动获取,主动写入”。我们不再依赖KEPServerEX去“拉取”数据,而是自己编写一个独立的应用程序(可以是C#、Python、Java等语言开发)。这个程序扮演双重角色:
- MySQL客户端:连接到MySQL数据库,执行我们所需的查询逻辑。这个逻辑可以非常复杂,可以包含事务、存储过程调用、联合查询等。
- KEPServerEX的OPC客户端:通过KEPServerEX提供的OPC DA、UA或.NET API,连接到KEPServerEX服务器,并将从MySQL查询到的结果,写入到KEPServerEX中预先定义好的“虚拟”标签(Tag)中。
为什么选择这个方案?它彻底解耦了数据查询逻辑和数据发布逻辑。你的应用程序可以自由控制从MySQL读取数据的时机:可以是定时轮询,可以是通过监听MySQL的binlog实现变更数据捕获(CDC),甚至可以是由外部事件(如收到一条MQTT消息)来触发。然后,应用程序将处理好的数据,以“写标签”的方式推送给KEPServerEX。这样,下游的SCADA等系统看到的,依然是KEPServerEX提供的、稳定且实时的OPC数据流。这个方案适用于数据同步逻辑复杂、对实时性要求高、或需要将数据库数据经过加工后再发布的场景。
2.3 方案三:利用脚本功能(如VBScript,Python)进行桥接
KEPServerEX的某些版本或搭配某些插件(如某些第三方脚本插件),支持在服务器端运行脚本。理论上,你可以编写一个脚本,周期性地连接MySQL,执行查询,并更新KEPServerEX内部的某个标签值。
为什么慎用这个方案?首先,KEPServerEX原生对脚本的支持有限,稳定性不如前两种方案。其次,脚本运行在KEPServerEX进程内,如果脚本出现异常或死循环,可能会影响整个KEPServerEX服务的稳定性,风险较高。因此,除非有非常特殊的轻量级需求,且对KEPServerEX环境有完全掌控,否则一般不作为首选方案。它更像是一个“技巧性”的补充,而不是一个工程化的解决方案。
综合选型建议:
- 需求简单,查询固定,周期在数秒以上:优先考虑方案一(Advanced Tags + ODBC),配置快速,维护简单。
- 需求复杂,逻辑多变,要求高实时性或事件驱动:必须选择方案二(自定义客户端应用),这是构建稳健数据管道的最佳实践。
- 快速原型验证或一次性临时任务:可以尝试方案三(脚本),但生产环境务必谨慎。
接下来,我们将以最常用、也最具代表性的方案二(自定义客户端应用)为例,展开详细的实操解析。因为方案一配置相对简单,而方案二涵盖了从数据库连接到OPC通信的完整链条,理解它之后,方案一的配置也会融会贯通。
3. 核心组件准备与环境搭建
在开始编写代码之前,我们需要准备好所有的“武器”和“战场”。这个环节的细致程度,直接决定了后续开发的顺利与否。
3.1 MySQL数据库环境配置
首先,确保你的MySQL数据库可以被远程访问。很多开发初期的坑都出在这里。
创建专用账户:不要在应用中使用root账户。为KEPServerEX数据同步创建一个专用账户,遵循最小权限原则。
CREATE USER 'kepserver_sync'@'%' IDENTIFIED BY 'YourStrongPassword123!'; -- 授予对特定数据库(例如`production_db`)的只读权限 GRANT SELECT ON production_db.* TO 'kepserver_sync'@'%'; FLUSH PRIVILEGES;注意:
@‘%’允许从任何主机连接,在生产环境中,为了安全,应替换为KEPServerEX或客户端应用所在服务器的具体IP地址,如@‘192.168.1.100’。确认网络与防火墙:确保运行客户端应用的机器可以访问MySQL服务器的3306端口。在MySQL服务器上检查
bind-address配置(通常在my.cnf或my.ini中),确保它不是127.0.0.1,而是0.0.0.0或服务器本机IP。同时,在服务器防火墙中放行3306端口。准备测试数据:创建一个简单的表用于测试。例如,一个存储产品标准参数的
product_spec表。USE production_db; CREATE TABLE product_spec ( product_id VARCHAR(20) PRIMARY KEY, product_name VARCHAR(100), max_temperature DECIMAL(5,2), min_pressure DECIMAL(6,2), target_speed INT ); INSERT INTO product_spec VALUES ('P001', '型号A', 85.50, 101.33, 1200), ('P002', '型号B', 92.00, 98.66, 1500);
3.2 KEPServerEX侧准备工作
在KEPServerEX中,我们需要为客户端应用“准备好位置”来存放数据。
创建虚拟设备:在KEPServerEX的工程树中,新建一个通道(Channel),协议可以选择“Simulator”(模拟器)或者“OPC DA Client”等任意一种,目的是创建一个逻辑容器。然后在该通道下新建一个设备(Device),命名为“MySQL_Bridge”之类的名称。
定义数据标签(Tags):在“MySQL_Bridge”设备下,创建与MySQL表中字段对应的标签。例如:
ProductA.MaxTemp(数据类型:Float)ProductA.MinPressure(Float)ProductA.TargetSpeed(Int)CurrentProductID(String) 这些标签的初始值可以任意设置,因为它们将被我们的客户端应用覆盖。关键一步:记录下每个标签在KEPServerEX中的完整ItemID(项目ID),通常格式如通道名.设备名.标签名,例如MySQLChannel.MySQL_Bridge.ProductA.MaxTemp。这个ItemID是客户端应用写入数据时的“地址”。
配置OPC访问权限:确保KEPServerEX的OPC DA或UA服务已启用,并且允许来自客户端应用所在机器的连接。检查DCOM配置(如果使用OPC DA Classic)或UA用户权限。
3.3 客户端应用开发环境搭建
我们以C# + .NET为例,这是工业领域最常用的组合之一。
安装开发工具:Visual Studio 2022 Community版(免费且功能强大)。
安装MySQL连接驱动:通过NuGet包管理器,为项目安装
MySql.Data包。这是官方提供的.NET连接器。Install-Package MySql.Data安装OPC库:KEPServerEX通常支持OPC DA和OPC UA。对于OPC DA,一个流行的选择是
OPCFoundation.NetAPI(原OpcNetApi),但更稳定易用的第三方库是OpcLabs.QuickOpc。对于OPC UA,可以使用OPCFoundation.NetStandard.Opc.Ua官方库。这里以OPC DA和OpcLabs.QuickOpc为例(请注意,这是一个商业库,但有试用版,用于学习和原型开发足够了)。Install-Package OpcLabs.QuickOpc实操心得:在工业环境,特别是与KEPServerEX这类成熟服务器交互时,OPC UA是更现代、更安全(内置加密)且跨平台兼容性更好的选择,是新项目的首选。但OPC DA在大量遗留系统中依然广泛存在。选择哪个协议,需要与你的KEPServerEX配置和下游客户端需求对齐。
4. 客户端应用程序的详细实现步骤
现在,我们进入核心的编码环节。我们将构建一个控制台应用程序,它定时从MySQL读取数据,并写入KEPServerEX。
4.1 项目结构与基础框架
在Visual Studio中创建一个新的C#控制台应用项目,命名为MySqlToKepserverBridge。
首先,定义配置模型,将数据库连接字符串、OPC服务器地址、查询语句和标签映射等可配置信息提取出来,方便后期修改。我们可以使用appsettings.json配合.NET Core的配置系统,或者简单点,先定义一个静态配置类。
using System; using System.Collections.Generic; namespace MySqlToKepserverBridge { public static class AppConfig { // MySQL 配置 public static string MySqlConnectionString = "Server=192.168.1.50;Database=production_db;Uid=kepserver_sync;Pwd=YourStrongPassword123!;"; // OPC DA Server 配置 (示例使用OPC DA) public static string OpcServerUrl = "opcda://localhost/Kepware.KEPServerEX.V6"; // 根据实际修改 // 数据同步间隔(毫秒) public static int SyncIntervalMs = 5000; // 5秒 // 定义需要同步的数据点映射:Key为MySQL查询结果列名,Value为KEPServerEX中的ItemID public static Dictionary<string, string> TagMappings = new Dictionary<string, string> { {"max_temperature", "MySQLChannel.MySQL_Bridge.ProductA.MaxTemp"}, {"min_pressure", "MySQLChannel.MySQL_Bridge.ProductA.MinPressure"}, {"target_speed", "MySQLChannel.MySQL_Bridge.ProductA.TargetSpeed"}, {"product_id", "MySQLChannel.MySQL_Bridge.CurrentProductID"} }; // 示例SQL查询(假设我们总是获取产品ID为P001的规格) public static string DataQuerySql = "SELECT product_id, max_temperature, min_pressure, target_speed FROM product_spec WHERE product_id = 'P001';"; } }4.2 实现MySQL数据读取模块
创建一个MySqlDataReader类,负责执行查询并返回一个易于处理的字典结果。
using MySql.Data.MySqlClient; using System; using System.Collections.Generic; using System.Data; namespace MySqlToKepserverBridge { public class MySqlDataReader { private string _connectionString; public MySqlDataReader(string connectionString) { _connectionString = connectionString; } public Dictionary<string, object> FetchCurrentData(string querySql) { var result = new Dictionary<string, object>(); using (var connection = new MySqlConnection(_connectionString)) { try { connection.Open(); using (var command = new MySqlCommand(querySql, connection)) { using (var reader = command.ExecuteReader(CommandBehavior.SingleRow)) // 假设只返回一行 { if (reader.Read()) { for (int i = 0; i < reader.FieldCount; i++) { string columnName = reader.GetName(i); object columnValue = reader.GetValue(i); // 处理DBNull result[columnName] = (columnValue == DBNull.Value) ? null : columnValue; } } else { Console.WriteLine($"[{DateTime.Now}] 警告:数据库查询未返回任何数据。"); } } } } catch (MySqlException ex) { Console.WriteLine($"[{DateTime.Now}] MySQL错误: {ex.Message}"); // 在实际应用中,这里可能需要更复杂的错误处理和重试逻辑 } } return result; } } }4.3 实现OPC数据写入模块
创建一个OpcDataWriter类,负责连接KEPServerEX并写入标签值。这里使用OpcLabs QuickOPC库作为示例。
using OpcLabs.EasyOpc.DataAccess; using System; using System.Collections.Generic; namespace MySqlToKepserverBridge { public class OpcDataWriter { private EasyDAClient _daClient; private string _serverUrl; public OpcDataWriter(string serverUrl) { _serverUrl = serverUrl; _daClient = new EasyDAClient(); // 创建OPC DA客户端实例 } public void WriteTagValues(Dictionary<string, object> tagValueMap) { if (tagValueMap == null || tagValueMap.Count == 0) { Console.WriteLine($"[{DateTime.Now}] 无有效数据可写入。"); return; } // 准备要写入的项参数列表 var argumentsList = new List<DAItemValueArguments>(); foreach (var mapping in AppConfig.TagMappings) { string mysqlColumnName = mapping.Key; string opcItemId = mapping.Value; if (tagValueMap.TryGetValue(mysqlColumnName, out object value)) { // 将值转换为合适的类型(这里简化处理,实际需要根据标签数据类型精细转换) var itemValueArguments = new DAItemValueArguments(_serverUrl, opcItemId, value); argumentsList.Add(itemValueArguments); } else { Console.WriteLine($"[{DateTime.Now}] 警告:查询结果中未找到列 '{mysqlColumnName}',对应标签 '{opcItemId}' 将不会被更新。"); } } if (argumentsList.Count > 0) { try { // 批量写入,效率更高 _daClient.WriteMultipleItemValues(argumentsList.ToArray()); Console.WriteLine($"[{DateTime.Now}] 成功写入 {argumentsList.Count} 个标签值。"); } catch (Exception ex) { Console.WriteLine($"[{DateTime.Now}] OPC写入错误: {ex.Message}"); } } } // 释放资源 public void Dispose() { _daClient?.Dispose(); } } }4.4 主程序循环与调度
最后,在Program.cs中,将读取器和写入器组合起来,形成一个定时同步的循环。
using System; using System.Threading; namespace MySqlToKepserverBridge { class Program { private static MySqlDataReader _dataReader; private static OpcDataWriter _dataWriter; private static bool _isRunning = true; static void Main(string[] args) { Console.WriteLine("MySQL to KEPServerEX 数据桥接服务启动..."); Console.WriteLine($"配置:每 {AppConfig.SyncIntervalMs / 1000.0} 秒同步一次。"); Console.WriteLine("按 Ctrl+C 停止服务。\n"); // 初始化组件 _dataReader = new MySqlDataReader(AppConfig.MySqlConnectionString); _dataWriter = new OpcDataWriter(AppConfig.OpcServerUrl); // 设置Ctrl+C事件处理,优雅关闭 Console.CancelKeyPress += (sender, eventArgs) => { Console.WriteLine("\n接收到停止信号,正在关闭服务..."); _isRunning = false; eventArgs.Cancel = true; // 阻止立即退出,让循环自然结束 }; // 主工作循环 while (_isRunning) { try { // 1. 从MySQL读取数据 var currentData = _dataReader.FetchCurrentData(AppConfig.DataQuerySql); // 2. 写入KEPServerEX _dataWriter.WriteTagValues(currentData); } catch (Exception ex) { Console.WriteLine($"[{DateTime.Now}] 主循环发生未预期错误: {ex.Message}"); } // 3. 等待下一个周期 if (_isRunning) { Thread.Sleep(AppConfig.SyncIntervalMs); } } // 清理资源 _dataWriter?.Dispose(); Console.WriteLine("服务已停止。"); } } }至此,一个基础但完整的KEPServerEX读取MySQL数据的客户端应用就构建完成了。编译并运行此程序,你就能在KEPServerEX的Quick Client或任何OPC客户端中,看到来自MySQL数据库的数据在动态更新了。
5. 高级功能扩展与优化策略
上面的基础版本实现了核心功能,但在生产环境中,我们还需要考虑更多。
5.1 实现变更数据捕获(CDC)与事件驱动
轮询始终是有延迟和开销的。更高级的模式是监听MySQL的数据变更。对于MySQL 8.0+,可以使用MySQL Binary Log。你可以使用Debezium这样的CDC工具,它会监控MySQL的binlog,将数据变更(增、删、改)转换为事件流(通常是发往Kafka)。然后,你的客户端应用不再轮询MySQL,而是订阅这个事件流。一旦收到事件,立即处理数据并写入KEPServerEX。
架构升级:MySQL (Binlog) -> Debezium -> Kafka -> 你的桥接应用 -> KEPServerEX。这种方式实现了真正的低延迟、事件驱动的数据同步,资源利用率更高,非常适合高频更新的数据表。
5.2 连接管理与错误恢复
生产级应用必须有健壮的容错能力。
- 连接池:对于MySQL,使用
MySqlConnection时,.NET Framework/ Core已经提供了内置的连接池,只需确保正确使用using语句或依赖注入来管理生命周期即可。避免频繁创建和销毁连接。 - OPC连接重连:网络波动可能导致OPC连接中断。需要在
OpcDataWriter中增加心跳检测和自动重连机制。可以定期读取一个“健康检查”标签,如果失败,则尝试重新初始化EasyDAClient对象。 - 异常处理与重试:在
Main循环中,对数据库查询和OPC写入的异常要进行分类处理。对于网络超时等临时性错误,可以实现指数退避重试策略。对于业务逻辑错误(如SQL语法错误),则记录日志并可能需要人工干预。 - 优雅降级:如果MySQL暂时不可用,是否可以使用上一次缓存的数据?或者将数据暂存到本地文件/内存中,待数据库恢复后再同步?这些策略需要根据业务重要性来设计。
5.3 性能优化与监控
- 批量操作:我们已经使用了
WriteMultipleItemValues进行批量写入,这比逐个写入标签效率高得多。对于数据读取,如果一次需要同步多行数据,也应考虑使用更高效的SQL查询,避免在循环中执行多次单行查询。 - 异步编程:将数据库查询和OPC写入改为异步模式(
async/await),可以避免在IO等待时阻塞线程,提高应用程序的吞吐量和响应性,尤其是在同步间隔很短或处理大量标签时。 - 日志记录:使用成熟的日志框架如
NLog或Serilog,替代Console.WriteLine。将信息、警告、错误等不同级别的日志输出到文件、数据库或日志聚合系统(如ELK),便于问题追踪和系统监控。 - 配置化:将SQL查询语句、标签映射关系、服务器地址等全部移至外部配置文件(如
appsettings.json)或数据库中。这样,在需要修改同步逻辑时,无需重新编译和部署应用程序。
6. 常见问题与故障排查实录
在实际部署和运行中,你几乎一定会遇到下面这些问题。这里记录了我的踩坑实录和解决方法。
6.1 连接类问题
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
MySQL连接失败:Unable to connect to any of the specified MySQL hosts. | 1. 网络不通或防火墙阻止。 2. MySQL服务未运行。 3. 连接字符串错误(IP、端口、用户名、密码)。 4. 用户权限不足或未允许远程连接。 | 1. 从客户端机器pingMySQL服务器IP,并用telnet [IP] 3306测试端口。2. 登录MySQL服务器,检查服务状态 sudo systemctl status mysql。3. 仔细核对连接字符串,密码中的特殊字符可能需要转义。 4. 在MySQL服务器上用 root登录,执行SELECT host, user FROM mysql.user;查看kepserver_sync用户的host是否包含客户端IP或%。 |
OPC连接失败:The RPC server is unavailable.(OPC DA常见) | 1. KEPServerEX的OPC DA服务未启动或DCOM配置问题。 2. 客户端与服务器不在同一域,且未配置正确的DCOM权限。 3. 防火墙阻止了DCOM动态端口。 | 1. 在KEPServerEX管理界面确认OPC DA服务已启用。 2. 这是最棘手的部分。需要在服务器端运行 dcomcnfg,配置OpcEnum和KEPServerEX应用程序的DCOM权限,为客户端机器或用户添加“远程访问”和“启动/激活”权限。通常简化测试时,可以暂时降低安全级别,但生产环境需谨慎。3. 考虑使用OPC UA替代OPC DA,它能绕过复杂的DCOM配置。 |
OPC UA连接失败:BadCertificateUntrusted | 客户端不信任服务器的证书。 | 1. 在KEPServerEX中导出服务器证书。 2. 在客户端应用程序的证书存储中,或通过OPC UA库的API,添加该证书到“受信任的颁发机构”或“受信任的应用程序”。 |
6.2 数据读写类问题
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 能连接,但写入KEPServerEX的标签值无变化 | 1. OPCItemID写错。2. 写入的数据类型与标签定义的数据类型不匹配。 3. 标签在KEPServerEX中处于“未激活”或“错误”状态。 4. 客户端应用有写入权限,但标签被设置为“只读”。 | 1. 使用KEPServerEX自带的“Quick Client”或第三方OPC客户端(如UAExpert)手动写入同一个ItemID,测试是否成功。这是最有效的定位方法。2. 在代码中检查写入的值类型。KEPServerEX的 Float对应C#的double或float,Int对应int。使用Convert.ChangeType进行安全转换。3. 在KEPServerEX工程树中检查标签状态图标。 4. 在KEPServerEX中检查标签的“访问权限”属性。 |
从MySQL读取的数据为null,导致写入失败 | 1. 数据库表中该字段值为NULL。2. SQL查询的列名与代码中 Dictionary的键名不匹配(大小写敏感性问题)。 | 1. 在代码中增加空值判断,如if (value != null) { // 写入逻辑 }。2. 在MySQL查询中使用 AS关键字明确指定列别名,确保与代码中的键名完全一致。例如:SELECT max_temperature AS max_temperature ...。 |
| 同步性能差,CPU或网络占用高 | 1. 同步间隔(SyncIntervalMs)设置过短。2. SQL查询未优化,扫描大量数据。 3. 网络延迟高。 | 1. 根据业务对实时性的要求,合理调整同步间隔。非关键数据可以设置为10秒、30秒甚至更长。 2. 为查询条件涉及的字段添加索引。只查询必需的列,避免 SELECT *。3. 确保客户端、KEPServerEX、MySQL服务器部署在同一个局域网内,减少网络跳数。 |
6.3 部署与运行类问题
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 应用程序以Windows服务运行时无法连接数据库/OPC | Windows服务运行在特定的用户账户(如Local System)下,该账户可能没有网络访问权限或访问某些资源的权限。 | 1. 将运行Windows服务的账户更改为一个有适当权限的域账户或本地账户。 2. 对于OPC DA,DCOM权限需要授予这个服务运行账户,而不是登录用户的账户。 3. 对于文件路径访问,使用绝对路径而非相对路径。 |
| 程序运行一段时间后内存持续增长 | 存在资源未释放(如数据库连接、OPC客户端对象)。 | 1. 确保所有实现了IDisposable接口的对象(如MySqlConnection,EasyDAClient)都在using语句块中或手动调用Dispose()。2. 使用内存分析工具(如Visual Studio的诊断工具或.NET Memory Profiler)检查内存泄漏点。 |
最后的叮嘱:在将任何桥接程序部署到生产环境前,务必在测试环境中进行长时间的压力测试和稳定性测试。模拟网络中断、数据库重启、KEPServerEX服务重启等异常情况,观察程序的恢复能力。日志是你的第一道防线,确保所有关键操作和异常都被清晰记录。这个由KEPServerEX和MySQL搭建的数据桥梁,虽然看起来只是一个小程序,但作为连接IT与OT的关键节点,它的稳定与否,直接影响着上层所有数据应用的可信度。