阿里云
阿里云多端小程序中小企业获客首选
发表主题 回复主题
  • 3727阅读
  • 0回复

[交流乐园]三分钟深入TT猫之故障转移

级别: 论坛版主
发帖
3414
云币
8980

引用
结束了一周繁忙的工作,趁着周末,小编手中的键盘早已饥渴难耐了,想知道上期省略号中发生了什么有趣的故事么?且听小编娓娓道来,结尾有彩蛋。
i#]}k  
s :ig;zb  
KK$t3e)  
.P(k |D&  
/}A"F[5  
风月前场 7niZ`doBA  
_#32hAI  
春风再续,书接上回,春香园的老鸨妈妈,给这位血气方刚的骚年挑选了一位佳人A,于是乎骚年兴致勃勃的进入了闺房,宜言饮酒,与子同欢,琴瑟在御,莫不静好,谁知佳人A突然来月事了(这个事先老鸨是不知道的) @ =g Px  
我了个擦,春宵一刻值千金啊,赶召唤系老鸨儿,老鸨先是把A从侍客名单中剔除,随后赶紧给这位骚年换了一位佳人B,歌管楼台声细细,秋千院落夜沉沉,哈哈哈,又是一个难忘的夜晚...... BV)o F2b:  
j'r"_*%  
'kU5  
E,IeW {6s  
梦回现实 D2}N6i  
哎,少年,醒醒,别做梦了,快起来搬砖了 $O nh2 ^  
x -;tV=E}  
~]f6@n  
其实在实际生产中,我们的负载均衡器可能要更加温柔体贴智能,不能让用户有一丝感觉到服务也来大姨妈。
  • X5U#^^O$E%  
    还记得我们的TT猫,下单失败的场景么?被强行跳转到登陆页。
  • h;TN$ /  
    还记得双十一妹子那幽怨的小眼神么?可能你已在偷偷乐了。
  • Y#e,NN  
    还记得程序员小明瞎白活了一顿原理么?其实可能他己都没搞明白。
'Fq +\J#%  
模拟老鸨 6LRvl6ik  
ZLI t 3  
i,V,0{$  
在讲如何体贴之前,先给大家传授几种老鸨经常使用的分配手法,为了让大家更加形象直观的了解老鸨的内心,小编决定带大家扒开来看,当然了鸨妈的内心也是一坨代码而已。 i}Q"'?  
XoNBq9Iu  
xeNj@\jdC5  
首先我们定义一个OldBird,接着安排四个smallBirds值班。 T W#s)iDi  
  1. /**
  2. * 老鸨
  3. * 创建时间 2017年9月16日
  4. */
  5. public class OldBird {
  6.     // Key代表风尘X子,Value代表该风尘X子的受欢迎程度
  7.     public static Map<String, Integer> smallBirds = new ConcurrentHashMap<String, Integer>();
  8.     static {
  9.         smallBirds.put("野鸡", 1);
  10.         smallBirds.put("幺二", 2);
  11.         smallBirds.put("长三", 3);
  12.         smallBirds.put("书寓", 4);
  13.     }
  14. }
[font=PingFangSC, &amp]开张了,开张了,显然第一位客人并没有入的了鸨儿的法眼,随机了一个后继续嗑她的瓜子。 /@w w"dmqU  
  1. /**
  2. * 随机
  3. * 创建时间 2017年9月16日
  4. */
  5. public class Random {
  6.     public static String getServer() {
  7.         // 获取值班名单
  8.         Set<String> keySet = ServerMap.servers.keySet();
  9.         ArrayList<String> keyList = new ArrayList<String>();
  10.         keyList.addAll(keySet);
  11.         // 老鸨看人办事 精打细算了一下、随即了一个
  12.         java.util.Random random = new java.util.Random();
  13.         int randomPos = random.nextInt(keyList.size());
  14.         // 程序员小明获取了一个smallBird
  15.         return keyList.get(randomPos);
  16.     }
  17. }
可能是鸨妈的随机有点看心情,导致后院有些人有点不高兴了,于是乎赶紧采取了另一种策略。 'MgYSP<  
  1. /**
  2. * 轮询
  3. * 创建时间 2017年9月16日
  4. */
  5. public class RoundRobin {
  6.     private static Integer pos = 0;
  7.     public static String getServer() {
  8.         //获取今日值班名单
  9.         Set<String> keySet = ServerMap.servers.keySet();
  10.         ArrayList<String> keyList = new ArrayList<String>();
  11.         keyList.addAll(keySet);
  12.         //有些人 活太少 可能会不高兴 还是排号来吧
  13.         String server = null;
  14.         synchronized (pos) {
  15.             if (pos >= keySet.size())
  16.                 pos = 0;
  17.             server = keyList.get(pos);
  18.             pos++;
  19.         }
  20.         // 程序员小明获取了一个smallBird
  21.         return server;
  22.     }
  23. }
这时候大茶壶急急忙忙的赶到老鸨身边,哎,别嗑了,韦爷点名要书寓,赶紧给安排安排,老鸨一想常客啊,不行,我得好好编排一下,省的老被打扰。 Z% DJ{!Hnh  
  1. /**
  2. * 源地址哈希
  3. * 创建时间 2017年9月16日
  4. */
  5. public class Hash {
  6.     public static String getServer()      
  7.     {      
  8.         //获取今日值班名单
  9.         Set<String> keySet = ServerMap.servers.keySet();      
  10.         ArrayList<String> keyList = new ArrayList<String>();      
  11.         keyList.addAll(keySet);  
  12.         //韦爷 悠哉的进来的 点名要书寓
  13.         String remoteGuest = "韦爷";      
  14.         //老鸨给韦爷 设置固定编号
  15.         int hashCode = remoteGuest.hashCode();
  16.         int serverListSize = keyList.size();
  17.         int serverPos = hashCode % serverListSize;
  18.         //韦爷获取到了指定服务
  19.         return keyList.get(serverPos);      
  20.     }      
  21. }
~&< Ls  
读到最后,小伙伴们可能要问了,那个Map中的Value并没有起作用啊,让老鸨吃了么?其实,只是感觉用在这里不妥而已,有些事,你懂我懂大家都懂。 a[_IG-l|i4  
具体到生产架构中,应该是这个样子的 4mHk,Dd9,  
  1. /**
  2. * 服务器负载均衡集群组
  3. * 创建时间 2017年9月16日
  4. */
  5. public class ServerMap {
  6.     // Key代表服务器,Value代表该服务的权重
  7.     public static Map<String, Integer> servers = new ConcurrentHashMap<String, Integer>();
  8.     static {
  9.         //这里有四个服务 权重分别是1234
  10.         servers.put("1核1G-服务器", 1);
  11.         servers.put("2核2G-服务器", 2);
  12.         servers.put("3核3G-服务器", 3);
  13.         servers.put("4核4G-服务器", 4);
  14.     }
  15. }
能者多劳,权重视服务器的性能而定,下面的算法,服务器4每次有百分之四十的几率被获取到。 VUi> ]v/e  
  1. [font=微软雅黑]/**[/font]
  2. * 加权轮询
  3. * 创建时间 2017年9月16日
  4. */
  5. public class WeightRoundRobin {
  6.     private static Integer pos = 0;  
  7.     public static String getServer()  
  8.     {  
  9.         //取得服务器List  
  10.         Set<String> keySet = ServerMap.servers.keySet();  
  11.         Iterator<String> iterator = keySet.iterator();  
  12.         //计算权重总数 累加 比如 4核4G-服务器  权重为4 上述10个服务器中存在4个4核4G-服务器服务  增加随机或者轮询几率
  13.         List<String> serverList = new ArrayList<String>();  
  14.         while (iterator.hasNext())  
  15.         {  
  16.             String server = iterator.next();  
  17.             int weight = ServerMap.servers.get(server);  
  18.             for (int i = 0; i < weight; i++)  
  19.                 serverList.add(server);  
  20.         }  
  21.         String server = null;  
  22.         synchronized (pos)  
  23.         {  
  24.             if (pos >= keySet.size())  
  25.                 pos = 0;  
  26.             server = serverList.get(pos);  
  27.             pos ++;  
  28.         }  
  29.         return server;  
  30.     }  
  31. }
B:Y F|k}T  
说了这么多,以上只是几种简单的负载均衡算法,在 记一次JavaWeb网站技术架构总结  中有提到十种负载均衡策略以及其优缺点,有兴趣的同学可以一看。 g=/!Ry=  
会话机制 @O`T|7v  
|}?H$d  
G?v!Uv8O  
各位看官莫急,要想弄明白故障转移是怎么回事,必须要弄明白客户端-服务端的会话认证机制。 bcq&yL'D  
由于HTTP协议本身是无状态的,这与HTTP协议本来的目的是相符的,那么小马哥是怎么知道那些用户买了那些东西的 Lf)JO|o  
以Tomcat为例,大家都知道session是在服务器端创建并存储到容器的JVM内存中的,浏览器初次访问服务器会生成一个叫JSESSIONID的cookie,浏览器的每次请求都会附带这个cookie,服务端通过JSESSIONID会找到内存中对应的状态信息 +%f6{&q$  
程序员小明,打开TT猫,输入自己的账号密码,附带cookie信息请求到了后台,TT猫后台校验成功以后,会把用户信息保存到JSESSIONID对应的内存中,这样小明和TT猫就可以无障碍的深入交流了。 A`#?Bj   
hF{gN3v5  
+_L]d6  
这个过程也可以用以下示意图来描述: #M||t|9iu?  
gnGh )  
8_E(.]U  
如果你觉得会话机制如此简单,那可就有点高看小编了,篇幅有限,对会话机制感兴趣的同学只能自行查阅资料了。 :%z#s  
eR,/} g\  
故障转移 `KtP ;nG  
Zs]n0iwM'@  
老鸨之所以能快速安抚骚年使其顺利度过这缠绵之夜,有没有感受到老鸨强大的人工智能气息? Ims?  
5S8>y7knQ  
S6}_N/;6~  
其实我们的负载均衡器Nginx,也是做的相当智能的,如果后端节点服务器宕掉的话,Nginx通过自带的模块可以把这台坏掉的服务踢出upstream负载集群组,然后自动切换到健康节点来提供访问。 fgs@oaoZ  
有过开发经验的小伙伴,都知道服务分有状态和无状态。
  • &XV9_{Hm  
    无状态服务(Stateless Service):游客浏览商品、搜索商品等等这种不需要鉴权的操作
  • zrqI^i"c  
    有状态服务(Stateful Service): 添加购物车,下单,支付等等需要用户认证的操作。
tkH]_cH'w  
对于这种无状态的服务请求,不管集群组使用任何负载均衡算法(随机、轮询、hash),只要有一个存活,小马哥的TT猫就可以提供正常服务。 h=S7Z:IaM  
但是对于支付这种需要用户认证的操作,不得不说,我们要选择合适的负载均衡算法。 %Z4*;VwQ  
服务独自存储用户状态
  • 随机、轮询算法,小明可能一辈子都无法登陆TT猫
  • hash算法,单一服务宕掉的话会导致用户状态丢失
8{=|<  
服务统一存储用户状态 1a/C(4 _k  
架构设计之Spring-Session分布式集群会话管理 ZG 0^O"B0  
(c)=Do=  
]\KVA)\  
总结 6lCpf1>6@  
cE:s\hG  
>O<a9wz  
秋名山上行人稀,常有框架较高低,如今原理依旧在,不见当年老框架。 &9^4- 5]  
底层原理可能你这辈子都不过时,解决问题的能力永远都不过时,积极向上的求知欲永远是你的强大后盾。 p:TE##  
既定目标,做个有追求的程序员,如果你连算法数据结构都能搞得明白,网络传输都可以手到擒来,怎学不会简单的API调用? JH{/0x#+  
塞内加在《论生命之短暂》中说过“如果一个人出海遇到狂风暴雨,被变换肆虐的风吹得团团转,你可能会觉得他航行了很远。其实航行得并不远,只是浮沉动荡的时间长而已”,没错如今的知识就像出海时遇到的狂风暴雨,我们只是被吹的原地团团转而已,并没有在知识的海洋航行很远。 QmjE\TcK/  
z]r'8Jc  
[ 此帖被小柒2012在2017-10-18 09:19重新编辑 ]
发表主题 回复主题
« 返回列表上一主题下一主题

限100 字节
批量上传需要先选择文件,再选择上传
 
验证问题: 48 - 3 = ?
上一个 下一个
      ×
      全新阿里云开发者社区, 去探索开发者的新世界吧!
      一站式的体验,更多的精彩!
      通过下面领域大门,一起探索新的技术世界吧~ (点击图标进入)