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. java设计模式-----1、简单工厂模式

    简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例,简单来说 ...

  2. 经典卷积神经网络(LeNet、AlexNet、VGG、GoogleNet、ResNet)的实现(MXNet版本)

    卷积神经网络(Convolutional Neural Network, CNN)是一种前馈神经网络,它的人工神经元可以响应一部分覆盖范围内的周围单元,对于大型图像处理有出色表现. 其中 文章 详解卷 ...

  3. asp.mvc中的vue分页实例,分页组件无法重置reload,解决点击查询按钮后,分页不刷新的问题

    刚刚接触Vue.js,现在需要做一个查询功能,并且进行服务端分页.主要思路是在页面中注册一个分页组件,然后进行调用.代码如下 1.引用vue.js,具体去网上下载 2.在html的body中添加如下代 ...

  4. SRE之道:创造软件系统来维护系统运行

    引言:本文作者Ben Treynor Sloss,Google 运维团队的高级副总裁,SRE 名称的发明者,在这里提供了他对SRE 的定义.  本文选自<SRE:Google运维解密>. ...

  5. Android 4.4以上使用HttpURLConnection底层使用OkHttp实现的源码分析

    研究了一下HttpURLConnection的源码: 在使用的时候都是通过URL.openConnection()来获取HttpURLConnection对象,然后调用其connect方法进行链接,所 ...

  6. [PHP开发] phpmailer问题 错误原因: Could not instantiate mail function

    Send via the PHP mail() function function mail_send($header, $body) { // Create mail recipient list ...

  7. 初试 Windows XP Embedded 系统开发1

    目前 Windows PE(Preinstallation Environment)和 Windows XP Embedded 是可以脱离主机里的硬盘独立运行的 Windows 操作系统,Window ...

  8. freemarker报错之五

    1.错误描述 freemarker.core.ParseException: Token manager error: freemarker.core.TokenMgrError: Lexical e ...

  9. vue轮播组件及去掉路由#

    最近公司要我去实现vue知识的系统讲解,总结一番,大致需要7节课,今天大致说一下我们使用vue需要学会的基本技能.vue是一个渐进性视图渲染框架,使用vue核心是数据出发,数据一般是我们前台从后台获取 ...

  10. 让微信,qq,uc浏览器使用全屏模式,全屏模式里,浏览器是不会上下左右滑动出现背景的

    <meta name="x5-fullscreen" content="true"> <meta name="full-screen ...