面向服务的体系架构 SOA(二) --- 服务的路由和负载均衡
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(二) --- 服务的路由和负载均衡的更多相关文章
- 面向服务的体系架构SOA
面向服务的体系架构SOA 序言 在.Net的世界中,一提及SOA,大家想到的应该是Web Service,WCF,还有人或许也会在.NET MVC中的Web API上做上标记,然后泛泛其谈! 的确,微 ...
- 面向服务的体系架构 SOA(三) --- Zookeeper API、zkClient API的使用
zookeeper简单介绍及API使用 1.1 zookeeper简介 zookeeper是一个针对大型分布式系统的可靠的协调系统,提供的功能包括配置维护.名字服务.分布式同步.组服务等.zookee ...
- 分布式架构设计(一) --- 面向服务的体系架构 SOA
1.1 基于TCP协议的RPC 1.1.1 RPC名词解释 RPC的全称是Remote Process Call,即远程过程调用,RPC的实现包括客户端和服务端,即服务调用方和服务提供方.服务调用方发 ...
- 说说面向服务的体系架构SOA
序言 在.Net的世界中,一提及SOA,大家想到的应该是Web Service,WCF,还有人或许也会在.NET MVC中的Web API上做上标记,然后泛泛其谈! 的确,微软的这些技术也确实推动着面 ...
- SOA——面向服务的体系架构
上一篇博文中提到了"紧耦合"的现象.怎样解决?SOA.採用面向服务的体系架构. 一.What? SOA=Service-oriented Architecture面向服务的体系结构 ...
- 面向服务的体系架构(SOA)
面向服务的体系架构(SOA) 1.面向服务的体系架构(SOA) 面向服务的架构(service-oriented architecture)是Gartner于2O世纪9O年代中期提出的面向服务架构的概 ...
- InnoDB体系架构(二)内存
InnoDB体系架构(二)内存 上篇文章 InnoDB体系架构(一)后台线程 介绍了MySQL InnoDB存储引擎后台线程:Master Thread.IO Thread.Purge Thread. ...
- 循序渐进nginx(二):反向代理、负载均衡、缓存服务、静态资源访问
目录 反向代理 使用 1.创建代理目标服务端: 2.配置nginx反向代理目标服务端: 3.测试使用: 负载均衡 使用 1.准备服务端 2.修改nginx配置 3.测试 负载均衡策略 负载均衡的额外参 ...
- RPC原来就是Socket——RPC框架到dubbo的服务动态注册,服务路由,负载均衡演化
序:RPC就是使用socket告诉服务端我要调你的哪一个类的哪一个方法然后获得处理的结果.服务注册和路由就是借助第三方存储介质存储服务信息让服务消费者调用.然我们自己动手从0开始写一个rpc功能以及实 ...
随机推荐
- jquery validate 动态增加删除验证规则(转载)
页面加载完成初始化form validate $("#user_regForm").validate({ errorPlacement: function(error, eleme ...
- 微信开发系列——微信订阅号前端开发利器:WeUI
前言:年前的两个星期,学习了下微信公众号的开发.后端基本能够基于盛派的第三方sdk能搞定大部分事宜.剩下的就是前端了,关于手机端的浏览器的兼容性,一直是博主的一块心病,因为博主一直专注于bootstr ...
- bzoj 3166 [Heoi2013]Alo 可持久化Trie
3166: [Heoi2013]Alo Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1227 Solved: 569[Submit][Status ...
- mac下使用mysql控制台命令行
命令行中输入 open .bash_profile 然后将 alias mysql=/usr/local/mysql/bin/mysqlalias mysqladmin=/usr/local/mysq ...
- CodeForces-731B
如果当天有m支队伍,昨天选择了k个B方案,那么今天还需要买m-k个披萨,如果m-k是奇数,那就先买一种B,剩下的全部买A,如果是偶数,全部买A.如果中途出现只有0支队伍,然而昨天却买了一次B,那么直接 ...
- WEB开发-动态验证码
1.基于Python实现,用到了django后台处理,刷新验证码功能,其他语言大同小异 2.登录界面 login.html <!DOCTYPE html> <html lang=&q ...
- home目录迁移至新分区
在用户home目录越来越大时,就可以考虑将home目录迁移至新的分区. 1.创建新分区. fidisk /dev/sda:用磁盘管理器打开磁盘 n:新建 +10g :设置分区为10G w :保存 保存 ...
- B+索引、Hash索引、数据类型长度
1.为什么在数据库中要用B树索引而不是Hash索引? Mysql Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这 ...
- Ambari安装小记
在Ambari配置过程中,组件的定制与分配很重要
- mysql:联合查询
SELECT t1.name, t2.salary FROM employee AS t1 INNER JOIN info AS t2 ON t1.name = t2.name; 可以对数据表使用别 ...