跨域访问及jsonp,cors,httpclient,dubbo总结

1.跨域访问

1.1什么是跨域

当前发起请求的域与该请求指向的资源所在的域不一样。这里的域指的是这样的一个概念:我们认为若协议 + 域名 + 端口号均相同,那么就是同域。

举个例子:假如一个域名为aaa.cn的网站,它发起一个资源路径为aaa.cn/books/getBookInfo的 Ajax 请求,那么这个请求是同域的,因为资源路径的协议、域名以及端口号与当前域一致(例子中协议名默认为http,端口号默认为80)。但是,如果发起一个资源路径为bbb.com/pay/purchase的 Ajax 请求,那么这个请求就是跨域请求,因为域不一致,与此同时由于安全问题,这种请求会受到同源策略限制。

以下情况都属于跨域:

跨域原因说明 示例
域名不同 www.jd.com 与 www.taobao.com
域名相同,端口不同 www.jd.com:8080 与 www.jd.com:8081
二级域名不同 item.jd.com 与 miaosha.jd.com

1.2 跨域请求的安全问题

通常,浏览器会对上面提到的跨域请求作出限制。浏览器之所以要对跨域请求作出限制,是出于安全方面的考虑,因为跨域请求有可能被不法分子利用来发动 CSRF攻击。

CSRF攻击: CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击页面,利用目标网站对用户的信任,以用户身份在攻击页面对目标网站发起伪造用户操作的请求,达到攻击目的。

CSRF攻击的原理大致描述如下:有两个网站,其中A网站是真实受信任的网站,而B网站是危险网站。在用户登陆了受信任的A网站是,本地会存储A网站相关的Cookie,并且浏览器也维护这一个Session会话。这时,如果用户在没有登出A网站的情况下访问危险网站B,那么危险网站B就可以模拟发出一个对A网站的请求(跨域请求)对A网站进行操作,而在A网站的角度来看是并不知道请求是由B网站发出来的(Session和Cookie均为A网站的),这时便成功发动一次CSRF攻击。

因而 CSRF 攻击可以简单理解为:攻击者盗用了你的身份,以你的名义发送而已请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。
因此,大多数浏览器都会跨域请求作出限制,这是从浏览器层面上的对 CSRF 攻击的一种防御,但是需要注意的是在复杂的网络环境中借助浏览器来防御CSRF攻击并不足够,还需要从服务端或者客户端方面入手防御。详细可以参考这篇文章浅谈CSRF攻击方式

1.3 同源策略

浏览器中规定 Ajax请求 协议://域名:端口三者必须全部相同时,才能实现数据访问(同域请求),如果违反上述规则中的任意一个则该请求就是跨域访问。如果浏览器进行跨域访问,则浏览器不予解析返回值。
在这里插入图片描述

1.4 跨域解决方法

虽然在安全层面上同源限制是必要的,但有时同源策略会对我们的合理用途造成影响,为了避免开发的应用受到限制,有多种方式可以绕开同源策略,下面介绍的是经常使用的 JSONP, CORS 方法。

1.4.1 JSONP实现跨域访问

1.4.1.2 原理:
  • JSONP 是一种非官方的跨域数据交互协议
  • JSONP 本质上是利用 <script><img><iframe>等标签不受同源策略限制,可以从不同域加载并执行资源的特性,来实现数据跨域传输。
  • JSONP由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数,而数据就是传入回调函数中的JSON数据。
  • JSONP 的理念就是,与服务端约定好一个回调函数名,服务端接收到请求后,将返回一段 Javascript,在这段 Javascript 代码中调用了约定好的回调函数,并且将数据作为参数进行传递。当网页接收到这段 Javascript 代码后,就会执行这个回调函数,这时数据已经成功传输到客户端了。

解决思路:
1.利用javaScript中的src开放原则 实现跨域!!!
2.自定义回调函数
3.将返回值进行特殊的格式封装 callback(返回值数据)

示例:

//1. 借助 <script><img><iframe> 等标签可以引入不同域资源的特性,将需要发送的请求的路径作为src参数
<script type="text/javascript" src="http://manager.jt.com/test.json"></script>
/*补充说明:一般src属性负责资源的加载.如果需要使用数据,则需要函数进行调用才行.
2.当前页面中声明一个自定义回调函数。
*/
<script type="text/javascript">
		/*JS是解释执行的语言  */
		/*定义回调函数  */
		function hello(data){
    
    
			alert(data.name);
		}
</script>
//3.将返回值的结果 进行特殊的格式封装!!!
hello({
    
    "id":"1","name":"tom"})

整体页面JS分析

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>	
	<script type="text/javascript">
		/*JS是解释执行的语言  */
		/*定义回调函数  */
		function hello(data){
     
     
			alert(data.name);
		}
	</script>
	<!--该json一直保存到浏览器中等待调用,但是没有函数名称无法调用  -->
	<script type="text/javascript" src="http://manager.jt.com/test.json"></script>
	<script type="text/javascript" src="http://manager.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
	</script>
</head>
<body>
	<h1>JS跨域问题</h1>
</body>
</html>
1.4.1.2 jQuery实现JSONP

需求:jsonp的方式如果采用原生的调用方式,则配置繁琐 需要如下步骤
1)javascript
2)自定义回调函数
3)特殊格式封装。

如果页面引入了 jQuery,那么可以通过它封装的方法很方便的实现JSONP操作了
页面封装:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSONP测试</title>
<script type="text/javascript" src="http://manager.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
	$(function(){
     
     
		alert("测试访问开始!!!!!")
		$.ajax({
     
     
			url:"http://manager.jt.com/web/testJSONP",
			type:"get",				//jsonp只能支持get请求   src只能进行get请求.
			dataType:"jsonp",       //dataType表示返回值类型 必须标识
			//jsonp: "callback",    //指定参数名称
			//jsonpCallback: "hello",  //指定回调函数名称
			success:function (data){
     
        //data经过jQuery封装返回就是json串
				alert(data.id);
				alert(data.name);
			}
		});	
	})
</script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>

在这里插入图片描述
编辑jt-manager中的Controller:

package com.jt.web.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class JSONPController {
    
    
    /**
     * 完成JSONP的调用
     * url:http://manager.jt.com/web/testJSONP?callback=jQuery111101021758391465013_1597656788213&_=1597656788214
     * 规定:返回值结果,必须经过特殊的格式封装.callback(json)
     */
    @RequestMapping("/web/testJSONP")
    public String  jsonp(String callback){
    
    
       return callback+"({'id':'100','name':'tomcat猫'})";
    }
}
1.4.1.3 优缺点:

JSONP 的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行。
JSONP 的缺点是:它只支持 GET 请求,而不支持 POST 请求等其他类型的 HTTP 请求

1.4.2 CORS跨域访问

跨源资源共享 Cross-Origin Resource Sharing(CORS) 是一个新的 W3C 标准,它新增的一组HTTP首部字段,允许服务端其声明哪些源站有权限访问哪些资源。换言之,它允许浏览器向声明了 CORS 的跨域服务器,发出 XMLHttpReuest 请求,从而克服 Ajax 只能同源使用的限制。

​ 另外,规范也要求对于非简单请求,浏览器必须首先使用 OPTION 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求,在服务器确定允许后,才发起实际的HTTP请求。对于简单请求、非简单请求以及预检请求的详细资料可以阅读HTTP访问控制(CORS)

知识回顾:
JSONP: 用户利用jsonp向服务器端动态获取数据的过程. 主体是用户.
CORS: 服务器是否允许客户端访问的技术. 主体是服务器.

编辑CORS跨域:
说明:为了以后能够实现通用,则在jt-common中添加cors操作.

package com.jt.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
    
    
        registry.addMapping("/**") //允许什么样的请求跨域  /* 只允许一级目录请求, /**标识允许多级目录请求
                .allowedOrigins("*") //允许那些服务进行跨域,例如:http://www.jt.com 标识只语序改网址进行跨域访问
                .allowedMethods("GET","POST","PUT","DELETE","HEAD")
                .allowCredentials(true) //是否允许携带cookies
                .maxAge(1800);//定义探针检测时间,在规定时间内,不再询问是否允许跨域
    }
}

编辑CORS流程图
在这里插入图片描述
CORS跨域响应信息.
在这里插入图片描述

2. httpclient

2.1 HttpClient介绍

HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。现在HttpClient最新版本为 HttpClient 4.5 .6(2015-09-11)
SpringCloud跨域中实现远程数据访问底层实现就是httpClient.
httpClient作用: 在java代码内部发起http请求.

2.2 HttpClient入门案例

2.2.1 引入httpClient工具包

package com.jt;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Test;
import java.io.IOException;
public class TestHttpClient {
    
    
    /**
     * 业务需求:在java代码中访问百度的页面
     * url: http://www.baidu.com    html代码片段
     * 实现步骤:
     *      1. 获取httpClient对象
     *      2. 自定义url地址
     *      3. 定义请求类型
     *      4. 发起请求 获取响应结果.
     *      5. 校验返回值状态,是否正确
     *      6. 获取返回值信息,之后完成后续业务处理.
     *      SDK......
     * */
    @Test
    public void test01(){
    
    
        HttpClient httpClient = HttpClients.createDefault();
        String url = "https://www.cctv.com";
        HttpGet get = new HttpGet(url);
        try {
    
    
            HttpResponse httpResponse = httpClient.execute(get);
            //获取返回值状态信息
            int status = httpResponse.getStatusLine().getStatusCode();
            if(status == 200){
    
    
                //请求正确的.  获取响应结果
                HttpEntity entity = httpResponse.getEntity(); //获取响应对象的实体信息.
                //将实体对象转化为用户能够识别的字符串
                String result = EntityUtils.toString(entity,"UTF-8");
                System.out.println(result);
            }else{
    
    
                System.out.println("httpClient调用异常.");
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }
}

2.3 关于HttpClient调用说明

1).httpClient使用时需要接收几个用户的URL请求? 2个
在这里插入图片描述2).跨域/httpClient代码调用分别为多少层
在这里插入图片描述

3. SOA思想

面向服务的架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和协议联系起来接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构件在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。
在这里插入图片描述

4. RPC

RPC是远程过程调用(Remote Procedure Call)的缩写形式。由不同的服务之间进行的通讯就称之为RPC,RPC通讯用户无需了解协议的细节.像调用本地服务一样简单. RPC调用本质就是代理思想的应用.

总结: 服务A想要完成某项任务,但是自己手中没有该资源,则通知服务B 帮我去完成该操作. 这样的操作方式称之为RPC

5. 注册中心

5.1 现有项目业务分析

说明:
1.使用传统的架构设计,所有的请求都经过NGINX负责中转,则nginx负载很大,如果nginx出现了问题,则直接影响用户.
2.如果服务器的数量改变了,则必然要修改nginx的配置文件.
需求:
1.保证nginx负载压力不要太高.
2.如果服务器数量发生变化,则可以自动的更新配置.,无需人为的干预
在这里插入图片描述

5.2 注册中心原理说明

在这里插入图片描述
原理说明:
1).当服务器启动时,会将自己的服务名称/IP:PORT写入注册中心.
2).当注册中心接收提供者数据时,会动态的维护服务列表数据.
3).当消费者服务器启动时,会链接注册中心.获取服务列表数据.
4).当请求注册中心之后,则将服务列表保存到本地(消费者内存中),方便以后使用.
5).根据已知的服务提供者 利用负载均衡机制挑选其中一个进行访问.
6).当注册中心利用心跳检查机制发现服务提供者宕机时,会"同步更新"注册列表,并且"同步所有消费者的服务列表".

5.3 为什么集中的节点数量是奇数台

公式: 剩余的主节点 > N/2
分析:
1个节点能否搭建集群? 1-1 > 0.5 假 不能搭建集群
2个节点能否搭建集群? 2-1 > 1 假 不能搭建集群
3个节点能否搭建集群? 3-1 > 1.5 真 可以搭建集群
4个节点能否搭建集群> 4-1 > 2 真 可以搭建集群

分析集群宕机的条件:
3个节点最多允许宕机1台. 奇数
4个节点最多允许宕机1台 偶数
奇数台和偶数台容灾能力相同.所以为了节省资源,一般集群都是奇数台.

结论:
1).搭建集群最小单位 3台.
2).一般集群搭建都是奇数台.

5.4 ZK选举机制

说明: zk选举采用最大值(myid)优先的机制.
在这里插入图片描述
面试题:
如果zk中有7台服务器.编号分别为1-7,并且依次启动.
问题1:谁当主机??? 4当主机
问题2: 哪几台永远不能当主机??? 123永远不能当主机.

6. dubbo

6.1 什么是 Dubbo?

Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC 框架,它提供了三大核心能力面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。简单来说 Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。

我们上面说了 Dubbo 实际上是 RPC 框架,那么什么是 RPC呢?

6.2 什么是 RPC?RPC原理是什么?

什么是 RPC?

RPC(Remote Procedure Call)—远程过程调用,**它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。**比如两个不同的服务 A、B 部署在两台不同的机器上,那么服务 A 如果想要调用服务 B 中的某个方法该怎么办呢?使用 HTTP请求当然可以,但是可能会比较麻烦。 RPC 的出现就是为了让你调用远程方法像调用本地方法一样简单。

RPC原理是什么?

我这里这是简单的提一下。详细内容可以查看下面这篇文章:

http://www.importnew.com/22003.html

RPC原理图

  1. 服务消费方(client)调用以本地调用方式调用服务;
  2. client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
  3. client stub找到服务地址,并将消息发送到服务端;
  4. server stub收到消息后进行解码;
  5. server stub根据解码结果调用本地的服务;
  6. 本地服务执行并将结果返回给server stub;
  7. server stub将返回结果打包成消息并发送至消费方;
  8. client stub接收到消息,并进行解码;
  9. 服务消费方得到最终结果。

下面再贴一个网上的时序图:

RPC原理时序图

说了这么多,我们为什么要用 Dubbo 呢?

6.3 为什么要用 Dubbo?

Dubbo 的诞生和 SOA 分布式架构的流行有着莫大的关系。SOA 面向服务的架构(Service Oriented Architecture),也就是把工程按照业务逻辑拆分成服务层、表现层两个工程。服务层中包含业务逻辑,只需要对外提供服务即可。表现层只需要处理和页面的交互,业务逻辑都是调用服务层的服务来实现。SOA架构中有两个主要角色:服务提供者(Provider)和服务使用者(Consumer)。

为什么要用 Dubbo

如果你要开发分布式程序,你也可以直接基于 HTTP 接口进行通信,但是为什么要用 Dubbo呢?

我觉得主要可以从 Dubbo 提供的下面四点特性来说为什么要用 Dubbo:

  1. 负载均衡——同一个服务部署在不同的机器时该调用那一台机器上的服务。
  2. 服务调用链路生成——随着系统的发展,服务越来越多,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。Dubbo 可以为我们解决服务之间互相是如何调用的。
  3. 服务访问压力以及时长统计、资源调度和治理——基于访问压力实时管理集群容量,提高集群利用率。
  4. 服务降级——某个服务挂掉之后调用备用服务。

另外,Dubbo 除了能够应用在分布式系统中,也可以应用在现在比较火的微服务系统中。不过,由于 Spring Cloud 在微服务中应用更加广泛,所以,我觉得一般我们提 Dubbo 的话,大部分是分布式系统的情况。

我们刚刚提到了分布式这个概念,下面再给大家介绍一下什么是分布式?为什么要分布式?

6.4 什么是分布式?

分布式或者说 SOA 分布式重要的就是面向服务说简单的分布式就是我们把整个系统拆分成不同的服务然后将这些服务放在不同的服务器上减轻单体服务的压力提高并发量和性能。比如电商系统可以简单地拆分成订单系统、商品系统、登录系统等等,拆分之后的每个服务可以部署在不同的机器上,如果某一个服务的访问量比较大的话也可以将这个服务同时部署在多台机器上。

6.5 为什么要分布式?

开发角度来讲单体应用的代码都集中在一起,而分布式系统的代码根据业务被拆分。所以,每个团队可以负责一个服务的开发,这样提升了开发效率。另外,代码根据业务拆分之后更加便于维护和扩展

另外,我觉得将系统拆分成分布式之后不光便于系统扩展和维护,更能提高整个系统的性能。你想一想嘛?把整个系统拆分成不同的服务/系统,然后每个服务/系统 单独部署在一台服务器上,是不是很大程度上提高了系统性能呢?

6.6 Dubbo 的架构

在这里插入图片描述上述节点简单说明:

  • Provider: 暴露服务的服务提供方
  • Consumer: 调用远程服务的服务消费方
  • Registry: 服务注册与发现的注册中心
  • Monitor: 统计服务的调用次数和调用时间的监控中心
  • Container: 服务运行容器

调用关系说明:
0)服务容器负责启动,加载,运行服务提供者。
1)服务提供者在启动时,向注册中心注册自己提供的服务。
2)服务消费者在启动时,向注册中心订阅自己所需的服务。
3)注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4)服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5)服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

重要知识点总结:

  • 注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小
  • 监控中心负责统计各服务调用次数,调用时间等,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展示
  • 注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外
  • 注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者
  • 注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表
  • 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者
  • 服务提供者无状态,任意一台宕掉后,不影响使用
  • 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

6.7 Dubbo 工作原理

Dubbo 工作原理图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖关系,每一层都可以剥离上层被复用,其中,Service 和 Config 层为 API,其它各层均为 SPI。

各层说明

  • 第一层:service层,接口层,给服务提供者和消费者来实现的
  • 第二层:config层,配置层,主要是对dubbo进行各种配置的
  • 第三层:proxy层,服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton
  • 第四层:registry层,服务注册层,负责服务的注册与发现
  • 第五层:cluster层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务
  • 第六层:monitor层,监控层,对rpc接口的调用次数和调用时间进行监控
  • 第七层:protocol层,远程调用层,封装rpc调用
  • 第八层:exchange层,信息交换层,封装请求响应模式,同步转异步
  • 第九层:transport层,网络传输层,抽象mina和netty为统一接口
  • 第十层:serialize层,数据序列化层,网络传输需要

6. 8 Dubbo负载均衡说明

6.8.1 什么是负载均衡

先来个官方的解释。

维基百科对负载均衡的定义:负载均衡改善了跨多个计算资源(例如计算机,计算机集群,网络链接,中央处理单元或磁盘驱动的的工作负载分布。负载平衡旨在优化资源使用,最大化吞吐量,最小化响应时间,并避免任何单个资源的过载。使用具有负载平衡而不是单个组件的多个组件可以通过冗余提高可靠性和可用性。负载平衡通常涉及专用软件或硬件。

上面讲的大家可能不太好理解,再用通俗的话给大家说一下。

比如我们的系统中的某个服务的访问量特别大,我们将这个服务部署在了多台服务器上,当客户端发起请求的时候,多台服务器都可以处理这个请求。那么,如何正确选择处理该请求的服务器就很关键。假如,你就要一台服务器来处理该服务的请求,那该服务部署在多台服务器的意义就不复存在了。负载均衡就是为了避免单个服务器响应同一请求,容易造成服务器宕机、崩溃等问题,我们从负载均衡的这四个字就能明显感受到它的意义。

6.8.2 Dubbo负载均衡策略

在集群负载均衡时,Dubbo 提供了多种均衡策略,默认为 random 随机调用。可以自行扩展负载均衡策略,参见:负载均衡扩展

6.8.2.1 Random LoadBalance(默认,基于权重的随机负载均衡机制)
  • 随机,按权重设置随机概率。
  • 在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。

基于权重的随机负载均衡机制

6.8.2.2 RoundRobin LoadBalance(不推荐,基于权重的轮询负载均衡机制)
  • 轮循,按公约后的权重设置轮循比率。
  • 存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

基于权重的轮询负载均衡机制

6.8.2.3 LeastActive LoadBalance
  • 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
  • 使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
6.8.2.4 ConsistentHash LoadBalance
  • 一致性 Hash,相同参数的请求总是发到同一提供者。(如果你需要的不是随机负载均衡,是要一类请求都到一个节点,那就走这个一致性hash策略。)
  • 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
  • 算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
  • 缺省只对第一个参数 Hash,如果要修改,请配置 <dubbo:parameter key="hash.arguments" value="0,1" />
  • 缺省用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key="hash.nodes" value="320" />

6.8.3 配置方式

xml 配置方式
服务端服务级别

<dubbo:service interface="..." loadbalance="roundrobin" />

客户端服务级别

<dubbo:reference interface="..." loadbalance="roundrobin" />

服务端方法级别

<dubbo:service interface="...">
    <dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:service>

客户端方法级别

<dubbo:reference interface="...">
    <dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:reference>

注解配置方式:
消费方基于基于注解的服务级别配置方式:

@Reference(loadbalance = "roundrobin")
HelloService helloService;

6.8.4 zookeeper宕机与dubbo直连的情况

zookeeper宕机与dubbo直连的情况在面试中可能会被经常问到,所以要引起重视。

在实际生产中,假如zookeeper注册中心宕掉,一段时间内服务消费方还是能够调用提供方的服务的,实际上它使用的本地缓存进行通讯,这只是dubbo健壮性的一种体现。

dubbo的健壮性表现:

  1. 监控中心宕掉不影响使用,只是丢失部分采样数据
  2. 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
  3. 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
  4. 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
  5. 服务提供者无状态,任意一台宕掉后,不影响使用
  6. 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

我们前面提到过:注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。所以,我们可以完全可以绕过注册中心——采用 dubbo 直连 ,即在服务消费方配置服务提供方的位置信息。

xml配置方式:

<dubbo:reference id="userService" interface="com.zang.gmall.service.UserService" url="dubbo://localhost:20880" />

注解方式:

 @Reference(url = "127.0.0.1:20880")   
 HelloService helloService;

6.8.5 zk数据存储结构

在这里插入图片描述

6.9 Dubbo通讯原理

通讯协议: dubbo协议(tcp-ip)
说明: dubbo协议将TCP-IP协议进行封装.
在这里插入图片描述Dubbo框架中使用dubbo协议建立了链接,之后通过IP:20880等端口进行通讯,与LinuxIP地址无关.
在这里插入图片描述

6.10 简述什么是客户端负载均衡/集中式负载均衡

  1. 什么是集中式的负载均衡 (nginx)
    特点:
    1).用户访问服务器时,自己不清楚访问的真实的服务器到底是谁,由nginx服务器动态的反向代理实现.
    2).统一由负载均衡服务器进行负载.。问题:负载均衡服务器访问压力高.

客户端负载均衡
1).消费者在访问服务提供者时清楚的了解到底应该访问哪台服务器.
2).由于每个客户端都进行负载均衡.相当于将压力均匀的分配给客户端.访问压力低.

核心:
1).nginx一般只负责反向代理
2).在微服务框架中 几乎都是客户端负载均衡服务器.

猜你喜欢

转载自blog.csdn.net/qianzhitu/article/details/108545268
今日推荐