nginx+tomcat负载均衡配置,实现流量切换

目前在用的方案是:
使用Nginx+Tomcat配置负载均衡,nginx.conf文件配置upstream主机群,供装载两个地址,其中一台设定主服务,另一台设定备用服务,当主服务启动时,所有的请求都转发到主服务,当主服务挂掉时,再将后续的服务转发到备用服务。

  • 下面是nginx配置
	upstream tomcatserver2 
    {  
		#服务群组
		#server 主机地址:服务端口 权重[weight=1] ;
		server 127.0.0.1:6901 ;#weight 1权重配置 1表示访问次数
        server 127.0.0.1:6902 backup;  #服务地址
    }
  • 目前遇到的一个问题是:

当我要更新服务时,必须先更新备用服务,然后更新主服务,当备用服务更新后,主服务却不敢关了,因为仍担心有未处理的任务。

实现方法有两种

1.第一种是需要两台以上服务器,在每个服务器都配置nginx,然后每次更新时,需要使用nginx -s quit停用主服务nginx,这是很好的办法,但是服务器资源有限的话,这个方案就不能采用了。
2.第二种需要开发一些程序,需要servlet拦截和nginx配合处理

根据现在服务器的资源情况,采用了第二套方案

  • 下图为设计简略图
    在这里插入图片描述

第一步:在Servlet配置

  • 1.1增加拦截器属性
public class SecurityServlet extends HttpServlet implements Filter
{
    //拦截器状态:0正常状态;其它为不通过
    private static int filterStatus = 0;
    /**
     * 设置拦截器状态
     */
    public static void setFilterStatus(int filterStatus)
    {
        SecurityServlet.filterStatus = filterStatus;
    }
    /**
     * 获取拦截器状态
     */
    public static int getFilterStatus()
    {
        return filterStatus;
    }
}
  • 1.2 增加URL请求状态
	//记录未完成的请求URI
    private static final Map<String, Date> uriMap = new HashMap<String, Date>();

    /**
     * 获取所有未完成的请求
     */
    public static Map<String, Date> getUrimap()
    {
        return uriMap;
    }
  • 1.3拦截器配置
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
        throws IOException, ServletException
    {
        HttpServletRequest request = (HttpServletRequest)arg0;
        HttpServletResponse response = (HttpServletResponse)arg1;
        String url = request.getRequestURI();
        url = url == null ? "" : url;
        //状态不正常则拦截请求
        if (SecurityServlet.filterStatus != 0 && url.indexOf("setServletFilterStatus") < 0
            && url.indexOf("getInProgressRequestInfo") < 0)
        {
            //设置《网关超时》状态
            response.setStatus(504);
            return;
        }
        //保存未完成的请求
        uriMap.put(url, new Date());
        arg2.doFilter(request, arg1);
        //移除已完成的请求
        uriMap.remove(url);
    }

第二步:配置nginx

http 
{
	location / 
	{
			proxy_pass http://tomcatserver2; #调用的服务群组
			
			proxy_connect_timeout 1s;   #如果连接超时的时间超过1秒,则更换另一个服务器。
			
			#如果后端的服务器返回502、504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。
			#invalid_header:服务器返回空响应或无效响应;
			#non_idempotent:通常,如果请求已经被发送到上游服务器(1.9.13),则具有非幂等方法的请求(POST,LOCK,PATCH)不被传递到下一个服务器;启用此选项明确允许重试此类请求;
			proxy_next_upstream http_504 non_idempotent;
	}
}

第三步:动态配置开发

  • 3.1后台
	/**
     * 设置服务过滤器状态
     */
    @RequestMapping(value = {"setServletFilterStatus"}, method = RequestMethod.POST)
    public void setServletFilterStatus(@RequestBody
    JSONObject requestParams, HttpServletRequest request, HttpServletResponse response)
    {
        JSONObject jsonObject = new JSONObject();
        try
        {
            if (requestParams.getInteger("filterStatus") == null)
                throw new Exception("无参数:状态");
            int filterStatus = requestParams.getIntValue("filterStatus");
            if (filterStatus < 0)
                throw new Exception("状态不可小于0");
            //查询所有的群集服务配置
            List<String> paramnames = new ArrayList<String>();
            paramnames.add("SERVER_BACKUP");
            paramnames.add("SERVER_MAIN");
            List<THParam> paramList = paramdao.get_One_Param(paramnames);
            String hostname = InetAddress.getLocalHost().getHostName();//本机IP
            int port = CommonFun.getTomcatPort();//当前服务端口
            String hostInfo = hostname + ":" + port;//主机信息
            boolean exist = false;
            for (THParam param : paramList)
            {
                JSONObject server = CommonFun.parseJSONObject(param.getParamdesc2());
                if (hostInfo.equals(server.getString("hostname") + ":" + server.getString("port")))
                    continue;
                exist = TelnetUtil.telnet(server.getString("hostname"), server.getIntValue("port"));
                if (exist)
                    break;
            }
            if (!exist && filterStatus != 0)
            {
                throw new Exception("当前只有一台服务在用,不可拦截服务");
            }
            //设置状态
            SecurityServlet.setFilterStatus(filterStatus);
            jsonObject.put("success_Info", "success");
        }
        catch (Exception ex)
        {
            jsonObject.put("wrong_Info", CommonFun.getExceptionInfo(ex));
        }
        InteractiveWithAjax printWriteAjax = new InteractiveWithAjax();
        printWriteAjax.printWriter(jsonObject, response);
    }
    
    /**
     * 获取所有正在进行中的uri请求信息
     */
    @RequestMapping(value = {"getInProgressRequestInfo"}, method = RequestMethod.POST)
    public void getInProgressRequestInfo(HttpServletRequest request, HttpServletResponse response)
    {
        JSONObject jsonObject = new JSONObject();
        try
        {
            Map<String, Date> uriMap = SecurityServlet.getUrimap();//正在执行的URI请求进程
            Integer filterStatus = SecurityServlet.getFilterStatus();//过滤器状态
            jsonObject.put("success_Info", "success");
            jsonObject.put("uriMap", uriMap);
            jsonObject.put("filterStatus", filterStatus);
        }
        catch (Exception ex)
        {
        }
        InteractiveWithAjax printWriteAjax = new InteractiveWithAjax();
        printWriteAjax.printWriter(jsonObject, response);
    }
  • 3.2前端

每秒加载未完成的任务信息,直至没有任务为止,方可停止主服务

图:前端设计页面
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TorZhu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值