目前所接触的项目还不涉及到分布式,都是单机模式。不过好在至今没出过什么大问题,基本能满足客户的需求。
由于数据量不是很大,单机的性能已经可以满足,按理不应该做加法,毕竟部署的越复杂,维护起来就越麻烦。
性能虽然可以满足,但有一个不得不提的痛点:项目无法随时更新。
目前的解决方式是:白天改bug、测试,等到晚上客户不使用系统时才停机维护,效率相对较低。
有没有可能让项目可以随时更新?
答案肯定是有,相对简单的解决方案是:双机热备(应用双活) 。
什么是双机热备?
这里引用一下百度百科的解释。
双机热备是应用于服务器的一种解决方案,其构造思想是主机和从机通过tcp/ip网络连接,正常情况下主机处于工作状态,从机处于监视状态,一旦从机发现主机异常,从机将会在很短的时间之内代替主机,完全实现主机的功能。
就是同时部署两套系统,一主一备。主节点负责对外提供服务,备用节点默认不提供服务,只有在主节点出问题的情况下,备用节点才顶替主节点,继续对外提供服务。
大哥不行了,二弟替一会儿。
可以解决什么问题?
利用这个思路,是否可以实现同时部署ab两套系统,当系统需要更新维护时,停用a服务,b服务顶替a工作。待a服务更新完毕后,a服务启动提供升级后的服务,b服务停用再更新。实现应用的热插拔?
答案当然也是可以的。
纸上得来终觉浅,绝知此事要躬行。
本人写了个小demo亲测!
实现思路
搭建项目前先简单理一下思路。
要做的分为以下几步:
1、启动两套简单的web服务
2、服务内就两个简单的方法
保存值到session
从session取值
3、nginx配置负载均衡,pc01主,pc02备
3、保存session到pc01服务,然后停用pc01
4、从pc02服务取值,看pc02能否正常工作并访问session
如果服务可以无缝切换,session也都正常则表示成功。
项目环境
两套springboot服务(双活)
redis(实现session共享)
nginx(负载均衡-主备模式) (也可使用keepalived)
为什么需要redis?
使用多套系统无法避开的一个问题就是session,再也不能像以前单机模式下直接从request中getsession了,session是保存在服务器的,多个服务器之间无法共享session。关于共享session有很多实现方案,这里采用的是redis。
搭建步骤
1、先简单看一下前端
由于只讲环境搭建,所以项目竟可能的简单。
只有两个功能,保存值到session和从session中取值。
const path = ‘/backend/'; //保存到session function savesession() { const personname = $('#personname').val(); if (personname.length <= 0) { alert('请输入再保存'); return; } $.ajax({ type:'post', url: path+"test/save", async:false, xhrfields: { withcredentials: true }, crossdomain: true, data: { personname:personname }, success: function(json) { $('#screen').text(json); } }); } //查询session function requestserver() { $.ajax({ type:'post', url: path+"test/query", async:false, xhrfields: { withcredentials: true }, crossdomain: true, success: function(json) { $('#screen').text(json); } }); }
2、再看一下后端服务
很简单的一个服务,就两个方法:保存值到session、从session中取值
只从request中获取sessionid作为key,数据作为value保存到redis。
@restcontroller @requestmapping("/test") public class testcontroller { private static final string server = "pc01"; @autowired private redisutil redisutil; @requestmapping("/save") public object save(string personname, httpservletrequest request, httpservletresponse response) { string sessionid = request.getrequestedsessionid(); if (redisutil.set(sessionid, personname)) { return server+",session保存成功"; } return "session保存失败"; } @requestmapping("/query") public object query(httpservletrequest request) { string sessionid = request.getrequestedsessionid(); object personname = redisutil.get(sessionid); if (personname != null) { return "hello," + personname+",我是"+server; } return "session为空"; } }
项目会编译两个jar包,同时部署。
pc01对应8081端口,pc02对应8082端口。
3、nginx配置负载均衡
#主备模式,backup只有在主节点故障时才提供服务 upstream backend { server 127.0.0.1:8081; server 127.0.0.1:8082 backup; } server { listen 81; server_name localhost; location /{ #前端 root www/back; } location /backend{ #反向代理到8081、8082 proxy_pass http://backend; } }
到这一步环境就算搭建完成了。
4、测试
现在虽然pc01和pc02都是启动的,但是只有pc01对外提供服务。
我们将‘小潘’保存到session,然后查询。
可以看到,我们现在访问的是pc01服务,且session也保存成功了。
接下来,我们停用pc01服务。
[root@localhost test]# lsof -i:8081 command pid user fd type device size/off node name java 71972 root 13u ipv6 88606 0t0 tcp *:tproxy (listen) [root@localhost test]# kill -9 71972
强制杀掉进程,项目会不会因此而挂掉呢?
再次请求查询session
可以看到,项目并没有挂掉。不仅如此,而且session也能正常访问,pc02迅速顶替了pc01的位置,继续对外提供服务。
接下来,就可以对pc01进行维护更新了,更新好了直接启用,pc02又会退居幕后,等待下一次复出。
整个过程对于用户而言是无缝的。
利用双机热备,不仅可以实现项目的随时更新,而且还实现了高可用。即使pc01意外宕机,pc02也会迅速接替,不至于整个项目瘫痪。
到此这篇关于nginx双机热备的实现步骤的文章就介绍到这了,更多相关nginx双机热备内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论