目录
一、商品上架
1、sku在ES中存储模型分析
只有上架的商品才可以在前台展示,不上架的在后台管理系统。上架就是放到ES中。
1、商品 Mapping
分析:商品上架在 es 中是存 sku 还是 spu?
1)、检索的时候输入名字,是需要按照 sku 的 title 进行全文检索的
2)、检索使用商品规格,规格是 spu 的公共属性,每个 spu 是一样的
3)、按照分类 id 进去的都是直接列出 spu 的,还可以切换。
4)、我们如果将 sku 的全量信息保存到 es 中(包括 spu 属性)就太多量字段了。
5)、我们如果将 spu 以及他包含的 sku 信息保存到 es 中,也可以方便检索。但是 sku 属于
spu 的级联对象,在 es 中需要 nested 模型,这种性能差点。
6)、但是存储与检索我们必须性能折中。
7)、如果我们分拆存储,spu 和 attr 一个索引,sku 单独一个索引可能涉及的问题。
检索商品的名字,如“手机”,对应的 spu 有很多,我们要分析出这些 spu 的所有关联属性,再做一次查询,就必须将所有 spu_id 都发出去。假设有 1 万个数据,数据传输一次就10000*4=4MB;并发情况下假设 1000 检索请求,那就是 4GB 的数据,,传输阻塞时间会很长,业务更加无法继续。
所以,我们如下设计,这样才是文档区别于关系型数据库的地方,宽表设计,不能去考虑数据库范式。
1)、PUT product
product 的 mapping
{ "mappings": { "properties": { "skuId": { "type": "long"
},"spuId": { "type": "keyword"
},"skuTitle": { "type": "text", "analyzer": "ik_smart"
},"skuPrice": { "type": "keyword"
},"skuImg": { "type": "keyword",
"index": false, "doc_values": false
},"saleCount": { "type": "long"
},"hasStock": { "type": "boolean"
},"hotScore": { "type": "long"
},"brandId": { "type": "long"
},"catalogId": { "type": "long"
},"brandName": { "type": "keyword", "index": false, "doc_values": false
},"brandImg": { "type": "keyword", "index": false, "doc_values": false
},"catalogName": { "type": "keyword", "index": false, "doc_values": false
},"attrs": { "type": "nested", "properties": { "attrId": { "type": "long"
},"attrName": { "type": "keyword", "index": false, "doc_values": false
},
"attrValue": { "type": "keyword"
}
}
}
}
}
}
index:
默认 true,如果为 false,表示该字段不会被索引,但是检索结果里面有,但字段本身不能
当做检索条件。
doc_values:
默认 true,设置为 false,表示不可以做排序、聚合以及脚本操作,这样更节省磁盘空间。
还可以通过设定 doc_values 为 true,index 为 false 来让字段不能被搜索但可以用于排序、聚
合以及脚本操作:
2、nested数据类型场景
https://www.elastic.co/guide/en/elasticsearch/reference/7.5/nested.html
3、构造基本数据(商品上架)
在SpuInfoController.java中编写上架接口spuUp。
需要远程调用库存系统,看下库存系统是否还有库存。
将上架数据保存到es中。
远程查询库存&泛型结果封装。
debug进行联调测试。
二、首页
1、项目介绍
整个项目是一个前后分离的项目,前端是需要给我们的后台发送微服务请求,返回相应的数据进行操作即可,包括商城也是一个前后分离的项目来进行开发,但是处于学习的考虑,使用前后分离就会屏蔽掉很多细节,所以最终页面模块代码基本已经写好了,进行服务端的页面渲染式开发,将这些页面放到微服务里面开发组成整个商城系统。
最终整个微服务架构如下:
用户访问所有请求,先访问nginx,nginx作为反向代理全部转发给网关,网关再路由到各个服务,网关的好处(做统一的鉴权、认证、以及限流),页面可以写到各个微服务里面,引用的静态资源可以放到nginx服务器上,这样就做到了静(静态资源,让nginx返回)动(动态请求)分离,可分担微服务的压力,如果将静态资源也放到微服务里面,请求一个图片也需要微服务的tomcat建立连接处理,再返回,tomcat的并发本来就不高,假如有5000个并发,4000个都是处理图片的,那么只有1000个是真正来进行业务调用和处理的,这样就会让我们的项目没有办法支持高并发的功能。
2、整合thymeleaf(spring-boot下模板引擎)渲染页面
自然化语言,编写的页面,前端可以直接使用,性能稍差,如果在生产环境开启缓存功能,性能也很高。
在product项目下引入spring-boot-starter-thymeleaf,不需要填写版本号,会有spring-boot控制
static:放静态资源,将静态资源index放到static下。
templates:将index.html页面放到templates下
thymeleaf要使用,需要做一个预先的配置(就算不配置,默认启动也可以使用),关闭缓存,开发期间可以看到效果,配置thymeleaf的前缀以及后缀,所有的默认的前缀都是classpath,就是要找所有页面都是到类路径(respurces)下的templates,后缀是.html
,相当于我们以后controller返回的数据只要不是json数据,而是一个字符串,按照这个字符串springmvc的视图解析解析字符串,来到我们的页面,前缀就是找templates,后缀就是找.html页面,而且我们的微服务也可以提供接口功能,controller里面都是一个rest接口,所有和web页面有关的,我们再单独放一个包,包模块就要web,然后就重启我们的商品服务,看看页面能不能访问。也可以访问index/css/GL.css静态资源(http://localhost:20001/index/css/GL.css)
重写访问页面
找到thymeleaf的官方文档,看下如何使用
https://www.thymeleaf.org/documentation.html
使用thymeleaf,需要给每一个页面加上名称空间
3、页面修改不重启服务器实时更新
pom中引入:devtools,修改完页面,ctrl shift F9重新自动编译一下。
4、渲染二级三级数据
三、搭建域名访问环境
1、nginx反向代理配置
nginx里面目前放了分词器,远程请求nginx,返回分词器的数据。
正向与反向对于我们这台电脑来说,如果是帮我们上网的,那么就是正向代理,如果是帮助对方服务器的就是反向代理,比如我们想要访问谷歌,访问不上,我们可以搭建一台代理服务器,我们电脑配置一台代理服务器的地址,以后电脑想访问所有的网址,我们的请求都会由代理服务器帮我们请求谷歌,拿到数据再帮我们返回,那么这个就是正向代理,作用就是隐藏客户端信息,因为我们的请求是发给我们的代理服务器的,由代理服务器转给我们的网络,所以互联网看到所有的访问都是代理服务器的ip。
反向代理对于搭建集群环境很需要,比如我们访问我们的商城,我们的商城由我们的后台集群,我们的集群都要由我们的服务器在内网部署,不可能把服务器的每个外网IP暴漏给外界,这样容易受到攻击,为了能找到内网集群服务器,可以在前面前置一个服务器,这个服务器就叫反向代理,前置一个nginx,这个nginx是一个公网ip,大家都可以访问的,如果我们访问我们公网nginx的服务器,真正的服务在内网中部署,所以由我们的nginx转给我们的内网服务器,这个nginx服务器也是和我们后台服务器搭建在同一个环境里面,只有这个服务器对外暴漏公网IP,屏蔽内部其他集群的信息。
真言商城,我们的客户端访问zhenyanmall,以我本机环境为例,搭建域名访问环境,本机访问zhenyanmall,或者访问www.baidu.com,这个请求会先被网络的DNS进行解析,解析到百度的IP地址到底在哪,然后我们的浏览器就会访问到这个地址对应的内容,就是因为这个域名解析,虽然我们没有购买zhenyanmall这个域名,我们可以在windows的hosts文件里面配置zhenyanmall.com域名对应哪个虚拟机IP地址,比如我们在浏览器里面请求zhenyanmall.com,windows如何知道域名对应哪个IP地址,第一步会先查看系统内部的域名映射规则,如果这个域名已经有映射了,说明这个zhenyanmall在哪个地址,那么浏览器就可以直接去这个地址,网卡带我们直接转过去。第二步,如果系统没有zhenyanmall这个域名映射,那么会去网络上的DNS(114.114.114.114等公共网络域名解析服务器),解析出我们的域名,DNS中保存了哪个域名对应哪个IP地址,再来转到那个IP地址。
因为我们访问zhenyanmall.com,在windows系统内部配置(hosts文件),告诉这个域名在哪,直接来到我们指定的IP地址,就不需要过网络DNS了,由于我们把nginx放到了虚拟机上,因此可以让zhenyanmall.com指定我们虚拟机的地址,完整的域名配置环境。
每次修改hosts有点麻烦,我们可以使用SwitchHosts管理域名映射,以管理员方式打开,创建zhenyanmall本地方案,记得勾选右下角的对号,应用当前方案。
我们使用域名访问es集群,能访问到,说明域名环境配置好了
我们每一个系统都有对应的域名,全部都是先访问虚拟机的的IP地址,接下来我们要访问虚拟机的nginx,开启虚拟机的nginx
将nginx设为开机自启。
直接请求域名,发现访问到nginx的index.html文件
第一步:当我们访问域名的时候,保证第一步访问虚拟机的nginx,接下来还要访问到我们的项目,让我们所有的请求都转给我们的网关,由网关再代转给每一个项目,也可以让nginx转给我们指定的项目,比如访问zhenyanmall.com,现在我们想要用商城的首页作为第一跳转,zhenyanmall的所有请求都转发到http://localhost:20001 端口(就是商品项目,拥有我们首页的内容)。这样做不好,当我们的product部署的有多台的时候,ip和port都不一样,每次我们都得修改nginx,所以需要nginx给我们做反向代理,那么和网关功能就是一样了,所有来自原zhenyanmall.com的请求,都转到商品服务,可以不用去网关,直接转到商品服务,转发到http://localhost:20001 端口。
nginx装好之后所有的配置都挂载到了/mydata/nginx/下
nginx有一个总配置:nginx.conf
nginx.conf介绍
用户组
工作线程
错误日志的地址
pid文件的位置
最大连接数
http块:支持的mime类型,默认返回的构造数据类型,日志格式,访问日志路径,以及是否开启压缩,做负载均衡upstream上下游信息,http的server块,
include /etc/nginx/conf.d/*.conf; 包含所有的conf配置,只要是conf.d下的文件都会被合并到nginx.conf中,这样一个文件不会很大,也会很清晰,看下默认配置default.conf
一个server块,配置虚拟主机相关的信息,监听80端口,server name 利用域名配置的主机,监听域名下的80端口,包括一些访问日志#access_log /var/log/nginx/log/host.access.log main;
,location /的意思是,这个域名下的所有请求都可以在 root /usr/share/nginx/html;
根文件夹找,包括默认的首页 index index.html index.htm;
,还能配置一些404页面。500页面。
我们现在想做的事就是,希望把源自与zhenyanmall.com的请求转给我们的商品服务,把default复制一份,编辑zhenyanmall.conf
修改server name 为zhenyanmall.com 意思是这个模块是监听来自zhenyanmall.com下的80端口,
请求zhenyanmall.com这个域名,是nginx的服务器地址,相当于把这个请求交给nginx,因为server name配置的是zhenyanmall.com,nginx会拿到请求的host进行匹配,看看是不是zhenyanmall.com的,类似于网关,将location下的root和index的配置删掉,添加proxy_pass(代理通过),就是代理给谁,把我们的请求再转发给(因为目前是开发环境,商品服务在我的机器,没在虚拟机,相当于又绕了一圈转回来)商品服务,目前是开发环境因此就是自己的机器,输入ipconfig,查看自己的ip地址,192.168.56.1虚拟网卡,192.168.137.1本机地址,172.28.65.75公网地址,配置这三个任何都可以,最好配置192.168.56.1,因为公网地址切换网络会变化
重启nginx,再次请求,页面就变成了商城的首页了
可以看到域名访问效果了。
但是还有一个问题,如果是分布式的情况下,商品系统有很多,不只一个,那我们每次都需要修改nginx的配置,每次修改就麻烦了,所以应该将nginx配置zhenyanmall.com这个请求直接给我们代理网关,由网关再自动转发给我们的服务,网关就能动态的发现哪些应用上线下线,以及负债均衡。
2、nginx负债均衡配置
http://nginx.org/en/index.html
在总的nginx.conf配置上游服务器配置网关,因为只配置了一个网关,只需要写一个即可。
修改zhenyanmall.conf,监听80端口的所有请求,代理的话不直接代理给商品服务了,直接代理给网关,网关上游服务器的名字为zhenyanmall。
重启nginx
然后请求zhenyanmall.com,报404,这是因为网关没有配置,网关也需要帮我们转到指定的服务,在网关添加路由规则,负债均衡给商品服务,以前是按照路径进行映射,现在按照host进行映射(参照网关对应的文档),只要是zhenyanmall.com下的请求,都转给商品服务。
然后重启网关服务。请求http://zhenyanmall.com/,还是404,是因为nginx代理给网关时,会丢失请求的host信息(会丢掉很多信息),我们用到什么需要加什么,需要配置nginx不要丢掉这些,我们需要修改nginx的路径映射规则location,加上proxy_set_header Host $host取出当前请求的真正的host值
重启nginx。
http://zhenyanmall.com/api/product/attrattrgrouprelation/list
也可以访问成功。
域名映射效果:
请求接口:zhenyanmall.com
请求页面:zhenyanmall.com
都可以使用域名,nginx直接代理给网关,网关判断,通过网关转发请求。如果是/api/**,转交给对应的服务器,如果是满足域名,转交给对应的服务。
3、多个网卡,nacos注册的服务ip有误,导致服务无法访问
因为电脑装了虚拟机,所以存在多块网卡,服务注册到nacos时默认使用了虚拟机的网卡,导致网关无法将请求路由到正确的服务上。
nacos查看服务的IP地址如下:
实际想使用的IP地址是 127.0.0.1 ,即我本机的IP地址,因为开发环境服务是运行在本机的。
解决办法,直接在nacos的配置里加上ip这一项属性,将注册的服务IP直接设置为想要的IP地址,然后重启服务即可。
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
ip: 127.0.0.1
修改完成重启服务之后在nacos查看的地址如下: