面向服务的体系架构 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功能以及实 ...
随机推荐
- 利用while语句,条件为输入的字符不为'\n'.
题目:输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数. 1.程序分析:利用while语句,条件为输入的字符不为'\n'. 一个很简单的问题,其实换种方式就能完成,但是我就想怎么着才能 ...
- hdu4148 Length of S(n)
Length of S(n) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)To ...
- Winform美化MessageBox
现在在做的项目美工要求比较高,所以根据网上搜索的资料,自定义了一整套的弹出框,供大家参考,之网上其他大神有调用系统ICO的,容易导致异常,我在此使用本地资源ICO,效率高不异常.using Syste ...
- DAY2-JAVA
2018-1-28学习笔记 1.在开发中定义类.方法时也可以先添加文档注释,再用javadoc工具生成自己的API文档.Java文档注释和java工具使用. 2.掌握查阅java JDK和API文档. ...
- 剑指offer第一天
15.反转链表 输入一个链表,反转链表后,输出链表的所有元素. 解法一:(使用栈) /* public class ListNode { int val; ListNode next = null; ...
- React Native填坑之旅 -- FlatList
在React Native里有很多种方法来创建可滚动的list.比如,ScrollView和ListView.他们都各有优缺点.但是在React Native 0.43里增加了两种行的list vie ...
- SQL总结手册
1.SQL语法 (1)查询 SQL查询是使用最多的,需要凭借结构.索引和字段类型等因素.大多数据库含有一个优化器(optimizer),把用户查询转换为可选形式,以提高查询效率. 基本语法为: SEL ...
- Centos中hive/hbase/hadoop/mysql实际操作及问题总结
目录 Hive中文乱码问题 hive和hbase的版本不一致 Ambari hive插入Hbase出错 Hive0.12和Hbase0.96不兼容,重新编译hive0.12.0 hiveserver不 ...
- 【java学习笔记】线程
1.线程的定义 ①继承Thread类,将执行的任务逻辑放到run方法中,调用start方法来开启线程 public class ThreadDemo { public static void main ...
- RGMII,MII,GMI接口
简介 RGMII(Reduced Gigabit Media Independent Interface)是Reduced GMII(吉比特介质独立接口).GMII和RGMII均采用8位数据接口,工作 ...