当前位置: 首页 > news >正文

erlang/OTP 平台(学习笔记)(三)

分布式 Erlang

借助于语言属性和基于复制的进程通信,Erlang程序天然就可以分布到多台计算机上。要问为什么,且让我们来看两个用Java或C++这类语言写成的进程,它们运作良好并以共享内存为通信手段。假设你已经搞定了锁的问题,一切精准而高效,但就在你试图将其中一个线程挪到另一台机器上时,问题出现了。或许是为了利用更高效的计算能力和内存,或许是为了预防两个线程在硬件故障造成的宕机中同时挂掉,无论如何,这一刻降临时,程序员往往被迫重新设计代码结构,以便配合新的分布式环境中迥异的通信机制。显然,这将耗费大量的开发成本,而且很可能会引入数年才能彻底清除的bug。
Erlang程序却不受这些问题的影响。Erlang规避了数据共享并通过复制进行通信,这使得Erlang代码可以直接分布到多台机器上。在命令式语言里用线程编程时,各部分代码往往会因数据共享引入复杂的依赖关系;这类问题在Erlang中则很少见。今天能跑在你的笔记本上,明天就能跑在集群上。
Erlang应用通常可以直接分布到多个网络节点上,这同时意味着伸缩性问题也简化为一个数量级。你仍然需要考虑好各类进程的职能,每类进程需要运行多少个实例,在哪些机器上运行,怎样均衡负载以及怎样管理数据;但至少以下这类问题不用再劳你费心了:“我到底该怎么切分现有的程序才能搭建出冗余的分布式系统?”,“它们之间该怎么通信?”,还有“我该怎样得体地处理故障?”。

Erlang运行时系统和虚拟机

标准Erlang实现的核心是一个称作Erlang运行时系统(ERTS)的应用:这是一大块用C语言写成的代码,负责Erlang中所有底层的玩意儿。通过它你才能跟文件系统和终端打交道,它还处理内存,实现Erlang进程的也是它。ERTS知道如何将这些进程分布到现有的CPU资源上才能充分发挥计算机硬件的能力。同时,哪怕你只有一个单核CPU它也能实现Erlang进程的并发执行。ERTS还负责处理进程间的消息传递,并使处在不同机器上运行在各自的ERTS中的进程能够像身处同一台机器上一样进行通信。Erlang中所有需要底层支持的东西都由ERTS处理,所以ERTS移植到哪个平台Erlang就能在哪个平台上跑。
ERTS中特别重要的一个部分就是Erlang的虚拟机模拟器:这是执行Erlang程序经编译后产出字节码的地方。这个虚拟机也就是Bogdan Erlang抽象机(BEAM ) ,它非常高效:虽然我们也可以将Erlang程序编译为本地机器码,但一般没有那个必要,因为BEAM模拟器已经够快的了。注意虚拟机和ERTS之间并没有明确的界线;通常人们(包括我们自己)口中的Erlang VM指的就是模拟器加上运行时系统。
运行时系统中有许多有趣的特性,若不在文档中挖地三尺或是长期浸淫于Erlang邮件列表,你是不会知道的。它们正是Erlang能同时处理那么多进程的精要之所在,也是Erlang如此特别的原因之一。Erlang语言的基本哲学加上实现者所采取的务实方案,共同为我们带来了异常高效、面向生产的稳定系统。

我们将讨论促成了Erlang的强大和高效的3个重要方面:

调度器——处理运行中的Erlang进程,令所有就绪的进程共享可用的CPU资源,并在新消息到达或发生超时的时候唤醒相应的睡眠中的进程;

IO模型——′防止系统在进程与外部设备通信时阻塞,令系统平稳运行;

垃圾回收器——回收不再使用的内存。
 

1.调度器

经过多年的演进,ERTS的进程调度器提供了其他平台无法比拟的灵活性。它最初的设计目标是在单CPU上并发运行轻量级Erlang进程,而不是关心底层用什么操作系统。ERTS运行的时候通常就是单个操作系统进程(在操作系统的进程列表中一般名为beam或werl),就跑着管理所有Erlang进程的调度器。
随着线程在大多数操作系统中的普及,ERTS也有所变化,开始将I/O系统这类东西从运行Erlang进程的线程中拿出来,放到独立的线程中去,但完成主体工作的线程仍然只有一个。如果你用的是多核系统,就必须在同一台机器上运行多个ERTS实例。Erlang/OTP第11版中增加了对称多处理器( SMP)支持。这是一项重大突破,令Erlang运行时系统可以在内部使用不止一个进程调度器,每个占用一个独立的操作系统线程。
这意味着现在Erlang进程可以以n :m的方式映射到操作系统线程。每个调度器处理一个进程池。可并行运行的Erlang进程最多能有m个(每个调度器线程执行一个),但同一池内的进程仍像之前所有进程共用一个调度器那样分时运行。在此基础之上,进程可以在进程池之间迁移以便维持可用调度器上的负载均衡。在最新的Erlang/OTP发布版中,甚至可以根据机器上CPU的拓扑情况将进程绑定到特定的调度器上,从而更好地利用硬件的缓存架构。这意味着,大多数时候,作为一名Erlang程序员你不用担心手头有多少CPU或有多少个核:你只要中规中矩地写程序,并尽量将程序切分为尺寸适中的并行任务就好,负载均衡之类的事情就让Erlang运行时系统去操心吧。不管是单核还是128核——都一样,只会更快。

2.I/O与调度

很多并发语言都有的一个毛病就是它们没怎么拿I/O当回事儿。单个进程进行IO时,它们几乎都存在整个系统或大半系统阻塞的问题。这真是既恼人又没有必要,尤其是Erlang早在二十年前就已经解决了这个问题。在前一节,我们曾讨论过Erlang的进程调度器。除了处理进程调度,调度器还替系统优雅地处理了IO问题。在系统的最底层,Erlang以事件驱动的方式处理所有IO,当数据进出系统时,程序可以以非阻塞方式完成数据处理。这降低了连接建立和断开的频次,还避免了OS层面上的加锁开销和上下文切换。
这是一种高效的IO处理方法。可惜,程序员往往难以分析和理解这种技术,这也是为什么只有在明确要求高可靠性和低延迟的系统中才能见到这种技术。早在2001年,Dan Kegel就在他的论文The C10K Problem中描述过这个问题,虽然现在已经略显过时,但这篇文章仍然很值得一读。它针对这个问题及可能的解决方案给出了良好的综述。这些方案实现起来全都既复杂又痛苦,·这正是Erlang运行时系统替你包办这些问题的原因。Erlang在进程调度器中整合了基于事件的I/O系统。事实上,你一点儿都不用操心就能享受一切便利。这让用Erlang/OTP构建高可靠性系统变得轻松了很多。

3.进程隔离与垃圾回收器

虽然实现相对简单,Erlang程序却不太会像其他语言开发的系统那样在GC时遭受停顿。这主要因为Erlang进程之间的隔离:每个进程所使用的内存都是自己的,随进程的创建和结束而分配和释放。听起来好像没什么要紧,实则不然。首先,这意味着垃圾回收器可以在不影响其他进程运行的前提下单独暂停目标进程。其次,单个进程占用的内存通常较小,遍历可以快速完成。(也有内存占用量大的进程,但这些进程一般不用做出快速响应。)再次,调度器知道每个进程最后一次运行的时间,如果某个进程自上次垃圾回收后什么也没干,调度器会跳过它。正是这些因素让Erlang既可以轻松使用垃圾回收器,又可以保证较短的停顿时间。除此以外,有时候进程自派生到完工,再到退出,根本就没有触发过垃圾回收。这种情况下,进程的作用相当于一块昙花一现的内存,除自动分配和释放外,没有任何额外的开销。

本节所描述的运行时系统的特性使Erlang程序能够充分利用可用的CPU来运行大量进程、执行IO操作,并自动回收内存,与此同时还能维持软实时响应能力。了解了平台这些方面的知识,便可更好地理解自己的系统自启动后的各种行为。
 

相关文章:

erlang/OTP 平台(学习笔记)(三)

分布式 Erlang 借助于语言属性和基于复制的进程通信,Erlang程序天然就可以分布到多台计算机上。要问为什么,且让我们来看两个用Java或C这类语言写成的进程,它们运作良好并以共享内存为通信手段。假设你已经搞定了锁的问题,一切精…...

Spring整理-Spring框架中用了哪些设计模式

Spring框架广泛应用了多种设计模式,这些模式提高了框架的灵活性、可扩展性和可维护性。下面是在Spring框架中常见的一些设计模式: 单例模式(Singleton):用于在应用的整个生命周期内保持一个类的单个实例。在Spring中,Bean默认是单例模式。 工厂模式(Factory Pattern):…...

Poi实现根据word模板导出-图表篇

往期系列传送门: Poi实现根据word模板导出-文本段落篇 (需要完整代码的直接看最后位置!!!) 前言: 补充Word中图表的知识: 每个图表在word中都有一个内置的Excel,用于…...

windows或mac端口转发

摘要 在内网开发中,由于出于公司安全考虑,部分IP192.168.0.100访问只能针对固定IP192.168.0.200开放,此时我需要通过我的电脑192.168.0.300去访问,由于未对我电脑IP192.168.0.300授权,导致我访问不到,此时…...

Linux工具-搭建文件服务器

当我们使用linux系统作为开发环境时,经常需要在Linux系统之间、Linux和Windows之间传输文件。 对少量文件进行传输时,可以使用scp工具在两台主机之间实现文件传输: rootubuntu:~$ ssh --help unknown option -- - usage: ssh [-46AaCfGgKkMN…...

深入理解@DubboReference与@DubboService【三】

欢迎来到我的博客,代码的世界里,每一行都是一个故事 探索Dubbo的核心:深入理解DubboReference与DubboService【三】 前言DubboService注解基本概念使用示例高级特性 DubboReference注解基本概念使用示例服务调用流程 最佳实践注解的最佳使用方…...

linux主机的免密登录

实现linux主机之间的相互免密登录 在进行远程登录的时,服务器和主机间进行认证阶段分为: 基于口令认证(不安全,易被抓包拦截获取) 客户机连接服务器时,服务器将自己的公钥返回给客户机 客户机会将服务器的…...

Git常用命令和QA(网摘)

主要内容 常用命令git checkout --orphan 分支与 git checkout -b 分支区别git如何创建一个新的空白分支branchgit开发分支本地分支合并远程分支git remote prune origingit log如何退出?如何退出git log或git commit模式git log如何退出git commit 的退出 git强制p…...

PHP AES 加密示例

PHP中实现AES加密的一个基本示例涉及到使用openssl_encrypt函数。这个函数允许你使用不同的加密算法,包括AES。下面是一个简单的示例,展示了如何使用AES加密一个字符串。 首先,你需要确定几个关键的参数: 数据(Data&…...

第十九章:特殊工具与技术

第十九章:特殊工具与技术 对于很多程序员来说,他们很少会用到本章的介绍的内容。 一.控制内存分配 我们能够重载new和delete,但其实不是对new和delete的重载,只是对new和delete操作符后面的函数进行重载。 当我们使用一条new表…...

大数据深度学习卷积神经网络CNN:CNN结构、训练与优化一文全解

文章目录 大数据深度学习卷积神经网络CNN:CNN结构、训练与优化一文全解一、引言1.1 背景和重要性1.2 卷积神经网络概述 二、卷积神经网络层介绍2.1 卷积操作卷积核与特征映射卷积核大小多通道卷积 步长与填充步长填充 空洞卷积(Dilated Convolution&…...

RabbitMQ(九)死信队列

目录 一、简介1.1 定义1.2 何时进入死信队列?1.3 死信消息的变化1.4 死信队列的应用场景1.5 死信消息的生命周期 二、代码实现2.1 死信队列的配置步骤2.2 配置类2.3 配置文件2.4 生产者2.5 业务消费者2.6 死信消费者2.7 测试结果 三、总结四、补充4.1 启动报错 ineq…...

KEI5许可证没到期,编译却出现Error: C9555E: Failed to check out a license.问题解决

一、编译出现如下报错 二、检查一下许可证 三、许可证在许可日期内,故应该不是许可证的问题 四、检查一下编译器,我用的是这个,这几个编译器的区别其实我不太明白,但我把问题解决是选的这个 五、找到编译器的路径,去复…...

南京观海微电子----时序图绘制工具

Wavedrom 是一款功能强大且简单易用的文本转图表工具,被广泛应用于生成时序图、波形图等交互式波形。其特点在于使用简单的文本语法,使得开发人员能够以可视化的方式表示数字信号和时间序列数据。Wavedrom 的优势在于其高度灵活性和可扩展性,…...

Gin CORS 跨域请求资源共享与中间件

Gin CORS 跨域请求资源共享与中间件 文章目录 Gin CORS 跨域请求资源共享与中间件一、同源策略1.1 什么是浏览器的同源策略?1.2 同源策略判依据1.3 跨域问题三种解决方案 二、CORS:跨域资源共享简介(后端技术)三 CORS基本流程1.CORS请求分类2.基本流程 四、CORS两种…...

TS:.d.ts 文件 和 declare 的作用

1 declare 做外部声明1.1 声明外部类型1.2 声明外部模块1.2.1 解决引入资源模块报错1.2.2 跳过对第三方库的类型检查 1.3 声明外部变量1.4 声明外部命名空间(作用域) 2 .d.ts 文件做外部声明3 declare global {} 在模块中做外部声明 先说一下我对 .d.ts文…...

JavaScript-jQuery2-笔记

1.获取元素文本、属性、内部结构、表单中的值 获取标签中所夹的文本内容:text() 获取标签的属性值:prop(属性名) 获取表单元素的内容:如 文本框中的内容 val() 获取元素的内部html结构:html() 2.筛选选择器 筛选选择器&#xff1…...

设计模式之多线程版本的if------Balking模式

系列文章目录 设计模式之避免共享的设计模式Immutability(不变性)模式 设计模式之并发特定场景下的设计模式 Two-phase Termination(两阶段终止)模式 设计模式之避免共享的设计模式Copy-on-Write模式 设计模式之避免共享的设计模…...

mybatis核心配置文件介绍

mybatis核心配置文件 1. properties配置介绍 properties标签:加载外部的资源配置文件 ​ 属性:resource 指定要引入的配置文件路径 ​ 在核心配置文件中,通过:${key}方式引入外部配置文件的数据 jdbc.peroperties 的文件内容…...

Linux完全卸载Anaconda3和MiniConda3

如何安装Anaconda3和MiniConda3请看这篇文章: 安装Anaconda3和MiniConda3_minianaconda3-CSDN博客文章浏览阅读474次。MiniConda3官方版是一款优秀的Python环境管理软件。MiniConda3最新版只包含conda及其依赖项如果您更愿意拥有conda以及超过720个开源软件包&…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则&#xf…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

Kafka入门-生产者

生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...