乐优商城(06)–门户网站
一、前台系统搭建
门户系统面向的是用户,安全性很重要,而且搜索引擎对于单页应用并不友好。因此门户系统不再采用与后台系统类似的SPA(单页应用)。依然是前后端分离,不过前端的页面会使用独立的html,在每个页面中使用vue来做页面渲染。
1.1、创建工程
1.2、导入静态资源
将压缩包leyou-portal
解压,并将其复制到新建的项目中
1.3、安装live-server
没有webpack,就无法使用webpack-dev-server运行这个项目,实现热部署。
所以,这里要使用另外一种热部署方式:live-server
地址:https://www.npmjs.com/package/live-server
这是一款带有热加载功能的小型开发服务器。用它来展示你的HTML / JavaScript / CSS,但不能用于部署最终的网站。
安装和运行参数
安装,使用npm命令即可,这里建议全局安装,以后任意位置可用
npm install -g live-server
运行时,直接输入命令:
live-server
另外,你可以在运行命令后,跟上一些参数以配置:
--port=NUMBER
- 选择要使用的端口,默认值:PORT env var或8080--host=ADDRESS
- 选择要绑定的主机地址,默认值:IP env var或0.0.0.0(“任意地址”)--no-browser
- 禁止自动Web浏览器启动--browser=BROWSER
- 指定使用浏览器而不是系统默认值--quiet | -q
- 禁止记录--verbose | -V
- 更多日志记录(记录所有请求,显示所有侦听的IPv4接口等)--open=PATH
- 启动浏览器到PATH而不是服务器root--watch=PATH
- 用逗号分隔的路径来专门监视变化(默认值:观看所有内容)--ignore=PATH
- 要忽略的逗号分隔的路径字符串(anymatch -compatible definition)--ignorePattern=RGXP
-文件的正则表达式忽略(即.*\.jade
)(不推荐使用赞成--ignore
)--middleware=PATH
- 导出要添加的中间件功能的.js文件的路径; 可以是没有路径的名称,也可以是引用middleware
文件夹中捆绑的中间件的扩展名--entry-file=PATH
- 提供此文件(服务器根目录)代替丢失的文件(对单页应用程序有用)--mount=ROUTE:PATH
- 在定义的路线下提供路径内容(可能有多个定义)--spa
- 将请求从/ abc转换为/#/ abc(方便单页应用)--wait=MILLISECONDS
- (默认100ms)等待所有更改,然后重新加载--htpasswd=PATH
- 启用期待位于PATH的htpasswd文件的http-auth--cors
- 为任何来源启用CORS(反映请求源,支持凭证的请求)--https=PATH
- 到HTTPS配置模块的路径--proxy=ROUTE:URL
- 代理ROUTE到URL的所有请求--help | -h
- 显示简洁的使用提示并退出--version | -v
- 显示版本并退出
测试
打开idea页面上的控制台,输入命令live-server
,默认端口为8080
1.4、域名访问
修改hosts文件
127.0.0.1 www.leyou.com
修改本地nginx配置,将www.leyou.com反向代理到127.0.0.1:8080
server {
listen 80;
server_name www.leyou.com;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_connect_timeout 600;
proxy_read_timeout 600;
}
}
重新加载nginx配置:nginx.exe -s reload
1.5、common.js简单介绍
为了方便后续的开发,在前台系统中定义了一些工具,放在了common.js中:
首先对axios进行了一些全局配置,请求超时时间,请求的基础路径,是否允许跨域操作cookie等
定义了对象 ly ,也叫leyou,包含了下面的属性:
- getUrlParam(key):获取url路径中的参数
- http:axios对象的别名。以后发起ajax请求,可以用ly.http.get()
- store:localstorage便捷操作,后面用到再详细说明
- formatPrice:格式化价格,如果传入的是字符串,则扩大100被并转为数字,如果传入是数字,则缩小100倍并转为字符串
- formatDate(val, pattern):对日期对象val按照指定的pattern模板进行格式化
- stringify:将对象转为参数字符串
- parse:将参数字符串变为js对象
ElasticSearch学习笔记
一、ElasticSearch概述
Elasticsearch官网:https://www.elastic.co/cn/products/elasticsearch
Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
Elaticsearch,简称为es ,es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据﹔本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。es也使用java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
如上所述,Elasticsearch具备以下特点:
- 分布式,无需人工搭建集群(solr就需要人为配置,使用Zookeeper作为注册中心)
- Restful风格,一切API都遵循Rest原则,容易上手
- 近实时搜索,数据更新在Elasticsearch中几乎是完全同步的。
Lucene和ElasticSearch的关系
- Lucene是一套信息检索工具包! jar包!不包含搜索引擎系统!包含的:索引结构!读写索引的工具!排序,搜索规则…工具类!
- ElasticSearch是基于Lucene做了一些封装和增强
二、ElasticSearch的安装
环境准备:Centos7、JDK1.8及以上,ES的版本要和springBoot中的版本对应。
2.1、安装和配置
官网下载Linux的7.6.2版本的压缩包
2.1.1、新建一个用户leyou
出于安全考虑,elasticsearch默认不允许以root账号运行。
创建用户:
useradd leyou
切换用户:
su - leyou
2.1.2、上传安装包,并解压
将安装包上传到:/home/leyou目录,一定要先创建leyou用户,创建后会自动生成该目录
#解压缩
tar -zxvf elasticsearch-7.6.2-linux-x86_64.tar.gz
把目录重命名:
mv elasticsearch-7.6.2/ elasticsearch
进入,查看目录结构:
bin 启动文件
config 配置文件
- log4j2.properties 日志配置文件
- jvm.options Java虚拟机相关配置
- elasticsearch.yml ES配置文件 默认9200端口
lib 相关jar包
logs 日志
modules 功能模块
plugins 插件
2.1.3、修改配置
进入config目录:cd config
需要修改的配置文件有两个:
- jvm.options
Elasticsearch基于Lucene的,而Lucene底层是java实现,因此需要配置jvm参数。
编辑jvm.options:
vim jvm.options
默认配置如下:
-Xms1g
-Xmx1g
内存占用太多了,我们调小一些:
-Xms512m
-Xmx512m
- elasticsearch.yml
vim elasticsearch.yml
修改数据和日志目录:
path.data: /home/leyou/elasticsearch/data # 数据目录位置
path.logs: /home/leyou/elasticsearch/logs # 日志目录位置
把data和logs目录修改指向了elasticsearch的安装目录。但是这data目录并不存在,因此需要创建出来。
进入elasticsearch的根目录,然后创建:
mkdir data
修改绑定的ip
network.host: 0.0.0.0 # 绑定到0.0.0.0,允许任何ip来访问
默认只允许本机访问,修改为0.0.0.0后则可以远程访问
目前是做的单机安装,如果要做集群,只需要在这个配置文件中添加其它节点信息即可。
elasticsearch.yml的其它可配置信息:
属性名 | 说明 |
---|---|
cluster.name | 配置elasticsearch的集群名称,默认是elasticsearch。建议修改成一个有意义的名称。 |
node.name | 节点名,es会默认随机指定一个名字,建议指定一个有意义的名称,方便管理 |
path.conf | 设置配置文件的存储路径,tar或zip包安装默认在es根目录下的config文件夹,rpm安装默认在/etc/ elasticsearch |
path.data | 设置索引数据的存储路径,默认是es根目录下的data文件夹,可以设置多个存储路径,用逗号隔开 |
path.logs | 设置日志文件的存储路径,默认是es根目录下的logs文件夹 |
path.plugins | 设置插件的存放路径,默认是es根目录下的plugins文件夹 |
bootstrap.memory_lock | 设置为true可以锁住ES使用的内存,避免内存进行swap |
network.host | 设置bind_host和publish_host,设置为0.0.0.0允许外网访问 |
http.port | 设置对外服务的http端口,默认为9200。 |
transport.tcp.port | 集群结点之间通信端口 |
discovery.zen.ping.timeout | 设置ES自动发现节点连接超时的时间,默认为3秒,如果网络延迟高可设置大些 |
discovery.zen.minimum_master_nodes | 主结点数量的最少值 ,此值的公式为:(master_eligible_nodes / 2) + 1 ,比如:有3个符合要求的主结点,那么这里要设置为2 |
2.2、运行
进入elasticsearch/bin目录,可以看到下面的执行文件:
./elasticsearch
运行后,发现报错:
错误1、进程虚拟内存
max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]
首先切换回root用户
vm.max_map_count:限制一个进程可以拥有的VMA(虚拟内存区域)的数量,继续修改配置文件, :
vim /etc/sysctl.conf
添加下面内容:
vm.max_map_count=655360
然后执行命令:
sysctl -p
错误2、节点错误
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
在elasticsearch
的config
目录下,修改elasticsearch.yml
配置文件,将下面的配置加入到该配置文件中:
ip替换host1等,多节点请添加多个ip地址,单节点可写按默认来
node.name: node-1
cluster.initial_master_nodes: ["node-1"] #这里的node-1为node-name配置的值
重启终端窗口,再次切换回leyou用户,启动
浏览器访问:ip地址+9200
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ti7v3LLG-1630373777912)(F:\MyProject\乐优商城笔记\assets\06-es浏览器访问.png)]
注意:阿里云安全组需要开放两个端口:
- 9300:集群节点间通讯接口
- 9200:客户端访问接口
三、安装kibana
3.1、什么是Kibana?
Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana ,可以通过各种图表进行高级数据分析及展示。Kibana让海量数据更容易理解。它操作简单,基于浏览器的用户界面可以快速创建仪表板( dashboard )) 实时显示Elasticsearch查询动态。设置Kibana非常简单。无需编码或者额外的基础架构,几分钟内就可以完成Kibana安装并启动Elasticsearch索引监测。
3.2、安装
这里选则安装在本地Windos系统中,方便操作查看,官网下载安装包,版本要与elasticsearch保持一致,即7.6.2
3.3、配置运行
Kibana可以汉化,将Kibana的配置文件中kibana.yml
的i18n.locale: "en"
改为zh-CN即可
配置
进入安装目录下的config目录,修改kibana.yml文件:
修改elasticsearch服务器的地址:
elasticsearch.url: "http://192.168.56.101:9200" #es的安装机器ip地址
运行
进入安装目录下的bin目录:
双击kibana.bat
即运行,等待一段时间,运行端口为5601,访问:http://127.0.0.1:5601
选择左侧的DevTools菜单,即可进入控制台页面:
四、安装ik分词器
K分词器概念
分词 :即把一段中文或者别的词汇划分成一个个的关键字,在搜索时候会把信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是将每个字看成一个词,比如“我爱学习”会被分成“我”、“爱”、“学”,“习”,这显然是不符合要求的,所以需要安装中文分词器ik来解决这个问题。
如果要使用中文,建议使用ik分词器!
IK提供了两种分词算法: ik_smart和ik_max_word,其中 ik_smart为最少切分,ik_max_word为最细粒度划分!
安装ik分词器
-
github找到下载地址:https://github.com/medcl/elasticsearch-analysis-ik
-
下载完毕将该文件解压至elasticsearch中的plugins文件夹中即可
- 注意:解压后记得将压缩包删除
-
启动es发现插件已被加载
-
启动kibana测试
- 模式一:ik_smart(为最少切分)
- 模式二:ik_max_word(为最细粒度划分)
当发现有的词汇不会分开,可以使用自定义字典分词:
ik的config目录下存在IKAnalyzer.cfg.xml配置文件
可以进行相关配置
扩展字典可以创建文件mydir.dir文件
五、ES核心概念
ES是如何去存储数据,数据结构是什么,又是如何实现搜索的呢?
集群,节点,索引,类型,文档,分片,映射
5.1、DBMS与ES的对比
DBMS | ES |
---|---|
数据库(database) | 索引(indices) |
表(tables) | types(慢慢被弃用) |
行(rows) | documents |
字段(columns) | fields |
elasticsearch(集群)中可以包含多个索引(数据库),每个索引中可以包含多个类型(表),每个类型下又包含多个文档(行),每个文档中又包含多个字段(列)。
物理设计:
elasticsearch在后台把每个索引划分成多个分片,每个分片可以在集群中的不同服务器间迁移
默认的集群名称就是elaticsearh
逻辑设计:
一个索引类型中,包含多个文档,比如说文档1,文档2。当我们索引一篇文档时,可以通过这样的一各顺序找到它:索引->类型->文档ID,通过这个组合我们就能索引到某个具体的文档。
注意:ID不必是整数,实际上它是个字符串。
5.2、文档
之前说elasticsearch是面向文档的,那么就意味着索引和搜索数据的最小单位是文档,elasticsearch中,文档有几个重要属性:
- 自我包含,一篇文档同时包含字段和对应的值,也就是同时包含key:value !
- 可以是层次型的,一个文档中包含自文档,复杂的逻辑实体就是这么来的!{就是一个json对象! 使用fastijson可以进行自动转换!}
- 灵活的结构,文档不依赖预先定义的模式,我们知道关系型数据库中,要提前定义字段才能使用,在elasticsearch中对于字段是非常灵活的,有时候,我们可以忽略该字段,或者动态的添加一个新的字段。
尽管我们可以随意的新增或者忽略某个字段,但是,每个字段的类型非常重要,比如一个年龄字段类型,可以是字符串也可以是整形。因为elasticsearch会保存字段和类型之间的映射及其他的设置。这种映射具体到每个映射的每种类型,这也是为什么在elasticsearch中,类型有时候也称为映射类型。
5.3、类型
类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。类型中对于字段的定义称为映射,比如name映射为字符串类型。我们说文档是无模式的,它们不需要拥有映射中所定义的所有字段,比如新增一个字段,elasticsearch会自动推断该字段是什么类型,但不一定准确,最好还是提前设定好字段的类型
5.4、索引
索引是映射类型的容器,elasticsearch中的索引是一个非常大的文档集合。索引存储了映射类型的字段和其他设置。然后它们被存储到了各个分片上了。
概念 | 说明 |
---|---|
索引库(indices) | indices是index的复数,代表许多的索引, |
类型(type) | 类型是模拟mysql中的table概念,一个索引库下可以有不同类型的索引,比如商品索引,订单索引,其数据格式不同。不过这会导致索引库混乱,因此未来版本中会移除这个概念 |
文档(document) | 存入索引库原始的数据。比如每一条商品信息,就是一个文档 |
字段(field) | 文档中的属性 |
映射配置(mappings) | 字段的数据类型、属性、是否索引、是否存储等特性 |
分片的工作流程
物理设计:
一个集群至少有一个节点,而一个节点就是一个elasricsearch进程,节点可以有多个索引(默认的),若创建了一个索引,那么索引将会有个5个分片( primary shard ,又称主分片)构成的,每一个主分片会有一个副本(replica shard ,又称复制分片)
上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内,这样有利于某个节点挂掉了,数据也不至于丢失。实际上,一个分片是一个Lucene索引,一个包含倒排索引的文件目录,倒排索引的结构使得elasticsearch在不扫描全部文档的情况下,就能知晓哪些文档包含特定的关键字。
倒排索引
倒排索引(Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。
倒排索引有两种不同的反向索引形式:
- 一条记录的水平反向索引(或者反向档案索引)包含每个引用单词的文档的列表。
- 一个单词的水平反向索引(或者完全反向索引)又包含每个单词在一个文档中的位置。
5.5、字段属性详解
Elasticsearch中支持的数据类型非常丰富:
5.5.1、常用属性说明
-
String类型,又分两种:
- text:可分词,不可参与聚合
- keyword:不可分词,数据会作为完整字段进行匹配,可以参与聚合
-
Numerical:数值类型,分两类
- 基本数据类型:long、interger、short、byte、double、float、half_float
- 浮点数的高精度类型:scaled_float
- 需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
-
Date:日期类型
elasticsearch可以对日期格式化为字符串存储,但是建议存储为毫秒值,存储为long,节省空间。
5.5.2、index
index影响字段的索引情况。
- true:字段会被索引,则可以用来进行搜索。默认值就是true
- false:字段不会被索引,不能用来搜索
index的默认值就是true,也就是说你不进行任何配置,所有字段都会被索引。
但是有些字段是我们不希望被索引的,比如商品的图片信息,就需要手动设置index为false。
5.5.3、store
否将数据进行额外存储。
在学习lucene和solr时,我们知道如果一个字段的store设置为false,那么在文档列表中就不会有这个字段的值,用户的搜索结果中不会显示出来。
但是在Elasticsearch中,即便store设置为false,也可以搜索到结果。
原因是Elasticsearch在创建文档索引时,会将文档中的原始数据备份,保存到一个叫做_source
的属性中。而且可以通过过滤_source
来选择哪些要显示,哪些不显示。
而如果设置store为true,就会在_source
以外额外存储一份数据,多余,因此一般都会将store设置为false,事实上,store的默认值就是false。
六、API语法学习
下面的操作 都是是kibana 中的 dev Tools工具操作的
6.1、索引
Elasticsearch采用Rest风格API,因此其API就是一次http请求,可以用任何工具发起http请求
//查看所有索引相关信息
GET /_cat/indices?v
//创建索引
PUT customer
PUT /customer //库名
{
"settings": {
"number_of_shards": 1, //分片数量
"number_of_replicas": 0 //副本数量
}
}
//查看所有索引相关信息
GET customer
//删除索引
DELETE customer
添加映射
PUT /索引库名/_mapping //(自7.0起取消了Type,不需要加索引类型名,统一为_doc)
{
"properties": {
"字段名": {
"type": "类型", //类型:可以是text、long、short、date、integer、object等
"index": true, //是否索引,默认为true
"store": true, //是否存储,默认为false
"analyzer": "分词器" //分词器,这里的`ik_max_word`即使用ik分词器
}
}
}
PUT /goods/_mapping
{
"properties":{
"title":{
"type": "text",
"analyzer": "ik_max_word"
},
"images":{
"type": "keyword",
"index": "false"
},
"price":{
"type":"float"
}
}
}
6.2、文档CRUD
6.2.1、创建文档
// create 创建文档
// _create 指定类型为create并不是type名称 默认是_doc 指定 ID 如果已经存在,就报错
PUT users/_create/1
{
"user" : "Jack2",
"post_date" : "2019-05-15T14:12:12",
"message" : "trying out Elasticsearch"
}
//index 创建文档
//与create的区别:index如果文档不存在,就索引新的文档。如果文档存在就覆盖原有的文档内容。版本信息+1
PUT users/_doc/1
{
"tags":["guitor","skateboard","reading"]
}
6.2.2、查询文档
//get 根据文档id查询 文档内容
GET users/_doc/1
- 找到文档,返回HTTP 200。
- 文档元信息
- _index/ _type /
- 版本信息,同一个ld的文档,即使被删除,Version号也会不断增加
- _souece 中默认包含了文档的所有原始信息
- 文档元信息
- 找不到文档,返回HTTP 404
6.2.3、修改文档
//PUT 方式
//缺点:相当与重新创建该文档达到更新的效果,漏写的字段会丢失
PUT users/_doc/1
{
"tags":["guitor","skateboard","reading","testing"]
}
//POST update 方式
//update 修改文档 不会删除原文档 而是在 文档的基础上更新文档中的字段内容
//该_update字段才会根据文档中字段信息 在原文档上增加字段 必须带有doc
POST users/_update/1/
{
"doc":{
"post_date" : "2019-05-18T14:12:12",
"message" : "trying out ElasticsearchOut",
"phone" : "1806185",
"pubtest":[1,2,3],
"pubtest2":"[1,2,3]"
}
}
6.2.4、删除文档
DELETE users/_doc/1
6.2.5、索引的 maping
maping 相当于表的 schema
//查看mapping信息
GET users/_mapping
//创建mapping
PUT /goods
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word"
},
"images": {
"type": "keyword"
},
"price": {
"type": "float"
}
}
}
}
6.3、文档批量操作
6.3.1、bulk api批量操作
- bulk相当于数据库里的bash操作
- 引入批量操作bulk,提高工作效率
- bulk API可以同时执行多个请求
bulk的格式
action:index/create/update/delete
metadata:_index,_type,_id
request body:_source (删除操作不需要加request body)
{
action: {
metadata }}
{
request body }
//单条操作失败不会影响其他操作
-
bulk不支持get操作,因为批量操作,里面放get操作,没啥用!所以,官方也不支持
-
bulk会把将要处理的数据载入内存中,所以数据量是有限制的,最佳的数据量不是一个确定的数值,它取决于机器硬件、文档大小以及复杂性、索引以及搜索的负载。
一般建议是1000-5000个文档,如果文档很大,可以适当减少队列,大小建议是5-15MB,默认不能超过100M,可以在es的配置文件(即$ES_HOME下的config下的elasticsearch.yml)中配置
//Bulk 操作 批量操作,其中一步错误,不影响其他操作
PUT _bulk
{
"index":{
"_index":"test","_id":"1"}}
{
"name":"dukun","post_date" : "2019-05-18T14:12:12","age":18,"phone" : "1806185","sex":"男"}
{
"index":{
"_index":"test","_id":"2"}}
{
"name":"dukun02","post_date" : "2019-05