# Docker 环境搭建 ## docker基础 ###docker安装 * docker的安装非常简单,我们可以直接使用centos系统中的yum命令进行安装。 ```shell yum install -y docker ``` * 安装完成之后。 ``` shell [root@VM-0-6-centos ~]# docker version Client: Docker Engine - Community Version: 19.03.13 API version: 1.40 Go version: go1.13.15 Git commit: 4484c46d9d Built: Wed Sep 16 17:03:45 2020 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.13 API version: 1.40 (minimum version 1.12) Go version: go1.13.15 Git commit: 4484c46d9d Built: Wed Sep 16 17:02:21 2020 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.2.13 GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429 runc: Version: 1.0.0-rc10 GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd docker-init: Version: 0.18.0 GitCommit: fec3683 ``` * 证明安装完成,docker的命令如下: ```shell systemctl start docker # 启动docker systemctl stop docker # 停止docker systemctl status docker # 查看docker状态 systemctl restart docker # 重新启动docker ``` * 在启动之前我们需要修改docker的镜像源: ```shell [root@VM-0-6-centos ~]# vim /etc/docker/daemon.json { "registry-mirrors": ["https://ftnejmh3.mirror.aliyuncs.com"] } ``` * 完成后运行systemctl start docker,启动docker服务。 ## docker环境搭建 >环境软件介绍: ```php 1. docker 2. nginx 3. mysql 4. php7.4 5. laravel7 ``` * docker搭建的lnmp目录结构: ```shell docker │ └── nginx │ │ └── default.conf #nginx配置文件 │ └── www │ └── lmrs-iteam #lmrs的laravel项目代码 ``` ### docker搭建Nginx > 我们可以使用docker search nginx命令查找 Docker Hub 上的 nginx 镜像,这里直接拉取官方的镜像。 ``` [root@VM-0-6-centos ~]# docker pull nginx ``` * 等待下载完成后,我们就可以在本地镜像列表里查到 REPOSITORY 为 nginx 的镜像。 ```shell [root@VM-0-6-centos docker]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 4cdc5dd7eaad 13 days ago 133MB ``` * 创建nginx配置 ```shell [root@VM-0-6-centos nginx]# pwd /root/docker/nginx [root@VM-0-6-centos nginx]# vim default.conf server { listen 80; listen [::]:80; server_name localhost; root /docker/www; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /docker/www; } location ~ \.php$ { root /docker/www/lmrs-2008/public; fastcgi_pass 172.17.0.3:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } ``` * 使用nginx镜像开启nginx应用容器 ```shell [root@VM-0-6-centos nginx]# docker run -p 80:80 -d --name nginx --link php -v /Users/super/Desktop/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf -v /Users/super/Desktop/docker/www:/docker/www --privileged=true nginx WARNING: IPv4 forwarding is disabled. Networking will not work. 如果出现:IPv4 forwarding is disabled. Networking will not work.(问题1) ``` ### docker搭建php7.4-fpm ```shell docker pull php:7.4-fpm ``` * 等待下载完成后,我们就可以在本地镜像列表里查到REPOSITORY为php,标签为7.4-fpm的镜像。 * 使用php镜像开启php-frm应用容器 ```shell docker run -p 9000:9000 -d --name php -v /Users/super/Desktop/docker/www:/docker/www --privileged=true php:7.4-fpm -p 9000:9000 :将容器的9000端口映射到主机的9000端口 -d 后台运行(守护进程) --name php:将容器命名为php -v 将主机中当前目录下的www挂载到容器的www目录 ``` * 查看容器启动情况 ```shell ✘ super@superdeiMac ~/Desktop/docker/nginx docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 01c012430faf nginx "/docker-entrypoint.…" 2 minutes ago Up About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp nginx 5a6d1d463389 php:7.4-fpm "docker-php-entrypoi…" 2 minutes ago Up About a minute 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp php #到这里,可以看到nginx和php都运行成功(STATUS为up说明正在运行) ``` ### swoole加速laravel框架 #### swoole是什么? > Swoole 是一个使用 C++ 语言编写的基于异步事件驱动和协程的并行网络通信引擎,为 PHP 提供协程、高性能网络编程支持。提供了多种通信协议的网络服务器和客户端模块,可以方便快速的实现 TCP/UDP服务、高性能Web、WebSocket服务、物联网、实时通讯、游戏、微服务等,使 PHP 不再局限于传统的 Web 领域。 > swoole的优势 > 常驻内存,避免重复加载带来的性能损耗,提升海量性能 > 协程异步,提高对 I/O 密集型场景并发处理能力(如:微信开发、支付、登录等) > 方便地开发 Http、WebSocket、TCP、UDP 等应用,可以与硬件通信 #### swoole的安装 ```shell 1.获取swoole安装包,地址:https://pecl.php.net/get/swoole-4.6.6.tgz 1.1 apt-get update && apt-get install wget 1.2 wget https://pecl.php.net/get/swoole-4.6.6.tgz 2. 解压swoole安装包 tar –zxvf swoole-4.6.6.tar 3. 将解压出来的安装包copy到php容器 docker cp swoole-4.6.6 php:/usr/src/php/ext/swoole 3.1 进入容器 docker exec -it php bash 4. 安装swoole docker-php-ext-install swoole 5. 完成安装后,查看swoole信息 php --ri swoole ``` > laravel使用swoole的组件 * 在 Laravel 应用中使用 Swoole 之前,先通过 Composer 安装 LaravelS 扩展包:composer require hhxsv5/laravel-s * 该扩展包具备自动发现功能(Laravel 5.5 以上版本可用),无需手动在 config/app.php 配置文件中注册,安装完成后,运行如下 Artisan 命令相应脚本和配置文件发布到根目录下:php artisan laravels publish * 该命令会发布配置文件 laravels.php 到 config 目录下,以及脚本文件到 bin 目录下:你可以在配置文件中对 Swoole 进行一些基本配置,而脚本文件主要用于管理 Swoole 服务的启动、重载、关闭等操作。 > 配置 * 也可以在.env 修改工作进程数并重启服务 * LARAVELS_LISTEN_IP=0.0.0.0 * LARAVELS_LISTEN_PORT=5200 * LARAVELS_WORKER_NUM=4 * 更多配置项: https://github.com/hhxsv5/laravel-s/blob/master/Settings-CN.md > 启动 LaravelS > 完成上述操作后,就可以通过 [^php bin/laravels start] 命令启动 LaravelS 了: ```shell root@5a6d1d463389:/docker/www/lmrs-2008# php bin/laravels start _ _ _____ | | | |/ ____| | | __ _ _ __ __ ___ _____| | (___ | | / _` | '__/ _` \ \ / / _ \ |\___ \ | |___| (_| | | | (_| |\ V / __/ |____) | |______\__,_|_| \__,_| \_/ \___|_|_____/ Speed up your Laravel/Lumen >>> Components +---------------------------+---------+ | Component | Version | +---------------------------+---------+ | PHP | 7.4.21 | | Swoole | 4.6.6 | | LaravelS | 3.4.4 | | Laravel Framework [local] | 7.30.4 | +---------------------------+---------+ >>> Protocols +-----------+--------+-------------------+--------------+ | Protocol | Status | Handler | Listen At | +-----------+--------+-------------------+--------------+ | Main HTTP | On | Laravel Framework | 0.0.0.0:5200 | +-----------+--------+-------------------+--------------+ >>> Feedback: https://github.com/hhxsv5/laravel-s [2021-07-20 03:58:23] [TRACE] Swoole is running, press Ctrl+C to quit. #没有用laravel+swoole前 每次300ms 用了swoole加速后 10ms 大大的提高了速度 ``` #### swoole nginx配置文件 ```nginx upstream swoole { server php:5200 weight=5 max_fails=3 fail_timeout=30s; keepalive 16; } server { listen 80; listen [::]:80; server_name localhost; root /docker/www/lmrs-2008/public; index index.php index.html; location / { try_files $uri @laravels; } location /api { proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-PORT $remote_port; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header Server-Protocol $server_protocol; proxy_set_header Server-Name $server_name; proxy_set_header Server-Addr $server_addr; proxy_set_header Server-Port $server_port; proxy_pass http://swoole; } location @laravels { proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-PORT $remote_port; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header Server-Protocol $server_protocol; proxy_set_header Server-Name $server_name; proxy_set_header Server-Addr $server_addr; proxy_set_header Server-Port $server_port; proxy_pass http://swoole; } } ``` #### Supervisor > 通过 Supervisor 管理 LaravelS > 如果是在生产环境使用,推荐使用 Supervisor 对 LaravelS 服务进行管理,从而提供服务的稳定性,相应的配置示例如下: ```shell [program:laravel-s-test] command=php /www/wwwroot/lms/blog/bin/laravels start -i numprocs=1 autostart=true autorestart=true startretries=3 user=root redirect_stderr=true stdout_logfile=/www/wwwroot/lms/blog/storage/logs/supervisord-stdout.log 其中 /www/wwwroot/lms/blog 为 Web 项目的目录,你可以根据自己的项目路径进行修改。 ``` ### docker 安装 elasticsearch 1. docker获取es镜像 ```shell docker pull elasticsearch:7.12.1 ``` 1. 创建es文件目录以及创建配置文件 2. mkdir /docker/es 3. mkdir /docker/es/conf 4. mkdir /docker/es/data 5. mkdir /docker/es/plugins 6. touch /docker/es/conf/elasticsearch.yml ```shell # elasticsearch.yml cluster.name: my-application #集群名称 node.name: node-1 #节点名称 数据和日志的存储目录 path.data: /usr/share/elasticsearch/data path.logs: /usr/share/elasticsearch/logs 设置绑定的ip,设置为0.0.0.0以后就可以让任何计算机节点访问到了 network.host: 0.0.0.0 http.port: 9200 #端口 设置在集群中的所有节点名称,这个节点名称就是之前所修改的,当然你也可以采用默认的也行,目前 是单机,放入一个节点即可 cluster.initial_master_nodes: ["node-1"] 构建容器 ``` ```shell docker run -p 9200:9200 -d --name es -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -v /Users/super/Desktop/docker/es/conf/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /Users/super/Desktop/docker/es/data:/usr/share/elasticsearch/data -v /Users/super/Desktop/docker/es/plugins:/usr/share/elasticsearch/plugins --privileged=true elasticsearch:7.12.1 docker run -p 9200:9200 -d --name es -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -v /docker/es/conf/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /docker/es/data:/usr/share/elasticsearch/data -v /docker/es/plugins:/usr/share/elasticsearch/plugins --privileged=true elasticsearch:7.12.1 ``` ### docker 安装 kibana > 可视化es管理器 ```shell docker pull kibana:7.12.1 kibana的配置文件 `mkidr /docker/kibana mkdir /docker/kibana/conf touch /docker/kibana/conf/kibana.yml 文件内容: server.name: kibana server.host: "0.0.0.0" elasticsearch.hosts: ["http://es:9200"] xpack.monitoring.ui.container.elasticsearch.enabled: true 构建kibana的容器 docker run -p 5601:5601 -d --link es --name kibana -v/docker/kibana/conf/kibana.yml:/usr/share/kibana/config/kibana.yml --privileged=true kibana:7.12.1 docker run -p 5601:5601 -d --link es --name kibana -v /Users/super/Desktop/docker/kibana/conf/kibana.yml:/usr/share/kibana/config/kibana.yml --privileged=true kibana:7.12.1 ``` ### docker 安装redis ```shell docker pull redis docker run -p 6379:6379 -d --name redis --privileged=true redis ``` ### docker 安装 mysql ```shell docker pull mysql docker run -p 3306:3306 -d --name mysql -v /Users/super/Desktop/docker/mysql/etc/my.cnf:/etc/mysql/my.cnf --privileged=true -e MYSQL_ROOT_PASSWORD=root mysql:8.0 docker run -p 3306:3306 -d --name mysql -v /docker/mysql/etc/my.cnf:/etc/mysql/my.cnf --privileged=true -e MYSQL_ROOT_PASSWORD=root mysql:8.0 mysql 8.0. 改密码 ALTER user 'root'@'%' IDENTIFIED WITH mysql_native_password by "huangxiang"; flush privileges; 8.0之前改密码 update user set password=password('新密码') where user="用户名" ``` ##dockeer 安装logstash > logstash 同步 mysql到es ```shell 安装7.12.1版本 docker pull logstash:7.12.1 启动 docker run -p 9900:9900 -d --link php --link es --name logstash -v /Users/super/Desktop/docker/logstash:/etc/logstash/pipeline -v /Users/super/Desktop/docker/logstash:/etc/logstash/pipline --privileged=true logstash docker run -p 9900:9900 -d --link php --link es --name logstash -v /docker/logstash:/etc/logstash/pipeline -v /docker/logstash:/etc/logstash/pipline --privileged=true logstash 安装 jdbc 和 elasticsearch 插件 logstash-plugin install logstash-input-jdbc logstash-plugin install logstash-output-elasticsearch 更改配置文件 /usr/share/logstash/config/pipeline.yml - pipeline.id: table1 path.config: "/etc/logstash/pipeline/logstash.conf" #配置文件的路径 logstash.conf 和 mysql-connector-java-8.0.24.jar !!eslasticsearch 必须要有 product表才能同步 ``` ## laravel 封装 es搜索 ### composer 安装 ```shell composer require elasticsearch/elasticsearch "7.12.x" --ignore-platform-reqs ``` ## 配置es ```php config/database.php 追加 'elasticsearch' =>[ 'host'=>explode(',',env('ES_HOSTS')) ] .env 追加 ES_HOSTS = 172.17.0.7 初始化 Elasticsearch 对象,并注入到 Laravel 容器中: App/Providers/AppServiceProvider.php app->singleton('es',function (){ $builder = ESClientBuilder::create()->setHosts(config('database.elasticsearch.hosts')); if (app()->environment()==='local'){ $builder->setLogger(app('log')->driver()); } return $builder->build(); }); } /** * Bootstrap any application services. * * @return void */ public function boot() { // } } ?> 在laravel容器中自定义一个名为es的服务对象,通过ESClientBuilder以及配置文件中的信息连接到es,我们可以通过app('es')->info()查看连接之后的es对象信息。 注册完成后,进行测试 php artisan tinker >>>app('es')->info() ``` ### es基本命令 >查看有哪些索引 ```shell GET /_cat/indices?v ``` >精确查询 ```shell GET /products/_doc/_search { "query":{ "term":{ "name":"法外狂徒" } } } ``` > 模糊查询 ```shell GET /products/_doc/_search { "query":{ "match":{ "name":"法外狂徒" } } } ``` > 高量查询 ```shell GET /products/_doc/_search { "query":{ "match":{ "name":"iPhone" } }, "highlight":{ "fields":{ "name":{} } } } ``` ```shell 创建表 PUT /products { "mappings": { "properties": { "name":{ "type": "text", "analyzer": "ik_smart" },"long_name":{ "type": "text", "analyzer": "ik_smart" },"bran_did":{ "type": "integer" },"category_id":{ "type": "integer" },"shop_id":{ "type": "integer" },"price":{ "type": "scaled_float", "scaling_factor": 100 },"sold_count":{ "type": "integer" },"review_count":{ "type": "integer" },"status":{ "type": "integer" },"create_time":{ "type": "date" },"last_time":{ "type": "date" } } } } ``` ### 新增数据 ```shell PUT /prodcuts/_doc/1 { "name":"HUAWEI Mate Book 14", "desc":"diannao", "price":9999.00, "tags":["bangong","dayouxi"] } 返回结果: { "_index" : "prodcuts", --索引名称 "_type" : "_doc", --类型 "_id" : "1", --id "_version" : 1, --数据版本 "result" : "created", --什么样的操作,有:创建,修改,删除 "_shards" : { --分片 "total" : 2, --分片数 "successful" : 1, --1个成功 "failed" : 0 --0个失败 }, "_seq_no" : 0, --文档更新一次后都会+1 "_primary_term" : 1 --文档所在主分片的编号 } PUT /prodcuts/_doc/2 { "name":"HUAWEI Mate Book 15", "desc":"diannao", "price":10000.00, "tags":["bangong","dayouxi"] } PUT /prodcuts/_doc/3 { "name":"HUAWEI Mate Book 16", "desc":"diannao", "price":8888.00, "tags":["bangong","dayouxi"] } ``` ### GET查询数据 ```shell GET /prodcuts/_doc/1 返回结果: { "_index" : "prodcuts", --索引名称 "_type" : "_doc", --类型 "_id" : "1", --id "_version" : 1, --数据版本 "_seq_no" : 0, --文档更新一次后都会+1 "_primary_term" : 1, --文档所在主分片的编号 "found" : true, --查询结果为true "_source" : { --查询数据结果 "name" : "HUAWEI Mate Book 14", "desc" : "diannao", "price" : 9999.0, "tags" : [ "bangong", "dayouxi" ] } } GET /prodcuts/_doc/2 ``` ### POST修改数据 ```shell PUT /prodcuts/_doc/1 { "name":"HUAWEI Mate Book 14", "desc":"diannao", "price":11000.00, "tags":["bangong","dayouxi"] } 返回结果: { "_index" : "prodcuts", "_type" : "_doc", "_id" : "1", "_version" : 2, "result" : "updated", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 1, "_primary_term" : 1 } PUT /prodcuts/_doc/1 { "name":"18" } 返回结果: { "_index" : "prodcuts", "_type" : "_doc", "_id" : "1", "_version" : 3, "result" : "updated", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 2, "_primary_term" : 1 } POST /prodcuts/_doc/2/_update { "doc":{ "name":"11111111" } } 返回结果: { "_index" : "prodcuts", "_type" : "_doc", "_id" : "2", "_version" : 2, "result" : "updated", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 4, "_primary_term" : 1 } id为1的数据与id为2的数据对比: GET /prodcuts/_doc/1 返回结果: { "_index" : "prodcuts", "_type" : "_doc", "_id" : "1", "_version" : 3, "_seq_no" : 2, "_primary_term" : 1, "found" : true, "_source" : { "name" : "18" } } GET /prodcuts/_doc/2 返回结果: { "_index" : "prodcuts", "_type" : "_doc", "_id" : "2", "_version" : 2, "_seq_no" : 4, "_primary_term" : 1, "found" : true, "_source" : { "name" : "11111111", "desc" : "diannao", "price" : 10000.0, "tags" : [ "bangong", "dayouxi" ] } } ``` ### DELETE数据 ```shell DELETE /prodcuts/_doc/1 返回结果: { "_index" : "prodcuts", "_type" : "_doc", "_id" : "1", "_version" : 4, "result" : "deleted", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 5, "_primary_term" : 1 } ``` ##LME搜索实战 ###商品表 > Product 商品表 ```table 字段 | 类型 | 描述 id | bigint | 主键 name | varchar(20) | 商品名称 long_name | varchar(200) | 商品副标题 one_category_id | bigint | 一级分类 two_category_id | bigint | 二级分类 three_category_id | bigint | 三级分类 shop_id | bigint | 店铺id price | decimal(19,2) | 商品价格 sold_count | int | 销量 review_count | int| 评价数量 status | tinyint | 状态 create_time | datetime | 创建时间 last_time | datetime | 最后修改时间 delete_time | datetime | 删除时间 ``` ### 属性表 >Attribute 商品属性表 ```table 字段 | 类型 | 描述 id | bigint | 主键 name | varchar(10) | 属性名称 category_id | bigint | 分类id sort|tinyint |排序 last_time | datetime |最后修改时间 create_time | datetime | 创建时间 delete_time | datetime | 删除时间 ``` ### 属性值 > Attribute _value 属性选项表 ```table 字段 | 类型 | 描述 |关联 id | bigint | 主键 name | varchar(10) | 属性名称 attribute_id | bigint | 属性id |Attribute => id sort | tinyint | 排序 last_time | datetime |最后修改时间 create_time | datetime | 创建时间 delete_time | datetime | 删除时间 ``` ### 商品属性选项表 > Product_attribute_value 商品属性选项表 ```table 字段 | 类型 | 描述 |关联 id | bigint | 主键 product_id | varchar(10) | 商品id | Product => id attribute_id | bigint | 属性 | Attribute => id attribute_value_id | bigint |属性值 | Attribute_value => id last_time | datetime | 最后修改时间 create_time | datetime | 创建时间 delete_time | datetime | 删除时间 ``` ###商品Sku表 ```table 字段 | 类型 | 描述 |关联 id | bigint | 主键 name | varchar(255) | 商品名 num | int | 库存 price | decimal(19,2) | 价格 status | tinyint | 状态 attribute_id |varchar(20) | 属性 id | Attribute => id shop_id | bigint | 店铺id last_time | datetime | 最后修改时间 create_time | datetime | 创建时间 delete_time | datetime | 删除时间 ``` #### 理解 > 商品表 ```table id | name 1 | iPhone 12 Pro Max Fuck ``` > 属性表 ```table id | name 1 | 颜色 2 |内存 2 |版本 ``` > 属性值表 ```table id | name | attribute_id 1 | 红色 | 1 2 | 16G | 2 3 |国行 |3 ``` > 商品属性选择表 ```table product_id | attribute_id | attribute_vaule_id 1 | 1 | 1 ``` > 商品sku表 ```table name | attribute_id 1 | 1 ``` ### ik分词 1. 获取ik分词器安装包:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.12.1 2. wget https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.12.1 3. 进入es的组件目录并解压压缩包 cd /docker/es/plugins 4. unzip elasticsearch-analysis-ik-7.12.1.zip 5. 这里解压出来可能会是很散乱的,需要将解压出来的问题同一进行整理,整理到一个统一存储ik分词器相关的文件的目录: mkdir ik 6. 完成后重启es:docker restart es ```shell mv /docker/es/plugins/commons-codec-1.9.jar /docker/es/plugins/ik/ mv /docker/es/plugins/config /docker/es/plugins/ik/ mv /docker/es/plugins/httpclient-4.5.2.jar /docker/es/plugins/ik/ mv /docker/es/plugins/plugin-descriptor.properties /docker/es/plugins/ik/ mv /docker/es/plugins/commons-logging-1.2.jar /docker/es/plugins/ik/ mv /docker/es/plugins/elasticsearch-analysis-ik-7.12.1.jar /docker/es/plugins/ik/ mv /docker/es/plugins/httpcore-4.4.4.jar /docker/es/plugins/ik/ mv /docker/es/plugins/plugin-security.policy /docker/es/plugins/ik/ ``` ### 花式查询 > PUT /products/ ```shell { "mappings": { "properties": { "name":{ "type": "text", "analyzer": "ik_smart" }, "long_name":{ "type": "text", "analyzer": "ik_smart" }, "brand_id":{ "type": "integer" }, "category_id":{ "type":"integer" }, "shop_id":{ "type":"integer" }, "price":{ "type":"scaled_float", "scaling_factor":100 }, "sold_count":{ "type":"integer" }, "review_count":{ "type":"integer" }, "status":{ "type":"integer" }, "create_time" : { "type" : "date" }, "last_time" : { "type" : "date" } } } } ``` #### 常用搜索 GET /products/_search 获取products数据 GET /_cat/indices?v。获取所有索引 #### 精确搜索 > term:通过倒排索引指定的词条进行精确的查找,配合keyword类型的字段,都不分词,直接匹配 > match:查询之前会通过分词器解析,解析后再进行查询 > 两个类型:text(会被分词器解析)和keyword(不会被分词器解析) ```shell GET /products/_doc/_search { "query":{ "term":{ "name":"华为" } } } ``` #### 模糊搜索 > match ```shell GET /products/_doc/_search { "query":{ "match":{ "name":"华为" } } } ``` #### 过滤字段 >结果过滤 name 和 price ```shell GET /products/_doc/_search { "query":{ "match":{ "name":"华为" } },"_source":["name","price"] } ``` #### 排序 > 根据price字段 降序 ```shell GET /products/_doc/_search { "query":{ "match":{ "name":"华为" } },"_source":["price"], "sort":{ "price":{ "order":"desc" } } } ``` #### 分页 > elasticsearch 分页 > from是指分页的起始索引,size是指分页容量 ```shell GET /products/_doc/_search { "query":{ "match":{ "name":"华为" } },"_source":["price"], "sort":{ "price":{ "order":"desc" } }, "from":0, "size":1 } ``` #### 条件查询 > 布尔查询,多条件查询[] > 获取name=华为 且 status =0 的数据 > must(and),所有的条件都要符合,相当于where id=1 and name=xxx > should(or),满足一个条件即可,相当于 where id=1 or name=xxx > must_not(!=),所有条件必须满足不等于,相当于where id!=1 and name!=xxx ```shell { "query":{ "bool":{ "must":[ { "match":{ "name":"华为" } },{ "match":{ "status":0 } } ] } } } ``` #### 过滤查询 > 查询name带有华为或者price,并筛选出1000 类似百度搜索关键色会呈现红色 ```shell GET /products/_doc/_search { "query":{ "match":{ "name":"iPhone" } }, "highlight":{ "fields":{ "name":{} } } } ``` ### logstash 安装 1. 拉取logstash镜像 2. Docker pull logstash:7.12.1(需要与es版本对应) 3. 构建logstash容器 4. mkdir /docker/logstash --创建一个用于存储logstash配置以及插件的目录 5. Docker run –p 9900:9900 –d –name logstash –v /docker/logstash:/etc/logstash/pipeline –privileged=true logstash:7.12.1 6. 进入容器内部安装 jdbc 和 elasticsearch 插件 ` docker exec -it logstash bash --进入logstash容器内部 7. logstash-plugin install logstash-input-jdbc(此插件镜像新版本自带) --使用logstash-plugin安装器安装logstash-input-jdbc插件,改安装器在bin目录下. 8. logstash-plugin install logstash-output-elasticsearch --安装数据输出到es的插件 9. 修改容器内部配置 10. vi config/logstash.yml 更改logstash.yml文件 11. 内容如下: http.host: "0.0.0.0" xpack.monitoring.elasticsearch.hosts: [ "http://172.17.0.7:9200" ] 12. vi config/pipelines.yml 更改pipelines.yml文件 13. 内容如下:pipeline.id: task path.config: "/etc/logstash/pipeline/logstash.config" 14. 需要注意的是自己目录是不是存在这些文件,不要找错地方了,一般进入容器就会是logstash的安装目录,ls查看就能够看到config目录的 15. 退出容器,配置文件创建与编辑 (此处属于全量的配置文件) `conf touch /docker/logstash/logstash.conf > 全量更新配置文件 ```shell input { stdin { } jdbc { #注意mysql连接地址一定要用ip,不能使用localhost等 jdbc_connection_string => "jdbc:mysql://172.17.0.4:3306/lmrs" jdbc_user => "root" jdbc_password => "root" #这个jar包的地址是容器内的地址 jdbc_driver_library => "/etc/logstash/pipeline/mysql-connector-java-8.0.24.jar" jdbc_driver_class => "com.mysql.jdbc.Driver" jdbc_paging_enabled => "true" jdbc_page_size => "50000" statement => "select a.`name`,a.long_name,a.brand_id,a.three_category_id as category_id,a.shop_id,a.price,a.status,a.sold_count,a.review_count,a.create_time,a.last_time,b.`name` as category,b.path from lmrs_products as a LEFT JOIN lmrs_product_categorys as b on a.three_category_id = b.id" schedule => "* * * * *" } } output { elasticsearch { #注意mysql连接地址一定要用ip,不能使用localhost等 hosts => "172.17.0.7:9200" index => "products" document_type => "_doc" document_id => "_id" } stdout { codec => json_lines } } ``` > 增量配置文件 ```shell input { stdin { } jdbc { #注意mysql连接地址一定要用ip,不能使用localhost等 jdbc_connection_string => "jdbc:mysql://192.168.63.1:3306/lmrs" jdbc_user => "starsky" jdbc_password => "root" #数据库重连尝试 connection_retry_attempts => "3" #数据库连接可用校验超时时间,默认为3600s jdbc_validation_timeout => "3600" #这个jar包的地址是容器内的地址 jdbc_driver_library => "/etc/logstash/pipeline/mysql-connector-java-8.0.24.jar" jdbc_driver_class => "com.mysql.jdbc.Driver" #开启分页查询(默认是false) jdbc_paging_enabled => "true" #单次分页查询条数(默认100000,字段较多的话,可以适当调整这个数值) jdbc_page_size => "50000" #执行的sql语句 statement => "SELECT a.id,a.`name`,a.long_name,a.brand_id,a.three_category_id AS category_id,a.shop_id,a.price,a.`STATUS`,a.sold_count,a.review_count,a.create_time,a.last_time FROM lmrs_products AS a where a.id > :sql_last_value" #需要记录查询结果某字段的值时,此字段为true,否则默认tracking_colum为timestamp的值 use_column_value => true #是否将字段名转为小写,默认为true(如果具备序列化或者反序列化,建议设置为false) lowercase_column_names => false #需要记录的字段,同于增量同步,需要是数据库字段 tracking_column => id #记录字段的数据类型 tracking_column_type => numeric #上次数据存放位置 record_last_run => true #上一个sql_last_value的存放路径,必须在文件中指定字段的初始值 last_run_metadata_path => "/etc/logstash/pipeline/products.txt" #是否清除last_run_metadata_path的记录,需要增量同步这个字段的值必须为false clean_run => false #同步的频率(分 时 天 月 年)默认为每分钟同步一次 schedule => "* * * * *" } } output { elasticsearch { #注意mysql连接地址一定要用ip,不能使用localhost等 hosts => "172.17.0.7:9200" index => "products" document_type => "_doc" document_id => "%{id}" } stdout { codec => json_lines } } ``` > last_run_metadata_path => "/etc/logstash/pipeline/products.txt":因为需要记录下上次同步的数据id,所以这里会有一个文件进行存储这个id,需要在logstash目录下去创建一个txt文件,用于存储这个id,同时需要给予权限。不给会出现权限异常问题!!!! ### Laravel 集成 es > 本来考虑用go-mysql-elasticsearch然后发现不灵活换成 logstash 1. php artisan make:service ElasticsearchService.php 2. App/Service/ElasticsearchService.php ```php 'products',//索引 'type' => '_doc',//类型 'body' => [ //主体 "query" => [ //查询 "bool" => [ //条件 'filter' => [], 'must' => [] ] ] ] ]; /** * Notes:是否是上架商品 * DateTime: 2021/7/21 6:05 下午 * @return $this */ public function IsStatus() { $this->params['body']['query']['bool']['filter'][] = [ 'term' => [ 'STATUS' => 1 ] ]; return $this; } /** * Notes:分页查询 * DateTime: 2021/7/21 6:08 下午 * @param $size * @param $page * @return $this */ public function Paginate($size, $page) { $this->params['body']['from'] = ($page - 1) * $size; $this->params['body']['size'] = $size; return $this; } /** * Notes:分类 * DateTime: 2021/7/21 6:12 下午 * @param ProductCategory $category 用户传递过来的分类对象或者id * @return $this */ public function category(ProductCategory $category) { if ($category->is_directory) { $this->params['body']['query']['bool']['fitler'] = [ 'prefix' => ['category_path' => $category->path . $category->id . '-'] ]; } else { $this->params['body']['query']['bool']['filter'][] = [ 'term' => [ 'category_id' => $category->id ] ]; } return $this; } /** * Notes:关键词搜索 * DateTime: 2021/7/21 6:15 下午 * @param $keywords */ public function keywords($keywords) { $keywords = is_array($keywords) ? $keywords : [$keywords]; foreach ($keywords as $keyword) { $this->params['body']['query']['bool']['must'][] = [ 'multi_match' => [ 'query' => $keyword, 'fields' => [ 'long_name^3', 'category^2', 'name^1' ] ] ]; } return $this; } /** * Notes:排序 * DateTime: 2021/7/21 6:17 下午 * @param $filed * @param $direction * @return $this */ public function orderBy($filed, $direction) { if (!isset($this->params['body']['sort'])) { $this->params['body']['sort'] = []; } $this->params['body']['sort'][] = [$filed => $direction]; return $this; } /** * Notes:返回结构体 * DateTime: 2021/7/21 6:17 下午 * @return array */ public function getParams() { return $this->params; } } ``` > ProductController.php ```php input('page', 1); //分页的数据数量 $perPage = 20; $builder = (new ElasticsearchService())->IsStatus()->paginate($perPage, $page); //分类搜索 if ($request->input('category_id') && $category = $this->category($request->input('cate_gory_id'))) { $builder->category($category); } //具备关键词,按照关键词进行搜索(可以是多个) if ($search = $request->input('search', '')) { $keywords = array_filter(explode(' ', $search)); $builder->keywords($keywords); } //根据销量,价格,评论数量进行排序 if ($order = $request->input('order', '')) { if (preg_match('/^(.+)_(asc|desc)$/', $order, $m)) { if (in_array($m[1], ['price', 'sold_count', 'review_count'])) { $builder->orderBy($m[1], $m[2]); } } } //通过容器注册的es单例调用search方法到es搜索数据,条件为上面构建的结构体 $restful = app('es')->search($builder->getParams()); return response()->json([ "data" => $restful ]); } public function category($category) { $category_array = explode(',', $category); $category_id = array_pop($category_array); return ProductCategory::query()->where('id', $category_id)->first(); } } ``` ## 问题总结 ### 出现问题(1) > 容器启动出现问题,配置转发即可 ```shell vim /etc/sysctl.conf 配置转发 net.ipv4.ip_forward=1 重启服务,让配置生效 systemctl restart network 查看是否成功,如果返回为“net.ipv4.ip_forward = 1”则表示成功 sysctl net.ipv4.ip_forward service docker restart 重启docker服务 ``` ### 出现问题(2) > 启动elasticsearch容器时报错:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] ```shell 修改配置 vi /etc/sysctl.conf 在尾行添加以下内容 vm.max_map_count=655300 执行命令 sysctl -p ``` 最后修改:2021 年 07 月 21 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏