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

TDengine 与 taosAdapter 的结合(二)

 五、开发实战步骤

(一)环境搭建

在开始 TDengine 与 taosAdapter 结合的 RESTful 接口开发之前,需要先完成相关环境的搭建,包括 TDengine 和 taosAdapter 的安装与配置,以及相关依赖的安装。

  • TDengine 安装
    • Linux 系统:可以从 TDengine 官方网站(https://www.taosdata.com/cn/all-downloads/ )下载适合系统的安装包,目前支持 x86_64、ARM64 等多种架构 。下载完成后,解压安装包,进入解压目录,执行安装脚本./install.sh。在安装过程中,可能需要设置一些参数,如主机名、集群节点信息等,按照提示进行设置即可。安装完成后,可以通过systemctl start taosd命令启动 TDengine 服务,使用systemctl status taosd命令查看服务状态。
    • Windows 系统:同样从官方网站下载 Windows 版本的安装包,双击安装程序,按照安装向导的提示完成安装。安装完成后,可以在开始菜单中找到 TDengine 的相关程序,或者在安装目录下找到taosd.exe文件,通过命令行启动服务,如taosd -c C:\TDengine\cfg(假设安装目录为 C:\TDengine)。
  • taosAdapter 安装与配置
    • 安装:taosAdapter 通常随 TDengine 安装包一起提供,在安装 TDengine 时会自动安装。如果需要单独安装,可以从 TDengine 官方网站下载对应的 taosAdapter 安装包。在 Linux 系统上,安装完成后,taosAdapter 服务默认由 systemd 管理 。
    • 配置:taosAdapter 的配置文件默认位于/etc/taos/taosadapter.toml(Linux)或C:\TDengine\cfg\taosadapter.toml(Windows)。打开配置文件,可以进行以下常见配置:
      • 端口配置:默认情况下,taosAdapter 监听 6041 端口提供 RESTful 服务 。如果该端口已被占用,可以修改[http]部分的port参数,指定其他可用端口。
      • 认证配置:可以配置用户名和密码进行身份认证。在[http]部分,设置user和password参数,确保安全性。
      • 其他配置:根据实际需求,还可以配置日志级别、连接池大小等参数。例如,修改[log]部分的level参数来调整日志记录的详细程度,将level = "info"改为level = "debug"可以获取更详细的调试信息。

配置完成后,通过systemctl start taosadapter(Linux)或在 Windows 服务中启动 taosAdapter 服务,使用systemctl status taosadapter(Linux)或检查 Windows 服务状态来确认服务是否正常运行。

  • 相关依赖安装:根据开发语言和框架的不同,可能需要安装一些相关依赖。如果使用 Python 进行开发,并且使用requests库来发送 HTTP 请求与 taosAdapter 进行交互,可以使用pip install requests命令安装requests库;如果使用 Java 开发,并且使用HttpClient来处理 HTTP 请求,需要在项目的pom.xml文件中添加HttpClient的依赖:
 

<dependency>

<groupId>org.apache.httpcomponents</groupId>

<artifactId>httpclient</artifactId>

<version>4.5.13</version>

</dependency>

以上步骤完成后,就搭建好了 TDengine 与 taosAdapter 结合开发 RESTful 接口的基础环境。

(二)接口开发流程

完成环境搭建后,就可以开始进行 RESTful 接口的开发了。以下是从需求分析、设计接口到编码实现的具体步骤:

  • 需求分析:首先需要明确业务需求,确定需要通过 RESTful 接口对 TDengine 进行哪些数据操作。在一个物联网设备监控项目中,可能需要实现以下功能:
    • 设备数据的实时写入,包括设备 ID、时间戳、各种传感器数据(如温度、湿度、压力等)。
    • 根据设备 ID 和时间范围查询设备的历史数据。
    • 获取所有设备的列表信息。
  • 设计接口:根据需求分析的结果,按照 RESTful 架构风格设计接口。设计原则是将 TDengine 中的数据和操作抽象为资源,并使用 HTTP 方法进行访问。
    • 数据写入接口:使用 POST 方法,将设备数据以 JSON 格式发送到/api/v1/databases/{database_name}/tables/{table_name}/data 。假设数据库名为iot_data,表名为device_sensor_data,则接口地址为/api/v1/databases/iot_data/tables/device_sensor_data/data。请求体示例如下:
 

[

{

"device_id": "device_001",

"ts": "2023-10-01T12:00:00Z",

"temperature": 25.5,

"humidity": 60.0,

"pressure": 1013.2

},

{

"device_id": "device_002",

"ts": "2023-10-01T12:00:00Z",

"temperature": 26.0,

"humidity": 58.0,

"pressure": 1012.8

}

]

  • 数据查询接口:使用 GET 方法,通过在 URL 中添加参数来指定查询条件。查询设备device_001在 2023 年 10 月 1 日的所有数据,接口地址可以设计为/api/v1/databases/iot_data/tables/device_sensor_data/data?device_id=device_001&start_time=2023-10-01T00:00:00Z&end_time=2023-10-01T23:59:59Z 。
  • 获取设备列表接口:使用 GET 方法,访问/api/v1/databases/{database_name}/devices 。对于上述物联网项目,接口地址为/api/v1/databases/iot_data/devices,返回所有设备的基本信息,如设备 ID、设备名称、设备类型等。
  • 编码实现:根据设计好的接口,使用选定的开发语言和框架进行编码实现。如果使用 Python 和 Flask 框架来实现上述接口,可以参考以下代码示例:
 

from flask import Flask, request, jsonify

import requests

app = Flask(__name__)

# TDengine RESTful 接口地址前缀

TDENGINE_REST_URL = "http://localhost:6041/rest/sql"

TDENGINE_USER = "root"

TDENGINE_PASSWORD = "taosdata"

# 数据写入接口

@app.route('/api/v1/databases/<database_name>/tables/<table_name>/data', methods=['POST'])

def write_data(database_name, table_name):

data = request.json

sql_values = []

for item in data:

device_id = item['device_id']

ts = item['ts']

temperature = item['temperature']

humidity = item['humidity']

pressure = item['pressure']

sql_values.append(f"('{device_id}', '{ts}', {temperature}, {humidity}, {pressure})")

sql = f"INSERT INTO {database_name}.{table_name} (device_id, ts, temperature, humidity, pressure) VALUES {','.join(sql_values)}"

response = requests.post(TDENGINE_REST_URL, auth=(TDENGINE_USER, TDENGINE_PASSWORD), data=sql)

if response.status_code == 200:

return jsonify({"status": "success", "message": "Data inserted successfully"}), 200

else:

return jsonify({"status": "error", "message": "Failed to insert data"}), 500

# 数据查询接口

@app.route('/api/v1/databases/<database_name>/tables/<table_name>/data', methods=['GET'])

def query_data(database_name, table_name):

device_id = request.args.get('device_id')

start_time = request.args.get('start_time')

end_time = request.args.get('end_time')

sql_conditions = []

if device_id:

sql_conditions.append(f"device_id = '{device_id}'")

if start_time:

sql_conditions.append(f"ts >= '{start_time}'")

if end_time:

sql_conditions.append(f"ts <= '{end_time}'")

sql_condition_str = " AND ".join(sql_conditions)

sql = f"SELECT * FROM {database_name}.{table_name}"

if sql_condition_str:

sql += f" WHERE {sql_condition_str}"

response = requests.post(TDENGINE_REST_URL, auth=(TDENGINE_USER, TDENGINE_PASSWORD), data=sql)

if response.status_code == 200:

result = response.json()

return jsonify({"status": "success", "data": result['data']}), 200

else:

return jsonify({"status": "error", "message": "Failed to query data"}), 500

# 获取设备列表接口

@app.route('/api/v1/databases/<database_name>/devices', methods=['GET'])

def get_devices(database_name):

sql = f"SELECT DISTINCT device_id FROM {database_name}.device_sensor_data"

response = requests.post(TDENGINE_REST_URL, auth=(TDENGINE_USER, TDENGINE_PASSWORD), data=sql)

if response.status_code == 200:

result = response.json()

device_list = [item[0] for item in result['data']]

return jsonify({"status": "success", "devices": device_list}), 200

else:

return jsonify({"status": "error", "message": "Failed to get device list"}), 500

if __name__ == '__main__':

app.run(debug=True, host='0.0.0.0', port=5000)

以上代码通过 Flask 框架创建了一个简单的 Web 服务,实现了数据写入、查询和获取设备列表的 RESTful 接口。每个接口通过requests库向 taosAdapter 提供的 RESTful 接口发送 SQL 语句,实现对 TDengine 的操作,并返回相应的结果。

(三)代码示例与解释

下面给出使用 Python 和 Java 调用 RESTful 接口进行数据操作的实际代码示例,并对关键代码进行解释。

Python 代码示例

 

import requests

# TDengine RESTful 接口地址前缀

TDENGINE_REST_URL = "http://localhost:6041/rest/sql"

TDENGINE_USER = "root"

TDENGINE_PASSWORD = "taosdata"

# 插入数据示例

def insert_data():

database_name = "test_db"

table_name = "test_table"

data = [

{

"col1": "value1",

"col2": 100,

"ts": "2023-10-05T10:00:00Z"

},

{

"col1": "value2",

"col2": 200,

"ts": "2023-10-05T10:01:00Z"

}

]

sql_values = []

for item in data:

col1 = item['col1']

col2 = item['col2']

ts = item['ts']

sql_values.append(f"('{col1}', {col2}, '{ts}')")

sql = f"INSERT INTO {database_name}.{table_name} (col1, col2, ts) VALUES {','.join(sql_values)}"

response = requests.post(TDENGINE_REST_URL, auth=(TDENGINE_USER, TDENGINE_PASSWORD), data=sql)

if response.status_code == 200:

print("Data inserted successfully")

else:

print("Failed to insert data")

# 查询数据示例

def query_data():

database_name = "test_db"

table_name = "test_table"

sql = f"SELECT * FROM {database_name}.{table_name}"

response = requests.post(TDENGINE_REST_URL, auth=(TDENGINE_USER, TDENGINE_PASSWORD), data=sql)

if response.status_code == 200:

result = response.json()

for row in result['data']:

print(row)

else:

print("Failed to query data")

if __name__ == "__main__":

insert_data()

query_data()

代码解释

  • TDENGINE_REST_URL:定义了 taosAdapter 提供的 RESTful 接口地址,这里假设 taosAdapter 运行在本地,端口为 6041。
  • TDENGINE_USERTDENGINE_PASSWORD:分别为 TDengine 的用户名和密码,用于身份认证。
  • insert_data 函数
    • 构建要插入的数据列表,每个数据项包含col1、col2和ts字段。
    • 通过循环构建 SQL 插入语句的 VALUES 部分,将数据转换为 SQL 可识别的格式。
    • 使用requests.post方法向 TDengine 发送 POST 请求,请求的 URL 为TDENGINE_REST_URL,认证信息为(TDENGINE_USER, TDENGINE_PASSWORD),请求体为构建好的 SQL 语句。
    • 根据响应状态码判断数据插入是否成功。
  • query_data 函数
    • 构建简单的 SQL 查询语句,查询指定数据库和表中的所有数据。
    • 同样使用requests.post方法发送请求,获取查询结果。
    • 如果响应状态码为 200,解析响应的 JSON 数据,遍历并打印查询结果中的每一行数据。

Java 代码示例

 

import org.apache.http.HttpEntity;

import org.apache.http.HttpResponse;

import org.apache.http.NameValuePair;

import org.apache.http.client.HttpClient;

import org.apache.http.client.entity.UrlEncodedFormEntity;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.message.BasicNameValuePair;

import org.apache.http.util.EntityUtils;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

public class TDengineRestExample {

private static final String TDENGINE_REST_URL = "http://localhost:6041/rest/sql";

private static final String TDENGINE_USER = "root";

private static final String TDENGINE_PASSWORD = "taosdata";

// 插入数据示例

public static void insertData() {

String databaseName = "test_db";

String tableName = "test_table";

List<NameValuePair> data = new ArrayList<>();

data.add(new BasicNameValuePair("col1", "value1"));

data.add(new BasicNameValuePair("col2", "100"));

data.add(new BasicNameValuePair("ts", "2023-10-05T10:00:00Z"));

data.add(new BasicNameValuePair("col1", "value2"));

data.add(new BasicNameValuePair("col2", "200"));

data.add(new BasicNameValuePair("ts", "2023-10-05T10:01:00Z"));

StringBuilder sqlValues = new StringBuilder();

for (int i = 0; i < data.size(); i += 3) {

String col1 = data.get(i).getValue();

String col2 = data.get(i + 1).getValue();

String ts = data.get(i + 2).getValue();

if (sqlValues.length() > 0) {

sqlValues.append(",");

}

sqlValues.append("('").append(col1).append("',").append(col2).append(",'").append(ts).append("')");

}

String sql = "INSERT INTO " + databaseName + "." + tableName + " (col1, col2, ts) VALUES " + sqlValues;

try (CloseableHttpClient httpClient = HttpClients.createDefault()) {

HttpPost httpPost = new HttpPost(TDENGINE_REST_URL);

httpPost.setHeader("Authorization", "Basic " + org.apache.commons.codec.binary.Base64.encodeBase64String((TDENGINE_USER + ":" + TDENGINE_PASSWORD).getBytes()));

httpPost.setEntity(new UrlEncodedFormEntity(List.of(new BasicNameValuePair("sql", sql))));

HttpResponse response = httpClient.execute(httpPost);

int statusCode = response.getStatusLine().getStatusCode();

if (statusCode == 200) {

System.out.println("Data inserted successfully");

} else {

System.out.println("Failed to insert data");

}

} catch (IOException e) {

e.printStackTrace();

}

}

// 查询数据示例

public static void queryData() {

String databaseName = "test_db";

String tableName = "test_table";

String sql = "SELECT * FROM " + databaseName + "." + tableName;

try (CloseableHttpClient httpClient = HttpClients.createDefault()) {

HttpPost httpPost = new HttpPost(TDENGINE_REST_URL);

httpPost.setHeader("Authorization", "Basic " + org.apache.commons.codec.binary.Base64.encodeBase64String((TDENGINE_USER + ":" + TDENGINE_PASSWORD).getBytes()));

httpPost.setEntity(new UrlEncodedFormEntity(List

## 六、常见问题与解决方案

在TDengine与taosAdapter结合进行RESTful接口开发过程中,可能会遇到一些常见问题,以下是对这些问题的分析及相应解决方案:

- **连接失败**:

- **问题描述**:客户端无法连接到taosAdapter提供的RESTful接口,返回连接超时或拒绝连接的错误信息。

- **原因分析**:可能是网络问题,如防火墙阻止了客户端与服务器之间的通信;也可能是taosAdapter服务未正常启动,或者配置的端口被其他程序占用;还可能是主机地址、端口号、用户名、密码等连接参数配置错误。

- **解决方案**:首先检查网络连接,确保客户端和服务器之间的网络畅通,可以通过ping命令测试网络连通性;检查防火墙设置,确保允许客户端访问taosAdapter服务所在的端口,在Linux系统上,可以使用`iptables -I INPUT -p tcp --dport 6041 -j ACCEPT`命令允许访问6041端口(假设taosAdapter使用该端口) ;确认taosAdapter服务已正常启动,使用`systemctl status taosadapter`命令查看服务状态,如果服务未启动,使用`systemctl start taosadapter`命令启动服务;仔细核对连接参数,确保主机地址、端口号、用户名、密码等配置正确无误。

- **数据传输错误**:

- **问题描述**:在进行数据写入或查询时,出现数据传输错误,如数据丢失、数据格式错误等。

- **原因分析**:数据丢失可能是由于网络不稳定,在数据传输过程中出现丢包现象;数据格式错误可能是因为客户端发送的数据格式不符合TDengine的要求,或者在数据解析过程中出现问题。

- **解决方案**:对于网络不稳定导致的数据丢失问题,可以增加重试机制。在代码中,使用循环和异常处理来实现数据传输失败后的重试操作。在Python中使用`requests`库进行数据写入时:

```python

import requests

import time

TDENGINE_REST_URL = "http://localhost:6041/rest/sql"

TDENGINE_USER = "root"

TDENGINE_PASSWORD = "taosdata"

data = [

{

"col1": "value1",

"col2": 100,

"ts": "2023-10-05T10:00:00Z"

}

]

sql_values = []

for item in data:

col1 = item['col1']

col2 = item['col2']

ts = item['ts']

sql_values.append(f"('{col1}', {col2}, '{ts}')")

sql = f"INSERT INTO test_db.test_table (col1, col2, ts) VALUES {','.join(sql_values)}"

max_retries = 3

retry_delay = 2

for retry in range(max_retries):

try:

response = requests.post(TDENGINE_REST_URL, auth=(TDENGINE_USER, TDENGINE_PASSWORD), data=sql)

if response.status_code == 200:

print("Data inserted successfully")

break

except Exception as e:

print(f"Failed to insert data, retry {retry + 1}: {e}")

time.sleep(retry_delay)

这段代码中,设置了最大重试次数为 3 次,每次重试间隔 2 秒。如果数据传输失败,会捕获异常并进行重试,直到成功插入数据或达到最大重试次数。对于数据格式错误问题,要仔细检查数据格式,确保符合 TDengine 的要求。在进行数据写入时,严格按照 TDengine 支持的数据类型和格式组织数据,在使用 JSON 格式传输数据时,确保 JSON 结构正确,字段名称和数据类型与 TDengine 表结构一致。在解析查询结果时,也要根据 TDengine 返回的数据格式进行正确的解析。

  • taosAdapter 无响应
    • 问题描述:客户端发送请求后,taosAdapter 长时间无响应,服务端也没有返回任何错误信息。
    • 原因分析:可能是 taosAdapter 负载过高,无法及时处理请求;也可能是请求处理过程中出现死锁或其他异常情况,导致 taosAdapter 服务挂起;还可能是某些频繁请求的操作(如健康检查语句)导致服务资源耗尽。
    • 解决方案:监控 taosAdapter 的性能指标,如 CPU 使用率、内存占用、请求队列长度等,使用top、htop等工具查看系统资源使用情况 。如果发现 taosAdapter 负载过高,可以考虑优化系统配置,增加服务器资源,如内存、CPU 等;对 taosAdapter 进行性能调优,如调整连接池大小、优化 SQL 语句等。在 taosadapter.toml 配置文件中,可以适当增加[http]部分的max_connections参数值,以提高并发处理能力 。如果是请求处理过程中出现死锁或异常情况,可以通过查看 taosAdapter 的日志文件(默认位于/var/log/taos/taosadapter.log )来排查问题。根据日志信息定位异常原因,如 SQL 语句错误、数据库连接问题等,进行相应的修复。对于由于频繁请求某些操作导致的问题,要优化请求策略。在黑格智能 3D 打印业务从 2.x 升级到 3.x 过程中,微服务通过 restful 方式连接 TDengine 时,taosAdapter 出现无响应但 taosd 服务正常的现象,经排查是大量使用 “show cluster alive” 作为微服务监听语句的频繁请求导致。后续将健康检查语句更换为 “select 1”,顺利解决了这个问题 。

七、总结与展望

通过本文的介绍和实践,我们深入了解了 TDengine 与 taosAdapter 结合在 RESTful 接口开发中的应用。TDengine 作为一款高性能的时序数据库,具备强大的时序数据处理能力,而 taosAdapter 则为 TDengine 提供了便捷的 RESTful 接口支持,使得 TDengine 能够更轻松地与各种应用程序集成。

在实际应用中,TDengine 与 taosAdapter 的结合展现出了诸多优势,便捷的跨平台访问能力,让不同操作系统和编程语言的应用都能与 TDengine 进行交互;简化了系统集成过程,降低了与现有系统集成的难度和成本;灵活的数据交互方式,满足了多样化的应用场景需求。通过开发实战步骤,我们学习了如何搭建环境、设计接口并进行编码实现,掌握了使用 Python 和 Java 调用 RESTful 接口进行数据操作的方法。同时,我们也了解了在开发过程中可能遇到的常见问题及解决方案,为实际项目的开发提供了保障。

展望未来,随着物联网、工业互联网等领域的不断发展,时序数据的处理需求将持续增长。TDengine 和 taosAdapter 也将不断演进和完善。在功能方面,可能会进一步优化 RESTful 接口的性能和稳定性,增加更多对复杂查询和数据分析的支持,以满足企业日益增长的业务需求;在兼容性方面,有望支持更多的协议和标准,与更多的第三方工具和系统实现无缝对接,进一步拓展其应用场景;在生态建设方面,社区可能会更加活跃,吸引更多的开发者参与,共同推动 TDengine 和 taosAdapter 的发展,为时序数据处理领域提供更强大、更完善的解决方案。作为开发者,我们应持续关注 TDengine 和 taosAdapter 的发展动态,不断探索其在不同场景下的应用,充分发挥其优势,为项目的成功实施提供有力支持 。

相关文章:

TDengine 与 taosAdapter 的结合(二)

五、开发实战步骤 &#xff08;一&#xff09;环境搭建 在开始 TDengine 与 taosAdapter 结合的 RESTful 接口开发之前&#xff0c;需要先完成相关环境的搭建&#xff0c;包括 TDengine 和 taosAdapter 的安装与配置&#xff0c;以及相关依赖的安装。 TDengine 安装&#xf…...

OBS 中如何设置固定码率(CBR)与可变码率(VBR)?

在使用 OBS 进行录制或推流时,设置“码率控制模式”(Rate Control)是非常重要的一步。常见的控制模式包括: CBR(固定码率):保持恒定的输出码率,适合直播场景。 VBR(可变码率):在允许的范围内动态调整码率,适合本地录制、追求画质。 一、CBR vs. VBR 的差异 项目CBR…...

优艾智合人形机器人“巡霄”,开启具身多模态新时代

近日&#xff0c;优艾智合-西安交大具身智能机器人研究院公布人形机器人矩阵&#xff0c;其中轮式人形机器人“巡霄”首次亮相。 “巡霄”集成移动导航、操作控制与智能交互技术&#xff0c;具备跨场景泛化能&#xff0c;适用于家庭日常服务、电力设备巡检、半导体精密操作及仓…...

蓝桥杯小白打卡第七天(第十四届真题)

小蓝的金属冶炼转换率问题 小蓝有一个神奇的炉子用于将普通金属 (O) 冶炼成为一种特殊金属 (X) 。 这个炉子有一个称作转换率的属性 (V) &#xff0c;(V) 是一个正整数&#xff0c;这意味着消耗 (V) 个普通金属 (O) 恰好可以冶炼出一个特殊金属 (X) &#xff0c;当普通金属 (…...

excel经验

Q:我现在有一个excel&#xff0c;有一列数据&#xff0c;大概两千多行。如何在这一列中 筛选出具有关键字的内容&#xff0c;并输出到另外一列中。 A: 假设数据在A列&#xff08;A1开始&#xff09;&#xff0c;关键字为“ABC”在相邻空白列&#xff08;如B1&#xff09;输入公…...

【Pandas】pandas DataFrame astype

Pandas2.2 DataFrame Conversion 方法描述DataFrame.astype(dtype[, copy, errors])用于将 DataFrame 中的数据转换为指定的数据类型 pandas.DataFrame.astype pandas.DataFrame.astype 是一个方法&#xff0c;用于将 DataFrame 中的数据转换为指定的数据类型。这个方法非常…...

【Netty4核心原理④】【简单实现 Tomcat 和 RPC框架功能】

文章目录 一、前言二、 基于 Netty 实现 Tomcat1. 基于传统 IO 重构 Tomcat1.1 创建 MyRequest 和 MyReponse 对象1.2 构建一个基础的 Servlet1.3 创建用户业务代码1.4 完成web.properties 配置1.5 创建 Tomcat 启动类 2. 基于 Netty 重构 Tomcat2.1 创建 NettyRequest和 Netty…...

4.6学习总结

包装类 包装类&#xff1a;基本数据类型对应的引用数据类型 JDK5以后新增了自动装箱&#xff0c;自动拆箱 以后获取包装类方法&#xff0c;不需要new&#xff0c;直接调用方法&#xff0c;直接赋值即可 //1.把整数转成二进制&#xff0c;十六进制 String str1 Integer.toBin…...

MySQL学习笔记五

第七章数据过滤 7.1组合WHERE子句 7.1.1AND操作符 输入&#xff1a; SELECT first_name, last_name, salary FROM employees WHERE salary < 4800 AND department_id 60; 输出&#xff1a; 说明&#xff1a;MySQL允许使用多个WHERE子句&#xff0c;可以以AND子句或OR…...

成为社交场的导演而非演员

一、情绪的本质&#xff1a;社交信号而非自我牢笼 进化功能&#xff1a;情绪是人类进化出的原始社交工具。愤怒触发群体保护机制&#xff0c;悲伤唤起同情支持&#xff0c;喜悦巩固联盟关系。它们如同可见光谱&#xff0c;快速传递生存需求信号。双刃剑效应&#xff1a;情绪的…...

怎么使用vue3实现一个优雅的不定高虚拟列表

前言 很多同学将虚拟列表当做亮点写在简历上面&#xff0c;但是却不知道如何手写&#xff0c;那么这个就不是加分项而是减分项了。实际项目中更多的是不定高虚拟列表&#xff0c;这篇文章来教你不定高如何实现。 什么是不定高虚拟列表 不定高的意思很简单&#xff0c;就是不…...

LemonSqueezy: 1靶场渗透

LemonSqueezy: 1 来自 <LemonSqueezy: 1 ~ VulnHub> 1&#xff0c;将两台虚拟机网络连接都改为NAT模式 2&#xff0c;攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 那么攻击机IP为192.168.23.182&#xff0c;靶场IP192.168.23.225 3&#xff0c;对靶机进…...

2025 年山东保安员职业资格考试要点梳理​

山东作为人口大省&#xff0c;保安市场规模庞大。2025 年考试报考条件常规。报名通过山东省各市公安机关指定的培训机构或政务服务窗口&#xff0c;提交资料与其他地区类似。​ 理论考试注重对山东地域文化特色相关安保知识的考查&#xff0c;如在孔庙等文化圣地安保中&#x…...

ARM处理器内核全解析:从Cortex到Neoverse的架构与区别

ARM处理器内核全解析&#xff1a;从Cortex到Neoverse的架构与区别 ARM作为全球领先的处理器架构设计公司&#xff0c;其内核产品线覆盖了从高性能计算到低功耗嵌入式应用的广泛领域。本文将全面解析ARM处理器的内核分类、架构特点、性能差异以及应用场景&#xff0c;帮助读者深…...

网络缓冲区

网络缓冲区分为内核缓冲区和用户态网络缓冲区 我们重点要实现用户态网络缓冲区 1.设计用户态网络缓冲区的原因 ①.生产者和消费者的速度不匹配问题&#xff0c; 需要缓存数据。 ②.粘包处理问题&#xff0c; 不能确保一次系统调用读取或写入完整数据包。 2.代码实现(cha…...

数据仓库的核心架构与关键技术(数据仓库系列二)

目录 一、引言 二、数据仓库的核心架构 三、数据仓库的关键技术 1 数据集成与治理 2 查询优化与性能提升 3 数据共享服务 BI&#xff1a;以Tableau为例 SQL2API&#xff1a;以麦聪QuickAPI为例 4 实时数据处理 四、技术的协同作用 五、总结与展望 六、预告 一、引言…...

基于PyQt5与OpenCV的图像处理系统设计与实现

1. 系统概述 本系统是一个集成了多种经典图像处理算法的图形用户界面(GUI)应用程序,采用Python语言开发,基于PyQt5框架构建用户界面,利用OpenCV库实现核心图像处理功能。 系统支持11种图像处理操作,每种操作都提供参数实时调节功能,并具备原始图像与处理后图像的双视图对…...

如何根据设计稿进行移动端适配:全面详解

如何根据设计稿进行移动端适配&#xff1a;全面详解 文章目录 如何根据设计稿进行移动端适配&#xff1a;全面详解1. **理解设计稿**1.1 设计稿的尺寸1.2 设计稿的单位 2. **移动端适配的核心技术**2.1 使用 viewport 元标签2.1.1 代码示例2.1.2 参数说明 2.2 使用相对单位2.2.…...

什么是大型语言模型(LLM)?哪个大模型更好用?

什么是 LLM&#xff1f; ChatGPT 是一种大型语言模型 (LLM)&#xff0c;您可能对此并不陌生。它以非凡的能力而闻名&#xff0c;已证明能够出色地完成各种任务&#xff0c;例如通过考试、生成产品内容、解决问题&#xff0c;甚至在最少的输入提示下编写程序。 他们的实力现已…...

集合学习内容总结

集合简介 1、Scala 的集合有三大类&#xff1a;序列 Seq、集Set、映射 Map&#xff0c;所有的集合都扩展自 Iterable 特质。 2、对于几乎所有的集合类&#xff0c;Scala 都同时提供了可变和不可变的版本&#xff0c;分别位于以下两个包 不可变集合&#xff1a;scala.collect…...

使用typedef和不使用的区别

使用 typedef 定义的函数指针类型 typedef sensor_drv_params_t* (*load_sensor_drv_func)(); 不使用 typedef 的函数指针声明 sensor_drv_params_t* (*load_sensor_drv_func)(); 这两者看似相似&#xff0c;但在语义和用途上有显著区别。下面将详细解释这两种声明的区别、各…...

基于线性回归模型的汽车燃油效率预测

基于线性回归模型的汽车燃油效率预测 1.作者介绍2.线性回归介绍2.1 线性回归简介2.2 线性回归应用场景 3.基于线性回归模型的汽车燃油效率预测实验3.1 Auto MPG Data Set数据集3.2代码调试3.3完整代码3.4结果展示 4.问题分析 基于线性回归模型的汽车燃油效率预测 1.作者介绍 郝…...

Playwright之自定义浏览器目录访问出错:BrowserType.launch: Executable doesn‘t exist

Playwright之自定义浏览器目录访问出错&#xff1a;BrowserType.launch: Executable doesn’t exist 问题描述&#xff1a; 在使用playwright进行浏览器自动化的时候&#xff0c;配置了自定义的浏览器目录&#xff0c;当按照自定义的浏览器目录启动浏览器进行操作时&#xff0c…...

如何拿到iframe中嵌入的游戏数据

在 iframe 中嵌入的游戏数据是否能被获取&#xff0c;取决于以下几个关键因素&#xff1a; 1. 同源策略 浏览器的同源策略是核心限制。如果父页面和 iframe 中的内容同源&#xff08;即协议、域名和端口号完全相同&#xff09;&#xff0c;那么可以直接通过 JavaScript 访问 …...

优选算法第七讲:分治

优选算法第七讲&#xff1a;分治 1.分治_快排1.1颜色分类1.2排序数组1.3数组中第k个最大元素1.4库存管理II 2.分治_归并2.1排序数组2.2交易逆序对的总数2.3计算右侧小于当前元素的个数2.4翻转对 1.分治_快排 1.1颜色分类 1.2排序数组 1.3数组中第k个最大元素 1.4库存管理II 2.…...

OpenBMC:BmcWeb 处理http请求4 处理路由对象

OpenBMC:BmcWeb 处理http请求2 查找路由对象-CSDN博客 Router::handle通过findRoute获取了FindRouteResponse对象foundRoute void handle(const std::shared_ptr<Request>& req,const std::shared_ptr<bmcweb::AsyncResp>& asyncResp){FindRouteResponse …...

直流电能表计量解决方案适用于光伏储能充电桩基站等场景

多场景解决方案&#xff0c;准确测量 01 市场规模与增长动力 全球直流表市场预测&#xff1a; 2025年市场规模14亿美元&#xff0c;CAGR超15%。 驱动因素&#xff1a;充电桩、光伏/储能、基站、直流配电 市场增长引擎分析&#xff1a; 充电桩随新能源车迅猛增长&#xff…...

x-cmd install | Slumber - 告别繁琐,拥抱高效的终端 HTTP 客户端

目录 核心优势&#xff0c;一览无遗安装应用场景&#xff0c;无限可能示例告别 GUI&#xff0c;拥抱终端 还在为调试 API 接口&#xff0c;发送 HTTP 请求而苦恼吗&#xff1f;还在各种 GUI 工具之间切换&#xff0c;只为了发送一个简单的请求吗&#xff1f;现在&#xff0c;有…...

git修改已经push的commit的message

1.修改信息 2.修改message 3.强推...

STM32 基础2

STM32中断响应过程 1、中断源发出中断请求。 2、判断处理器是否允许中断&#xff0c;以及该中断源是否被屏蔽。 3、中断优先级排队。 4、处理器暂停当前程序&#xff0c;保护断点地址和处理器的当前状态&#xff0c;根据中断类型号&#xff0c;查找中断向量表&#xff0c;转到…...

【STL 之速通pair vector list stack queue set map 】

考list 的比较少 --双端的啦 pair 想下&#xff0c;程序是什么样的. 我是我们要带着自己的思考去学习DevangLic.. #include <iostream> #include <utility> #include <string>using namespace std;int main() {// 第一部分&#xff1a;创建并输出两个 pair …...

深度学习篇---LSTM+Attention模型

文章目录 前言1. LSTM深入原理剖析1.1 LSTM 架构的进化理解遗忘门简介数学表达式实际作用 输入门简介数学表达式后选候选值实际作用 输出门简介数学表达式最终输出实际作用 1.2 Attention 机制的动态特性内容感知位置无关可解释性数学本质 1.3 LSTM与Attention的协同效应组合优…...

React 多个 HOC 嵌套太深,会带来哪些隐患?

在 React 中&#xff0c;使用多个 高阶组件&#xff08;HOC&#xff0c;Higher-Order Component&#xff09; 可能会导致组件层级变深&#xff0c;这可能会带来以下几个影响&#xff1a; 一、带来的影响 1、调试困难 由于组件被多个 HOC 包裹&#xff0c;React 开发者工具&am…...

企业工厂生产线马达保护装置 功能参数介绍

安科瑞刘鸿鹏 摘要 工业生产中&#xff0c;电压暂降&#xff08;晃电&#xff09;是导致电动机停机、生产中断的主要原因之一&#xff0c;给企业带来巨大的经济损失。本文以安科瑞晃电再起动控制器为例&#xff0c;探讨抗晃电保护器在生产型企业工厂中的应用&#xff0c;分析…...

Redis 的五种数据类型面试回答

这里简单介绍一下面试回答、我之前有详细的去学习、但是一直都觉得太多内容了、太深入了 然后面试的时候不知道从哪里讲起、于是我写了这篇CSDN帮助大家面试回答、具体的深入解析下次再说 面试官你好 我来介绍一下Redis的五种基本数据类型 有String List Set ZSet Map 五种基…...

多线程代码案例(定时器) - 3

定时器&#xff0c;是我们日常开发所常用的组件工具&#xff0c;类似于闹钟&#xff0c;设定一个时间&#xff0c;当时间到了之后&#xff0c;定时器可以自动的去执行某个逻辑 目录 Timer 的基本使用 实现一个 Timer 通过这个类&#xff0c;来描述一个任务 通过这个类&…...

基于大模型的GCSE预测与治疗优化系统技术方案

目录 技术方案文档:基于大模型的GCSE预测与治疗优化系统1. 数据预处理模块功能:整合多模态数据(EEG、MRI、临床指标等),标准化并生成训练集。伪代码流程图2. 大模型架构(Transformer-GNN混合模型)功能:联合建模时序信号(EEG)与空间结构(脑网络)。伪代码流程图3. 术…...

IntelliJ IDEA 中 Continue 插件使用 DeepSeek-R1 模型指南

IntelliJ IDEA 中 Continue 插件使用 DeepSeek-R1 模型指南 Continue 是一款开源的 AI 编码助手插件&#xff0c;支持 IntelliJ IDEA 等 JetBrains 系列 IDE。它可以通过连接多种语言模型&#xff08;如 DeepSeek-R1&#xff09;提供实时代码生成、问题解答和单元测试生成等功…...

Valgrind——内存调试和性能分析工具

文章目录 一、Valgrind 介绍二、Valgrind 功能和使用1. 主要功能2. 基本用法2.1 常用选项2.2 内存泄漏检测2.3 详细报告2.4 性能分析2.5 多线程错误检测 三、在 Ubuntu 上安装 Valgrind四、示例1. 检测内存泄漏2. 使用未初始化的内存3. 内存读写越界4. 综合错误 五、工具集1. M…...

京东API智能风控引擎:基于行为分析识别恶意爬虫与异常调用

京东 API 智能风控引擎基于行为分析识别恶意爬虫与异常调用&#xff0c;主要通过以下几种方式实现&#xff1a; 行为特征分析 请求频率&#xff1a;正常用户对 API 的调用频率相对稳定&#xff0c;受到网络延迟、操作速度等因素限制。若发现某个 IP 地址或用户在短时间内对同一…...

Swift 解 LeetCode 250:搞懂同值子树,用递归写出权限系统检查器

文章目录 前言问题描述简单说&#xff1a;痛点分析&#xff1a;到底难在哪&#xff1f;1. 子树的概念搞不清楚2. 要不要“递归”&#xff1f;递归从哪开始&#xff1f;3. 怎么“边遍历边判断”&#xff1f;这套路不熟 后序遍历 全局计数器遍历过程解释一下&#xff1a;和实际场…...

Nginx搭建API网关服务教程-系统架构优化 API统一管理

超实用&#xff01;用Nginx搭建API网关服务&#xff0c;让你的系统架构更稳更强大&#xff01;&#x1f680; 亲们&#xff0c;今天来给大家种草一个超级实用的API网关搭建方案啦&#xff01;&#x1f440; 在如今的Web系统架构中&#xff0c;一个稳定、高性能、可扩展的API网…...

SQL2API是什么?SQL2API与BI为何对数据仓库至关重要?

目录 一、SQL2API是什么&#xff1f; 二、SQL2API的历史演变&#xff1a;从数据共享到服务化革命 1990年代&#xff1a;萌芽于数据仓库的数据共享需求 2010年代初&#xff1a;数据中台推动服务化浪潮 2022年左右&#xff1a;DaaS平台的兴起 2025年代&#xff1a;麦聪定义…...

CentOS 7无法上网问题解决

CentOS 7无法上网问题解决 问题 配置了桥接模式以后&#xff0c;能够ping通本地IP但是无法ping通www.baidu.com 这里的前提是VWare上已经对虚拟机桥接模式网卡做了正确的选择&#xff0c;比如我现在选择的就是当前能够上外网的网卡&#xff1a; 问题根因 DNS未正确配置。…...

优化 Web 性能:使用 WebP 图片(Uses WebP Images)

在 Web 开发中&#xff0c;图片资源的优化是提升页面加载速度和用户体验的关键。Google 的 Lighthouse 工具在性能审计中特别推荐“使用 WebP 图片”&#xff08;Uses WebP Images&#xff09;&#xff0c;因为 WebP 格式在保持视觉质量的同时显著减少文件大小。本文将基于 Chr…...

SQL121 创建索引

-- 普通索引 CREATE INDEX idx_duration ON examination_info(duration);-- 唯一索引 CREATE UNIQUE INDEX uniq_idx_exam_id ON examination_info(exam_id);-- 全文索引 CREATE FULLTEXT INDEX full_idx_tag ON examination_info(tag);描述 现有一张试卷信息表examination_in…...

Leetcode - 周赛443

目录 一、3502. 到达每个位置的最小费用二、3503. 子字符串连接后的最长回文串 I三、3504. 子字符串连接后的最长回文串 II四、3505. 使 K 个子数组内元素相等的最少操作数 一、3502. 到达每个位置的最小费用 题目链接 本题是一道脑筋急转弯&#xff0c;实际就是计算前缀最小…...

dolphinscheduler单机部署链接oracle

部署成功请给小编一个赞或者收藏激励小编 1、安装准备 JDK版本:1.8或者1.8oracle版本&#xff1a;19Coracle驱动版本&#xff1a;8 2、安装jdk 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/#java8 下载后上传到/tmp目录下。 然后执行下面命…...

Three.js 系列专题 5:加载外部模型

内容概述 Three.js 支持加载多种 3D 文件格式(如 GLTF、OBJ、FBX),这让开发者可以直接使用专业建模软件(如 Blender、Maya)创建的复杂模型。本专题将重点介绍 GLTF 格式的加载,并调整模型的位置和材质。 学习目标 理解常见 3D 文件格式及其特点。掌握使用 GLTFLoader 加…...

【C++算法】50.分治_归并_翻转对

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a;图解 题目链接&#xff1a; 493. 翻转对 题目描述&#xff1a; 解法 分治 策略一&#xff1a;计算当前元素cur1后面&#xff0c;有多少元素的两倍比我cur1小&#xff08;降序&#xff09; 利用单…...