资讯详情

SpringCloud RabbitMQ Docker Redis 搜索 分布式 - 2

Docker Day3,2022年4月3日

1、初始-Docker

docker 架构

我们要使用Docker为了操作镜像和容器,必须安装它们Docker。

Docker是一个CS由两部分组成:

  • 服务端(server):Docker守护过程,负责处理Docker指令,管理镜像、容器等
  • 客户端(client):通过命令或RestAPI向Docker服务器发送指令。指令可以在本地或远程发送到服务器。 请添加图片描述
  • 包装应用程序及其依赖、环境和配置
  • 镜像是一个容器,一个镜像可以运行多个容器
  • 服务:接收命令或远程请求,操作镜像或容器
  • 客户端:发送命令或请求Docker服务端
  • 一个镜像托管的服务器,类似的还有阿里云镜像服务,统称为

2、安装Docker

以前安装过旧版本的,Docker,以下命令可用于卸载:

yum remove docker \                   docker-client \                   docker-client-latest \                   docker-common \                   docker-latest \                   docker-latest-logrotate \                   docker-logrotate \                   docker-selinux \                   docker-engine-selinux \                   docker-engine \                   docker-ce 

安装yum工具

yum install -y yum-utils \            device-mapper-persistent-data \            lvm2 --skip-broken 

然后更新本地镜像源:

# 设置docker镜像源 yum-config-manager \     --add-repo \     https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo      sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo  yum makecache fast 

然后输入命令:

yum install -y docker-ce 

docker-ce免费版本的社区。等一会儿,docker可成功安装。

3、启动docker

Docker应用程序需要使用各种端口,逐一修改防火墙设置。很麻烦,所以建议直接关闭防火墙!

启动docker一定要关好防火墙!

# 关闭 systemctl stop firewalld # 禁止启动防火墙 systemctl disable firewalld 

从命令开始docker:

systemctl start docker  # 启动docker服务 systemctl stop docker  # 停止docker服务 systemctl restart docker  # 重启docker服务 systemctl status docker # 查看状态 systemctl enable docker # 开机自启 

然后输入命令查看docker版本:

docker -v 

4.配置镜像加速

docker官方镜像仓库网速差,需要设置国内镜像服务: 参考阿里云镜像加速文件:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://tujdejyp.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker 

5、docker的基本操作

①、从dockerub中获取镜像,根据查看到的镜像名称,拉取自己需要的镜像:

docker pull nginx

注:镜名称一般分两部分组成:[repository]:[tag]。在没有指定tag时,默认是latest,代表最新版本的镜像 ②、保存、导入镜像

利用docker save将nginx镜像导出磁盘,然后再通过load加载回来 利用docker xx --help命令查看docker save和docker load的语法

命令格式:

docker save -o [保存的目标文件名称] [镜像名称]

1).使用docker save导出镜像到磁盘

docker save -o nginx.tar nginx:latest

2).使用docker load加载镜像 先删除本地的nginx镜像:

docker rmi nginx:latest

然后运行命令,加载本地文件:

docker load -i nginx.tar

6、docker容器基本操作

  • 运行:进程正常运行
  • 暂停:进程暂停,CPU不再运行,并不释放内存
  • 停止:进程终止,回收进程占用的内存、CPU等资源

  • docker run:创建并运行一个容器,处于运行状态
  • docker pause:让一个运行的容器暂停 docker
  • unpause:让一个容器从暂停状态恢复运行
  • docker stop:停止一个运行的容器 docker
  • start:让一个停止的容器再次运行
  • docker rm:删除一个容器

docker run --name containerName -p 80:80 -d nginx

  • docker run :创建并运行一个容器
  • –name : 给容器起一个名字,比如叫做mn
  • -p :将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口
  • -d:后台运行容器
  • nginx:镜像名称,例如nginx

这里的-p参数,是将容器端口映射到宿主机端口。 默认情况下,容器是隔离环境,我们直接访问宿主机的80端口,肯定访问不到容器中的nginx。 现在,将容器的80与宿主机的80关联起来,当我们访问宿主机的80端口时,就会被映射到容器的80,这样就能访问到nginx了: 进入容器修改文件 **需求:**进入Nginx容器,修改HTML文件内容,添加“传智教育欢迎您” **提示:**进入容器要用到docker exec命令。

docker exec -it mn bash

  • docker exec :进入容器内部,执行一个命令
  • -it : 给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互
  • mn :要进入的容器的名称
  • bash:进入容器后执行的命令,bash是一个linux终端交互命令

容器内部会模拟一个独立的Linux文件系统,看起来如同一个linux服务器一样 docker run命令的常见参数有哪些?

  • –name:指定容器名称
  • -p:指定端口映射
  • -d:让容器后台运行

  • docker logs
  • 添加 -f 参数可以持续查看日志

  • docker ps
  • docker ps -a 查看所有容器,包括已经停止的

7、数据卷

docker volume [COMMAND]

docker volume命令是数据卷操作,根据命令后跟随的command来确定下一步的操作:

  • create 创建一个volume
  • inspect 显示一个或多个volume的信息
  • ls 列出所有的volume
  • prune 删除未使用的volume
  • rm 删除一个或多个指定的volume

需求:创建一个数据卷,并查看数据卷在宿主机的目录位置 ① 创建数据卷

docker volume create html

② 查看所有数据

docker volume ls

③ 查看数据卷详细信息卷

docker volume inspect html

可以看到,我们创建的html这个数据卷关联的宿主机目录为/var/lib/docker/volumes/html/_data目录。

  • 将容器与数据分离,解耦合,方便操作容器内数据,保证数据安全

  • docker volume create:创建数据卷
  • docker volume ls:查看所有数据卷
  • docker volume inspect:查看数据卷详细信息,包括关联的宿主机目录位置
  • docker volume rm:删除指定数据卷
  • docker volume prune:删除所有未使用的数据卷

docker run \
  --name mn \
  -v html:/root/html \
  -p 8080:80
  nginx \

这里的-v就是挂载数据卷的命令:

  • -v html:/root/htm :把html数据卷挂载到容器内的/root/html这个目录中

创建mysql容器

docker run \
--name mysql \
-e MYSQL_ROOT_PASSWORD=12356 \
-p 3306:3306 \
-v /tmp/mysql/conf/hmy.cnf:/home/lyd/mysql/conf/hmy.cnf \
-v /tmp/mysql/data:/home/lyd/mysql/data/ms \
-d \
mysql:5.7.25

RabbitMQ Day4,2022年4月6日

1、初始MQ

csdn上好多博客都有介绍

2、RabbitMQ

1)、下载镜像

方式一:在线获取

docker pull rabbitmq:3-management

方式二:本地加载 上传到虚拟机中后,使用命令加载镜像即可:

2)、安装MQ

docker run \
 -e RABBITMQ_DEFAULT_USER=itcast \
 -e RABBITMQ_DEFAULT_PASS=123456 \
 --name mq \
 --hostname mq1 \
 -p 15672:15672 \
 -p 5672:5672 \
 -d \
 rabbitmq:3-management

15672:ui管理端口

// 1.建立连接
ConnectionFactory factory = new ConnectionFactory();
// 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
factory.setHost("192.168.237.128");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("itcast");
factory.setPassword("123456");
// 1.2.建立连接
Connection connection = factory.newConnection();

// 2.创建通道Channel
Channel channel = connection.createChannel();

// 3.创建队列
String queueName = "simple.queue";
channel.queueDeclare(queueName, false, false, false, null);

// 4.发送消息
String message = "hello, rabbitmq!";
channel.basicPublish("", queueName, null, message.getBytes());
System.out.println("发送消息成功:【" + message + "】");

// 5.关闭通道和连接
channel.close();
connection.close();

// 1.建立连接
ConnectionFactory factory = new ConnectionFactory();
// 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
factory.setHost("192.168.237.128");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("itcast");
factory.setPassword("123456");
// 1.2.建立连接
Connection connection = factory.newConnection();

// 2.创建通道Channel
Channel channel = connection.createChannel();

// 3.创建队列
String queueName = "simple.queue";
channel.queueDeclare(queueName, false, false, false, null);

// 4.消息订阅
channel.basicConsume(queueName, true, new DefaultConsumer(channel){ 
        
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { 
        
        // 5.处理消息
        String message = new String(body);
        System.out.println("接收消息成功:【" + message + "】");
    }
});
System.out.println("等待接收消息...");

  1. 建立connection
  2. 创建channel
  3. 利用channel声明队列
  4. 利用channel向队列发送消息

  1. 建立connection
  2. 创建channel
  3. 利用channel声明队列
  4. 定义consumer的消费行为handleDelivery()
  5. 利用channel将消费者与队列绑定

3、SpringAMQP

Basic Queue 简单队列模型 在父工程mq-demo中引入依赖

<!--AMQP依赖,包含RabbitMQ-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

首先配置MQ地址,在publisher服务的application.yml中添加配置:

spring:
  rabbitmq:
    host: 192.168.150.101 # 主机名
    port: 5672 # 端口
    virtual-host: / # 虚拟主机
    username: itcast # 用户名
    password: 123321 # 密码

然后在publisher服务中编写测试类SpringAmqpTest,并利用RabbitTemplate实现消息发送:

package cn.itcast.mq.spring;
​
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
​
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringAmqpTest { 
        
​
    @Autowired
    private RabbitTemplate rabbitTemplate;
​
    @Test
    public void testSimpleQueue() { 
        
        // 队列名称
        String queueName = "simple.queue";
        // 消息
        String message = "hello, spring amqp!";
        // 发送消息
        rabbitTemplate.convertAndSend(queueName, message);
    }
}

首先配置MQ地址,在consumer服务的application.yml中添加配置:

spring:
  rabbitmq:
    host: 192.168.150.101 # 主机名
    port: 5672 # 端口
    virtual-host: / # 虚拟主机
    username: itcast # 用户名
    password: 123321 # 密码

然后在consumer服务的cn.itcast.mq.listener包中新建一个类SpringRabbitListener,代码如下:

package cn.itcast.mq.listener;
​
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
​
@Component
public class SpringRabbitListener { 
        
​
    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueueMessage(String msg) throws InterruptedException { 
        
        System.out.println("spring 消费者接收到消息:【" + msg + "】");
    }
}

ElasticSearch Day5 2022年4月7日

mysql与elasticsearch

两者各自有自己的擅长支出:

  • Mysql:擅长事务类型操作,可以确保数据的安全和一致性
  • Elasticsearch:擅长海量数据的搜索、分析、计算

因此在企业中,往往是两者结合使用:

  • 对安全性要求较高的写操作,使用mysql实现
  • 对查询性能要求较高的搜索需求,使用elasticsearch实现
  • 两者再基于某种方式,实现数据的同步,保证一致性

mapping映射属性

mapping是对索引库中文档的约束,常见的mapping属性包括:

  • type:字段数据类型,常见的简单类型有: 字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址) 数值:long、integer、short、byte、double、float、 布尔:boolean 日期:date 对象:object
  • index:是否创建索引,默认为true
  • analyzer:使用哪种分词器
  • properties:该字段的子字段

索引库的CRUD

创建索引库和映射

PUT /索引库名称
{ 
        
  "mappings": { 
        
    "properties": { 
        
      "字段名":{ 
        
        "type": "text",
        "analyzer": "ik_smart"
      },
      "字段名2":{ 
        
        "type": "keyword",
        "index": "false"
      },
      "字段名3":{ 
        
        "properties": { 
        
          "子字段": { 
        
            "type": "keyword"
          }
        }
      },
      // ...略
    }
  }
}

 PUT /heima
{ 
        
  "mappings": { 
        
    "properties": { 
        
      "info":{ 
        
        "type": "text",
        "analyzer": "ik_smart"
      },
      "email":{ 
        
        "type": "keyword",
        "index": "falsae"
      },
      "name":{ 
        
        "properties": { 
        
          "firstName": { 
        
            "type": "keyword"
          }
        }
      },
      // ... 略
    }
  }
}

查询索引库

请求方式:GET 请求路径:/索引库名 请求参数:无

GET /索引库名

修改索引库

倒排索引结构虽然不复杂,但是一旦数据结构改变(比如改变了分词器),就需要重新创建倒排索引,这简直是灾难。因此索引库

虽然无法修改mapping中已有的字段,但是却允许添加新的字段到mapping中,因为不会对倒排索引产生影响。

PUT /索引库名/_mapping
{ 
        
  "properties": { 
        
    "新字段名":{ 
        
      "type": "integer"
    }
  }
}

删除索引库

请求方式:DELETE 请求路径:/索引库名 请求参数:无

DELETE /索引库名

文档操作

新增文档

POST /索引库名/_doc/文档id
{ 
        
    "字段1": "值1",
    "字段2": "值2",
    "字段3": { 
        
        "子属性1": "值3",
        "子属性2": "值4"
    },
    // ...
}

查询文档

GET /{ 
        索引库名称}/_doc/{ 
        id}

GET /heima/_doc/1

删除文档

删除使用DELETE请求,同样,需要根据id进行删除:

DELETE /{ 
        索引库名}/_doc/id值

#根据id删除数据
DELETE /heima/_doc/1

修改文档

修改有两种方式:

  • 全量修改:直接覆盖原来的文档
  • 增量修改:修改文档中的部分字段

全量修改是覆盖原来的文档,其本质是:

  • 根据指定的id删除文档
  • 新增一个相同id的文档

**注意:**如果根据id删除时,id不存在,第二步的新增也会执行,也就从修改变成了新增操作了。

PUT /{ 
        索引库名}/_doc/文档id
{ 
        
    "字段1": "值1",
    "字段2": "值2",
    // ... 略
}

PUT /heima/_doc/1
{ 
        
    "info": "黑马程序员高级Java讲师",
    "email": "zy@itcast.cn",
    "name": { 
        
        "firstName": "云",
        "lastName": "赵"
    }
}

增量修改是只修改指定id匹配的文档中的部分字段。

POST /{ 
        索引库名}/_update/文档id
{ 
        
    "doc": { 
        
         "字段名": "新的值",
    }
}

POST /heima/_update/1
{ 
        
  "doc": { 
        
    "email": "ZhaoYun@itcast.cn"
  }
}

RestAPI

创建索引库

代码分为三步:

  • 1)创建Request对象。因为是创建索引库的操作,因此Request是CreateIndexRequest。
  • 2)添加请求参数,其实就是DSL的JSON参数部分。因为json字符串很长,这里是定义了静态字符串常量MAPPING_TEMPLATE,让代码看起来更加优雅。
  • 3)发送请求,client.indices()方法的返回值是IndicesClient类型,封装了所有与索引库操作有关的方法。 在hotel-demo的cn.itcast.hotel.constants包下,创建一个类,定义mapping映射的JSON字符串常量:
package cn.itcast.hotel.constants;
​
public class HotelConstants { 
        
    public static final String MAPPING_TEMPLATE = "{\n" +
            " \"mappings\": {\n" +
            " \"properties\": {\n" +
            " \"id\": {\n" +
            " \"type\": \"keyword\"\n" +
            " },\n" +
            " \"name\":{\n" +
            " \"type\": \"text\",\n" +
            " \"analyzer\": \"ik_max_word\",\n" +
            " \"copy_to\": \"all\"\n" +
            " },\n" +
            " \"address\":{\n" +
            " \"type\": \"keyword\",\n" +
            " \"index\": false\n" +
            " },\n" +
            " \"price\":{\n" +
            " \"type\": \"integer\"\n" +
            " },\n" +
            " \"score\":{\n" +
            " \"type\": \"integer\"\n" +
            " },\n" +
            " \"brand\":{\n" +
            " \"type\": \"keyword\",\n" +
            " \"copy_to\": \"all\"\n" +
            " },\n" +
            " \"city\":{\n" +
            " \"type\": \"keyword\",\n" +
            " \"copy_to\": \"all\"\n" +
            " },\n" +
            " \"starName\":{\n" +
            " \"type\": \"keyword\"\n" +
            " },\n" +
            " \"business\":{\n" +
            " \"type\": \"keyword\"\n" +
            " },\n" +
            " \"location\":{\n" +
            " \"type\": \"geo_point\"\n" +
            " },\n" +
            " \"pic\":{\n" +
            " \"type\": \"keyword\",\n" +
            " \"index\": false\n" +
            " },\n" +
            " \"all\":{\n" +
            " \"type\": \"text\",\n" +
            " \"analyzer\": \"ik_max_word\"\n" +
            " }\n" +
            " }\n" +
            " }\n" +
            "}";
}

在hotel-demo中的HotelIndexTest测试类中,编写单元测试,实现创建索引:

@Test
void createHotelIndex() throws IOException { 
        
    // 1.创建Request对象
    CreateIndexRequest request = new CreateIndexRequest("hotel");
    // 2.准备请求的参数:DSL语句
    request.source(MAPPING_TEMPLATE, XContentType.JSON);
    // 3.发送请求
    client.indices().create(request, RequestOptions.DEFAULT);
}

删除索引库

删除索引库的DSL语句非常简单:

DELETE /hotel

与创建索引库相比:

  • 请求方式从PUT变为DELTE
  • 请求路径不变
  • 无请求参数

所以代码的差异,注意体现在Request对象上。依然是三步走: 1)创建Request对象。这次是DeleteIndexRequest对象 2)准备参数。这里是无参 3)发送请求。改用delete方法 在hotel-demo中的HotelIndexTest测试类中,编写单元测试,实现删除索引:

@Test
void testDeleteHotelIndex() throws IOException { 
        
    // 1.创建Request对象
    DeleteIndexRequest request = new DeleteIndexRequest("hotel");
    // 2.发送请求
    client.indices( 

标签: 61082连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台