结束了一周繁忙的工作,趁着周末,小编手中的键盘早已饥渴难耐了,想知道上期省略号中发生了什么有趣的故事么?且听小编娓娓道来,结尾有彩蛋。

目录

风月前场

春风再续,书接上回,春香园的老鸨妈妈,给这位血气方刚的骚年挑选了一位佳人A,于是乎骚年兴致勃勃的进入了闺房,宜言饮酒,与子同欢,琴瑟在御,莫不静好,谁知佳人A突然来月事了(这个事先老鸨是不知道的)

我了个擦,春宵一刻值千金啊,赶召唤系老鸨儿,老鸨先是把A从侍客名单中剔除,随后赶紧给这位骚年换了一位佳人B,歌管楼台声细细,秋千院落夜沉沉,哈哈哈,又是一个难忘的夜晚......

梦回现实

哎,少年,醒醒,别做梦了,快起来搬砖了

其实在实际生产中,我们的负载均衡器可能要更加温柔体贴智能,不能让用户有一丝感觉到服务器也来大姨妈。

  • 还记得我们的TT猫,下单失败的场景么?被强行跳转到登陆页。

  • 还记得双十一妹子那幽怨的小眼神么?可能你已在偷偷乐了。

  • 还记得程序员小明瞎白活了一顿原理么?其实可能他自己都没搞明白。

模拟老鸨

在讲如何体贴之前,先给大家传授几种老鸨经常使用的分配手法,为了让大家更加形象直观的了解老鸨的内心,小编决定带大家扒开来看,当然了鸨妈的内心也是一坨代码而已。

首先我们定义一个OldBird,接着安排四个smallBirds值班。

/**
* 老鸨
* 创建时间 2017年9月17日
*/
public class OldBird {
// Key代表风尘X子,Value代表该风尘X子的受欢迎程度
public static Map<String, Integer> smallBirds = new ConcurrentHashMap<String, Integer>(); static {
smallBirds.put("野鸡", 1);
smallBirds.put("幺二", 2);
smallBirds.put("长三", 3);
smallBirds.put("书寓", 4);
}
}

开张了,开张了,显然第一位客人并没有入的了鸨儿的法眼,随机了一个后继续嗑她的瓜子。

/**
* 随机
* 创建时间 2017年9月17日
*/
public class Random {
public static String getServer() {
// 获取值班名单
Set<String> keySet = ServerMap.servers.keySet();
ArrayList<String> keyList = new ArrayList<String>();
keyList.addAll(keySet);
// 老鸨看人办事 精打细算了一下、随即了一个
java.util.Random random = new java.util.Random();
int randomPos = random.nextInt(keyList.size());
// 程序员小明获取了一个smallBird
return keyList.get(randomPos);
}
}

可能是鸨妈的随机有点看心情,导致后院有些人有点不高兴了,于是乎赶紧采取了另一种策略。

/**
* 轮询
* 创建时间 2017年9月17日
*/
public class RoundRobin {
private static Integer pos = 0; public static String getServer() {
//获取今日值班名单
Set<String> keySet = ServerMap.servers.keySet();
ArrayList<String> keyList = new ArrayList<String>();
keyList.addAll(keySet);
//有些人 活太少 可能会不高兴 还是排号来吧
String server = null;
synchronized (pos) {
if (pos >= keySet.size())
pos = 0;
server = keyList.get(pos);
pos++;
}
// 程序员小明获取了一个smallBird
return server;
}
}

这时候大茶壶急急忙忙的赶到老鸨身边,哎,别嗑了,韦爷点名要书寓,赶紧给安排安排,老鸨一想常客啊,不行,我得好好编排一下,省的老被打扰。

/**
* 源地址哈希
* 创建时间 2017年9月17日
*/
public class Hash {
public static String getServer()
{
//获取今日值班名单
Set<String> keySet = ServerMap.servers.keySet();
ArrayList<String> keyList = new ArrayList<String>();
keyList.addAll(keySet);
//韦爷 悠哉的进来的 点名要书寓
String remoteGuest = "韦爷";
//老鸨给韦爷 设置固定编号
int hashCode = remoteGuest.hashCode();
int serverListSize = keyList.size();
int serverPos = hashCode % serverListSize;
//韦爷获取到了指定服务
return keyList.get(serverPos);
}
}

读到最后,小伙伴们可能要问了,那个Map中的Value并没有起作用啊,让老鸨吃了么?其实,只是感觉用在这里不妥而已,有些事,你懂我懂大家都懂。

具体到生产架构中,应该是这个样子的

/**
* 服务器负载均衡集群组
* 创建时间 2017年9月17日
*/
public class ServerMap {
// Key代表服务器,Value代表该服务的权重
public static Map<String, Integer> servers = new ConcurrentHashMap<String, Integer>();
static {
//这里有四个服务 权重分别是1234
servers.put("1核1G-服务器", 1);
servers.put("2核2G-服务器", 2);
servers.put("3核3G-服务器", 3);
servers.put("4核4G-服务器", 4);
}
}

能者多劳,权重视服务器的性能而定,下面的算法,服务器4每次有百分之四十的几率被获取到。

/**
* 加权轮询
* 创建时间 2017年9月17日
*/
public class WeightRoundRobin {
private static Integer pos = 0; public static String getServer()
{
//取得服务器List
Set<String> keySet = ServerMap.servers.keySet();
Iterator<String> iterator = keySet.iterator();
//计算权重总数 累加 比如 4核4G-服务器 权重为4 上述10个服务器中存在4个4核4G-服务器服务 增加随机或者轮询几率
List<String> serverList = new ArrayList<String>();
while (iterator.hasNext())
{
String server = iterator.next();
int weight = ServerMap.servers.get(server);
for (int i = 0; i < weight; i++)
serverList.add(server);
} String server = null;
synchronized (pos)
{
if (pos >= keySet.size())
pos = 0;
server = serverList.get(pos);
pos ++;
} return server;
}
}

说了这么多,以上只是几种简单的负载均衡算法,在 记一次JavaWeb网站技术架构总结 中有提到十种负载均衡策略以及其优缺点,有兴趣的同学可以一看。

会话机制

各位看官莫急,要想弄明白故障转移是怎么回事,必须要弄明白客户端-服务端的会话认证机制。

由于HTTP协议本身是无状态的,这与HTTP协议本来的目的是相符的,那么小马哥是怎么知道那些用户买了那些东西的呢?

以Tomcat为例,大家都知道session是在服务器端创建并存储到容器的JVM内存中的,浏览器初次访问服务器会生成一个叫JSESSIONID的cookie,浏览器的每次请求都会附带这个cookie,服务端通过JSESSIONID会找到内存中对应的状态信息。

程序员小明,打开TT猫,输入自己的账号密码,附带cookie信息请求到了后台,TT猫后台校验成功以后,会把用户信息保存到JSESSIONID对应的内存中,这样小明和TT猫就可以无障碍的深入交流了。

这个过程也可以用以下示意图来描述:

如果你觉得会话机制如此简单,那可就有点高看小编了,篇幅有限,对会话机制感兴趣的同学只能自行查阅资料了。

故障转移

老鸨之所以能快速安抚骚年使其顺利度过这缠绵之夜,有没有感受到老鸨强大的人工智能气息?

其实我们的负载均衡器Nginx,也是做的相当智能的,如果后端节点服务器宕掉的话,Nginx通过自带的模块可以把这台坏掉的服务踢出upstream负载集群组,然后自动切换到健康节点来提供访问。

有过开发经验的小伙伴,都知道服务分有状态和无状态。

  • 无状态服务(Stateless Service):游客浏览商品、搜索商品等等这种不需要鉴权的操作。

  • 有状态服务(Stateful Service): 添加购物车,下单,支付等等需要用户认证的操作。

对于这种无状态的服务请求,不管集群组使用任何负载均衡算法(随机、轮询、hash),只要有一个存活,小马哥的TT猫就可以提供正常服务。

但是对于支付这种需要用户认证的操作,不得不说,我们要选择合适的负载均衡算法。

服务独自存储用户状态

  • 随机、轮询算法,小明可能一辈子都无法登陆TT猫
  • hash算法,单一服务宕掉的话会导致用户状态丢失

服务统一存储用户状态

架构设计之Spring-Session分布式集群会话管理

总结

秋名山上行人稀,常有框架较高低,如今原理依旧在,不见当年老框架。

底层原理可能你这辈子都不过时,解决问题的能力永远都不过时,积极向上的求知欲永远是你的强大后盾。

既定目标,做个有追求的程序员,如果你连算法数据结构都能搞得明白,网络传输都可以手到擒来,怎学不会简单的API调用?

塞内加在《论生命之短暂》中说过“如果一个人出海遇到狂风暴雨,被变换肆虐的风吹得团团转,你可能会觉得他航行了很远。其实航行得并不远,只是浮沉动荡的时间长而已”,没错如今的知识就像出海时遇到的狂风暴雨,我们只是被吹的原地团团转而已,并没有在知识的海洋航行很远。

最后,愿大家都不会被吹昏头脑,据说留言的程序员都找到女朋友了...

三分钟深入TT猫之故障转移的更多相关文章

  1. 三分钟浅谈TT猫的前端优化

    首先看一张访问TT猫首页的截图: 测试环境为谷歌浏览器,暂且不讨论其它浏览器,截图下方我们可以观察到以下参数: DOMContentLoaded:1.42s | Load:2.31s 以上参数是在CT ...

  2. 在Windows Server 2012中搭建SQL Server 2012故障转移集群

    OK~ WSFC 2012 R2 年度盛宴开始~ 在本文中,老王将用一系列的场景,把动态仲裁,动态见证,票数调整,LowerQuorumPriorityNodeID,阻止仲裁等群集仲裁技术串起来,完成 ...

  3. 从0开始搭建SQL Server 2012 AlwaysOn 第二篇(配置故障转移集群)

    本篇主要讲配置Windows 故障转移集群及遇到的相关问题(坑),因为AlwaysOn是基于Windows的故障转移集群的 在讲解步骤之前需要了解一下故障转移集群仲裁配置 四种集群的仲裁配置: 1.多 ...

  4. Windows Azure 故障转移模式及高可用个模式探讨!

     眼下国内非常多用户对于云服务的可用性存在误解,什么样子的误解呢?比方某云服务商,在华南某地有一个机房,在华东有一个机房. 这个客户就提到一个需求,你提供的99%可用性的概念是什么意思呢?是不是我 ...

  5. 004.Windows Server 故障转移群集 (WSFC)简介

    一 WSFC 简介 1.1 WSFC 概述 “Windows Server 故障转移群集”(WSFC) 群集是一组独立的服务器,它们共同协作以提高应用程序和服务的可用性.SQL Server 2012 ...

  6. 三分钟读懂TT猫分布式、微服务和集群之路

    针对入门新手的普及,有过大型网站技术架构牛人路过,别耽误浪费了时间,阅读之前,请确保有一定的网络基础,熟练使用Linux,浏览大概需要3-5分钟的时间,结尾有彩蛋. 目录 分布式 微服务 负载均衡集群 ...

  7. 一片非常有趣的文章 三分钟读懂TT猫分布式、微服务和集群之路

    原文http://www.cnblogs.com/smallSevens/p/7501932.html#3782600 三分钟读懂TT猫分布式.微服务和集群之路   针对新手入门的普及,有过大型网站技 ...

  8. 三分钟读懂TT猫分布式、微服务和集群之路 (转)

    http://www.cnblogs.com/smallSevens/p/7501932.html 针对新手入门的普及,有过大型网站技术架构牛人路过,别耽误浪费了时间,阅读之前,请确保有一定的网络基础 ...

  9. 部署AlwaysOn第三步:集群资源组的健康检测和故障转移

    资源组是由一个或多个资源组成的组,WSFC的故障转移是以资源组为单位的,资源组中的资源是相互依赖的.一个资源所依赖的其他资源必须和该资源处于同一个资源组,跨资源组的依赖关系是不存在的.在任何时刻,每个 ...

随机推荐

  1. 写java代码遇到的一些问题

    记录一些做论文实验写代码时遇到的问题. 数据库SQL语句方面: 1.java通过JDBC连接MySql数据库方法 参见:http://hzy3774.iteye.com/blog/1689525 2. ...

  2. CSS基础语法

    一.CSS常用选择器 前言: 页面中,所有的CSS代码,需要写入到<style></style>标签中. style标签的type属性应该选择"text/css&qu ...

  3. 使用Visual Studio 2017开发python,并在iis上部署Python Django

    作为宇宙第一IDE,怎么可以不支持python开发呢? 1.Visual Studio Installer 扩展Python开发 开始菜单中打开Visual Studio Installer,点修改. ...

  4. Unity 5.3.5f1 (32-bit) 的简单塔防游戏

    我以前使用过unity但是第一次写这么全面的塔防小游戏.我以后会陆续的将我跟过的一些项目的心得经验与体会发表出来希望各位能人能够给出评价,我在此感激各位的批评与赞扬.另外我只是一个学生学艺不精,粗制滥 ...

  5. 一起来学linux:目录与路径

    p { margin-bottom: 0.25cm; line-height: 120% } 首先介绍目录相关的路径的表示法: 1 . 代表此目录 2 .. 代表上一层目录 3 – 代表前一个工作目录 ...

  6. 8.23.4 IO-输入输出16个流

    字节流: FileInputStream FileInputStream fIn = new FileInputStream("1.avi");   FileOutputStrea ...

  7. 修改windows user 文件夹中的用户名

    假设我们需要将帐户A改名为B.首先我们需要用另一个管理员帐户C登陆系统. 1.在控制面板-〉用户帐户中将帐户A改名为B. 2.打开C:/Users或"用户"文件夹,将文件夹A重命名 ...

  8. Map中的entrySet();跟keySet();的区别是什么

    JAVA中entrySet();跟keySet();的区别是什么 红叶_书生 | 浏览 10397 次  2014-04-10 10:45 2014-04-10 10:49   最佳答案   keyS ...

  9. CSS3笔记之第二天

    1.CSS盒模型 指定元素的宽度和高度width,height 2.CSS边框 border-style:solid; border-width:5px; border-top-width:15px; ...

  10. Python之set

    set set集合,是一个无序且不重复的元素集合 set的优势 set 的访问数度快 set 原生解决数据重复问题 # 数据库中原有 old_dict = { "#1":{ 'ho ...