单机多节点 elasticsearch 集群安全认证

news2025/2/12 8:02:03

es 版本:7.6.2
部署环境:CentOS Linux release 7.6.1810 (Core)

一:生成 ca 证书

cd 到 es 的安装目录,并执行下面的命令来生成 ca 证书:

./bin/elasticsearch-certutil ca Elasticsearch

碰到第一个直接回车,不用管。

碰到第二个输入密码,例如 123456。

完成后会在当前目录生成一个文件:elastic-stack-ca.p12

二:用 ca 证书签发节点证书

./bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12

需要输入密码时就直接输入刚才的密码,需要输入路径的地方不要输入地址,就直接回车,之后会生成一个 elastic-certificates.p12 文件。

三:将节点证书迁移到指定目录

先创建目录用于存放节点证书:

mkdir ./config/certificates

移动节点证书到该目录:

mv ./elastic-certificates.p12 ./config/certificates/

赋值权限给非 root 用户(如自己创建的 es 用户),不然会出现无法操作的问题:

chmod 777 ./config/certificates/elastic-certificates.p12
chown -R es:es ./config/certificates

四:将凭证复制到集群中的每一个 es 节点

就是在每个 es 节点都创建 certificates 目录,并将之前生成的 elastic-certificates.p12 证书复制到该目录(不再需要重新生成啦)。

五:修改 es 配置文件

每一个 es 节点都需要修改

下面是我创建的 3 个节点的配置文件:

es-9200 节点:

# 集群名称,三台集群,要配置相同的集群名称!!!
cluster.name: es-cluster
# 节点名称
node.name: es-9200
# 是否有资格被选举为master,ES默认集群中第一台机器为主节点
node.master: true
# 是否存储数据
node.data: true
#最⼤集群节点数,为了避免脑裂,集群节点数最少为 半数+1
node.max_local_storage_nodes: 3
# 修改 network.host 为 0.0.0.0,表示对外开放,如对特定ip开放则改为指定ip
network.host: 192.168.1.101
# 设置对外服务http端口,默认为9200
http.port: 9200
# 内部节点之间沟通端口
transport.tcp.port: 9901
# 候选主节点的设备地址,在开启服务后可以被选为主节点
discovery.seed_hosts: ["192.168.1.101:9901","192.168.1.101:9902","192.168.1.101:9903"]
# 初始化一个新的集群时需要此配置来选举 master
cluster.initial_master_nodes: ["es-9200"]
# 数据和日志目录
#path.data: /data/es/data
#path.logs: /data/es/logs
# 设置集群中N个节点启动时进行数据恢复,默认为1
gateway.recover_after_nodes: 3 

#bootstrap.memory_lock: true
#bootstrap.system_call_filter: false

# 跨域,如果安装了 elasticsearch-head 插件,那么前两个配置也会用到
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization,X-Requested-With,Content-Type,Content-Length
# 安全认证
xpack.security.enabled: true
xpack.security.authc.accept_default_password: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: /opt/module/es-9200/config/certificates/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: /opt/module/es-9200/config/certificates/elastic-certificates.p12

es-9300 节点:

# 集群名称,三台集群,要配置相同的集群名称!!!
cluster.name: es-cluster
# 节点名称
node.name: es-9300
# 是否有资格被选举为master,ES默认集群中第一台机器为主节点
node.master: true
# 是否存储数据
node.data: true
#最⼤集群节点数,为了避免脑裂,集群节点数最少为 半数+1
node.max_local_storage_nodes: 3
# 修改 network.host 为 0.0.0.0,表示对外开放,如对特定ip开放则改为指定ip
network.host: 192.168.1.101
# 设置对外服务http端口,默认为9200
http.port: 9300
# 内部节点之间沟通端口
transport.tcp.port: 9902
# 候选主节点的设备地址,在开启服务后可以被选为主节点
discovery.seed_hosts: ["192.168.1.101:9901","192.168.1.101:9902","192.168.1.101:9903"]
# 初始化一个新的集群时需要此配置来选举 master
cluster.initial_master_nodes: ["es-9200"]
# 数据和日志目录
#path.data: /data/es/data
#path.logs: /data/es/logs
# 设置集群中N个节点启动时进行数据恢复,默认为1
gateway.recover_after_nodes: 3 

#bootstrap.memory_lock: true
#bootstrap.system_call_filter: false

# 跨域,如果安装了 elasticsearch-head 插件,那么前两个配置也会用到
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization,X-Requested-With,Content-Type,Content-Length
# 安全认证
xpack.security.enabled: true
xpack.security.authc.accept_default_password: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: /opt/module/es-9300/config/certificates/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: /opt/module/es-9300/config/certificates/elastic-certificates.p12

es-9400 节点

# 集群名称,三台集群,要配置相同的集群名称!!!
cluster.name: es-cluster
# 节点名称
node.name: es-9400
# 是否有资格被选举为master,ES默认集群中第一台机器为主节点
node.master: true
# 是否存储数据
node.data: true
#最⼤集群节点数,为了避免脑裂,集群节点数最少为 半数+1
node.max_local_storage_nodes: 3
# 修改 network.host 为 0.0.0.0,表示对外开放,如对特定ip开放则改为指定ip
network.host: 192.168.1.101
# 设置对外服务http端口,默认为9200
http.port: 9400
# 内部节点之间沟通端口
transport.tcp.port: 9903
# 候选主节点的设备地址,在开启服务后可以被选为主节点
discovery.seed_hosts: ["192.168.1.101:9901","192.168.1.101:9902","192.168.1.101:9903"]
# 初始化一个新的集群时需要此配置来选举 master
cluster.initial_master_nodes: ["es-9200"]
# 数据和日志目录
#path.data: /data/es/data
#path.logs: /data/es/logs
# 设置集群中N个节点启动时进行数据恢复,默认为1
gateway.recover_after_nodes: 3 

#bootstrap.memory_lock: true
#bootstrap.system_call_filter: false

# 跨域,如果安装了 elasticsearch-head 插件,那么前两个配置也会用到
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization,X-Requested-With,Content-Type,Content-Length
# 安全认证
xpack.security.enabled: true
xpack.security.authc.accept_default_password: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: /opt/module/es-9400/config/certificates/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: /opt/module/es-9400/config/certificates/elastic-certificates.p12

需要注意的点:

xpack.security.transport.ssl.keystore.pathxpack.security.transport.ssl.truststore.path 替换为自己的 es 安装路径。

六:添加密码

每一个 es 节点都需要

./bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
# 输入密码:第一步中设置的密码,例如本样例中的123456
./bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password
# 输入密码:第一步中设置的密码,例如本样例中的123456

ps: 如果询问你是否要创建 elasticsearch.keystore 文件,输入 y 后按回车即可。

七:逐个启动节点

./bin/elasticsearch

后续确认没问题的话可以改成后台启动:

./bin/elasticsearch -d

八:设置密码

在第一个节点设置即可,会自动同步到其他节点

./bin/elasticsearch-setup-passwords  interactive
# 下面会要输入很多密码,都要自己能记住,以后要用
# 需要设置 elastic,apm_system,kibana,kibana_system,logstash_system,beats_system

九:通过浏览器 or 终端访问 es

image-20230612223553713

实际上第一次访问的时候会要求输入账号密码(如下图),我这里已经不是第一次了,因此不再需要输入。

通过终端来查看是否成功:

curl --user elastic:<自己设置的密码> http://192.168.1.101:9200
image-20230612223718459

十:通过 Java API 来操作 es 集群

  1. 配置 pom 文件,引入相关依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.12</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.rainfall</groupId>
    <artifactId>es-secure</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>es-secure</name>
    <description>es7.6.2 安全认证</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--es 授权-->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>x-pack-transport</artifactId>
            <version>7.8.1</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.6.2</version>
        </dependency>
        <!-- elasticsearch 的客户端 -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.6.2</version>
        </dependency>
        <!-- elasticsearch 依赖 2.x 的 log4j -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.8.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.8.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.9</version>
        </dependency>
        <!-- junit 单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  1. 例子:添加 doc
public class DocInsert {
    public static void main(String[] args) throws IOException {
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        // 设置用户名以及密码
        UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials("elastic", "123456");
        credentialsProvider.setCredentials(AuthScope.ANY, usernamePasswordCredentials);

        RestClientBuilder builder = RestClient.builder(new HttpHost("192.168.1.101", 9200, "http"))
                .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
        RestHighLevelClient client = new RestHighLevelClient(builder);

        // 插入数据
        IndexRequest indexRequest = new IndexRequest();
        indexRequest.index("user1").id("1003");

        User user = new User("xiao li","男",22);

        // 向es插入数据必须将数据转换成JSON格式
        ObjectMapper objectMapper = new ObjectMapper();
        String userJson = objectMapper.writeValueAsString(user);

        indexRequest.source(userJson, XContentType.JSON);
        IndexResponse res = client.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(res.getResult());

        client.close();
    }
}
  1. 例子:查询刚才添加的 doc 数据
public class DocGet {
    public static void main(String[] args) throws IOException {
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        // 设置用户名以及密码
        UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials("elastic", "123456");
        credentialsProvider.setCredentials(AuthScope.ANY, usernamePasswordCredentials);

        RestClientBuilder builder = RestClient.builder(new HttpHost("192.168.1.101", 9200, "http"))
                .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
        RestHighLevelClient client = new RestHighLevelClient(builder);

        // 查询数据
        GetRequest getRequest = new GetRequest();
        getRequest.index("user1");
        getRequest.id("1003");

        GetResponse response = client.get(getRequest, RequestOptions.DEFAULT);
        System.out.println(response.getSourceAsString());

        client.close();
    }
}

十一:Kibana 访问带有安全认证的 es 集群

从官网下载与 es 版本一致的 Kibana,下载完成后上传到 linux 服务器,进行安装。

接着对config 目录下的 kibana.yml 配置文件进行修改:

#配置端口号
server.port: 5601
#配置网络访问地址,建议使用内网 ip 或 0.0.0.0 表示谁都可以访问
server.host: "0.0.0.0"
#配置es链接地址(es集群,可以用逗号分隔)
elasticsearch.hosts: ["http://192.168.1.101:9200","http://192.168.1.101:9300","http://192.168.1.101:9400"]
# kibana 在 es 中的索引
kibana.index: ".kibana"
##明文认证 es 账户密码,要用的账户为 kibana。(不过更加推荐密文设置,下面会提到)
#elasticsearch.username: "kibana"
#elasticsearch.password: "123456"
# 不增加下面会导致 kibana 启动失败,字符串内容是什么无所谓,保证不少于 32 个字符就行。
xpack.encryptedSavedObjects.encryptionKey: "something_at_least_32_characters_123123"
xpack.reporting.encryptionKey: "something_at_least_32_characters_12312345"
xpack.security.encryptionKey: "something_at_least_32_characters_658568"
#配置中文语言界面
i18n.locale: "zh-CN"

密文认证方式为:

/usr/share/kibana/bin/kibana-keystore --allow-root create
/usr/share/kibana/bin/kibana-keystore --allow-root add elasticsearch.username # 输入kibana
/usr/share/kibana/bin/kibana-keystore --allow-root add elasticsearch.password # 输入自己配置的密码,我这是 123456

启动 kibana:

./bin/kibana --allow-root # 要关闭服务的话输入 exit 后回车。

此外,也可以选择后台启动:

nohup ./bin/kibana --allow-root &

要关闭服务的话,查找 Kibana 进程,找到对应的 Kibana 进程号,然后 kill 掉即可。

ps -ef | grep '.*node/bin/node.*src/cli' # 查找方式

之后访问 kibana 就需要输入账号和密码了。

image-20230612222750297

十三:可能会遇到的坑

1.不要用 root 用户去启动 es,需要切换到其他用户,记得事先赋予相应的权限。

chown -R es:es /opt/module/es-9200 # 如将 es-9200 目录属于的用户和用户组都指定为 es

2.集群成功启动,但是浏览器即使输入账户密码也无法成功登录。具体而言报错为:failed to authenticate user [elastic]

可能原因是一开始部署了安全认证的单节点 es,并在登录后做了增删改查。

解决办法是重新生成节点证书和账户、密码。可以参考:链接。

3.es 启动时报异常:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

原因是系统虚拟内存默认最大映射数为 65530,无法满足 es 系统要求,需要调整为 262144 以上。

解决办法是设置 vm.max_map_count 参数:

# 修改文件
sudo vim /etc/sysctl.conf
# 添加参数
vm.max_map_count = 262144

重新加载/etc/sysctl.conf配置:

sysctl -p

4.es 启动时报异常:max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]

解决办法:

sudo vi /etc/security/limits.conf

将下面这行代码添加到这个配置文件的末尾就好:

es soft nofile 65536 # es 是自己的用户名
es hard nofile 65536

5.如果啥也不配置,上来直接启动 es,会报如下错误:

ERROR: [1] bootstrap checks failed
[1]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured
ERROR: Elasticsearch did not exit normally - check the logs at /opt/module/elasticsearch-7.6.2/logs/elasticsearch.log

这点和 windows 上的 es 不同,windows 可以直接成功运行。

解决办法是做相应的配置。

6.kibana 启动报错 socket hang up 错误

原因是配置文件中的 elasticsearch.hosts 需要的是 ip 地址 + es 中的 http 端口号,错写成 ip 地址 + tcp 端口号就会出现端口访问不到的问题。

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

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

相关文章

面试专题:Mysql

1.说说自己对于 MySQL 常见的两种存储引擎&#xff1a;MyISAM与InnoDB的理解 关于二者的对比与总结: 1.count运算上的区别&#xff1a;因为MyISAM缓存有表meta-data&#xff08;行数等&#xff09;&#xff0c;因此在做COUNT(*)时对于一个结构很好的查询是不需要消耗多少资源的…

[CKA]考试之K8s 版本升级

由于最新的CKA考试改版&#xff0c;不允许存储书签&#xff0c;本博客致力怎么一步步从官网把答案找到&#xff0c;如何修改把题做对&#xff0c;下面开始我们的 CKA之旅 题目为&#xff1a; Task 现有的Kubernetes 集群正在运行版本1.22.0。仅将master节点上的所有 Kuberne…

【Python】集合 set ② ( 集合常用操作 | 集合中添加元素 | 集合中移除元素 | 集合中随机取出元素 )

文章目录 一、集合中添加元素二、集合中移除元素三、集合中随机取出元素 在 Python 中 , 集合 set 是无序的 , 因此 集合 数据容器 不支持 使用 下标索引 访问 集合元素 ; 一、集合中添加元素 调用 集合#add(新元素) 函数 , 可以将新元素添加到 集合 数据容器中 ; 集合添加元素…

Vue- ref属性

ref属性 被用来给元素或者子组件注册引用信息&#xff08;id的替代者&#xff09; 通过案例来演示_ref属性 1 编写案例 如图&#xff1a;有一个按钮&#xff0c;点击按钮可以输出dom元素 备注&#xff1a;虽然vue不用我们亲自操作dom&#xff0c;但是有的特殊的情况下就要…

【2023华中杯】B题 小学教学应用题 相似性度量及难度评估 29页论文及MATLAB代码

1 题目 B 题 小学数学应用题相似性度量及难度评估 某 MOOC 在线教育平台希望能够进行个性化教学&#xff0c;实现用户自主学习。在用户学习时&#xff0c;系统从题库中随机抽取若干道与例题同步的随堂测试题&#xff0c;记录、分析学生的学习和答题信息&#xff0c;并且课后会自…

【Pytest实战】解决ModuleNotFoundError: No module named ‘pytest’问题

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c;主要职责&#xff1a;测试开发、CI/CD 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。&#x1f60a; 座右铭&#xff1a;不想…

JAVA程序的性能优化实践总结

1、 衡量程序性能的指标 可以从常用的性能评估指标入手&#xff1a; 并发&#xff1a;同一时间有多少请求访问TPS&#xff1a;transaction per second(每秒的事物数)QPS&#xff1a;query per second(每秒请求数)耗时&#xff1a;端到端耗时&#xff0c;服务端耗时&#xff…

并行计算——MPI编程

目录 基础知识 进程与线程&#xff0c;并行与并发 奇偶排序 MPI实现 odd-even sort 思路 环境部署 编程实现&#xff08;C&#xff09; “若干”的问题 参考链接 一个偶然的机会&#xff0c;我接触到了国立清华大学的MPI编程作业&#xff0c;也就接触到了并行计算。这…

基于Python3接口自动化测试初探

自动化测试是什么&#xff1f; 自动化测试简单来说就是借助工具的方式来辅助手动测试的行为就可以看做是自动化测试。 自动化测试工具有哪些&#xff1f; 现在常用的自动化测试工具包括&#xff1a; QTP&#xff1a;主要用于回归测试和测试同一软件的新版本 Robot Framewor…

大数据ETL工具Kettle

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言最近公司在搞大数据数字化&#xff0c;有MES,CIM,WorkFlow等等N多的系统&#xff0c;不同的数据源DB&#xff0c;需要将这些不同的数据源DB里的数据进行整治统一…

【算法】模拟,高精度

高精度加法 P1601 AB Problem&#xff08;高精&#xff09; - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路就是模拟&#xff0c;值得注意的就是要用字符串类型输入。存进自己的int数组时要倒着存&#xff0c;因为如果是正着存的话&#xff0c;进位会有点trouble。 时间…

Spread.NET v16.0.20222.0 ASP.NET cRACK

关于 Spread.NET 提供类似 Excel 的电子表格体验。 Spread.NET 可帮助您创建电子表格、网格、仪表板和表单。它包括一个强大的计算引擎&#xff0c;具有450 函数以及导入和导出Excel电子表格的能力。利用广泛的 .NET 电子表格 API 和强大的计算引擎来创建分析、预算、仪表板、…

【C++ 基础篇:24】:【重要模板】C++ 输入输出运算符重载【以 Date 日期类为例】

系列文章说明 本系列 C 相关文章 仅为笔者学习笔记记录&#xff0c;用自己的理解记录学习&#xff01;C 学习系列将分为三个阶段&#xff1a;基础篇、STL 篇、高阶数据结构与算法篇&#xff0c;相关重点内容如下&#xff1a; 基础篇&#xff1a;类与对象&#xff08;涉及C的三大…

Mysql Access denied for user ‘root‘@ ‘*.*.*.*‘ (using password: YES)异常处理

目录 一、异常错误二、原因三、解决方法 一、异常错误 PS C:\Users\10568> mysql -u root -p Enter password: **** ERROR 1045 (28000): Access denied for user rootlocalhost (using password: YES)Access denied表示拒绝访问&#xff0c;using password&#xff1a;NO/…

计算机视觉 | 语义分割与Segmentation

前 言 「MMSegmentation」 是一个基于 PyTorch 的语义分割开源工具箱。它是 OpenMMLab 项目的一部分。 MMSegmentation v1.x 在 0.x 版本的基础上有了显著的提升&#xff0c;提供了更加灵活和功能丰富的体验。 主要特性 统一的基准平台 我们将各种各样的语义分割算法集成到了…

Linux权限维持

SSH后门&VIM后门 ssh后门&#xff1a; 创建一个软链接&#xff1a; ln -sf /usr/sbin/sshd /tmp/su 拓展&#xff1a;软链接相当于一个快捷键&#xff0c;硬链接相当于一个指针指向文件地址&#xff0c;也类似于复制 开启后门&#xff1a; /tmp/su -oport12345 开启后…

chatgpt赋能python:Python另存为:如何保存你的程序代码

Python另存为&#xff1a;如何保存你的程序代码 简介 Python是一种高级编程语言&#xff0c;最初由Guido van Rossum于1991年创建。自创建以来&#xff0c;Python已被广泛应用于Web开发、数据分析、人工智能等领域。作为一名有10年Python编程经验的工程师&#xff0c;我发现在…

万物的算法日记|第一天

笔者自述&#xff1a; 一直有一个声音也一直能听到身边的大佬经常说&#xff0c;要把算法学习搞好&#xff0c;一定要重视平时的算法学习&#xff0c;虽然每天也在学算法&#xff0c;但是感觉自己一直在假装努力表面功夫骗了自己&#xff0c;没有规划好自己的算法学习和总结&am…

内部服务器端口映射实验:打通内外网络,实现公网访问内部服务

内部服务器端口映射实验&#xff1a;打通内外网络&#xff0c;实现公网访问内部服务 【实验目的】 部署服务器地址转换。熟悉服务器地址转换的应用方法。验证配置。 【实验拓扑】 实验拓扑如图所示。 实验拓扑 设备参数如表所示。 设备参数表 设备 接口 IP地址 子网掩…

BOM,什么是BOM?

4.BOM 4.1 什么是BOM? BOM&#xff08;Browser Object Model&#xff09;即浏览器对象模型&#xff0c;它提供了独立于内容而与浏览器窗口进行交互的对象&#xff0c;其核心对象是 window。 ​ BOM 由一系列相关的对象构成&#xff0c;并且每个对象都提供了很多方法与属性。 …