2. 服务的路由和负载均衡

1.2.1 服务化的演变

SOA设计思想:分布式应用架构体系对于业务逻辑复用的需求十分强烈,上层业务都想借用已有的底层服务来快速搭建更多、更丰富的应用,降低新业务开展的人力和时间成本,快速满足瞬息万变的市场需求。公共的业务被拆分出来行程可共用的服务,最大程度的保障了代码和逻辑的复用,避免重复建设,这种设计也称为SOA 。

服务的路由:SOA架构中,服务消费者通过服务名称,在众多的服务器中找到要调用的服务的地址列表,称为服务的路由。

负载均衡:对于负载较高的服务来说,往往对应着由多台服务器组成的集群,在请求到来时,为了将请求均衡的分配到后端服务器,负载均衡程序将从服务器对应的地址列表中,通过相应的负载均衡算法和规则,选取一台服务器进行访问,这个过程称为服务的负载均衡。

服务配置中心:当服务器数量庞大时,人工来管理和维护服务及地址的配置信息变得困难,依赖单一的硬件负载均衡设备或者使用LVS、Nginx等软件方案进行路由和负载均衡调度也容易引发单点问题,一旦服务路由或者负载均衡服务器宕机,依赖它的所有服务均将失效。此时,需要一个能够动态注册和获取服务信息的地方来统一管理服务名称和其对应的服务器列表信息,称为服务配置中心。

服务配置中心的意义:服务提供者在启动时,会将其提供的服务名称、服务器地址注册到服务配置中心,服务消费者通过服务配置中心来获得需要调用的服务的机器列表,通过相应的负载均衡算法,选取其中一台服务器进行调用。当服务器宕机或者下线时,相应的机器需要动态的从服务配置中心移除,并通知相应的服务消费者,防止其调用到已经失效的服务而发生错误。在这个过程中,服务消费者只有在第一次调用服务时需要查询服务配置中心,然后将查询到的信息缓存到本地,后面的调用直接使用缓存的服务地址列表信息即可,直到服务的地址列表有变更(机器上线或者下线)。这种无中心化的结构解决了单点故障问题,并且大大减轻了服务配置中心的压力。

1.2.2 负载均衡算法

常见的负载均衡算法包括:轮询法、随机法、源地址哈希法、加权轮询法、加权随机法、最小连接法等,根据不同场景需要选取不同的算法。

我们暂时将服务器地址及其权重置于map中:

     serverWeightMap.put("192.168.1.10", 1);
serverWeightMap.put("192.168.1.11", 1);
serverWeightMap.put("192.168.1.12", 3);
serverWeightMap.put("192.168.1.13", 1);
serverWeightMap.put("192.168.1.14", 5);
serverWeightMap.put("192.168.1.15", 2);
serverWeightMap.put("192.168.1.16", 1);

1)轮询法:

将请求按顺序轮流的分配到后端服务器上,它均衡的对待后端每一台服务器,而不关心服务器实际的连接数和当前的系统负载。

   public String getServerIP() {
//新建map,避免出现服务器上线、下线、宕机引发的并发问题、数组越界等
Map<String, Integer> serverMap = new HashMap<String, Integer>();
serverMap.putAll(serverWeightMap);
//取得服务器列表list
List<String> serverList = new ArrayList<String>();
serverList.addAll(serverMap.keySet()); String server = null;
Integer pos = 0;//当前服务器位置
synchronized (pos) {
if (pos >= serverList.size()) {
pos = 0;
}
server = serverList.get(pos);
pos++;
}
return server;
}

将服务器地址先复制到本地,可以避免被多个线程修改,但这样也会引发新的问题,当出现新增或者下线服务器时,负载均衡算法将无法获知,因此,在服务消费者的实现端需要考虑该问题并进行相应的容错处理,比如重新发起一次调用。轮询的位置pos添加synchronized锁可防止pos变量被并发修改,导致数组越界问题,但也导致轮询代码的并发吞吐量发生明显的下降。

2)随机法:

     public String getServerIP() {
//新建map,避免出现服务器上线、下线引发的并发问题
Map<String, Integer> serverMap = new HashMap<String, Integer>();
serverMap.putAll(serverWeightMap);
//取得服务器列表list
List<String> serverList = new ArrayList<String>();
serverList.addAll(serverMap.keySet()); java.util.Random random = new java.util.Random();
int pos = random.nextInt(serverList.size());
return serverList.get(pos);
}

由概率统计理论可知,随着调用量的增大,随机法的效果会越来越接近轮询的效果。因此,你还会考虑一定要使用需要付出一定性能代价的轮询算法吗?

3)源地址哈希(Hash)法

源地址哈希的思想是获取客户端访问的IP地址值,通过哈希函数计算得到一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是要访问的服务器的需要。这样相同IP地址的客户端,当后端服务器列表不变时,它都会被映射到同一个后端服务器。

     public String getServerIP(String targetIP) {
//新建map,避免出现服务器上线、下线引发的并发问题
Map<String, Integer> serverMap = new HashMap<String, Integer>();
serverMap.putAll(serverWeightMap);
//取得服务器列表list
List<String> serverList = new ArrayList<String>();
serverList.addAll(serverMap.keySet()); int hashcode = targetIP.hashCode();
int pos = hashcode % serverList.size();
return serverList.get(pos);
}

源地址哈希法可以在服务消费者与服务提供者之间建立有状态的session会话。

4)加权轮询法:

     public String getServerIP() {
//新建map,避免出现服务器上线、下线引发的并发问题
Map<String, Integer> serverMap = new HashMap<String, Integer>();
serverMap.putAll(serverWeightMap);
Set<String> keySet = serverMap.keySet();
Iterator<String> iterator = keySet.iterator();
//新建空的服务器列表list
List<String> serverList = new ArrayList<String>();
while(iterator.hasNext()) {
String server = iterator.next();
Integer weight = serverMap.get(server);
//若该服务器的权重为4,则在服务器列表中添加四个该服务器
for (int i = 0; i < weight; i++) {
serverList.add(server);
}
}
Integer pos = 0;
String server = null;
synchronized (pos) {
if (pos >= serverList.size()) {
pos = 0;
}
server = serverList.get(pos);
pos++;
}
return server;
}

5)加权随机法:

     public String getServerIP() {
//新建map,避免出现服务器上线、下线引发的并发问题
Map<String, Integer> serverMap = new HashMap<String, Integer>();
serverMap.putAll(serverWeightMap);
Set<String> keySet = serverMap.keySet();
Iterator<String> iterator = keySet.iterator();
//新建空的服务器列表list
List<String> serverList = new ArrayList<String>();
while(iterator.hasNext()) {
String server = iterator.next();
Integer weight = serverMap.get(server);
//若该服务器的权重为4,则在服务器列表中添加四个该服务器
for (int i = 0; i < weight; i++) {
serverList.add(server);
}
} Random random = new Random();
int pos = random.nextInt(serverList.size());
return serverList.get(pos);
}

6)最小连接法:

以上算法我们都是为了平均给后端服务器分配工作量,最大程度的提高服务器的利用率,但是实际情况并非一定如此,我们可以从算法实施的角度来看,以后端服务器的视角来观察系统的负载,而非请求发起方来观察。因此,我们需要有其他的算法来实现可供选择,最小连接法变属于此类算法。

最小连接法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理快慢不同,它正是根据后端服务器当前的连接情况动态选取当前积压连接数最少的一台服务器来处理当前请求,尽可能的提高后端服务器的利用效率,将负载合理的分流到每一台机器。

面向服务的体系架构 SOA(二) --- 服务的路由和负载均衡的更多相关文章

  1. 面向服务的体系架构SOA

    面向服务的体系架构SOA 序言 在.Net的世界中,一提及SOA,大家想到的应该是Web Service,WCF,还有人或许也会在.NET MVC中的Web API上做上标记,然后泛泛其谈! 的确,微 ...

  2. 面向服务的体系架构 SOA(三) --- Zookeeper API、zkClient API的使用

    zookeeper简单介绍及API使用 1.1 zookeeper简介 zookeeper是一个针对大型分布式系统的可靠的协调系统,提供的功能包括配置维护.名字服务.分布式同步.组服务等.zookee ...

  3. 分布式架构设计(一) --- 面向服务的体系架构 SOA

    1.1 基于TCP协议的RPC 1.1.1 RPC名词解释 RPC的全称是Remote Process Call,即远程过程调用,RPC的实现包括客户端和服务端,即服务调用方和服务提供方.服务调用方发 ...

  4. 说说面向服务的体系架构SOA

    序言 在.Net的世界中,一提及SOA,大家想到的应该是Web Service,WCF,还有人或许也会在.NET MVC中的Web API上做上标记,然后泛泛其谈! 的确,微软的这些技术也确实推动着面 ...

  5. SOA——面向服务的体系架构

    上一篇博文中提到了"紧耦合"的现象.怎样解决?SOA.採用面向服务的体系架构. 一.What? SOA=Service-oriented Architecture面向服务的体系结构 ...

  6. 面向服务的体系架构(SOA)

    面向服务的体系架构(SOA) 1.面向服务的体系架构(SOA) 面向服务的架构(service-oriented architecture)是Gartner于2O世纪9O年代中期提出的面向服务架构的概 ...

  7. InnoDB体系架构(二)内存

    InnoDB体系架构(二)内存 上篇文章 InnoDB体系架构(一)后台线程 介绍了MySQL InnoDB存储引擎后台线程:Master Thread.IO Thread.Purge Thread. ...

  8. 循序渐进nginx(二):反向代理、负载均衡、缓存服务、静态资源访问

    目录 反向代理 使用 1.创建代理目标服务端: 2.配置nginx反向代理目标服务端: 3.测试使用: 负载均衡 使用 1.准备服务端 2.修改nginx配置 3.测试 负载均衡策略 负载均衡的额外参 ...

  9. RPC原来就是Socket——RPC框架到dubbo的服务动态注册,服务路由,负载均衡演化

    序:RPC就是使用socket告诉服务端我要调你的哪一个类的哪一个方法然后获得处理的结果.服务注册和路由就是借助第三方存储介质存储服务信息让服务消费者调用.然我们自己动手从0开始写一个rpc功能以及实 ...

随机推荐

  1. Python3实现QQ机器人自动爬取百度文库的搜索结果并发送给好友(主要是爬虫)

    一.效果如下: 二.运行环境: win10系统:python3:PyCharm 三.QQ机器人用的是qqbot模块 用pip安装命令是: pip install qqbot (前提需要有request ...

  2. C#实现七牛云存储

    云存储,就是把本地的资源文件存放至网络上,可以公网访问.相当于网盘功能,感觉非常方便. 这里介绍的是七牛云存储.有兴趣的可以去官方网站详看 根据官网的介绍,本身是提供SDK的,下载地址,大家可以根据自 ...

  3. unbuntu 系统登录华南师范大学校园网的方法

    最近刚装了unbuntu 系统,刚开始网络连接遇到了点小问题,原来是校园网不知道怎么认证,于是向好基友请教了下,得出快捷的方法如下: 下载学校网络的认证客户端,记住位置,一般都是默认下载地址是 Dow ...

  4. CSS布局(五) 网页布局方式

    网页实质是块与块之间的位置,块挨着块,块嵌套块,块叠着块. 三种关系:相邻,嵌套,重叠. 下面介绍网页布局的常用几种方式 1.一列布局: 一般都是固定的宽高,设置margin : 0 auto来水平居 ...

  5. 一个简单清晰的Redis操作类

    <?php /** * redis处理的二次封装 * */ class Redis{ private $_redis; private $_config; public function __c ...

  6. #pragma预处理命令

    #pragma comment(lib,"XXX.lib") 表示链接XXX.lib这个库,和在工程设置里写上XXX.lib的效果一样. #pragma comment(linke ...

  7. UVA - 11292 Dragon of Loowater 贪心

    贪心策略:一个直径为X的头颅,应该让雇佣费用满足大于等于X且最小的骑士来砍掉,这样才能使得花费最少. AC代码 #include <cstdio> #include <cmath&g ...

  8. HDU - 1847 巴什博弈

    思路:    0  1  2  3  4  5  6  7  8  9 10 11 12    P N  N P  N N  P N N  P N   N   P 不难发现:当n为三的倍数时,KIKI ...

  9. hdu1242 Rescue bfs+优先队列

    直接把Angle的位置作为起点,广度优先搜索即可,这题不是步数最少,而是time最少,就把以time作为衡量标准,加入优先队列,队首就是当前time最少的.遇到Angle的朋友就退出.只需15ms A ...

  10. python导入模块

    1.模块的定义: 模块定义:用来逻辑上组织python代码(变量.函数.类.逻辑:目的是:实现一个功能),本质就是.py结尾的python文件. 补充: 包的定义:用来从逻辑组织模块的,本质就是一个目 ...