通过logstash同步elasticsearch数据

news2024/11/16 11:56:46

1 概述

logstash是一个对数据进行抽取、转换、输出的工具,能对接多种数据源和目标数据。本文介绍通过它来同步elasticsearch的数据。


2 环境

实验仅仅需要一台logstash机器和两台elasticsearch机器(elasticsearch v7.1.0)。本文用docker来模拟,使用docker-compose来启动elasticsearch容器。
elasticsearch机器A是192.168.243.128:9200。
elasticsearch机器B是192.168.243.128:19200。


2.1 安装elasticsearch机器A

2.1.1 编写docker-compose.yml

version: '2.2'
services:
  cerebro:
    image: lmenezes/cerebro:0.8.3
    container_name: cerebro
    ports:
      - "9000:9000"
    command:
      - -Dhosts.0.host=http://elasticsearch:9200
  kibana:
    image: docker.elastic.co/kibana/kibana:7.1.0
    container_name: kibana7
    environment:
      - I18N_LOCALE=zh-CN
      - XPACK_GRAPH_ENABLED=true
      - TIMELION_ENABLED=true
      - XPACK_MONITORING_COLLECTION_ENABLED="true"
    ports:
      - "5601:5601"
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.0
    container_name: es7_01
    environment:
      - cluster.name=xttblog
      - node.name=es7_01
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - discovery.seed_hosts=es7_01
      - cluster.initial_master_nodes=es7_01,es7_02
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - es7data1:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
  elasticsearch2:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.0
    container_name: es7_02
    environment:
      - cluster.name=xttblog
      - node.name=es7_02
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - discovery.seed_hosts=es7_01
      - cluster.initial_master_nodes=es7_01,es7_02
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - es7data2:/usr/share/elasticsearch/data
volumes:
  es7data1:
    driver: local
  es7data2:
    driver: local

2.1.2 修改vm.max_map_count

cat >> /etc/sysctl.conf << EOF
vm.max_map_count = 2621440
EOF
sysctl -p

2.1.3 启动

docker-compose up -d 

2.1.3 导入样例数据

localhost:5601,用于访问kibana并导入样例数据
localhost:9000,用于访问cerebro

2.2 安装elasticsearch机器B

2.2.1 编写docker-compose.yml

version: '2.2'
services:
  cerebro:
    image: lmenezes/cerebro:0.8.3
    container_name: cerebro-2
    ports:
      - "19000:9000"
    command:
      - -Dhosts.0.host=http://elasticsearch:9200
  kibana:
    image: docker.elastic.co/kibana/kibana:7.1.0
    container_name: kibana7-2
    environment:
      - I18N_LOCALE=zh-CN
      - XPACK_GRAPH_ENABLED=true
      - TIMELION_ENABLED=true
      - XPACK_MONITORING_COLLECTION_ENABLED="true"
    ports:
      - "15601:5601"
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.0
    container_name: es7_03
    environment:
      - cluster.name=xttblog
      - node.name=es7_03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - discovery.seed_hosts=es7_03
      - cluster.initial_master_nodes=es7_03,es7_04
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - es7data3:/usr/share/elasticsearch/data
    ports:
      - 19200:9200
  elasticsearch2:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.0
    container_name: es7_04
    environment:
      - cluster.name=xttblog
      - node.name=es7_04
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - discovery.seed_hosts=es7_03
      - cluster.initial_master_nodes=es7_03,es7_04
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - es7data4:/usr/share/elasticsearch/data
volumes:
  es7data3:
    driver: local
  es7data4:
    driver: local

2.2.2 修改vm.max_map_count

cat >> /etc/sysctl.conf << EOF
vm.max_map_count = 2621440
EOF
sysctl -p

2.2.3 启动

docker-compose up -d 

2.2 logstash机器上准备python环境

在centos7机器上执行如下命令,可安装python环境:

yum install python2
yum install python-pip

由于python脚本需要导入requests模块哈yaml模块,因此需要执行如下命令在机器上安装python模块:

pip install pyyaml
pip install requests

2.2 logstash机器上准备python脚本

2.2.1 准备migrateConfig.yaml

本文件用于描述源端和目标端是谁,是否开启SSL连接。
一般只需要修改src_ip、dest_ip。

cat > /tmp/migrateConfig.yaml << EOF
es_cluster_new:
  # 源集群的名称
  clustername: es_cluster_new
  # 源Elasticsearch集群的访问地址,加上“http://”。
  src_ip: http://x.x.x.x:9200
  # 访问源Elasticsearch集群的用户名和密码,如果为非安全集群则设置为""。
  src_username: ""
  src_password: ""
  # 目标Elasticsearch集群的访问地址,加上“http://”。
  dest_ip: http://x.x.x.x:9200
  # 访问目标Elasticsearch集群的用户名和密码,如果为非安全集群则设置为""。
  dest_username: ""
  dest_password: ""
  # only_mapping 可以不定义,默认值为false,需要搭配“migrateMapping.py”使用,表示是否只处理这个文件中mapping地址的索引。
  #  当设置成false时,则迁移源集群中除“.kibana”和“.*”之外的所有索引数据。
  #  当设置成true时,则只迁移源集群中和下面mapping的key一致的索引数据;迁移过程中会将索引名称与下面的mapping匹配,如果匹配一致,则使用mapping的value作为目标集群的索引名称;如果匹配不到,则使用源集群原始的索引名称。
  only_mapping: false
  # 当only_mapping = true时,mapping用于设置要迁移的索引,key为源集群的索引名字,value为目标集群的索引名字。
  mapping:
      test_index_1: test_index_1
  # only_compare_index 可以不定义,默认值为false,需要搭配“checkIndices.py”使用,当设置为false会比较所有的索引和文档数量,当设置为true只比较索引数量。
  only_compare_index: false  
EOF

2.2.1 准备migrateTemplate.py

用于迁移索引模板,此文件不需要修改,直接复制。

cat > /tmp/migrateTemplate.py << EOF
# -*- coding:UTF-8 -*-
import sys
import yaml
import requests
import json
import os


def printDividingLine():
    print("<=============================================================>")


def loadConfig(argv):
    if argv is None or len(argv) != 2:
        config_yaml = "migrateConfig.yaml"
    else:
        config_yaml = argv[1]
    config_file = open(config_yaml)
    # config = yaml.load(config_file, Loader=yaml.FullLoader)
    return yaml.load(config_file)


def put_template_to_target(url, template, cluster, template_name, dest_auth=None):
    headers = {'Content-Type': 'application/json'}
    create_resp = requests.put(url, headers=headers, data=json.dumps(template), auth=dest_auth, verify=False)
    if not os.path.exists("templateLogs"):
        os.makedirs("templateLogs")
    if create_resp.status_code != 200:
        print(
            "create template " + url + " failed with response: " + str(
                create_resp) + ", source template is " + template_name)
        print(create_resp.text)
        filename = "templateLogs/" + str(cluster) + "#" + template_name
        with open(filename + ".json", "w") as f:
            json.dump(template, f)
        return False
    else:
        return True


def main(argv):
    requests.packages.urllib3.disable_warnings()
    print("begin to migration template!")
    config = loadConfig(argv)
    src_clusters = config.keys()
    print("process cluster name:")
    for name in src_clusters:
        print(name)
    print("cluster total number:" + str(src_clusters.__len__()))

    for name, value in config.items():
        printDividingLine()
        source_user = value["src_username"]
        source_passwd = value["src_password"]
        source_auth = None
        if source_user != "":
            source_auth = (source_user, source_passwd)
        dest_user = value["dest_username"]
        dest_passwd = value["dest_password"]
        dest_auth = None
        if dest_user != "":
            dest_auth = (dest_user, dest_passwd)

        print("start to process cluster name:" + name)
        source_url = value["src_ip"] + "/_template"

        response = requests.get(source_url, auth=source_auth, verify=False)
        if response.status_code != 200:
            print("*** get all template failed. resp statusCode:" + str(
                response.status_code) + " response is " + response.text)
            continue
        all_template = response.json()
        migrate_itemplate = []

        for template in all_template.keys():
            if template.startswith(".") or template == "logstash":
                continue
            if "index_patterns" in all_template[template]:
                for t in all_template[template]["index_patterns"]:
                    # if "kibana" in template:
                    if t.startswith("."):
                        continue
                    migrate_itemplate.append(template)

        for template in migrate_itemplate:
            dest_index_url = value["dest_ip"] + "/_template/" + template
            result = put_template_to_target(dest_index_url, all_template[template], name, template, dest_auth)
            if result is True:
                print('[success] delete success, cluster: %-10s, template %-10s ' % (str(name), str(template)))
            else:
                print('[failure] delete failure, cluster: %-10s, template %-10s ' % (str(name), str(template)))


if __name__ == '__main__':
    main(sys.argv)

EOF

2.2.1 准备migrateMapping.py

脚本用于迁移索的表结构,此文件不需要修改,直接复制。

cat > /tmp/migrateMapping.py << EOF
# -*- coding:UTF-8 -*-
import sys
import yaml
import requests
import re
import json
import os


def printDividingLine():
    print("<=============================================================>")


def loadConfig(argv):
    if argv is None or len(argv) != 2:
        config_yaml = "migrateConfig.yaml"
    else:
        config_yaml = argv[1]
    config_file = open(config_yaml)
    # config = yaml.load(config_file, Loader=yaml.FullLoader)
    return yaml.load(config_file)


def get_cluster_version(url, auth=None):
    response = requests.get(url, auth=auth)
    if response.status_code != 200:
        print("*** get ElasticSearch message failed. resp statusCode:" + str(
            response.status_code) + " response is " + response.text)
        return False
    cluster = response.json()
    version = cluster["version"]["number"]

    return True


def process_mapping(index_mapping, dest_index):
    # remove unnecessary keys
    del index_mapping["settings"]["index"]["provided_name"]
    del index_mapping["settings"]["index"]["uuid"]
    del index_mapping["settings"]["index"]["creation_date"]
    del index_mapping["settings"]["index"]["version"]

    if "lifecycle" in index_mapping["settings"]["index"]:
        del index_mapping["settings"]["index"]["lifecycle"]

    # check alias
    aliases = index_mapping["aliases"]
    for alias in list(aliases.keys()):
        if alias == dest_index:
            print(
                "source index " + dest_index + " alias " + alias + " is the same as dest_index name, will remove this alias.")
            del index_mapping["aliases"][alias]
    # if index_mapping["settings"]["index"].has_key("lifecycle"):
    if "lifecycle" in index_mapping["settings"]["index"]:
        lifecycle = index_mapping["settings"]["index"]["lifecycle"]
        opendistro = {"opendistro": {"index_state_management":
                                         {"policy_id": lifecycle["name"],
                                          "rollover_alias": lifecycle["rollover_alias"]}}}
        index_mapping["settings"].update(opendistro)
        # index_mapping["settings"]["opendistro"]["index_state_management"]["rollover_alias"] = lifecycle["rollover_alias"]
        del index_mapping["settings"]["index"]["lifecycle"]

    # replace synonyms_path
    if "analysis" in index_mapping["settings"]["index"]:
        analysis = index_mapping["settings"]["index"]["analysis"]
        if "filter" in analysis:
            filter = analysis["filter"]
            if "my_synonym_filter" in filter:
                my_synonym_filter = filter["my_synonym_filter"]
                if "synonyms_path" in my_synonym_filter:
                    index_mapping["settings"]["index"]["analysis"]["filter"]["my_synonym_filter"][
                        "synonyms_path"] = "/rds/datastore/elasticsearch/v7.10.2/package/elasticsearch-7.10.2/plugins/analysis-dynamic-synonym/config/synonyms.txt"
    return index_mapping


def getAlias(source, source_auth):
    # get all indices
    response = requests.get(source + "/_alias", auth=source_auth)
    if response.status_code != 200:
        print("*** get all index failed. resp statusCode:" + str(
            response.status_code) + " response is " + response.text)
        exit()

    all_index = response.json()
    system_index = []
    create_index = []
    for index in list(all_index.keys()):
        if (index.startswith(".")):
            system_index.append(index)
        else:
            create_index.append(index)

    return system_index, create_index


def put_mapping_to_target(url, mapping, cluster, source_index, dest_auth=None):
    headers = {'Content-Type': 'application/json'}
    create_resp = requests.put(url, headers=headers, data=json.dumps(mapping), auth=dest_auth, verify=False)
    if not os.path.exists("mappingLogs"):
        os.makedirs("mappingLogs")
    if create_resp.status_code != 200:
        print(
            "create index " + url + " failed with response: " + str(create_resp) +
            ", source index is " + str(source_index))
        print(create_resp.text)
        filename = "mappingLogs/" + str(cluster) + "#" + str(source_index)
        with open(filename + ".json", "w") as f:
            json.dump(mapping, f)
        return False
    else:
        return True


def main(argv):
    requests.packages.urllib3.disable_warnings()
    print("begin to migrate index mapping!")
    config = loadConfig(argv)
    src_clusters = config.keys()

    print("begin to process cluster name :")
    for name in src_clusters:
        print(name)
    print("cluster count:" + str(src_clusters.__len__()))

    for name, value in config.items():
        printDividingLine()
        source = value["src_ip"]
        source_user = value["src_username"]
        source_passwd = value["src_password"]
        source_auth = None
        if source_user != "":
            source_auth = (source_user, source_passwd)
        dest = value["dest_ip"]
        dest_user = value["dest_username"]
        dest_passwd = value["dest_password"]
        dest_auth = None
        if dest_user != "":
            dest_auth = (dest_user, dest_passwd)

        print("start to process cluster:   " + name)
        # only deal with mapping list
        if 'only_mapping' in value and value["only_mapping"]:
            for source_index, dest_index in value["mapping"].iteritems():
                print("start to process source index" + source_index + ", target index: " + dest_index)
                source_url = source + "/" + source_index
                response = requests.get(source_url, auth=source_auth)
                if response.status_code != 200:
                    print("*** get ElasticSearch message failed. resp statusCode:" + str(
                        response.status_code) + " response is " + response.text)
                    continue
                mapping = response.json()
                index_mapping = process_mapping(mapping[source_index], dest_index)
                dest_url = dest + "/" + dest_index
                result = put_mapping_to_target(dest_url, index_mapping, name, source_index, dest_auth)
                if result is False:
                    print("cluster name:" + name + ", " + source_index + ":failure")
                    continue
                print("cluster name:" + name + ", " + source_index + ":success")
        else:
            # get all indices
            system_index, create_index = getAlias(source, source_auth)
            success_index = 0
            for index in create_index:
                source_url = source + "/" + index
                index_response = requests.get(source_url, auth=source_auth)
                if index_response.status_code != 200:
                    print("*** get ElasticSearch message failed. resp statusCode:" + str(
                        index_response.status_code) + " response is " + index_response.text)
                    continue
                mapping = index_response.json()

                dest_index = index
                if 'mapping' in value:
                    if index in value["mapping"].keys():
                        dest_index = value["mapping"][index]
                index_mapping = process_mapping(mapping[index], dest_index)

                dest_url = dest + "/" + dest_index
                result = put_mapping_to_target(dest_url, index_mapping, name, index, dest_auth)
                if result is False:
                    print("[failure]: migrate mapping cluster name: " + name + ", " + index)
                    continue
                print("[success]: migrate mapping cluster name: " + name + ", " + index)
                success_index = success_index + 1
            print("create index mapping success total: " + str(success_index))


if __name__ == '__main__':
    main(sys.argv)

EOF

3 同步数据

3.1 同步元数据

python /tmp/migrateTemplate.py
python /tmp/migrateMapping.py

3.2 同步实际数据

准备logstash.conf文件,放在/tmp/目录中即可。需要在logstash.conf指定源端和目标端,待同步数据的索引有哪些。
实际需要改动字段是input.elasticsearch.hosts 、input.elasticsearch.index,output.elasticsearch.hosts。

vim /tmp/logstash.conf,输入以下内容:

input{
     elasticsearch{
        # 源Elasticsearch的访问地址,不需要添加协议,添加HTTPS协议会导致报错。
        hosts =>  ["192.168.243.128:9200"]
        # 访问源集群的用户名和密码,非安全集群无需配置。
        # user => "css_logstash"
        # password => "*****"
        # 配置待迁移的索引信息,多个索引以逗号隔开,可以使用通配符设置,例如“index*”。
        index => "kibana_sample_data_flights,kibana_sample_data_ecommerce"
        docinfo => true
        slices => 3
        size => 3000
        # 当源集群是HTTPS访问方式时,则设置ssl => false。
        # ssl => false
     }
 }

 
# 移除一些logstash增加的字段。
 filter {
   mutate {
     remove_field => ["@metadata", "@version"]
   }
 }

 output{
     elasticsearch{
       # 目标Elasticsearch集群的访问地址
       hosts =>  ["192.168.243.128:19200"]
       # 访问目标集群的用户名和密码,非安全集群无需配置。
       # user => "css_logstash"
       # password => "*****"
       # 配置目标集群的索引,以下配置为索引名称和源端保持一致,保持默认。
       index => "%{[@metadata][_index]}"
       document_type => "%{[@metadata][_type]}"
       document_id => "%{[@metadata][_id]}"
       # 当目标集群是HTTPS访问方式时,则需额外配置以下信息。
       # 配置集群HTTPS访问证书,CSS集群保持以下不变。     
       #cacert => "/rds/datastore/logstash/v7.10.0/package/logstash-7.10.0/extend/certs/CloudSearchService.cer" 
       # 是否开启HTTPS通信,HTTPS访问集群则设置为true。
       #ssl => true
       # 是否验证服务端Elasticsearch证书,设置为false表示不验证证书。
       #ssl_certificate_verification => false
     }
 }

执行如下命令来启动logstash进程,进程执行完后会自动退出:

docker run -it --rm -v /tmp/logstash.conf:/tmp/logstash.conf docker.elastic.co/logstash/logstash:7.1.0 logstash -f /tmp/logstash.conf

在这里插入图片描述

4 小结

logstash可用于同步elasticsearch的数据,不仅可以进行全量同步,其实还能进行增量同步(数据带时间字段,用该字段进行query即可抽取出增量的数据),虽然本文没演示增量同步。

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

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

相关文章

NLP 序列标注任务核心梳理

句向量标注 用 bert 生成句向量用 lstm 或 bert 承接 bert 的输出&#xff0c;保证模型可以学习到内容的连续性。此时 lstm 输入形状为&#xff1a; pooled_output.unsqueeze(0) (1, num_sentence, vector_size) 应用场景 词性标注句法分析 文本加标点 相当于粗粒度的分词任…

实时同步 解决存储问题 sersync

目录 1.sersync服务 2.sersync同步整体架构 ​编辑 3.rsync服务准备 4.sersync部署使用 5.修改配置文件 6.启动sersync 7.接入nfs服务 8.联调测试 1.sersync服务 sersync服务其实就是由两个服务组成一个是inotify服务和rsync服务组成 inotify服务用来监控那个…

Linux 文件系统(上)

目录 一.预备阶段 1.认识文件 2.OS对内存文件的管理 3.C库函数和系统调用接口 a.C库函数——fopen b.系统调用接口——open 二.理解文件描述符 1.一张图&#xff0c;详解文件描述符的由来 2.fd的分配规则 3.从fd的角度理解FILE 三.重定向和缓冲区 1.前置知识——理解…

网络安全-CSRF

一、环境 DVWA网上找 二、简单介绍 这个漏洞很早之前了&#xff0c;但是为了避免大家在面试等等的时候被问到&#xff0c;这里给大家温习一下 CSRF全程是没有黑客参与的&#xff0c;全程都是用户自己在操作 三、环境演练 这个是DVWA的提交表单页面&#xff0c;我这里伪造…

【2020工业图像异常检测文献】PaDiM

PaDiM: a Patch Distribution Modeling Framework for Anomaly Detection and Localization 1、Background 在单类学习&#xff08;仅使用正常数据&#xff08;即“单一类”&#xff09;来训练模型&#xff09;环境中的异常检测和定位任务方法中&#xff0c;要么需要深度神经网…

结合HashMap与Java 8的Function和Optional消除ifelse判断

shigen坚持更新文章的博客写手&#xff0c;记录成长&#xff0c;分享认知&#xff0c;留住感动。个人IP&#xff1a;shigen 在文章的开头我们先从这些场景进入本期的问题&#xff1a; 业务代码中各种if-else有遇到过吗&#xff0c;有什么好的优化方式&#xff1b;java8出来这么…

鸿蒙开发(NEXT/API 12)【跨设备互通特性简介】协同服务

跨设备互通提供跨设备的相机、扫描、图库访问能力&#xff0c;平板或2in1设备可以调用手机的相机、扫描、图库等功能。 说明 本章节以拍照为例展开介绍&#xff0c;扫描、图库功能的使用与拍照类似。 用户在平板或2in1设备上使用富文本类编辑应用&#xff08;如&#xff1a;…

学习 git 命令行的简单操作, 能够将代码上传到 Gitee 上

首先登录自己的gitee并创建好仓库 将仓库与Linux终端做链接 比如说我这里已经创建好了一个我的Linux学习仓库 点开克隆/下载&#xff1a; 在你的终端中粘贴上图中1中的指令 此时他会让你输入你的用户名和密码&#xff0c;用户名就是上图中3中Username for ....中后面你的一个…

预付费计量系统实体模型

1. 预付费计量系统实体模型 A generic entity model for electricity payment metering systems is shown in Figure 2. Although it provides a limited perspective, it does serve to convey certain essential concepts. 关于电子式预付费电表系统的实体模型见图 2…

李宏毅结构化学习 03

文章目录 一、Sequence Labeling 问题概述二、Hidden Markov Model(HMM)三、Conditional Random Field(CRF)四、Structured Perceptron/SVM五、Towards Deep Learning 一、Sequence Labeling 问题概述 二、Hidden Markov Model(HMM) 上图 training data 中的黑色字为x&#xff…

如何备份SqlServer数据库

第一步&#xff1a;登录你要备份的服务器数据库ssms 第二步&#xff1a;选择你要备份的数据库 此处已PZ-SJCS 数据库为例 右键该数据库-->任务-->备份 第三步&#xff1a;选择你备份的类型备份组件等&#xff0c;目标磁盘 &#xff0c;点击添加选择将你备份的文件备份那…

全面详尽的 PHP 环境搭建教程

目录 目录 PHP 环境搭建概述 在 Windows 上搭建 PHP 环境 使用集成环境 XAMPP 安装步骤 配置和测试 常用配置 手动安装 Apache、PHP 和 MySQL 安装 Apache 安装 PHP 安装 MySQL 配置 PHP 连接 MySQL 在 Linux 上搭建 PHP 环境 使用 LAMP 方案 安装 Apache 安装 …

【25.6】C++智能交友系统

常见错误总结 const-1 如下代码会报错 原因如下&#xff1a; man是一个const修饰的对象&#xff0c;即man不能修改任何内容&#xff0c;但是man所调用的play函数只是一个普通的函数&#xff0c;所以出现了报错。我们需要在play函数中加上const修饰&#xff0c;或者删除man对…

《论分布式存储系统架构设计》写作框架,软考高级系统架构设计师

论文真题 分布式存储系统&#xff08;Distributed Storage System&#xff09;通常将数据分散存储在多台独立的设备上。传统的网络存储系统采用集中的存储服务器存放所有数据&#xff0c;存储服务器成为系统性能的瓶颈&#xff0c;也是可靠性和安全性的焦点&#xff0c;不能满…

FreeRTOS-时间片调度

FreeRTOS-时间片调度 一、时间片调度简介二、时间片调度实验 一、时间片调度简介 同等优先级任务轮流的享有相同的CPU时间(可设置)&#xff0c;叫时间片&#xff0c;在FreeRTOS中&#xff0c;一个时间片就等于SysTick中断周期&#xff0c;所以说时间片大小取决于滴答定时器中断…

windows安装Anaconda教程

一、简介 Anaconda 是一个开源的 Python 和 R 语言的分发平台&#xff0c;专为科学计算和数据分析设计。它包含了包管理器 Conda&#xff0c;可以方便地安装和管理库、环境和依赖项。此外&#xff0c;Anaconda 还附带了许多数据科学工具和库&#xff0c;如 Jupyter Notebook 和…

【HTTPS】中间人攻击和证书的验证

中间人攻击 服务器可以创建出一堆公钥和私钥&#xff0c;黑客也可以按照同样的方式&#xff0c;创建一对公钥和私钥&#xff0c;冒充自己是服务器&#xff08;搅屎棍&#xff09; 黑客自己也能生成一对公钥和私钥。生成公钥和私钥的算法是开放的&#xff0c;服务器能生产&…

iOS17找不到developer mode

iOS17找不到开发者模式 developer mode 下载过app之后、弹窗Developer Mode Required之后&#xff0c;这个菜单就出现了&#xff08;之前死活找不到&#xff09;。 背景&#xff1a;用蒲公英分发测试app&#xff0c;有个同事买了新机(iphone 15 pro max)&#xff0c;添加了白名…

双虚拟机部署php项目

前言 经过前面的学习,我们对分布式部署有了一定的了解,这次我们尝试做些东西 准备 我打算用虚拟机部署一个外联网盘 一台虚拟机安装php另一台安装MySQL,但是之前已经安装过 MariaDB 了,就不打算改了。 通常MariaDB与MySQL兼容性很好,可以作为替代使用。彩虹外链网盘项目…

OpenAI的O1模型达到AGI二级,类人推理能力被提示危险,细思极恐!

大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 今天让我们一起来聊聊最近科技圈的大新闻—…