IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

标签:Erlang

共 43 篇相关文章

IT 累计浏览 2,019

Erlang公平调度的误解

这篇讲的是Erlang引以为傲的“公平调度”哲学,在实际工程中可能并不像想象中那么完美。作者从Erlang虚拟机(BEAM)的时间片分配、抢占式调度说起,点明了它在云计算等场景下保障用户体验的初衷。 但文章的重点在于“祛魅”。作者指出,尽管Erlang的BIF、NIF等模块都在努力维护公平,但一些基础设计环节却可能无意中打破这种平衡。例如,消息队列的无保护单向队列结构,在极端负载下可能导致队列暴增和内存激增;而内存分配器在向系统申请内存时使用的锁,以及SMP架构下难以避免的锁竞争,都可能成为公平性的破坏者。文章最终总结,这些实现细节上的“坑”影响了Erlang在某些情况下的公平性表现,也解释了为何近期Erlang引入dirty scheduler等新机制来应对。 作者最后将视角拉高,提醒架构师需从上到下,在业务层面也进行“公平”设计,才能与系统哲学和谐统一。世界没有绝对公平,但理解其边界至关重要。

IT 累计浏览 1,704

erlang和其他语言读文件性能大比拼

这篇讲的是不同语言在处理大文件读取时的性能较量,主角是Erlang。作者从公司一次技术比武的真实案例出发——有同事用Erlang处理1.1GB文本的词频统计耗时55秒,而用C只需2.6秒,Java为3.2秒——引出了一个普遍疑问:Erlang读文件真的这么慢吗? 为了重新验证,作者准备了一个1GB的测试文件,详细对比了多种读取策略的性能。数据很有说服力:在单线程缓冲读取模式下,Erlang耗时0.322秒,与C语言的dd命令(0.264秒)处于同一量级;而启用多线程并发读取后,耗时缩短至0.214秒,性能甚至超越了C语言。但反例也很明显,如果以4KB小块读取,耗时会骤增至3.56秒,性能急剧下降。 文章揭示了性能差异背后的核心机制:Erlang的文件IO通过efile驱动实现,本质是轻量级的C封装,但每次操作都涉及“发消息→驱动执行→等待结果”三个阶段。这种设计在IO操作粒度过小时,消息传递开销会被放大,违背了Erlang“小消息,大计算”的原则。因此,性能的关键在于使用大块缓冲区读取,并充分利用异步线程池并行化IO,从而将Erlang的IO性能推到理论极限。

IT 累计浏览 2,330

Erlang集群全联通问题及解决方案

这篇讲的是Erlang集群一个看似“贴心”但可能致命的设计:默认全联通。 作者从Erlang集群节点加入时的“引荐”机制讲起,新节点会被介绍给所有现有节点,从而建立一个完全连接的网状拓扑。问题在于,这种全联通连接数(N*(N-1)/2)会随节点数增加而爆炸式增长,不仅消耗大量系统资源,更因定期的心跳检测引发网络风暴,严重制约集群规模。 解决这个问题的方案出人意料地简单:在节点启动参数中加入“-hidden”标志,使其成为“隐藏节点”。如此一来,节点间的连接不会被主动发布,从而有效避免了不必要的全联通。 不过,作者特别提醒了一个关键细节:隐藏节点的行为是“或”逻辑——只要通信双方中有一方是隐藏节点,global模块就不会进行自动引荐。这个特性在实际部署和故障排查时必须留意。文章最后指出,社区已开始正视并规避这一设计带来的问题,对从事大规模分布式Erlang开发的工程师来说,这个经验颇具价值。

IT 累计浏览 2,875

Erlang集群RPC通道拥塞问题及解决方案

当Erlang集群采用默认的全联通架构时,节点间通过RPC通道的密集调用可能引发严重的通道拥塞。文章从社区主流的分层服务架构出发,指出大量节点间消息流易导致dist端口忙,进而阻塞发送进程——由于RPC模块基于单进程gen_server,这种阻塞会直接拖累系统响应时间。 作者指出,这类问题可通过`erlang:system_monitor`的`busy_dist_port`事件及时感知,例如Riak系统便利用此机制告警。解决关键在于调整`dist_buf_busy_limit`参数:默认1MB的分布缓冲区上限可能不足,通过启动参数`+zdbbl`将其调大(如Riak案例中增至8MB),即可显著缓解阻塞、提升吞吐。文章结合监控实践与参数调优案例,提供了从问题定位到彻底解决的完整路径。

IT 累计浏览 6,065

gen_tcp发送缓冲区以及水位线问题分析

这篇讲的是一个线上 Erlang 服务器遇到的具体困惑:为什么按预期,客户端发送第 4 字节就该阻塞,实际上却到了第 7 字节才阻塞?作者从这个问题出发,深入剖析了 gen_tcp 的发送缓冲区与水位线(high_watermark/low_watermark)机制。 文章指出,理解的关键在于 ERTS 内部 port 的消息队列模型。发送数据(send)实质是向 port 发消息,当队列数据达到高水位线时,port 进入“忙碌”状态,调用者进程会被挂起,直到数据降至低水位线。文章结合参数设置详细推演了缓冲区与水位线的实际交互过程,并澄清了一个常见误解:高水位线更多是一个“软”限制,用于流程控制,而非精确的阻塞点;最终发送端的阻塞,很大程度上取决于接收端的 recv 行为。 作者通过源码与机制分析,将配置选项、内部数据流与观察到的行为串联起来,为理解 Erlang 网络编程中的流量控制提供了清晰的视角。

IT 累计浏览 3,425

gen_tcp如何限制封包大小

这篇讲的是如何在Erlang的TCP服务器(基于gen_tcp)中,从底层实现上来限制单个数据包的大小,以防范潜在的安全风险和资源耗尽问题。 文章从两种包接收模式入手。对于同步接收({active, false}),作者指出,当使用gen_tcp:recv时,实际上内核会为接收分配一个缓冲区。通过源码可以看到,这个缓冲区大小存在一个硬编码的上限:TCP_MAX_PACKET_SIZE(64MB),一旦请求超过此限制,就会直接返回ENOMEM错误。这可以看作是系统级的防线。 而对于更常见的异步消息投递({active, true}),控制则发生在协议解析层面。通过inet:setopts设置的packet_size选项,会在数据解析时被检查。文章通过追踪tcp_remain等函数的源码揭示了这一机制:当解析器发现包头声明的长度超过了设定的psize值,这个数据包就会被判定为无效。 核心巧妙之处在于,这两种机制一个在缓冲区分配时卡住,一个在协议解析时拦截,共同构成了对包大小的纵深防御。文章通过解读底层C驱动代码,让读者清晰地看到这些看似简单的应用层选项是如何被严格实现的,对于需要定制或深入理解Erlang网络编程的开发者来说,提供了扎实的内部视角。

IT 累计浏览 1,639

gen_tcp接收缓冲区易混淆概念纠正

这篇讲的是 Erlang/OTP 中 `gen_tcp` 模块几个缓冲区参数之间的常见混淆。很多开发者看到 `buffer`、`sndbuf` 和 `recbuf` 这三个选项时容易困惑:它们到底是什么关系?文档的简要说明往往不足以理清头绪。 作者选择直接深入 C 驱动层源码(`inet_drv.c`)来寻找答案。通过分析 `inet_set_opts` 函数的实现,文章揭示了核心事实:`sndbuf` 和 `recbuf` 设置的是内核 Socket 层的发送与接收缓冲区大小,这符合常规理解。而 `buffer` 选项则完全不同,它设置的其实是 Erlang VM 内部、应用层用于暂存从 Socket 读上来的原始数据的缓冲区大小提示(`desc->bufsz`)。 文章一个巧妙的发现是,源码中存在自动调整逻辑:当显式设置 `sndbuf` 或 `recbuf` 后,`buffer` 的值会被自动更新为两者中的较大值,以确保应用层缓冲区足够容纳内核传上来的数据。但其影响范围仅限于接收路径——因为发送数据可以利用队列,无需类似的额外缓冲。 通读全文,它厘清了一个关键结论:这三个参数分属不同层级,`buffer` 专注于控制 Erlang 侧接收数据的临时缓存大小,其默认值和动态扩容策略都围绕接收场景设计,而不直接影响内核的 Socket 缓冲区。对于需要精细调优 TCP 通信性能的开发者,理解这层区别至关重要。

IT 累计浏览 5,832

whatsapp深度使用Erlang有感

当很多人还在争论Erlang是否过于小众、能否胜任大规模商业系统时,WhatsApp用事实给出了响亮的回答。这篇文章分享了作者对WhatsApp深度使用Erlang技术栈的观察与思考。 文章的核心是一个极具说服力的案例:一个以Erlang为主的后台架构,支撑了数亿用户。作者通过引用WhatsApp主要开发者Rick Reed的分享,揭示了一个有趣的成长故事——这位有深厚系统性能背景的工程师,在2011年加入WhatsApp时竟是一位Erlang新手,但短短两三年后,他已能将Erlang的虚拟机、集群、Mnesia数据库等特性运用到极致。 文中列举的数据令人印象深刻:仅用两台服务器承载百万级的长连接、Mnesia数据库支撑起巨大的数据集,以及背后惊人的消息吞吐量。作者指出,Rick Reed的工作并非创造了全新的魔法,而是将Erlang已知的特性进行了系统化整理并坚决落地于商业系统,这是从理论到实践的巨大飞跃。 文章最终的结论很直接:任何系统开发到最后,都是在操作系统和硬件能力的边界内解决同类问题,Erlang为解决高并发、高可用等特定规模问题提供了坚实的基础。作者鼓励读者停止对它的怀疑,因为它在正确的场景下确实能带来巨大的价值。

IT 累计浏览 1,373

riak_sysmon使用和源码分析

这篇讲的是 riak_sysmon 这个 Erlang 监控工具的实战与原理拆解。它基于 Erlang VM 内置的 `system_monitor` BIF 函数,专注于捕获四类关键事件:进程堆内存过大、垃圾回收耗时过长、端口(文件或套接字)繁忙,以及节点间网络繁忙。 文章的核心是剖析其内部的两个进程协作。`riak_sysmon_filter` 进程扮演“过滤器”角色:它读取配置的阈值,启动底层监控,并对原始消息进行限流(例如每秒只上报前 N 条),避免告警风暴。过滤后的消息被通知给一个 `riak_sysmon_mgr` 的 `gen_event` 进程,由用户注册的 handler 来具体处理。 作者通过一个制造内存增长的 gen_server 示例,直观展示了当进程堆超过 `heap_word_limit` 后,系统如何触发并报告 `large_heap` 事件。这种 filter + event manager 的设计很巧妙:filter 解决了原生 `system_monitor` 消息洪泛和单一接收者的局限,而 event manager 则将事件处理解耦,允许灵活扩展。

IT 累计浏览 2,114

Skynet 的一些改进和进展

作者近期将重心完全放到了Skynet框架的开发与演进上。作为一款轻量级、高并发的游戏服务器框架,Skynet的持续改进一直是社区关注的焦点。 这篇内容并非泛泛而谈,而是聚焦于框架在实际迭代中发生的数项具体改进。作者从近期的工作出发,分享了在多个方向上的进展,其中既可能包含对核心调度模型的优化,也可能涉及关键模块的功能增强与性能提升。文章以第一手的开发视角,阐述了为何要做这些改动、设计思路如何,以及改进后的初步效果,为理解框架的演进脉络提供了直接线索。 对于关注游戏服务器与高并发系统架构的读者而言,这篇分享提供了宝贵的工程实践参考,展示了如何在一个成熟的开源框架上进行持续优化。

IT 累计浏览 1,512

ERLANG OTP源码分析 – code_server

这篇讲的是Erlang OTP中code_server模块的源码分析,重点探讨代码升级的基本原理。作者从sys模块升级的话题出发,深入到code和code_server模块的工作机制。code_server是Erl

IT 累计浏览 2,105

ERLANG OTP源码分析 – sys

这篇讲的是 Erlang OTP 中负责进程管理的基石模块——`sys` 的内部运作。作者直接从源码切入,剖析了它支撑两大核心功能(统计跟踪与热升级)的底层机制。 对于“跟踪”功能,文章揭示了 `sys` 如何巧妙地通过拦截目标进程的邮箱,插入控制消息(如 `get_statem_state`)来实现无侵入的状态查询,而非让进程自身实现复杂逻辑。而对更关键的“热升级”,则详细拆解了 `sys` 如何利用 `:sys.replace_code` 等回调,在进程执行间隙替换模块代码,并通过发送特殊字符消息来触发重载,保障了服务不中断。 文章的价值在于,它不止于说明“做什么”,更聚焦于“如何做到”。通过阅读这些实现细节——例如对消息队列的精妙操控与状态机的协作——读者能深刻理解 OTP 框架“让进程行为可管理”的设计哲学,这为在生产中进行更高级的监控与维护打下了坚实的基础。

IT 累计浏览 3,916

从Go看,语言设计(二)

这篇接着上一篇,深入探讨Go语言的设计哲学。作者从Go的核心设计原则出发,聚焦于其独特的并发模型(goroutine与channel)和精简的语法如何影响程序构建与团队协作。 文章将Go与传统多线程模型(如Java线程)进行了对比,指明Go的并发原语如何以更轻量级的方式,降低了并发编程的复杂度与资源开销。作者也提到了Go的快速编译、垃圾回收机制以及对组合优于继承的坚持,这些选择共同塑造了其清晰、高效的代码风格。 最终,文章阐述了这些设计决策的适用边界:Go尤其适合构建需要高并发、快速迭代和易于维护的网络服务与基础设施。它可能不适用于所有场景,但其明确的设计取舍为开发者提供了一种可靠且高效的工程化路径。

IT 累计浏览 2,859

开发笔记 : 热更新

作者在最近的工作中,着手为未来游戏服务器设计一套热更新系统。在游戏开发与运维中,热更新意味着无需停服即可替换业务逻辑或更新数据,这对保持游戏稳定性和玩家体验至关重要。 文章的核心围绕这套系统的设计展开。作者面临的主要背景问题是如何在复杂的游戏服务器架构中,安全、灵活地实现代码与数据的动态加载与替换。他/她的方案需要解决模块隔离、版本管理、资源加载以及与原生代码的互操作等挑战。从笔记来看,设计重点可能在于如何构建一个既能支持快速迭代、又不至于引入严重稳定性风险的机制。 最终,这篇笔记记录了一次从问题定义到方案设计的思考过程。它展示了热更新在游戏后端场景下的具体实践考量,对于同样面临服务端动态化需求的开发者来说,其中对技术选型和权衡的探讨提供了有价值的参考。

IT 累计浏览 2,651

ERLANG OTP源码分析 – gen_fsm

这篇文章从一个有趣的视角切入,对比分析了Erlang/OTP中`gen_fsm`与更为人熟知的`gen_server`模块。作者没有停留在概念表面,而是直接深入源码,揭示了两者在实现层面的核心差异。 关键的突破口在于进程状态的管理。`gen_server`中,进程主要通过一个统一的状态数据(`StateData`)来记住上下文。而`gen_fsm`则在递归循环中引入了一个额外的原子型状态名称(`StateName`)。正是这个`StateName`,像一个路由开关,决定了下一次循环时具体调用哪个处理函数,从而实现了状态的流转与切换。 另一个精妙的对比在于消息驱动模式。`gen_server`通常遵循经典的“请求-响应”客户端/服务器模型,由外部调用者发送请求消息。然而`gen_fsm`的许多转换中,发送关键消息的往往是状态机自身——例如,在完成某个处理后主动通知另一个进程。这体现了它作为自主状态机的设计哲学。 归根结底,这篇文章拆解了`gen_fsm`作为“带名称的递归”这一核心实现思路。理解这一点,也就明白了为何它天生适合建模那些具有明确离散状态、并需要根据状态自主执行不同逻辑的流程。

IT 累计浏览 3,618

ERLANG OTP源码分析 – gen_server

这篇讲的是深入Erlang OTP框架最核心的组件之一——gen_server。作者没有停留在API用法,而是直接扎进了lib/stdlib/src下的官方源码,试图从Erlang语言本身的级别,把gen_server循环、消息处理、状态机等核心模块的实现逻辑摊开来讲。 对于想写出更健壮Erlang程序的开发者来说,理解这些底层机制至关重要。文章不仅分析gen_server,还计划对比gen_fsm和supervisor的实现,这意味着能一次性理清OTP中几个关键行为模式的设计哲学与共同基础。作者还贴心地准备了完整的流程图,帮助读者将抽象的源码执行路径可视化,这种从代码到图形再到原理的拆解方式,对理解框架的巧妙封装和错误处理设计特别有帮助。 如果你在使用gen_server时曾有过“它到底是怎么做到的”这样的疑问,或者希望自己的并发设计能更贴近OTP的设计思想,那么从源码层面看透它的骨架与血肉,会是一个非常扎实的进阶路径。

IT 累计浏览 2,019

ERLANG OTP源码分析 – supervisor

这篇讲的是 Erlang OTP 框架中核心的 supervisor 进程。作者深入其源码,剖析了这个“监督者”的本质:它其实就是一个基于 gen_server 实现的系统进程,专门负责监控子进程的退出状态,并按照预设策略进行重启管理。 文章从 supervisor 的初始化过程切入,揭示了它如何解析监督规范(Supervisor Specification),构建起一颗监督树。重点分析了它的重启策略——“one_for_one”、“one_for_all”和“rest_for_one”在源码层面是如何区分和实现的,让抽象的策略概念变得具体可感。 最巧妙的部分在于,作者拆解了 supervisor 处理子进程退出的内部逻辑。它并非简单粗暴地重启,而是通过状态机管理子进程的运行状态,并在子进程异常退出时,根据“强度”(intensity)和“周期”(period)两个参数来判断是否触发重启上限,从而决定自身是该重启子进程还是优雅退出,避免了系统陷入无限重启的死循环。 通过阅读这篇源码分析,能理解 OTP 框架构建高可靠性应用的一个基石:它把进程管理的复杂逻辑封装在一个优雅、可配置的监督者角色中,让开发者能专注于业务进程本身。

IT 累计浏览 2,611

Erlang虚拟机基础设施dtrace探测点介绍和使用

这篇讲的是 Erlang 虚拟机(R15B01 版本)中新增的 dtrace 探测点支持。文章从生产环境运维的角度切入,指出在复杂分布式系统中定位性能瓶颈的传统手段往往不够用。作者详细解读了这次更新带来的关键能力:通过在虚拟机底层基础设施(如调度器、内存管理、垃圾回收)埋入 dtrace 探测点,开发者和运维人员现在能够像使用系统级的“探照灯”一样,实时、低开销地观察 Erlang VM 的内部运行状态。 文章进一步探讨了这些探测点的具体应用场景,例如如何追踪特定调度器的上下文切换、监控消息传递的延迟,或是分析垃圾回收事件对系统吞吐量的影响。核心亮点在于,这些能力直接内建于 BEAM 虚拟机,无需修改应用代码即可在已部署的生产系统中动态启用,极大地降低了性能诊断的门槛。对于需要保障高可用 Erlang 服务稳定性的团队来说,这提供了一套深入内核的实用工具箱。

IT 累计浏览 1,669

Erlang节点间ping失败原因分析

这篇讲的是在 Erlang/OTP 应用中,一个看似简单的节点间 `ping` 调用失败,却可能涉及从应用层到网络层的多重隐藏问题。 作者从一个典型的故障场景出发:两个 Erlang 节点部署在同一集群,程序调用 `net_adm:ping/1` 或 `erlang:connect_node/1` 时,意外返回 `pang` 或 `{error, {badrpc, ...}}`。文章没有停留在表面错误,而是层层剖析了可能的“坑”。它详细分析了从应用层捕获的 `{dist, no_connect}` 错误信息,如何指引排查方向,并最终将问题定位到了网络基础设施——特别是 EPMD(Erlang Port Mapper Daemon)所使用的 TCP 端口(默认 4369)以及节点间通信用到的动态端口范围,被防火墙规则意外阻断。 文章的实用价值在于,它不仅点明了根因,还提供了系统性的检查清单与解决方案。例如,确认 EPMD 进程运行状态、检查并调整服务器防火墙或安全组规则以放行相关端口。这对于在云环境或复杂网络架构下部署 Erlang 分布式系统的开发者来说,是一次清晰的实战排障指南。

IT 累计浏览 2,657

Riak Core说明

这篇讲的是Riak Core这个分布式系统编程库的核心设计思路。作者从构建一个高可用、可扩展的分布式应用(如类似亚马逊购物车的场景)所面临的挑战出发,引出了Riak Core所解决的关键问题:如何在部分节点故障时保证服务可用,以及如何高效地管理数据分片与负载均衡。 文章的重点剖析了Riak Core的两大核心机制。其一是“一致性哈希”与“虚拟节点”的结合,它允许将数据范围划分为大量小分片,并动态地将它们分配到物理节点上,当节点增减时只需少量数据迁移,实现了灵活的弹性伸缩。其二是基于“有限状态机”的协调框架,这使得开发者能以相对简单的方式,在不可靠的网络环境中实现复杂的分布式协调逻辑。 将它与Cassandra或DynamoDB等系统对比,Riak Core的独特之处在于它提供的是一个底层库而非完整的数据库。它把分布式系统的通用挑战(如数据复制、故障检测、成员管理)封装成可复用的组件,留给开发者充分的定制自由度。这使得它特别适合需要深度定制存储逻辑或网络层行为的项目,比如构建专属的分布式数据库或消息系统。 总而言之,这篇文章清晰地展示了如何通过精巧的抽象来分解分布式系统的复杂性。对于希望深入理解分布式计算模式,或者打算自己动手构建高可靠性服务的开发者来说,Riak Core的设计哲学提供了非常有价值的工程化视角。