Mall商城的高级篇的开发(一)
作者:互联网
Mall商城的高级篇的开发
项目的整体架构图
实现全文检索和日志分析
在本项目中,全文检索使用ElasticSearch
来做全文检索。
做日志存储和日志检索(日志的快速定位)使用ELK(ElasticSearch+Kibana+LogStash).
比如,腾讯云的ES服务器利用LogStash
来进行数据传输汇聚到我们的ES
中进行存储和异常定位与监控。
他会收集我们项目中日志,包括前台服务和后台服务,还有第三方的中间件
实现全文检索
流程是这样:在我们后台管理系统中对应着有SPU管理,有一个商品上架的功能。
通过点击商品的上架功能,我们的后台服务器将改商品的所有属性传给我们的ES服务器并在ES服务器保存(index),之后在实现我们的全文检索的功能。
其中保存商品的数据,不是说将商品的所有信息都保存在ES服务器,主要的原因是ES服务器保存的数据都在内存中,内存相对硬盘,性价比还是相差很大。
SKU在ES中的存储模型分析
当然在ES服务器中保存的是JSON数据,基于此,我们约定好需要检索的内容。
{
"skuId":"1",
"spuId":"11"
"skuTitle":"Apple xx",
"price":"99",
"seleCount":"990"
"attrs":[
{"尺寸":"xx"},
{"CPU":"xx"},
{"分辨率":""},
]
}
这样进行存储,很容易产生冗余字段。但是呢,这样检索起来方便。这个是利用空间换时间。
其实呢,为了减少冗余字段,因为每个商品的属性有的就是一样。
sku索引{
"skuId":"1",
"skuTitle":"Apple xx",
"price":"99",
"seleCount":"990"
}
attr索引{
"spuId":"11",
"attrs":[
{"尺寸":"xx"},
{"CPU":"xx"},
{"分辨率":""}
]
}
这个使用时间换空间。
最后我们还是选择浪费时间少的存储模型。
PUT product
{
"mappings":{
"properties": {
"skuId":{ "type": "long" },
"spuId":{ "type": "keyword" }, # 不可分词
"skuTitle": {
"type": "text",
"analyzer": "ik_smart" # 中文分词器
},
"skuPrice": { "type": "keyword" }, # 保证精度问题
"skuImg" : {
"type": "keyword",
"index":false,
"doc_value"
},
"saleCount":{ "type":"long" },
"hasStock": { "type": "boolean" },
"hotScore": { "type": "long" },
"brandId": { "type": "long" },
"catalogId": { "type": "long" },
"brandName": {"type": "keyword"}, # 视频中有false
"brandImg":{
"type": "keyword",
"index": false, # 不可被检索,不生成index,只用做页面使用
"doc_values": false # 不可被聚合,默认为true
},
"catalogName": {"type": "keyword" }, # 视频里有false
"attrs": {
"type": "nested",
"properties": {
"attrId": {"type": "long" },
"attrName": {
"type": "keyword",
"index": false,
"doc_values": false
},
"attrValue": {"type": "keyword" }
}
}
}
}
}
使用Nginx做动静分离和反向代理
动静分离
用户在请求的时候,如果只是简单访问图片、html等静态资源的时候,Nginx
直接返回。
如果用户发送动态请求,Nginx
就会把动态请求发送给网关,网关在路由给响应的后台服务。
Nginx
的动静分离简单来说就是把静态请求和动态请求分开来处理,不能简单理解成只是单纯的把动态页面和静态页面物理分离。
严格意义上来说应该是动态请求和静态请求分开,可以理解成使用Nginx
处理静态请求,使用Tomcat处理动态请求。
动静分离从目前的实现角度,大致分为两种:
- 一种是单纯的把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流的实现方案。
- 另外一种是就是动态和静态文件混合在一起发布,通过
Nginx
来分开。
页面开发
引入模版引擎thymeleaf。
配置的步骤:
-
关闭
thymeleaf
的缓存。目的是:为了在我们调式项目方便。 -
静态资源放在static目录下
-
html
页面放在templates目录下。 -
页面修改实时更新(不重启服务器的情况下)
- 导入devtools依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>
- 重新build
以上功能可以实现,都是因为SpringBoot的
WebMvcAutoConfiguration
。
反向代理
在此和几个很常见的面试题有关联:
1、在浏览器地址栏输入一个URL后回车,背后发生了什么
2、同时关于TCP三次握手和四次挥手。
后面会有专门的博客,对此内容在此讲解。
要实现的逻辑:本机浏览器请求gulimall.com,通过配置hosts文件之后,那么当你在浏览器中输入gulimall.com的时候,相当于域名解析DNS服务解析得到ip 192.168.56.10,也就是并不是访问java服务,而是先去找nginx。
什么意思呢?是说如果某一天项目上线了,gulimall.com应该是nginx的ip,用户访问的都是nginx
请求到了nginx之后,
- 如果是静态资源
/static/*
直接在nginx服务器中找到静态资源直接返回。 - 如果不是静态资源
/
(他配置在/static/*
的后面所以才优先级低),nginx把他upstream转交给另外一个ip 192.168.56.1:88这个ip端口是网关gateway。- (在upstream的过程中要注意配置proxy_set_header Host $host;)
到达网关之后,通过url信息断言判断应该转发给nacos中的哪个微服务(在给nacos之前也可以重写url),这样就得到了响应。
而对于openFeign,因为在服务中注册了nacos的 ip,所以他并不经过nginx。
实现负载均衡的步骤和解释
- Nginx+Mac搭建访问域名的访问的环境(也就是讲我们的虚拟机的IP地址配置到我们的本地域名服务器中)
Mac 的本地域名文件:
/etc/hosts
- 测试结果
- 实现的第一个效果
访问gulimall.com
通过Nginx的反向代理将请求转到我们的商品服务(product
)的index.html
。
此时需要我们来对Nginx进行修改它的配置文件:
需要大概了解一下它的配置文件:
nginx.conf的配置文件的分布图:
//======全局块=====start======
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
//======全局块=====end======
//======events块=====start======
events {
worker_connections 1024;//每个进程的最大连接数
}
//======events块=====end======
//======http块=====start======
http {
//====http全局块=====start=====
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf; //包含其他的配置
//====http全局块=====end=====
}
在nginx.conf
中我们不能发现它是没有server
块,但是我们可以看到的是include /etc/nginx/conf.d/*.conf;
server { listen 80; //监听我们的80端口 listen [::]:80; server_name localhost; //域名 #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }
我们需要在这一块配置,来达到我们一开始的需求:访问gulimall.com
通过Nginx的反向代理将请求转到我们的商品服务(product
)的index.html
。
我们先通过访问我们自定义的域名,可以看到它跳到我们的Nginx的80端口的index页面。
现在我们是希望它可以帮我们转到我们的商品服务。也就是8081/
。
所以此时我们需要在server块,进行反向代理的配置。为了安全起见,我们可以选择复制一份我们的default.conf。
cp default.conf gulimall.conf
所以我们针对我们的需求,对Nginx的server块,进行一个配置:
最后呢,我们需要重启我们的Nginx服务。
docker restart nginx
测试页面,发现访问失败,开始对失败定位。
# 看一下nginx是否启动 docker ps nginx # 看一下nginx的日志 docker logs nginx
说我们的第10行又问题。
通过这个命令,可以看到我们的行数。
其实就是少了个分号。
最后还有一个错误就是格式错误:
- 测试成功
![image-20220507165956313](/Users/wanglufei/Library/Application Support/typora-user-images/image-20220507165956313.png)
- 改动(由于我们的后台服务后多,如果每一个服务都配置,显然是不友好的,此时我们只需要将请求带给我们的网关,让我们的网关自己去在服务的注册中心去找),也就是负载均衡到我们的网关
要实现的效果:
使用Nginx做负载均衡配置官方文档的地址:http://nginx.org/en/docs/http/load_balancing.html
Introduction
Load balancing across multiple application instances is a commonly used technique for optimizing resource utilization, maximizing throughput, reducing latency, and ensuring fault-tolerant configurations.
在多个应用实例之间进行负载均衡是一种常用的技术,可以优化资源利用,最大限度地提高吞吐量,减少延迟,并确保容错配置。
It is possible to use nginx as a very efficient HTTP load balancer to distribute traffic to several application servers and to improve performance, scalability and reliability of web applications with nginx.
可以使用nginx作为一个非常有效的HTTP负载均衡器,将流量分配到几个应用服务器上,用nginx提高网络应用的性能、可扩展性和可靠性。
Load balancing methods(负载平衡方法)
The following load balancing mechanisms (or methods) are supported in nginx:(nginx支持下列负载平衡机制(或方法)。)
round-robin — requests to the application servers are distributed in a round-robin fashion,
round-robin - 对应用服务器的请求是以轮流方式分配的。
least-connected — next request is assigned to the server with the least number of active connections,
最少连接 - 将下一个请求分配给活动连接数最少的服务器。
ip-hash — a hash-function is used to determine what server should be selected for the next request (based on the client’s IP address).
ip-hash - 用一个哈希函数来决定下一个请求应该选择哪个服务器(基于客户端的IP地址)。
官方提出的负载均衡最简单的实例:
http { upstream myapp1 { //上有服务器 server srv1.example.com; server srv2.example.com; server srv3.example.com; } server { listen 80; location / { proxy_pass http://myapp1; } } }
官方对他作出的解释:
In the example above, there are 3 instances of the same application running on srv1-srv3. When the load balancing method is not specifically configured, it defaults to round-robin. All requests are proxied to the server group myapp1, and nginx applies HTTP load balancing to distribute the requests.
在上面的例子中,有3个相同应用程序的实例在srv1-srv3上运行。当没有特别配置负载均衡方法时,它默认为轮循。所有请求都被代理到服务器组myapp1,nginx应用HTTP负载均衡来分配请求。
Reverse proxy implementation in nginx includes load balancing for HTTP, HTTPS, FastCGI, uwsgi, SCGI, memcached, and gRPC.
nginx的反向代理实现包括HTTP、HTTPS、FastCGI、uwsgi、SCGI、memcached和gRPC的负载均衡。
To configure load balancing for HTTPS instead of HTTP, just use “https” as the protocol.
要为HTTPS而不是HTTP配置负载均衡,只需使用 "https "作为协议。
When setting up load balancing for FastCGI, uwsgi, SCGI, memcached, or gRPC, use fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, and grpc_pass directives respectively.
当为FastCGI、uwsgi、SCGI、memcached或gRPC设置负载均衡时,分别使用fastcgi_pass、uwsgi_pass、scgi_pass、memcached_pass和grpc_pass指令
进入到我们的nginx.conf
配置http块:
进入到/nginx/conf/conf.d
修改我们的代理服务器:
同时我们还需要配置网关,使用host路由断言:
- id: gulimall_host_route uri: lb://product predicates: - Host=**.gulimall.com
重启我们的网关服务,测试
也就是出现了:Nginx代理到网关丢失了请求头的信息(Host)
解决办法:
需要到我们的nginx的server块,进行设置一个代理的请求头的信息:
location / { # 设置请求头的host 给Host设置$host(当前请求的host的值 ) proxy_set_header Host $host; proxy_pass http://gulimall; }
测试:
梳理一下流程
我们通过在本机的host文件中进行了域名映射,
192.168.1.115 gulimall.com
所以当我们在浏览器中输入gulimall.com
的时候,由于我们在本机配置了域名的映射,所以它会访问到我们映射的192.168.1.115
这个IP地址。
为了实现我们在浏览器中输入gulimall.com
标签:Nginx,高级,server,nginx,Mall,html,pass,type,商城 来源: https://www.cnblogs.com/bearbrick0/p/16244198.html