Distributed System 分布式学习笔记(尝试持续更新ing)

写在开头:因为下学期有分布式的课程,想提前了解一下,所以看了一部分书和网课。因为资源大部分都是外文的,感觉篇幅很长,再看可能很难回忆起来,就想顺手写个博客记录一下。因为totally green hands,所以肯定会有一些大问题,如果看到的话,欢迎指正。

Concurrent and Distributed System是剑桥大学的一门课。公开的视频资源好像只有分布式系统这一块,可以上B站看:剑桥大学Distributed System。比较简短,只有8个lecture。

图书资源在L1中有给出,我看的是Steen等人的Distributed Systems。

Lecture 1 Introduction

并发和分布式系统

一台电脑上的并发可以看作是内存共享的并发:一个进程的多个线程可以访问同一个地址空间。所以数据可以轻松的从一个线程传递到另一个线程。(借助指针或者变量)

当转到分布式系统的时候,我们依然需要并发,因为不同的计算机要并行执行程序。但是此时,我们没有内存共享(分布式系统的每台计算机运行自己的操作系统,拥有自己独有的地址空间)。不同的计算机通过网络发送消息进行交流。(并不是绝对的,在一些超级计算机和研究系统中是存在一定形式的分布式的内存共享的,例如RDMA等)。

node节点 分布式系统中的任何计算设备都可以称为节点。


1. 为什么需要分布式系统

  • 一些应用本身就是分布式的

example:你想要用手机发消息给你朋友的手机。这个操作不可避免地需要两台手机设备(节点)和网络。

  • 为了更可靠

可能一些任务原则上一台计算机也可以完成,但是可能会失败或者可能时不时重启。如果使用分布式系统,投入更多的节点,那么在一个节点重启的时候,其他的节点仍然可以持续提供服务。所以分布式系统对比之下拥有更可靠的潜力。

  • 更好的性能(网络相关)

如果只有一个节点提供服务,考虑到如果向全球各地的用户提供服务,那么对于偏远地区的用户而言,服务会十分缓慢。如果有很多的节点提供服务,我们就可以将用户的请求路由到更近的节点。

  • 可以解决更大规模的问题

一些大规模数据处理或者数据计算的问题对于单点而言过于庞大,可能会慢的令人抓狂。


2. 分布式系统的困难

  • 节点间通信可能会失败

因为网络是不可靠的,所以节点之间可能会无法通讯。

  • 状况总是会突变

原来的设想:如果有一个节点崩溃了,或者运行的比其他节点缓慢,或者操作失误,希望有其他的节点去接替它的工作。

问题:无论是网络崩溃还是节点出问题都是不可预测的发生,很难监测。

2.1 容错性 Fault tolerance

故障Fault指的是系统的某个组成部分停制工作的情况。我们希望分布式系统能尽可能提供容错性:系统作为一个整体能够持续工作,即使会有故障发生。


3. 分布式系统和计算机网络

将通信抽象为:节点 i 向节点 j 发送信息 m 。

只考虑两个问题:时延(从发送到被接收的时间)和带宽(单位时间可以传送的数据量)。

分布式算法决定:传送的报文是什么?报文被接收的时候应该如何处理?

example:Web

当加载web页面的时候,web浏览器首先发送HTTP请求给指定的服务器,服务器收到请求返回响应报文,报文中包含了客户端请求的页面内容。


4. RPC Remote Procedure Calls 远程过程调用

情景导入:当网上购物需要使用银行卡支付的时候,当你输入银行卡号时,电商会通过网络给专门处理银行卡支付的服务发送支付请求。支付服务方会和一个银行卡网络(应该就是各种银行卡例如Visa,MasterCard等组成的网络,银行卡网络会和管理你卡的银行进行通信来取钱)进行通信。

对于实现电商平台的程序员而言,处理销售的代码可能是这样的:

Card card = new Card() ;
card.setCardNumber( "1234 5678 8765 4321");
card.setExpiryDate( "10/2024") ;
card.setcVC( "123");


Result result = paymentsService.processPayment(card,3.99,Currency .GBP);//此方法实现在另外一个节点上,非电商节点

if(result.isSuccess()){
    
    
	fulfil0rder() ;
}

processPayment方法实际上是商铺像支付服务方发送请求,等待响应,然后返回它接收的响应。其实际的实现逻辑是与银行卡网络和银行进行通信(这一部分不存在在电商的代码中),这是支付服务方的一部分,运行在其他公司的一个节点的程序上。

RPC定义:一个节点的代码去调用另一个节点上的程序

RPC在Java中被称为RMI(Remote Method Invocation)。实现RPC的软件被称为RPC框架或中间件。(但不是所有的中间件都是基于RPC的,他们可能会使用其他的通讯模型)

stub桩 当一个应用想要调用另一个节点上的方法时,RPC框架会提供stub。(可以看作代理点,不做真正的事情,而是通过RPC由外部完成真正的工作)。stub和真正的方法的签名是一样的,但是不同于执行真实的方法,它将函数参数进行编码到报文中,然后将该报文发送给远处的节点,要求调用该节点的方法。对函数参数进行编码的过程就成为marshalling。(JSON例如)

在这里插入图片描述

从RPC客户端发报文给RPC服务器会发生在HTTP层(或者其他网络协议层).在服务器端,RPC框架会对报文进行解码,然后使用参数调用客户端希望的方法,当方法返回时,上述的操作就反转一下。

所以,对于stub的调用者而言,方法看上去像是在本地执行的那样。

Location transparency:系统隐藏了资源所在位置(虽然我也不知道为什么要把这个称为透明,但它的意思就是调用远程节点提供的服务就像是调用本地的方法一样)。

在实际过程中,这会遇到很多问题:在方法调用的时候服务方如果崩溃了;报文丢失;报文超时;是否安全等问题。


Exercise1

  • 访问网络和节点都可能会失败,那么对于需要通过RPC调用其他节点的代码而言需要注意什么?

    报文丢失时RPC会超时,即使我们重试,也不能保证报文一定能收发成功。所以程序必须要处理这种错误情况,反应可能的错误。举例而言,Java的RPC库经常会抛出异常,JavaScript RPC客户端经常会返回一个promise(成功或失败)。

  • RPC和本地函数调用有那些不同?

    • 超时发生的时候,RPC客户端是不知道服务器是否执行了方法,但是本地函数调用就不存在这种不确定性。
    • RPC通常比本地函数调用慢一些(考虑网络时延)。更进一步讲,网络延时是变化的,不可预测的。但是本地函数的执行通常是可预测的。
    • RPC客户端和服务器必须要实现方法调用时幂等的(相同参数情况下,会得到相同结果),在信息丢失的情况下也能保证安全的重新尝试。
    • 另一个不同是当引用对象作为参数被传递的时候,对于本地函数调用而言这个对象是可变的。但是RPC就不行,因为远程方法无法访问调用者的内容。远程方法唯一能做的是通过返回值将信息发送给调用方,或者它可以再使用另外一个RPC。
  • Location Transparency可以被实现吗?

    完美的location transparency只能通过将本地函数调用变得更像RPC来实现。(允许它们会不可预测地失败)。但在多数情况下这是不理想的。因此多数地系统不会去尝试完全隐藏本地和远程调用地区别。


常见的RPC形式

使用JSON数据在HTTP上传输来实现。对于这样基于HTTP的API的一系列设计原则被称为representational state transfer或REST,遵守这些原则的API被称为是RESTful的。这些原则包括:

  • 通讯是无状态的。(每个请求是独立于其他请求的)
  • 用URL来表示资源
  • 资源的状态是由HTTP请求来更新的。HTTP请求会带有一个标准的方法类型(POST或者PUT),针对一个确定的URL来请求。

REST流行原因

浏览器端的Javascript代码可以轻松实现上述的HTTP请求。在现代网站上,使用JavaScript来对服务器发起HTTP请求(不用重载整个页面)是一件非常常见的事情。(Ajax)。

RESTful APIs和基于HTTP的RPC尽管起源于web,但是它们现在也被广泛应用于其他的客户端(手机app等)或者是服务器-服务器间的通信。

在大企业中,这样的服务器间的RPC是十分常见的,因为企业的软件系统过于庞大和复杂,不太可能运行在单一机器的单一进程上。为了解决这种复杂性问题,系统会被分解成多个服务,由不同团队来开发和管理,也有可能使用不同的编程语言来实现。RPC框架简化这些服务之间的通信。这就需要RPC框架进行数据类型转换使得被调用方能够理解调用方的参数(同样对于被调用方的返回值也需要转换)。典型方法是使用IDL(接口定义语言)来提供无关语言的函数签名规范。通过IDL,软件开发商就可以针对每种服务方和客户各自的编程语言自动生成编码会解码代码以及RPC桩。

下面是一个IDL的例子:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43329358/article/details/113149940