微服务Day7学习-数据聚合、同步、补全

news2025/1/16 19:53:52

文章目录

  • 数据聚合
    • 聚合分类
  • 自动补全
    • DSL实现Bucket聚合
    • DSL实现Metrics聚合
    • RestAPI实现聚合
    • 多条件聚合
    • 对接前端接口
    • 拼音分词器
    • 自定义分词器
    • 自动补全查询
    • 实现酒店搜索框自动补全
  • 数据同步
    • 数据同步思路分析
    • 利用mq实现mysql与elasticsearch数据同步
  • 集群
    • 介绍
    • 搭建ES集群

数据聚合

聚合分类

自动补全

在这里插入图片描述
在这里插入图片描述

DSL实现Bucket聚合

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

DSL实现Metrics聚合

在这里插入图片描述

RestAPI实现聚合

在这里插入图片描述
测试类

    @Test
    void testAggregation() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        //2.1 设置size
        request.source().size(0);
        //2.2 聚合
        request.source().aggregation(AggregationBuilders
                .terms("brandAgg")
                .field("brand")
                .size(20));
        //3.发出请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析结果
        System.out.println(response);
    }

在这里插入图片描述

    @Test
    void testAggregation() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        //2.1 设置size
        request.source().size(0);
        //2.2 聚合
        request.source().aggregation(AggregationBuilders
                .terms("brandAgg")
                .field("brand")
                .size(20));
        //3.发出请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析结果
        Aggregations aggregations = response.getAggregations();
        //4.1 根据聚合名称获取聚合结果
        Terms brandTerms = aggregations.get("brandAgg");
        //4.2 获取buckets
        List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
        //4.3 遍历
        for (Terms.Bucket bucket : buckets) {
            //4.4获取key
            String key = bucket.getKeyAsString();
            System.out.println(key);
        }
    }

多条件聚合

在这里插入图片描述
Service实现类中

    @Override
    public Map<String, List<String>> filters() {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        //2.1 设置size
        request.source().size(0);
        //2.2 聚合
        buildAggregation(request);
        //3.发出请求
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //4.解析结果
        Map<String, List<String>> result = new HashMap<>();
        Aggregations aggregations = response.getAggregations();
        //4.1 根据名称获取品牌结果 并放入map
        List<String> brandList = getAggByName(aggregations,"brandAgg");
        result.put("品牌", brandList);
        List<String> cityList = getAggByName(aggregations,"cityAgg");
        result.put("城市", cityList);
        List<String> starList = getAggByName(aggregations,"starAgg");
        result.put("星级", starList);
        return result;
    }

    private List<String> getAggByName(Aggregations aggregations,String aggName) {
        //4.1 根据聚合名称获取聚合结果
        Terms brandTerms = aggregations.get(aggName);
        //4.2 获取buckets
        List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
        //4.3 遍历
        List<String> brandList = new ArrayList<>();
        for (Terms.Bucket bucket : buckets) {
            //4.4获取key
            String key = bucket.getKeyAsString();
            brandList.add(key);
        }
        return brandList;
    }

    private void buildAggregation(SearchRequest request) {
        request.source().aggregation(AggregationBuilders
                .terms("brandAgg")
                .field("brand")
                .size(100));
        request.source().aggregation(AggregationBuilders
                .terms("cityAgg")
                .field("city")
                .size(100));
        request.source().aggregation(AggregationBuilders
                .terms("starAgg")
                .field("starName")
                .size(100));
    }

对接前端接口

在这里插入图片描述

拼音分词器

在这里插入图片描述
在这里插入图片描述

自定义分词器

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

自动补全查询

在这里插入图片描述
在这里插入图片描述

实现酒店搜索框自动补全

在这里插入图片描述
DSK代码

DELETE /hotel
# 酒店数据索引库
PUT /hotel
{
  "settings": {
    "analysis": {
      "analyzer": {
        "text_anlyzer": {
          "tokenizer": "ik_max_word",
          "filter": "py"
        },
        "completion_analyzer": {
          "tokenizer": "keyword",
          "filter": "py"
        }
      },
      "filter": {
        "py": {
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "name":{
        "type": "text",
        "analyzer": "text_anlyzer",
        "search_analyzer": "ik_smart", 
        "copy_to": "all"
      },
      "address":{
        "type": "keyword",
        "index": false
      },
      "price":{
        "type": "integer"
      },
      "score":{
        "type": "integer"
      },
      "brand":{
        "type": "keyword",
        "copy_to": "all"
      },
      "city":{
        "type": "keyword"
      },
      "starName":{
        "type": "keyword"
      },
      "business":{
        "type": "keyword",
        "copy_to": "all"
      },
      "location":{
        "type": "geo_point"
      },
      "pic":{
        "type": "keyword",
        "index": false
      },
      "all":{
        "type": "text",
        "analyzer": "text_anlyzer",
        "search_analyzer": "ik_smart"
      },
      "suggestion":{
          "type": "completion",
          "analyzer": "completion_analyzer"
      }
    }
  }
}

GET /hotel/_search
{
  "query": {
    "match_all": {}
  }
}

GET /hotel/_search
{
  "suggest": {
    "suggestions": {
      "text": "",
      "completion": {
        "field": "suggestion",
        "skip_duplicates": true,
        "size": 10
      }
    }
  }
}

修改实体类

@Data
@NoArgsConstructor
public class HotelDoc {
    private Long id;
    private String name;
    private String address;
    private Integer price;
    private Integer score;
    private String brand;
    private String city;
    private String starName;
    private String business;
    private String location;
    private String pic;
    private Object distance;
    private Boolean isAD;
    private List<String> suggestion;

    public HotelDoc(Hotel hotel) {
        this.id = hotel.getId();
        this.name = hotel.getName();
        this.address = hotel.getAddress();
        this.price = hotel.getPrice();
        this.score = hotel.getScore();
        this.brand = hotel.getBrand();
        this.city = hotel.getCity();
        this.starName = hotel.getStarName();
        this.business = hotel.getBusiness();
        this.location = hotel.getLatitude() + ", " + hotel.getLongitude();
        this.pic = hotel.getPic();
        if (this.business.contains("/")){
            //business有多个点,需要切割
            String[] arr = this.business.split("/");
            //添加元素
            this.suggestion = new ArrayList<>();
            this.suggestion.add(this.brand);
            Collections.addAll(this.suggestion, arr);
        }else {
            this.suggestion = Arrays.asList(this.brand,this.business);
        }
    }
}

在这里插入图片描述
建立测试类

    @Test
    void testSuggest() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().suggest(new SuggestBuilder().
                addSuggestion("suggestions", SuggestBuilders
                        .completionSuggestion("suggestion")
                        .prefix("h")
                        .skipDuplicates(true)
                        .size(10)
                ));
        //3.发起请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        ///4.解析结果
        System.out.println(response);
    }

在这里插入图片描述
测试类

    @Test
    void testSuggest() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().suggest(new SuggestBuilder().
                addSuggestion("suggestions", SuggestBuilders
                        .completionSuggestion("suggestion")
                        .prefix("h")
                        .skipDuplicates(true)
                        .size(10)
                ));
        //3.发起请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        ///4.解析结果
        Suggest suggest = response.getSuggest();
        //4.1根据补全查询名称获取补全结果
        CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
        //4.2 获取options
        List<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();
        //4.3 遍历
        for (CompletionSuggestion.Entry.Option option : options) {
            String text = option.getText().toString();
            System.out.println(text);
        }
    }

在这里插入图片描述

    @Override
    public List<String> getSuggestions(String prefix) {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().suggest(new SuggestBuilder().
                addSuggestion("suggestions", SuggestBuilders
                        .completionSuggestion("suggestion")
                        .prefix(prefix)
                        .skipDuplicates(true)
                        .size(10)
                ));
        //3.发起请求
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        ///4.解析结果
        Suggest suggest = response.getSuggest();
        //4.1根据补全查询名称获取补全结果
        CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
        //4.2 获取options
        List<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();
        //4.3 遍历
        List<String> list = new ArrayList<>(options.size());
        for (CompletionSuggestion.Entry.Option option : options) {
            String text = option.getText().toString();
            list.add(text);
        }
        return list;
    }

数据同步

数据同步思路分析

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

利用mq实现mysql与elasticsearch数据同步



声明excahnge、queue、RoutingKey

public class MqConstants {
    //交换机
    public final  static String HOTEL_EXCHANGE = "hotel.topic";
    //新增修改的队列
    public final  static String HOTEL_INSERT_QUEUE = "hotel.insert.queue";
    //删除队列
    public final  static String HOTEL_DELETE_QUEUE = "hotel.delete.queue";
    //新增获修改RoutingKey
    public final  static String HOTEL_INSERT_KEY = "hotel.insert";
    //删除的RoutingKey
    public final  static String HOTEL_DELETE_KEY = "hotel.delete";
}

@Configuration
public class MqConfig {
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange(MqConstants.HOTEL_EXCHANGE,true,false);
    }
    @Bean
    public Queue insertQueue(){
        return new Queue(MqConstants.HOTEL_INSERT_QUEUE,true);
    }
    @Bean
    public Queue deleteQueue(){
        return new Queue(MqConstants.HOTEL_DELETE_QUEUE,true);
    }
    @Bean
    public Binding insertQueueBinding(){
        return BindingBuilder.bind(insertQueue()).to(topicExchange()).with(MqConstants.HOTEL_INSERT_KEY);
    }
    @Bean
    public Binding deleteQueueBinding(){
        return BindingBuilder.bind(deleteQueue()).to(topicExchange()).with(MqConstants.HOTEL_DELETE_KEY);
    }
}

yaml配置

  rabbitmq:
    host: xxx.xxx.x.xxx(主机地址)
    port: 5672
    username: itcast
    password: 123321
    virtual-host: /

在hotel-admin中增、删、改业务中完成消息发送
mq组件

@Component
public class HotelListener {
    @Autowired
    private IHotelService hotelService;
    /**
     * 监听酒店新增或修改的业务
     * @param id
     */
    @RabbitListener(queues = MqConstants.HOTEL_INSERT_QUEUE)
    public void listenHotelInsertOrUpdate(Long id){
        hotelService.insertById(id);
    }

    /**
     * 监听酒店删除的业务
     * @param id
     */
    @RabbitListener(queues = MqConstants.HOTEL_DELETE_QUEUE)
    public void listenHotelDelete(Long id){
        hotelService.deleteById(id);
    }
}

实现类

    @Autowired
    private RabbitTemplate rabbitTemplate;
        @PostMapping
    public void saveHotel(@RequestBody Hotel hotel){
        hotelService.save(hotel);
        rabbitTemplate.convertAndSend(MqConstants.HOTEL_EXCHANGE, MqConstants.HOTEL_INSERT_KEY, hotel.getId());
    }

    @PutMapping()
    public void updateById(@RequestBody Hotel hotel){
        if (hotel.getId() == null) {
            throw new InvalidParameterException("id不能为空");
        }
        hotelService.updateById(hotel);
        rabbitTemplate.convertAndSend(MqConstants.HOTEL_EXCHANGE, MqConstants.HOTEL_INSERT_KEY, hotel.getId());
    }

    @DeleteMapping("/{id}")
    public void deleteById(@PathVariable("id") Long id) {
        hotelService.removeById(id);
        rabbitTemplate.convertAndSend(MqConstants.HOTEL_EXCHANGE, MqConstants.HOTEL_DELETE_KEY, id);

    }

在hotel-demo中完成消息监听,并更新elasticsearch中的数据

    @Override
    public void deleteById(Long id) {
        //1.准备Request
        DeleteRequest request = new DeleteRequest("hotel",id.toString());
        //2.准备发送请求
        try {
            client.delete(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void insertById(Long id) {
        //0.根据id查询酒店数据
        Hotel hotel = getById(id);
        //转换文档类型
        HotelDoc hotelDoc = new HotelDoc(hotel);
        //1.准备Request
        IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
        //2.准备JSON文档
        request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
        //3.准备发送请求
        try {
            client.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

集群

介绍

在这里插入图片描述

搭建ES集群

version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
    container_name: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic
  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
    container_name: es02
    environment:
      - node.name=es02
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic
  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
    container_name: es03
    environment:
      - node.name=es03
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data03:/usr/share/elasticsearch/data
    networks:
      - elastic

volumes:
  data01:
    driver: local
  data02:
    driver: local
  data03:
    driver: local

networks:
  elastic:
    driver: bridge

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

搭建vauditdemo靶场mysql为NO问题

一、问题 在搭建vauditdemo时&#xff0c;遇到如下显示问题&#xff1a; mysql版本检测为NO 二、解决 查找该方面问题时&#xff0c;并没有找到解决方法 然后换mysql版本换了五六个也没有解决问题 问了AI后给的答复有一条为将mysql改为mysqli 修改保存后解决问题 步骤如…

力扣 T62 不同路径

题目 连接 思路 思路1 &#xff1a; BFS爆搜 class Solution { public:queue<pair<int,int>>q;int uniquePaths(int m, int n) {q.push({1,1}); // 起始位置vector<pair<int, int>> actions;actions.push_back({0, 1}); // 向下actions.push_bac…

OBS 录屏软件:录制圆形头像画中画,设置卡通人像(保姆级教程,有步骤图,建议收藏)

Mac分享吧 文章目录 一、OBS录屏软件 圆形头像画中画效果注意&#xff1a;圆形画中画仅需要在软件中设置一次&#xff0c;每次录制&#xff0c;使用带有圆形头像画中画的场景 录制视频即可。该场景不可删除&#xff01;&#xff01;&#xff01;若删除&#xff0c;则需要重新设…

Vue3学习日记(day2)

目录 前言 注意事项 vite使用 1&#xff1a;控制台vite创建vue 2&#xff1a;使用可视化软件&#xff08;我使用为vscode&#xff09;npm安装对应依赖包 3&#xff1a;使用npm脚本或者直接在终端输入命令运行软件后打开生成网址 4&#xff1a;打开网址正常进入网页 rou…

【漏洞复现】飞企互联-FE企业运营管理平台 treeXml.jsp SQL注入漏洞

0x01 产品简介 飞企互联-FE企业运营管理平台是一个基于云计算、智能化、大数据、物联网、移动互联网等技术支撑的云工作台。这个平台可以连接人、链接端、联通内外&#xff0c;支持企业B2B、C2B与020等核心需求&#xff0c;为不同行业客户的互联网转型提供支持。其特色在于提供…

限流(服务降级):基于自定义注解+切面的方式实现接口调用频率限制

文章目录 引言I 基于GuavaCache实现频率限制1.1 基于LoadingCache实现(灵活控制,高效率)【推荐】1.2 基于LoadingCache自定义RateLimiter (无法灵活控制限制时间范围)1.3 基于google的RateLimiter实现(效率低)II 基于Redis实现限流引言 背景:提供接口给下游(外部厂商)…

DeepSpeed Huggingface模型的自动Tensor并行、kernel注入、训练阶段的优化版kernel

推理阶段。 在后台&#xff0c;1. DeepSpeed会把运行高性能kernel(kernel injection)&#xff0c;加快推理速度&#xff0c;这些对用户是透明的&#xff1b; 2. DeepSpeed会根据mp_size来将模型放置在多个GPU卡上&#xff0c;自动模型并行&#xff1b; import os import torch …

Mysql学习(八)——多表查询

文章目录 五、多表查询5.1 多表关系5.2 多表查询概述5.3 内连接5.4 外连接5.5 自连接5.6 联合查询5.7子查询5.8 总结 五、多表查询 5.1 多表关系 概述&#xff1a;项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;…

freertos源码分析DAY2 (消息队列 )

目录 1. 队列原理 1.1 顺序队列操作 1.2 循环队列操作 2.消息队列原理 2.1消息队列的构成 2.2 消息队列出入队原则 2.3 消息队列发送/接收消息原理 2.4 队列锁机制 3. 消息队列创建及删除 3.1 创建消息队列函数 3.1.1 xQueueGenericCreate通用任务创建函数 3.1.1.1 …

人工智能在医学领域的应用及技术实现

欢迎来到 Papicatch的博客 目录 &#x1f349;引言 &#x1f349; 医学影像分析 &#x1f348;技术实现 &#x1f34d;数据准备 &#x1f34d;模型构建 &#x1f34d;模型训练 &#x1f34d;模型评估 &#x1f34d;应用部署 &#x1f348;示例代码 &#x1f349; 基因…

简单动态字符串SDS

简单动态字符串&#xff08;simple dynamic string&#xff09;: redis虽然说是用C语言重写的&#xff0c;但它也进行了一些创新&#xff0c;自己构建了简单动态字符串SDS&#xff0c;从名字也看得出来有别于以空字符结尾的字符数组&#xff08;C字符串&#xff09; reids中只…

谷歌AI助力软件工程的进展及未来展望

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【教学类-64-03】20240611色块眼力挑战(三)-2-10宫格色差10-50(10倍)适合中班幼儿园(星火讯飞)

背景需求&#xff1a; 【教学类-64-02】20240610色块眼力挑战&#xff08;二&#xff09;-2-25宫格&色差10-100&#xff08;10倍&#xff09;&#xff08;星火讯飞&#xff09;-CSDN博客文章浏览阅读360次&#xff0c;点赞17次&#xff0c;收藏13次。【教学类-64-02】2024…

34、matlab输入命令汇总

1、ans:最近计算的答案 代码示例1 12ans 3 代码示例2 Brand(7)B 列 1 至 60.7060 0.3171 0.1869 0.6797 0.5853 0.95930.0318 0.9502 0.4898 0.6551 0.2238 0.54720.2769 0.0344 0.4456 0.1626 0.7513 0.13860.0462 0.4387…

[大模型]GLM4-9B-chat Lora 微调

本节我们简要介绍如何基于 transformers、peft 等框架&#xff0c;对 LLaMA3-8B-Instruct 模型进行 Lora 微调。Lora 是一种高效微调方法&#xff0c;深入了解其原理可参见博客&#xff1a;知乎|深入浅出 Lora。 这个教程会在同目录下给大家提供一个 nodebook 文件&#xff0c…

python科研做图系列之时序图的绘制——对比折线图

参考知乎 折线图 我需要从两个不同的excel都读取第一列作为时间列,第二列作为编码列。 在同一张图上画出两条时间序列的折线图 横坐标是分钟,纵坐标是编码 帮我画的好看一些,记得解决中文乱码问题 英文版折线图 ,先搞个英文版,导师要求中文的话,再换成中文版 impor…

新技术前沿-2023-大模型学习根据个人数据集微调一个Transformer模型

参考如何根据自己的数据集微调一个 Transformer 模型 我们将通过NLP中最常见的文本分类任务来学习如何在自己的数据集上利用迁移学习(transfer learning)微调一个预训练的Transformer模型——DistilBERT。DistilBERT是BERT的一个衍生版本&#xff0c;它的优点在它的性能与BERT相…

区间预测 | Matlab实现GRU-ABKDE门控循环单元自适应带宽核密度估计多变量回归区间预测

区间预测 | Matlab实现GRU-ABKDE门控循环单元自适应带宽核密度估计多变量回归区间预测 目录 区间预测 | Matlab实现GRU-ABKDE门控循环单元自适应带宽核密度估计多变量回归区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现GRU-ABKDE门控循环单元自适应…

沐风老师3DMAX一键多孔结构建模插件Porous使用方法

​3DMAX一键多孔结构建模插件Porous使用教程 3dMax是大家熟知的3D建模软件之一&#xff0c;其功能非常的强大&#xff0c;在科研绘图领域有着非常广泛的应用&#xff0c;但是由于科研绘图的图形&#xff08;模型&#xff09;一般都属于异形结构&#xff0c;手工绘制建模&#x…

Docker | 入门:原理探究

Docker | 入门&#xff1a;原理探究 Run 的运行流程 Docker 底层原理 Docker 是怎么工作的&#xff1f; Docker 是一个 Client-Server 结构的系统&#xff0c;Docker 的守护进程运行在主机上&#xff0c;通过 Socket 从客户端访问。DockerServer 接受到 Docker-Client 的指令…