首页渲染与Nginx域名搭建
一、首页
- 项目微服务介绍
将静态资源保存在 nginx 的 index 目录下,所有请求过来先经过 nginx 服务器,根据 nginx 的动静分离特点静态资源直接返回数据,动态资源再经过服务器处理后返回,达到减轻每个微服务的压力,提升服务器的吞吐量。
1.1 整合 thymeleaf
- 导入依赖
<!-- 模板引擎 thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 将静态资源导入到 product 项目中,静态资源都放在 static 文件夹下就可以按照路径直接访问,页面放在 templates 下,直接访问,SpringBoot 访问项目的时候,默认会找 index。
- 关闭缓存
spring:
thymeleaf:
cache: false
- 访问项目效果如下图
1.2 整合 dev-tools
- 首页渲染一级分类
@GetMapping({"/","/index.html"})
public String indexPage(Model model){
//Model是springmvc里面的,它会帮我们把值放到请求域中
//1.查出所有的1级分类
List<CategoryEntity> categoryEntities = categoryService.getLevel1Categorys();
//视图解析器进行拼串;
//classpath:/templates/ +返回值+ .html
model.addAttribute("categorys",categoryEntities);
return "index";
}
- 查询所有一级分类数据
@Override
public List<CategoryEntity> getLevel1Categorys() {
log.info("getLevel1Categories.....");
//要得到集合 所以用selectList
long startTime = System.currentTimeMillis();
List<CategoryEntity> categoryEntities =
baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
long endTime = System.currentTimeMillis();
log.info("消耗时间:{}",(endTime - startTime));
return categoryEntities;
}
- dev-tools工具,调整页面数据的时候,我们不希望通过项目重启的方式,就可以使用dev-tools工具,CTRL+F9 即可刷新界面。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
1.3 渲染分类数据
- 根据 JSON 数据封装 VO
/**
* 2级分类vo
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Catelog2Vo {
//一级父分类(这里我们以2级菜单为中心写的vo)
private String catalog1Id;
//三级子分类
private List<Catelog3Vo> catalog3List;
private String id;
private String name;
/**
* 3级分类vo
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public static class Catelog3Vo{
//父分类,2级分类id
private String catalog2Id;
private String id;
private String name;
}
}
- 编写接口
/**
* index/catalog.json
*
* @return
*/
@ResponseBody
@GetMapping("/index/catalog.json")
public Map<String, List<Catelog2Vo>> getCatalogJson(){
Map<String, List<Catelog2Vo>> catalogJson = categoryService.getCatalogJson();
return catalogJson;
}
- 业务代码
@Override
public Map<String, List<Catelog2Vo>> getCatalogJson() {
System.out.println("查询了数据库....");
//1、将数据库的多次查询变为一次,查询所有分类信息
List<CategoryEntity> selectList = baseMapper.selectList(null);
//1、查出所有1级分类
List<CategoryEntity> level1Categorys = getParent_cid(selectList, 0L);
//2、封装数据
Map<String, List<Catelog2Vo>> parent_cid = level1Categorys.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> {
//1、每一个的一级分类,查到这个一级分类的二级分类
List<CategoryEntity> categoryEntities = getParent_cid(selectList, v.getCatId());
//2、封装上面的结果
List<Catelog2Vo> catelog2Vos = null;
if (categoryEntities != null) {
catelog2Vos = categoryEntities.stream().map(l2 -> {
Catelog2Vo catelog2Vo = new Catelog2Vo(v.getCatId().toString(), null, l2.getCatId().toString(), l2.getName());
//1、找当前二级分类的三级分类封装成vo
List<CategoryEntity> level3Catelog = getParent_cid(selectList, l2.getCatId());
if (level3Catelog != null) {
List<Catelog2Vo.Catelog3Vo> collect = level3Catelog.stream().map(l3 -> {
//2、封装成指定格式
Catelog2Vo.Catelog3Vo catelog3Vo = new Catelog2Vo.Catelog3Vo(l2.getCatId().toString(), l3.getCatId().toString(), l3.getName());
return catelog3Vo;
}).collect(Collectors.toList());
catelog2Vo.setCatalog3List(collect);
}
return catelog2Vo;
}).collect(Collectors.toList());
}
return catelog2Vos;
}));
return parent_cid;
}
- 返回数据
二、Nginx 域名搭建
2.1 搭建域名访问环境
- 示例图
2.2 Nginx 核心概念
代理是在服务器和客户端之间假设的一层服务器,代理将接收客户端的请求并将它转发给服务器,然后将服务端的响应转发给客户端。
2.2.1 正向代理
正向代理意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。
正向代理是为我们服务的,即为客户端服务的,客户端可以根据正向代理访问到它本身无法访问到的服务器资源。
正向代理对我们是透明的,对服务端是非透明的,即服务端并不知道自己收到的是来自代理的访问还是来自真实客户端的访问。
2.2.2 反向代理
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
反向代理是为服务端服务的,反向代理可以帮助服务器接收来自客户端的请求,帮助服务器做请求转发,负载均衡等。
反向代理对服务端是透明的,对我们是非透明的,即我们并不知道自己访问的是代理服务器,而服务器知道反向代理在为他服务。
反向代理的优势:
-
隐藏真实服务器;
-
负载均衡便于横向扩充后端动态服务;
-
动静分离,提升系统健壮性;
2.2.3 动静分离
动静分离是指在 web 服务器架构中,将静态页面与动态页面或者静态内容接口和动态内容接口分开不同系统访问的架构设计方法,进而提示整个服务的访问性和可维护性。
一般来说,都需要将动态资源和静态资源分开,由于 Nginx 的高并发和静态资源缓存等特性,经常将静态资源部署在 Nginx 上。如果请求的是静态资源,直接到静态资源目录获取资源,如果是动态资源的请求,则利用反向代理的原理,把请求转发给对应后台应用去处理,从而实现动静分离。
使用前后端分离后,可以很大程度提升静态资源的访问速度,即使动态服务不可用,静态资源的访问也不会受到影响。
2.2.4 负载均衡
一般情况下,客户端发送多个请求到服务器,服务器处理请求,其中一部分可能要操作一些资源比如数据库、静态资源等,服务器处理完毕后,再将结果返回给客户端。
这种模式对于早期的系统来说,功能要求不复杂,且并发请求相对较少的情况下还能胜任,成本也低。随着信息数量不断增长,访问量和数据量飞速增长,以及系统业务复杂度持续增加,这种做法已无法满足要求,并发量特别大时,服务器容易崩。
很明显这是由于服务器性能的瓶颈造成的问题,除了堆机器之外,最重要的做法就是负载均衡。
请求爆发式增长的情况下,单个机器性能再强劲也无法满足要求了,这个时候集群的概念产生了,单个服务器解决不了的问题,可以使用多个服务器,然后将请求分发到各个服务器上,将负载分发到不同的服务器,这就是负载均衡,核心是「分摊压力」。 Nginx 实现负载均衡,一般来说指的是将请求转发给服务器集群。
举个具体的例子,晚高峰乘坐地铁的时候,入站口经常会有地铁工作人员大喇叭“请走 B 口, B 口人少车空…”,这个工作人员的作用就是负载均衡。
Nginx 实现负载均衡的策略:
-
轮询策略:默认情况下采用的策略,将所有客户端请求轮询分配给服务端。这种策略是可以正常工作的,但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。
-
最小连接数策略:将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。
-
最快响应时间策略:优先分配给响应时间最短的服务器。
-
客户端 IP 绑定策略:来自同一个 IP 的请求永远只分配一台服务器,有效解决了动态网页存在的 session 共享问题。
2.3 Nginx 配置文件
-
示例图
-
修改 host 文件,将虚拟机地址映射为 gulimall.com 域名
- 查看 nginx.conf
[root@localhost conf]# cat nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
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;
upstream gulimall{
server 192.168.57.1:88;
}
include /etc/nginx/conf.d/*.conf;
}
- 网关配置:将 nginx 转发过来的 gulimall.com 域名请求转发到商品服务
- id: gulimall_host_route
uri: lb://gulimall-product
predicates:
- Host=gulimall.com,item.gulimall.com
- gulimall.conf 配置
- 效果如下图
- 域名映射效果
- 请求接口 gulimall.com
- 请求页面 gulimall.com
- nginx直接代理给网关,网关判断
- 如果/api/****,转交给对应的服务器
- 如果是满足域名,转交给对应的服务
2.4 总结
浏览器输入 gulimall.com 回车,由于 windows 的 host 文件配置了域名规则,浏览器会去访问 192.168.57.129 虚拟机地址,又因为虚拟机里面安装了 nginx 且默认会监听 80 端口,且 gulimall.com 域名符合 gulimall.conf 配置的 server_name gulimall.com -> nginx 就将其代理到 proxy_pass http://gulimall -> nginx.conf 的 server 192.168.57.1:88 -> 网关再路由到商品服务。