IK分词器热刷新词库实践分享

目录

前言

什么是分词器?

ik分词器简介

ik分词器和默认分词器的对比

ik分词器介绍

ik分词器的分词问题

自定义词库

主配置解说

通过配置文件自定义词库

Step1: 新建自定义分词库

Step2: 将我们的自定义词添加到ik的配置文件中

Step3: 重启es,查看分词

配置化方式自定义词库存在的问题

热更新词库方案

ik分词器热更新词库实践

IK分词器源码下载

导入maven工程

源码中词典加载大体流程

修改源码

修调整elasticsearch.version

在pom文件中添加mysql驱动器依赖

创建数据库配置文件jdbc-reload.properties,放在IK项目的config文件夹下

新增HotDictReloadThread类

修改org.wltea.analyzer.dic.Dictionary#loadMainDict方法

修改org.wltea.analyzer.dic.Dictionary#loadStopWordDict方法

org.wltea.analyzer.dic.Dictionary#initial调用HotDictReloadThread方法

修改插件的权限

建立数据库表

打包

加入依赖

package

安装

测试验证

关键词验证

1. “水平思维”关键词验证

2. 网络流行语“他是显眼包”验证

3. 网络流行语“香菇蓝瘦”验证

停用词验证

1. “我是熊二呢”短语验证

2. “一个老流氓”短语验证

总结


前言

本篇文章介绍了ElasticSearch分词器相关内容,介绍了什么是分词器,什么是ik分词器,ik分词器目前存在的问题以及如何通过修改ik分词器的源码来实现热更新词库。

什么是分词器?

Elasticsearch是基于倒排索引来实现搜索功能,而倒排索引的基础就是分词。Elasticsearch默认的分词器支持英文的分词,因为分词很简单,基本基于空格就可以分出来,而汉语的分词则困难很多。分词是把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个 匹配操作。

ik分词器简介

ik分词器和默认分词器的对比

默认的中文分词器是将每个字看成一个词,比如"中国人很喜欢吃油条",会被分为“中 国 人 很 喜 欢 吃 油 条”这几个字,而采用IK分词器 可以分为“中国人 很 喜欢 吃 油条”,看下上面分词后的结果,肯定是 ik 的分词结果比较符合中文。

以“中国人很喜欢吃油条”这个句话为例,标准分词器会将这句话分为:“中”  “国”  “人”  “很”  “喜” “欢” “吃”  “油”  “条”,例如:

image.png

可以看出来,很不符合中文词的表述习惯,因为这段话不仅仅可以分为这10个字,还可以组成如:“中国”,“中国人”,“喜欢”等等。

我们来看看ik分词器的分词效果,以ik分词器的ik_max_word为例,“中国人很喜欢吃油条”这句话就可以拆成很多种,如:“中国人”,“中国”,“国人”,“很喜欢”等,例如:

image.png

从上面分词后的结果可以看出,肯定是ik分词结果比较符合中文习惯

ik分词器介绍

在搜索引擎领域,比较成熟和流行的中文分词器,就是ik分词器,它提供了2种分词的模式,分别为ik_max_word和ik_smart

  • ik_max_word:将需要分词的文本做最小粒度的拆分,尽量分更多的词

  • ik_smart:将需要分词的文本做最大粒度的拆分

ik_max_word 的分词效果

语句

POST _analyze
{"text": ["中国人很喜欢吃油条"], "analyzer": "ik_max_word"
}

结果

{"tokens" : [{"token" : "中国人","start_offset" : 0,"end_offset" : 3,"type" : "CN_WORD","position" : 0},{"token" : "中国","start_offset" : 0,"end_offset" : 2,"type" : "CN_WORD","position" : 1},{"token" : "国人","start_offset" : 1,"end_offset" : 3,"type" : "CN_WORD","position" : 2},{"token" : "很喜欢","start_offset" : 3,"end_offset" : 6,"type" : "CN_WORD","position" : 3},{"token" : "喜欢吃","start_offset" : 4,"end_offset" : 7,"type" : "CN_WORD","position" : 4},{"token" : "喜欢","start_offset" : 4,"end_offset" : 6,"type" : "CN_WORD","position" : 5},{"token" : "吃油","start_offset" : 6,"end_offset" : 8,"type" : "CN_WORD","position" : 6},{"token" : "油条","start_offset" : 7,"end_offset" : 9,"type" : "CN_WORD","position" : 7}]
}

ik_smart的分词效果

语句

POST _analyze
{"text": ["中国人很喜欢吃油条"], "analyzer": "ik_smart"
}

结果

{"tokens" : [{"token" : "中国人","start_offset" : 0,"end_offset" : 3,"type" : "CN_WORD","position" : 0},{"token" : "很喜欢","start_offset" : 3,"end_offset" : 6,"type" : "CN_WORD","position" : 1},{"token" : "吃","start_offset" : 6,"end_offset" : 7,"type" : "CN_CHAR","position" : 2},{"token" : "油条","start_offset" : 7,"end_offset" : 9,"type" : "CN_WORD","position" : 3}]
}

ik分词器的分词问题

虽然通过ik_smart和ik_max_word可以做到中文分词效果,但是如果对于一些网络流行语或者我们公司内部的一些自定义的短语,无法做到分词的效果,如网络流行语:“香菇蓝瘦”,我们期望的是“香菇蓝瘦”也是其中的一个词,然后并没有

image.png

如公司的一些短语,如“星云思维”、“水平思维”,我们期望它成为一个完整的词,然后确没有

image.png

image.png

那么如何去按照我们定义的词去进行分词自适应呢?

自定义词库

主配置解说

ik配置文件地址:/usr/share/elasticsearch/plugins/ik/config 目录下都是存放配置文件

image.png

下面是这些主要配置文件含义:

  • IKAnalyzer.cfg.xml:用来配置自定义词库

  • main.dic:原生内置的中文词库,总共有27万多条,只要是这些单词,都会被分在一起,每个单词占据一行

  • quantifier.dic:放了一些单位相关的词

  • suffix.dic:放了一些后缀

  • surname.dic:中国的姓氏

  • stopword.dic:英文停用词

  • preposition.dic:介词词典

IKAnalyzer.cfg.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties><comment>IK Analyzer 扩展配置</comment><!--用户可以在这里配置自己的扩展字典 --><entry key="ext_dict"></entry><!--用户可以在这里配置自己的扩展停止词字典--><entry key="ext_stopwords"></entry><!--用户可以在这里配置远程扩展字典 --><!-- <entry key="remote_ext_dict">words_location</entry> --><!--用户可以在这里配置远程扩展停止词字典--><!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

ik原生最重要的两个配置文件

  • main.dic:包含了原生的中文词语,会按照这个里面的词语去分词

  • stopword.dic:包含了英文的停用词。custom/ext_stopword.dic 中包含了中文的一些扩展词

什么是停用词?与其他词相比,功能词没有什么实际含义,比如'the'、'is'、'at'、'which'、'on'等。

通过配置文件自定义词库

通过配置化的方式新增词库主要分为3步,分别为:

1. 新建自定义分词库

2. 添加到ik的配置文件中

3. 重启es,查看分词

下面介绍一下这3步的具体配置

Step1: 新建自定义分词库

我们在/usr/share/elasticsearch/plugins/ik/config目录下新建一个文件夹custom,然后建一个dic文件(zj.dic),如:

image.png

把这些热门词放到该文件中,如:

image.png

Step2: 将我们的自定义词添加到ik的配置文件中

image.png

Step3: 重启es,查看分词

重启es,然后在kibana上查看分词

image.png

image.png

这样我们通过配置化的方式实现了分词效果

配置化方式自定义词库存在的问题

我们使用配置化的方式自定义词库的时候,每次都得重启,而且得逐个节点依次修改,是不是有点不方便呢?这种方式的主要缺点有:

  • 每次添加完词库,都要重启es才能生效,非常麻烦

  • es是分布式的,生产环境一般几十个个es节点,每次添加完词库,然后重启节点,可想而知......

热更新词库方案

目前ik分词器热更新词库的方案有两种

  • 修改ik分词器源码,后台启动一个线程,每隔一段时间从MySQL数据库中,抽取数据,进行自动加载词库

  • 基于ik分词器原生的热更新方案,部署一个web服务器,提供一个http接口,通过modified和tag两个http响应头,来提供词语的热更新

推荐第一种方案修改ik分词器源码, 第二种方案ik git社区官方都不建议采用,不太稳定。下面也是围绕着第一种方案进行源码改造来实现热更新词库

ik分词器热更新词库实践

IK分词器源码下载

下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases

我选择的版本是7.9.3的版本,选中图中的Source code(zip)进行下载

image.png

导入maven工程

image.png

源码中词典加载大体流程

ik分词器实现了ES的AnalysisPlugin接口,通过工厂方法初始化词典,加载默认配置

image.png

image.png

image.png

默认会根据DefaultConfiguration找到主词典和中文量词词典路径,同时DefaultConfiguration会根据classpath下配置文件IKAnalyzer.cfg.xml,找到扩展词典和停止词典路径,用户可以在该配置文件中配置自己的扩展词典和停止词典。找到个词典路径后,初始化Dictionary.java,Dictionary是单例的。在Dictionary的构造函数中加载词典。Dictionary是IK的词典管理类,真正的词典数据是存放在DictSegment中,该类实现了一种树结构,如下图。

image.png

举个例子,要对字符串“A股市场”进行分词,首先拿到字符串的第一个字符'A',在上面的tree中可以匹配到A节点,然后拿到字符串第二个字符'股',首先从前一个节点A往下找,我们找到了股节点,股是一个终点节点。所以,“A股“是一个词。

Dictionary加载主词典,以,将主词典保存到它的_MainDict字段中,加载完主词典后,立即加载扩展词典,扩展词典同样保存在_MainDict中。

image.png

fillSegment方法是DictSegment加载单个词的核心方法,charArray是词的字符数组,先是从存储节点搜索词的第一个字符开始,如果不存在则创建一个节点用于存储第一个字符,后面递归存储,直到最后一个字符。

image.png

image.png

因此,我们只需要在加载加载主词典及扩展词典的时候,通过fillSegment方法填充词典即可,下面介绍具体的源码修改流程。

修改源码

简单说下整体思路: 开启一个后台线程,扫描mysql中定义的表,加载数据。

修调整elasticsearch.version

本次下载的是7.9.3版本,但是下载下来后是7.4.0版本,因为我用的是7.9.3版本的ES这里需要改一下版本

image.png

修改为:

image.png

在pom文件中添加mysql驱动器依赖

<!--mysql驱动-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.29</version>
</dependency>

创建数据库配置文件jdbc-reload.properties,放在IK项目的config文件夹下

jdbc.url=jdbc:mysql://10.xxx.xxx.XX:3306/canal-test?serverTimezone=UTC
jdbc.user=ueranme
jdbc.password=password
jdbc.reload.extend.sql=select word from es_extra_main
jdbc.reload.stop.sql=select word from es_extra_stopword
# 间隔时间 毫秒
jdbc.reload.interval=10000

reload间隔,1秒钟轮训一次

新增HotDictReloadThread类

在org.wltea.analyzer.dic目录下,新增一个HotDictReloadThread类,死循环去调用Dictionary.getSingleton().reLoadMainDict(),重新加载词典,HotDictReloadThread结构如下:

package org.wltea.analyzer.dic;import org.wltea.analyzer.help.ESPluginLoggerFactory;/*** @author * @version 1.0* @date 2024/1/12 下午7:21* <p>Copyright: Copyright (c) 2024<p>*/
public class HotDictReloadThread implements Runnable {private static final org.apache.logging.log4j.Logger logger = ESPluginLoggerFactory.getLogger(HotDictReloadThread.class.getName());@Overridepublic void run() {while (true) {logger.info("[======HotDictReloadThread======] begin to reload hot dict from dataBase......");Dictionary.getSingleton().reLoadMainDict();}}
}

看下reLoadMainDict这个方法的执行逻辑

image.png

reLoadMainDict方法的核心逻辑有两块:

  • tmpDict.loadMainDict():加载主词库

  • tmpDict.loadStopWordDict():加载停用词词库

由此可以看出,只要我们把读取数据库的逻辑放到这两个方法里面就可以了,下面我们分别来修改这两个方法。

修改org.wltea.analyzer.dic.Dictionary#loadMainDict方法

通过修改loadMainDict来读取MySQL中的主词库,来实现热加载,修改的点如下:

增加this.loadMySQLExtDict(),该方法就是将MySQL表中的数据加载到词库中

image.png

loadMySQLExtDict()方法的主体逻辑是通过JDBC查询MySQL

代码如下:

private static Properties prop = new Properties();static {try {Class.forName("com.mysql.cj.jdbc.Driver");} catch (ClassNotFoundException e) {logger.error("error", e);}
}/*** 从mysql加载热更新词典*/
private void loadMySQLExtDict() {Connection conn = null;Statement stmt = null;ResultSet rs = null;try {Path file = PathUtils.get(getDictRoot(), "jdbc-reload.properties");prop.load(new FileInputStream(file.toFile()));logger.info("[==========]jdbc-reload.properties");for(Object key : prop.keySet()) {logger.info("[==========]" + key + "=" + prop.getProperty(String.valueOf(key)));}logger.info("[==========]query hot dict from mysql, " + prop.getProperty("jdbc.reload.extend.sql") + "......");conn = DriverManager.getConnection(prop.getProperty("jdbc.url"),prop.getProperty("jdbc.user"),prop.getProperty("jdbc.password"));stmt = conn.createStatement();rs = stmt.executeQuery(prop.getProperty("jdbc.reload.extend.sql"));while(rs.next()) {String theWord = rs.getString("word");logger.info("[==========]hot word from mysql: " + theWord);_MainDict.fillSegment(theWord.trim().toCharArray());}Thread.sleep(Integer.valueOf(String.valueOf(prop.get("jdbc.reload.interval"))));} catch (Exception e) {logger.error("erorr", e);} finally {if(rs != null) {try {rs.close();} catch (SQLException e) {logger.error("error", e);}}if(stmt != null) {try {stmt.close();} catch (SQLException e) {logger.error("error", e);}}if(conn != null) {try {conn.close();} catch (SQLException e) {logger.error("error", e);}}}
}

修改org.wltea.analyzer.dic.Dictionary#loadStopWordDict方法

在loadStopWordDict方法中增加loadMySQLStopWordDict,该方法实现从MySQL中加载停用词到词典中

image.png

loadMySQLStopWordDict实现代码为:

/*** 从mysql加载停用词*/
private void loadMySQLStopWordDict() {Connection conn = null;Statement stmt = null;ResultSet rs = null;try {Path file = PathUtils.get(getDictRoot(), "jdbc-reload.properties");prop.load(new FileInputStream(file.toFile()));logger.info("[====loadMySQLStopWordDict======] jdbc-reload.properties");for(Object key : prop.keySet()) {logger.info("[==========]" + key + "=" + prop.getProperty(String.valueOf(key)));}logger.info("[==========]query hot stop word dict from mysql, " + prop.getProperty("jdbc.reload.stop.sql") + "......");conn = DriverManager.getConnection(prop.getProperty("jdbc.url"),prop.getProperty("jdbc.user"),prop.getProperty("jdbc.password"));stmt = conn.createStatement();rs = stmt.executeQuery(prop.getProperty("jdbc.reload.stop.sql"));while(rs.next()) {String theWord = rs.getString("word");logger.info("[==========]hot stop word from mysql: " + theWord);_StopWords.fillSegment(theWord.trim().toCharArray());}Thread.sleep(Integer.valueOf(String.valueOf(prop.get("jdbc.reload.interval"))));} catch (Exception e) {logger.error("error", e);} finally {if(rs != null) {try {rs.close();} catch (SQLException e) {logger.error("error", e);}}if(stmt != null) {try {stmt.close();} catch (SQLException e) {logger.error("error", e);}}if(conn != null) {try {conn.close();} catch (SQLException e) {logger.error("error", e);}}}
}

org.wltea.analyzer.dic.Dictionary#initial调用HotDictReloadThread方法

image.png

修改插件的权限

image.png

grant {// needed because of the hot reload functionalitypermission java.net.SocketPermission "*", "connect,resolve";permission java.lang.RuntimePermission "setContextClassLoader";
};

如何还不行的话,切换到/usr/share/elasticsearch/jdk/conf/security目录下,在java.policy文件最后一行加上

permission java.lang.RuntimePermission "setContextClassLoader";

如果还有java.net.SocketPermission的报错,则在java.policy文件的后面再加上

permission java.net.SocketPermission "*", "connect,resolve";

image.png

建立数据库表

CREATE TABLE `es_extra_main`
(`id`          int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`word`        varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '词',`is_deleted`  tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',`update_time` timestamp(6)                       NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP (6) COMMENT '更新时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `es_extra_stopword`
(`id`          int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`word`        varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '词',`is_deleted`  tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',`update_time` timestamp(6)                       NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP (6) COMMENT '更新时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

打包

加入依赖

将MySQL的jar包依赖加入进来,否则打包会缺少jar包保持错。

image.png

<include>mysql:mysql-connector-java</include>

package

打包成zip文件,然后加压成文件夹

image.png

安装

将elasticsearch-analysis-ik-7.9.3.zip文件拷贝到/usr/share/elasticsearch/plugins/ik目录下:

cp elasticsearch-analysis-ik-7.9.3.zip /usr/share/elasticsearch/plugins/ik/

解压

unzip elasticsearch-analysis-ik-7.9.3.zip

image.png

然后重启es和kibana,可以看到es已经开始加载词库了

image.png

测试验证

在数据库表中中新增下面自己的想要的关键词,然后去Kibana中做测试验证

关键词验证

1. “水平思维”关键词验证

未在数据中插入词库验证

image.png

在数据中插入词库验证,插入“水平思维”

image.png

image.png

分词的效果

image.png

2. 网络流行语“他是显眼包”验证

在数据中插入网络流行语“显眼包”验证,插入“他是显眼包”

插入之前

image.png

数据库中增加“显眼包”,验证

image.png

image.png

3. 网络流行语“香菇蓝瘦”验证

image.png

image.png

image.png

停用词验证

停用词指的是有些词是关键词,但是出于某些业务场景,不想使用这些关键词被检索到,可以将这些词语放到停用词典

1. “我是熊二呢”短语验证

验证前,测试短语“我是熊二呢”

image.png

我们将“呢”、“二”放到停用词中

image.png

在kibana上验证,发现“呢”、“二”已经没了

image.png

2. “一个老流氓”短语验证

验证前,测试短语“一个老流氓”,分词后的效果为:

image.png

我们发现“流氓”也在其中,对于这种污秽的言辞,我们希望屏蔽它,营造一个良好的网络环境,我们将“流氓”加到停用词库中,再进行测试

image.png

我们再次运行,发现“流氓”已经没了,达到了我们验证的效果

image.png

总结

本文主要讲解了什么是ik分词器,如何通过配置化的方式实现自定义词库,配置化方式存在的一些问题,以及如何通过修改ik分词器源码来实现扩展词库以及停用词库热刷新,该实践证明了通过该方案实现的可行性,后续有项目需要基于es分词器实现热刷新,可以借鉴。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/33238.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

黑盒测试中的完整性测试:确保系统的功能完整性

在软件开发过程中&#xff0c;为了保证系统的质量和可靠性&#xff0c;测试是一个不可或缺的环节。而黑盒测试作为常用的测试方法之一&#xff0c;以用户的角度出发&#xff0c;测试系统在不知道内部工作原理的情况下&#xff0c;对输入数据的处理和输出结果的正确性进行验证。…

MySQL字典数据库设计与实现 ---项目实战

软件准备✍&#xff1a;Mysql与Navicat可视化命令大全 ----项目实战 文章前言部分 目录 一.摘要 二.设计内容 三.项目实现 一.摘要 本项目关注于字典数据库表结构的设计和数据管理。通过现有的sql文件&#xff0c;实现system_dict_type和system_dict_data两个数据表。随后…

去中心化衍生品协议内卷,ZKX 能否通过差异化道路突出重围?

去中心化衍生品赛道目前从协议类型来看&#xff0c;主要有两种解决方案&#xff1a; 以 GMX 为代表的 Vault 模式&#xff0c;LP 作为交易者的对手盘&#xff0c;由 Orcale 喂价决定交易价格。 以 dYdX 为代表的订单薄模式&#xff0c;链下撮合链上结算。 这两种解决方案虽然…

Redis-数据类型-Hash

文章目录 1、查看redis是否启动2、通过客户端连接redis3、切换到db3数据库4、插入新数据返回15、获取指定哈希&#xff08;hash&#xff09;对象的所有字段&#xff08;field&#xff09;名6、获取存储在指定哈希&#xff08;hash&#xff09;对象中的所有字段&#xff08;fiel…

Javascript中的this关键字指向

this关键字介绍 不同情况下的this 1.对象调用方法中的this 2.在全局使用this(单独使用) 3.函数中的this 4.函数严格模式下 5.事件中的this 6.构造函数中的this 7.箭头函数没有this call()、apply()、bind() 的用法 this关键字介绍 面向对象语言中 this 表示当前对象…

Charles 显示内存不足解决方法

弹窗出现&#xff1a;Charles is running low on memory. Recording has been stopped. Please clear the session to free memory and continue recording. 官网解决方法&#xff1a; Charles runs out of memory After recording for a while Charles will run low on ava…

喜讯:ISO年度审核通过!

在数字化时代&#xff0c;质量是我们不变的追求。近日&#xff0c;矩阵起源迎来了一个值得庆祝的时刻——三项ISO体系年度考核顺利通过&#xff01;分别为&#xff1a;ISO9001 质量管理体系标准认证、ISO20000信息技术服务管理体系认证及ISO27001 信息安全管理体系认证。 ISO标…

Grafana+Prometheus(InfluxDB)+Jmeter使用Nginx代理搭建可视化性能测试监控平台

前言 在这篇博客文章中&#xff0c;将分享JMeter > Prometheus(InfluxDB) > Grafana的集成&#xff0c;以及Nginx端口反向代理各服务的端口。 背景 在JMeter插件库中&#xff0c;有一些后端监听器可供Kafka、ElasticSearch和Azure使用。默认情况下&#xff0c;JMeter支…

探索 Screen:一个强大的终端复用工具

在日常的系统管理和开发工作中&#xff0c;我们经常需要同时运行多个终端任务&#xff0c;或者需要在一个终端会话中保持任务的持续运行&#xff0c;即使我们断开了与服务器的连接。这时&#xff0c;screen 命令就成为了一个非常有用的工具。本文将详细介绍 screen 的功能、使用…

苹果加码AI合作:继OpenAI后再携手Meta|TodayAI

两家长期竞争对手的合作前景 近日&#xff0c;据《华尔街日报》报道&#xff0c;苹果公司&#xff08;Apple&#xff09;和Meta公司&#xff08;Facebook母公司&#xff09;正在就一项潜在合作进行讨论&#xff0c;旨在将Meta的生成式AI模型整合到Apple Intelligence中。这一合…

nginx实现反向代理出现502的解决方法

目录 1. 出现原因 1.1. 防火墙拦截了端口 1.1.1. 使用 iptables 1.1.2. 使用 firewall-cmd&#xff08;适用于 CentOS/RHEL 7&#xff09; 1.2. docker容器中的ip和宿主机ip不一致 1. 出现原因 这里我是用的docker容器来进行nginx的启动的&#xff0c;在我们用nginx的配置…

Power Apps

目录 一、引言1、Power Apps2、应用场景3、Power Apps的优势与前景4、补充 二、数据源介绍1、SharePoint2、Excel3、Dataverse4、SQL5、补充&#xff08;1&#xff09;OneDrive 三、Power Apps应用类型1、画布应用2、模型驱动应用3、网站 Power Pages 四、Power Automate五、Po…

如何提高LabVIEW开发的效率?

提高LabVIEW开发效率对于工程师和研究人员来说非常重要&#xff0c;因为这不仅能缩短开发周期&#xff0c;还能提高系统的可靠性和可维护性。以下从多个角度详细分析如何提高LabVIEW开发的效率。 1. 项目规划与管理 1.1 明确需求 在项目开始前&#xff0c;详细明确项目需求&…

解决Playwright在Ubuntu下启动报错的问题:从环境到依赖的全面优化

在Ubuntu环境中使用Python进行web自动化测试时,Playwright是一个非常强大的工具。然而,在具体实践中,我们常常会遇到各种错误,尤其是在不同Python版本和依赖版本之间切换时。本文将详细介绍如何应对这些问题,并提供一些解决方法。 问题背景 在使用Playwright时,我们有时…

天气冷电脑不能启动找不到硬盘

https://diy.zol.com.cn/2004/0611/101994.shtml

微信小程序开发用uni-app开发框架还是微信原生开发?

小程序依托微信入口&#xff0c;借助微信生态对流量补充的优势&#xff0c;拥有超12亿微信用户群体&#xff0c;微信小程序成为流量变现的一个重要通道。 从商家角度来说&#xff0c;借助小程序触达和获取线上用户的门槛更低&#xff0c;用户路径和交易转化也更快。同时&#…

Jmeter多用户token使用问题

背景 在测试的时候&#xff0c;经常会有模拟用户登录&#xff0c;拿到用户 token 后再去请求接口的场景。 这个模拟用户登录就会分为两种&#xff0c;一种是单用户&#xff0c;另一种是多用户。 日常自动化测试的时候可能一个用户对应 n 个用例就可以满足大多数场景&#xf…

MySQL集群高可用架构之MySQL InnoDB Cluste

今天我将详细的为大家介绍Centos 7.5 基于 MySQL 5.7的 InnoDB Cluster 多节点高可用集群环境部署的相关知识&#xff0c;希望大家能够从中收获多多&#xff01;如有帮助&#xff0c;请点在看、转发支持一波&#xff01;&#xff01;&#xff01; 一、MySQL InnoDB Cluster 介…

RK3568平台(音频篇)音频ALSA框架

一.ALSA框架简介 ALSA表示先进linux声音架构&#xff08;Advanced Linux Sound Archiecture&#xff09;&#xff0c;它由一系列的内核驱动、应用程序编程接口&#xff08;API&#xff09;以及支持linux下声音的应用程序组成、 ALSA项目发起的原有是linux下的声卡驱动&#x…

PAT A1016. 最短路径

题意 有N个结点围成一个圈&#xff0c;相邻两个点之间的距离已知&#xff0c;且每次只能移动到相邻点。然后给出M个询问&#xff0c;每个询问给出两个数字A和B即结点编号(1≤A,B≤N)&#xff0c;求从A号结点到B号结点的最短距离。样例解释 如图3-2所示,共有5个结点&#xff0c;…