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

后端

共 1964 篇文章

IT 2016-03-30 15:57:09 / 累计浏览 2,263

PHP扩展内如何定义类、方法?

这篇讲的是PHP扩展开发中的核心操作——如何在C语言层面定义一个PHP类。作者从PHP类的底层数据结构`zend_class_entry`入手,解释了这个结构体如何容纳类名、方法表、属性以及各类魔术方法。 文章的核心思路是,首先声明一个类入口指针(通常命名为`xxx_ce`),然后在模块初始化阶段(`PHP_MINIT_FUNCTION`)完成类的注册。具体步骤包括:声明方法实现、通过`zend_function_entry`数组绑定方法到类,最后调用`INIT_CLASS_ENTRY`和`zend_register_internal_class`完成类的注册。作者还分享了一个实用技巧:把类入口定义放在文件靠前位置,便于后续代码引用。 整篇文章从底层结构到具体实现代码,完整演示了从零开始在PHP扩展中“创建”一个类的过程。对于需要编写PHP扩展的开发者来说,这清晰地揭示了PHP面向对象特性在底层的实现起点。

本机暂存
IT 2016-03-30 13:02:30 / 累计浏览 1,846

玩转npm

这篇讲的是npm这个包管理工具的各种实用技巧。作者从日常使用出发,重点分享了安装、更新、发布这几个核心操作的“正确姿势”,比如用npm init -y快速生成package.json,通过-i、-S、-D等选项管理依赖,以及如何用npm version patch/minor/major优雅地更新版本号。 文章还对比了npm2和npm3在依赖处理上的关键差异。npm3最大的改进是将依赖模块扁平化存放,从而解决了Windows系统上因node_modules目录嵌套过深而导致的路径过长问题。虽然初期安装速度较慢,但后续版本已明显优化。作者建议大家及时更新到npm3,以获得更好的依赖管理体验和修复后的安装进度条显示。 对于想尝试最新库的开发者,文中介绍了如何使用npm dist-tags ls和npm outdated来查看版本信息并进行更新,整个流程非常清晰实用。

本机暂存
IT 2016-03-30 12:05:38 / 累计浏览 2,984

Java处理InterruptedException异常小结

这篇文章聚焦于Java开发中一个常见却容易被误用的异常处理场景:如何正确对待 `InterruptedException`。作者指出,许多开发者习惯性地“吞掉”这个异常,但这会损害程序响应中断、实现优雅取消的能力。 文章的核心在于阐明 `InterruptedException` 的特殊含义:当一个方法抛出此异常,它不仅是一个检查型异常,更是在声明自己是一个可被中断的阻塞方法。基于此,作者对比了几种关键的处理策略:其一是将异常直接向上抛出;其二是在进行必要的清理工作后重新抛出;其三,当在Runnable中无法抛出时,必须通过 `Thread.currentThread().interrupt()` 恢复中断状态。文中同时明确批判了仅仅记录日志或完全忽略的“生吞”做法。 通过代码示例,文章清晰地展示了正确与错误模式之间的分野,并解释了为何必须保留中断信号——因为中断是协作式的,且可能由线程池等机制多重消费。最终,作者建议通过轮询中断状态来实现灵活的、可取消的任务。整篇文章为处理这类并发问题提供了明确、实用的操作指南。

本机暂存
IT 2016-03-24 17:20:56 / 累计浏览 2,186

浅谈Web缓存

作者从Web性能优化的实践角度出发,深入探讨了缓存机制在提升网页加载速度中的关键作用。文章首先区分了数据库缓存、代理服务器缓存、CDN缓存和浏览器缓存等类型,并聚焦于浏览器缓存如何通过将资源保存在客户端来减少服务器请求、降低网络负荷。 核心内容详细解析了浏览器缓存的控制原理,重点对比了Cache-Control头部的多个指令:max-age(例如设置30天有效期)直接控制缓存时长,s-maxage则专用于CDN等共享缓存;public和private指令分别决定资源是否在多用户间共享或仅限私有使用;no-cache和no-store则涉及缓存验证和禁止策略。此外,文章对比了Expires、Last-modified和ETag的差异:Expires指定服务器端的具体过期时间点,但优先级低于Cache-Control;Last-modified基于文件最后修改时间进行验证,而ETag通过内容生成哈希字符串,更精确地检测资源变化,解决了Last-mod

本机暂存
IT 2016-03-23 15:50:52 / 累计浏览 2,364

协程与多任务调度

这篇讲的是如何用协程和 yield 手工打造一个协作式多任务调度系统。作者从现代计算机主流的抢占式多任务说起,自然地引出协程作为更轻量的协作式方案,并重点解决了一个关键问题:如何让协程真正“调度”起来。 文章的核心是实现一个调度器。它定义了任务类来封装协程,设计了调度器来管理任务队列。最巧妙的地方在于利用 yield 的“暂停-恢复”特性,实现了任务的交替执行,这就像一个简单的协作式中断。每当任务 yield,控制权就交还调度器,调度器再运行下一个任务。 更进一步,文章还演示了如何通过 yield 进行双向通信。任务可以 yield 一个系统调用对象,调度器捕获它并执行相应操作(如获取任务ID),再将结果 send 回协程。这模仿了操作系统与进程的交互模式,展示了协程调度的灵活性和控制能力。 对于想理解协程调度本质、不满足于仅会用 yield 关键字的开发者来说,这篇文章提供了一个从零构建的完整思路。它剥离了底层复杂性,让你看清协作式多任务调度器是如何用最基本的工具一点点搭建起来的。

本机暂存
IT 2016-03-23 15:30:23 / 累计浏览 2,244

学习设计API

这篇文章讲的是如何为前后端交互设计出清晰、可协作的API。它从API的基本定义出发,聚焦于一个实际问题:当团队协作时,混乱的接口定义会导致沟通成本激增。作者给出的核心方案是,团队必须先就返回值格式达成明确约定。 文章重点对比了两种主流的JSON返回值结构。第一种方式中,`errcode`字段可选,它的出现即意味着错误,并伴有可选的`msg`描述。成功则通常返回`items`数据或特定字段。第二种方式则要求`errcode`必须存在,并约定以`0`表示成功,其他值则为错误码。文章指出,这些错误码可以建立为公共码(如1001代表未登录),便于前端统一处理。 作者强调,JSON因其轻量和可扩展性已成为首选。通过建立这样的强约定,前端可以依据`errcode`进行明确的逻辑判断,而后端也能遵循规范返回数据。这种前置的、统一的接口设计,能够显著减少联调时的误解,让前后端协作更加顺畅,也使得接口本身更为健壮和可维护。

本机暂存
IT 2016-03-23 15:17:17 / 累计浏览 2,169

PHP empty和isset源码分析

作者从一个具体的PHP问题出发:`empty('00')` 到底返回 `true` 还是 `false`?他原本猜测 `empty()` 会将字符串 `'00'` 转换成数字进行判断,但觉得又不对。为了验证,他决定直接从源码一探究竟。 文章跟随作者的思路,首先发现 `empty()` 和 `isset()` 在操作码层面都调用了同一个函数 `ISSET_ISEMPTY_VAR`。顺藤摸瓜,最终定位到实际执行判断的核心函数是 `i_zend_is_true()`。 通过阅读这段精炼的源码,作者得出了明确的结论:`empty()` 在判断时并没有进行类型转换。对于字符串,它的判断逻辑非常直接——先检查字符串长度是否为0(即空字符串),若不是,则进一步检查是否长度为1且唯一字符为 `'0'`。只有这两种情况才会返回“空”(`true`),否则都返回非空(`false`)。 因此,对于 `'00'` 这样长度为2的字符串,它不满足上述任一条件,所以 `empty('00')` 的结果就是 `false`。而 `isset()` 则更简单,在变量未赋值时就直接返回了,根本不会走到这个判断逻辑。这个源码级的分析,清晰地解答了最初的那个疑问。

本机暂存
IT 2016-03-21 23:50:24 / 累计浏览 3,168

PHP内存耗尽错误分析

这篇讲的是一个让人困惑的PHP内存报错问题:明明报错信息显示“试图分配的内存(1.4MB)小于允许的上限(33.7MB)”,脚本却依然因内存耗尽而崩溃。作者从WordPress插件的实际报错出发,通过设计两组对比实验揭开了谜底。 实验首先确认了PHP的`memory_limit`机制本身工作正常。关键在于第二个实验:当设置15MB内存限制并连续加载两次10MB文件时,报错信息显示的是“试图分配10MB”而非累计的20MB。这揭示了根因——PHP报错时只提示引发最终崩溃的那一次内存申请量,而实际内存消耗是整个脚本运行期间所有操作的累加值。那个看起来“小得多”的数字,仅仅是压垮内存配额的“最后一根稻草”。 因此,直接调高`memory_limit`只是治标之策。更稳妥的方式是通过监控(例如在脚本关闭时记录`memory_get_usage`)来分析站点实际内存消耗模式,从而设定一个既安全又够用的合理阈值。这个案例很好地提醒我们,解读错误日志时,需要理解其背后的累计逻辑,避免被表面数字误导。

本机暂存
IT 2016-03-21 23:49:02 / 累计浏览 2,804

PHP输出缓冲及其应用

这篇讲的是PHP里一个常被忽略但挺实用的特性:输出缓冲。作者从计算机科学里“缓冲”这个基础概念切入,清晰区分了缓冲(写时用)与缓存(读时用)的差异,为理解PHP行为打下了基础。 核心内容围绕PHP的“ob_”系列函数展开。文章用简单代码演示了,为什么即使调用了sleep,浏览器也会一次性显示所有内容——秘密就在于PHP脚本执行完后才一次性发送数据。更实用的是,利用ob_start()、ob_get_contents()等函数,我们能在数据发送前“截获”并修改它,比如实现URL协议替换这种操作。 文章还深入探讨了php.ini中的output_buffering配置。有趣的是,即使关闭它,由于系统层面和浏览器的缓冲存在,也无法简单实现分段输出。最终,作者给出了一个结合flush()函数的可行方案,并延伸到一个实际应用:如何用缓冲机制实现简易的服务器推送(Comet),让内容像“挤牙膏”一样分批到达客户端。这让我们看到了缓冲技术从原理到实战的完整链条。

本机暂存
IT 2016-03-21 23:42:29 / 累计浏览 2,002

从 Nginx 默认不压缩 HTTP/1.0 说起

这篇讲的是,Nginx 默认只为 HTTP/1.1 启用 GZip 压缩,而对 HTTP/1.0 请求关闭压缩,这背后并非配置疏忽,而是 HTTP 协议特性在服务端实现中的一个关键权衡。 文章从移动端异常高比例的 HTTP/1.0 流量这一现象切入,深入剖析了原因。Nginx 默认采用即时压缩(On-The-Fly Compression)以优化首字节时间,但这导致无法预知响应大小,无法设置 Content-Length。在 HTTP/1.0 中,没有 HTTP/1.1 的 Transfer-Encoding: chunked 分块传输机制,客户端只能依靠 Content-Length 或断开连接来判断结束。因此,Nginx 为了在 HTTP/1.0 上尽可能保持持久连接(keep-alive),默认选择了放弃压缩。一旦启用 HTTP/1.0 压缩,Nginx 就只能返回 Connection: close 来结束传输。 文章通过对比测试验证了这一机制,并给出了务实建议:对于动态内容(如 PHP 输出的 HTML),因其本身无法预知大小,不妨启用 GZip 以节省流量;对于可预知大小的静态文件(JS、CSS),则建议将关键资源内联,非关键资源用外链并启用压缩,接受连接断开以换取流量节省。一个看似简单的 Nginx 配置,背后其实是 HTTP/1.0 与 1.1 在协议能力上的深刻差异。

本机暂存
IT 2016-03-21 14:07:28 / 累计浏览 2,063

探究 Node.js 中的 drain 事件

这篇讲的是 Node.js 中一个容易被忽视的事件——`drain`,作者从自己频繁看到却不知其所以然的使用场景出发,带着“什么时候触发”和“能用来干嘛”的疑问,进行了一番探究。 核心发现直指 `socket.write` 的返回值与底层“高水位线”(`highWaterMark`,默认 16KB)的关系:只有当写入的数据量累积超过这个阈值,`write` 才会返回 `false`,并在缓冲区被清空后触发 `drain` 事件。这解释了为什么简单的数据写入或高并发但数据处理极快的场景下,事件往往不会出现。 作者通过传输大文件的 HTTP 服务器实验,成功复现了事件触发,并揭示了它的核心作用——**用于实现流量控制,避免内存无限增长**。最佳实践是:当 `write` 返回 `false` 时暂停读取或生产数据的流,在 `drain` 事件触发后恢复,从而根据消费速度反向调节生产速度。 文章最后通过内存监控数据的对比,直观地验证了这种流控制策略在防止内存泄漏方面的必要性和有效性。

本机暂存
IT 2016-03-21 13:46:42 / 累计浏览 2,485

WordPress 插件工作原理剖析

这篇文章从一个资深开发者的视角出发,剖析了 WordPress 插件系统背后精巧的实现逻辑。作者首先拆解了插件的发现与管理过程:系统通过扫描特定目录并解析文件头部的注释块来获取插件列表和描述信息。 文章的核心在于揭示插件的“激活”与“工作”机制。它并非简单地将代码塞进系统,而是依托一套优雅的“钩子(Hook)”与“事件(Action)”体系。每个启用的插件在页面加载时都会被包含进来,并利用 `add_action` 等函数将自身功能注册到系统预定义的扩展点(如 `admin_head`、`publish_post`)上。当系统执行到对应环节时(通过 `do_action` 触发),便会调用所有已挂接的插件函数。 这种类似“插销”与“插座”的设计,使得功能扩展变得异常灵活且低侵入。无论是后台界面输出一段文字,还是添加一个管理菜单,插件只需关注自己要挂接的事件,无需修改核心代码。正是这种开放且规范的插件架构,成为了 WordPress 生态能够蓬勃发展的重要基石。

本机暂存
IT 2016-03-20 22:17:59 / 累计浏览 2,884

从Java和JavaScript来学习Haskell和Groovy(引子)

这篇讲的是作者如何打破两个根深蒂固的编程学习误区。他犀利地指出,“语言不重要”和“设计模式万能”这类观点在广义上是误导人的,尤其强调了编程语言绝不仅仅是语法工具,更是其背后范式与思维方式的载体。 作者以自身Java(静态)与JavaScript(动态)的背景为例,提出了一个清晰的学习路径:通过类比已知语言,来深刻理解新的编程范式。他瞄准了两个代表性目标:一是Groovy,为了探索动态语言强大的元编程能力;二是Haskell,为了领略纯粹函数式编程的严谨与独特魅力,比如模式匹配带来的优雅。 文章的后续计划也很明确,将从类型系统、元编程机制等维度,对这四门语言进行特性的横向比较。这种从熟悉到陌生、带着问题对比学习的方法,为想拓宽语言视野的开发者提供了一个扎实的起点。

本机暂存
IT 2016-03-20 22:02:49 / 累计浏览 3,585

分布式系统设计系列 -- 基本原理及高可用策略

这篇从分布式系统的基本构成讲起,将其拆解为节点、网络、存储三元组,并探讨了节点状态(有状态与无状态)及系统异常的基本分类。文章的核心在于剖析分布式环境与单节点系统的关键差异:例如,一次write()调用并不能保证对端成功接收数据;TCP协议虽可靠,但双方无法同时确认消息送达,这引出了经典的“拜占庭将军”问题。开发者必须面对多出的“超时”等第三种不可控状态,并将各种故障视为常态而非偶然。 在此基础上,文章重点解读了分布式系统的经典CAP理论(一致性、可用性、分区容忍性),阐明了强一致性与弱一致性的具体应用场景与权衡。最后,文章开始介绍应对这些挑战的设计策略,比如通过重试机制处理暂时性故障。对于希望构建健壮分布式系统的工程师而言,理解这些无法绕开的底层原理与固有约束,是进行可靠架构设计的第一步。

本机暂存
IT 2016-03-20 21:57:39 / 累计浏览 2,983

ZooKeeper编程指导

这篇讲的是 ZooKeeper 这个分布式协调服务的编程实战指南。作者从分布式应用开发者的角度出发,将 ZooKeeper 的核心概念与实际操作紧密结合,提供了一份从入门到避坑的完整路线图。 文章前半部分重点梳理了关键概念:比如类似文件系统的分层数据模型,以及其中每个“znode”节点可以携带数据和监听器(Watches)的特性;会话的生命周期管理,包括超时与断线重连的机制;还有确保分布式一致性的基础。这部分为理解 ZooKeeper 如何工作打下了必要的理论基础。 后半部分则深入实际编程场景,覆盖了客户端操作指南、常用语言绑定,以及简单的程序结构示例。特别值得一提的是,文章专门总结了“陷阱:常见问题和故障排查”,将分布式系统中常见的“羊群效应”、会话过期处理等难题和盘托出,实用性很强。 无论你是想了解 ZooKeeper 如何通过临时节点、顺序节点实现分布式锁、队列等协调服务,还是需要在生产环境中规避网络分区、会话管理带来的风险,这篇文章都从原理到细节给出了扎实的指引,是扎实理解并用好 ZooKeeper 不可多得的参考资料。

本机暂存
IT 2016-03-19 22:50:41 / 累计浏览 1,625

Linux内核参数调整

这篇讲的是如何通过调整一系列Linux内核参数,来解决高并发服务器性能瓶颈与稳定性问题。作者从实践出发,将原本分散的配置点系统地串联起来。 文章的核心在于将ulimit文件描述符限制提升到10万以上,这是支撑海量并发连接的基础。同时,详细拆解了几个关键网络参数的调整:比如增大socket缓存区以优化数据吞吐,设置tcp_tw_reuse和tcp_tw_recycle以加速服务重启时的端口回收,以及启用tcp_syncookies来防御SYN洪水攻击。对于进程间通信,也给出了消息队列的具体配额建议。 除了性能,文章还关注了调试与兼容性。它解释了如何开启并配置coredump,以便在程序崩溃时快速定位问题;并补充了FreeBSD/MacOS下的类似调整方法。整篇文章更像一份精心整理的“调优清单”,把影响高负载服务器的文件限制、网络栈、IPC和故障诊断等关键环节都梳理到了一起,给出了从原理到具体配置值的直接指导。

本机暂存
IT 2016-03-19 22:46:41 / 累计浏览 1,225

分布式选主 -- 利用Mysql ACID和Lease协议实现选主和高可用

在分布式系统中,选主和高可用是常见挑战。作者从实际生产场景出发,探讨了在对一致性要求并非极致严格、且允许短暂不可用的情况下,一种利用现有基础设施实现简易选主的方案。 针对ZooKeeper在节点存活不足半数时无法工作的限制,文章提出了一种基于MySQL ACID特性与Lease(租约)协议的替代设计。核心思路是利用一张MySQL表的唯一记录来维护全局Master信息,其事务特性保障了数据一致性。集群中的每个节点持有一个唯一ID,并按照约定的Lease周期进行心跳维护和竞选。 具体运作上,Master节点需定期向MySQL更新心跳,确保Lease未过期。其他Slave节点则定期检查:若发现数据库中Master的Lease已过期,便发起竞争写入自己作为新主。通过Lease机制,即使原Master因网络分区而失联,它也会在租期耗尽后自动停止服务,有效避免了“双主”脑裂问题。方案也坦诚指出了在数据库访问时延等情况下,可能存在极短时间窗口内的极限冲突,但可通过后续选举自动恢复。 该方案特别适用于需要一主一备、且对秒级故障可容忍的系统,它在ZooKeeper集群规模受限或希望降低依赖复杂度的场景中,提供了一个轻量且实用的工程化思路。

本机暂存
IT 2016-03-19 22:42:12 / 累计浏览 1,327

Yahoo的流计算引擎基准测试

这篇来自雅虎工程博客的文章,对他们团队开源的流计算基准测试(streaming-benchmarks)进行了详细解读。测试背景是雅虎生产环境中大规模使用Storm,但面对Flink、Spark Streaming等新兴框架的竞争,需要一份更贴近真实世界场景的性能对比报告。 基准测试设计了一个典型用例:从Kafka读取JSON事件,处理后写入Redis时间窗口计数。核心对比聚焦于三大主流引擎:Apache Storm、Apache Flink 和 Apache Spark Streaming。 测试的关键结论非常明确:Storm 0.10.0 和 Flink 0.10.1 均展现出亚秒级的低延迟特性,其中Storm在99%的百分位数上取得了最低的延迟表现,体现了其在实时性上的传统优势。Flink在保持低延迟的同时,也提供了较高的吞吐量。相比之下,Spark Streaming 1.5.1 能够支持很高的吞吐量,但代价是其端到端延迟明显高于前两者。 文章也坦诚地指出,早期版本的Flink基准测试代码存在一个调试残留问题,这提醒读者在参考任何性能数据时,都需要关注其测试条件与代码版本的严谨性。整个测试的价值在于,它并非空谈理论,而是基于一个与雅虎内部使用场景高度相似的开源基准,为不同流处理技术在延迟与吞吐量这对核心指标上的权衡,提供了直接的参考依据。

本机暂存
IT 2016-03-19 22:40:54 / 累计浏览 1,503

Akka简单性能分析

这篇讲的是如何把异步任务从应用服务器拆分出去时遇到的问题与选型。作者面临的需求是将异步处理独立部署,最初考虑了MQ配合线程池的传统方案,但发现这种方式在某些场景下仍需依赖共享变量(如HashMap或ThreadLocal),导致客户端阻塞,本质上并未完全摆脱多线程共享状态的并发隐患。 于是转向了更现代的Akka框架。文章梳理了Akka的核心特性:高吞吐(单机每秒千万级消息)、低内存占用(1GB内存可承载250万Actor)、弹性自愈与无中心设计。作者没有停留在理论介绍,而是用一个极简的例子——循环发送一千万条消息——做了直观的性能验证。通过VisualVM监控截图可以看出,Akka的调度器(dispatcher)仅凭三个线程就高效完成了海量异步消息的处理,展现了其轻量与高性能的特点。 整体来看,作者通过实际场景对比,清晰地指出了传统MQ方案在并发模型上的局限,并用可复现的测试案例证明了Akka在实现高性能异步处理时的优势,为架构选型提供了扎实的参考。

本机暂存
IT 2016-03-18 17:11:42 / 累计浏览 4,306

RabbitMQ与Redis队列对比

这篇技术文章聚焦于RabbitMQ与Redis作为消息队列时的核心差异。作者从可靠消费、发布确认、高可用性、持久化、负载均衡等关键维度展开对比,指出Redis在消息可靠性和系统监控方面需要较多自行实现,而RabbitMQ内置了完整的确认、持久化和监控机制。 具体来看,两者在可靠消费上差异明显:Redis消费失败可能导致消息丢失,而RabbitMQ能自动将失败消息重归队列。性能测试数据显示,在处理128Bytes到10K的不同数据体量时,两者出入队性能各有特点。文章最终提炼出适用场景:Redis更适合轻量级、高并发的即时计算或缓存场景,例如秒杀计数器;RabbitMQ则更适用于需要保证消息可靠传递的批量异步处理或任务负载均衡。 文章并未给出绝对结论,而是强调最终选择需结合系统对可靠性、监控能力和实际负载的具体要求来综合权衡。

本机暂存