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

后端

共 1964 篇文章

IT 2013-05-14 22:21:29 / 累计浏览 1,586

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 2013-05-13 14:03:01 / 累计浏览 3,424

对.net系统架构改造的一点经验和教训

这篇文章从作者在CSDN的亲身经历出发,探讨了从Windows .NET架构迁移到Linux平台的实战经验与教训。作者首先指出了一个普遍困境:许多依赖.NET的大型网站面临扩展瓶颈,但“去.NET化”的迁移风险极高,常因技术复杂性和内部团队政治斗争而失败。他以5173网站的失败案例为例,新旧团队并行、利益冲突导致迁移流产。 作者接手CSDN时,也面临.NET团队流失、系统脆弱的两难局面。他的核心方案是采取折衷策略:并非完全抛弃.NET,而是“去Windows化”。具体做法是保留.NET作为应用层,但将数据层、缓存、文件系统等全面迁移至Linux开源方案(如MySQL、Redis、Nginx),并用LVS实现负载均衡。这样既利用了.NET在应用层的开发效率,又通过Linux生态解决了扩展性和成本问题。 两年后的实践证明,这一策略成功实现了团队稳定、改造平顺、业务无影响且支持增强的多重目标。作者由此总结,架构改造远非单纯技术问题,必须妥善处理团队利益、业务平滑过渡与长期投入之间的关系。技术债务的背后,往往是技术被长期低估的管理文化问题。

本机暂存
IT 2013-05-13 13:58:16 / 累计浏览 5,162

用星际争霸讲解面向对象的概念

这篇讲的是如何用《星际争霸》的游戏单位来具象化理解面向对象编程的核心概念。作者从星际争霸的机枪兵单位出发,解释了每个机枪兵作为“对象”拥有独立的血量数据,同时共享攻击力等属性,这自然引出了“类”作为模板的概念。 文章进一步展开,用游戏机制来类比技术要点:单位的创建与销毁对应构造函数与析构函数,自动管理人口数;所有机枪兵共享的攻击力升级,清晰地演示了静态属性的作用。继承关系则通过兵营、坦克房等不同建筑共享“建筑”父类的飞行能力,但各自拥有独特的生产功能来体现。 最巧妙的是对访问控制的解释:如果攻击力属性是公开的,玩家就可能通过作弊修改它,而设为私有或保护后,只能通过特定方式升级,保证了游戏平衡。这些例子把 public、private、protected 的权限区别变得非常直观。整篇文章将抽象的OOP概念落地到玩家熟悉的游戏场景里,让知识理解变得轻松许多。

本机暂存
IT 2013-05-08 13:40:40 / 累计浏览 7,002

Linux grep命令用法

这篇讲的是如何用好Linux下强大的文本搜索工具grep。它远不止`grep pattern file`这么简单,文章系统梳理了grep从基础到高级的28个参数,把每个参数的用法、场景和注意事项都讲透了。 比如,除了常见的`-i`忽略大小写,它还深入讲解了如何用`-A`、`-B`和`-C`参数灵活地展示匹配行的上下文,这在分析日志时非常实用。对于二进制文件这种容易出错的情况,文章也明确了`-a`和`-I`参数如何改变grep的行为。从递归搜索目录(`-r`)到只显示文件名(`-l`),再到精确匹配单词(`-w`),文章用大量实例(如`grep -A 1 panda file`)展示了这些参数如何组合,解决实际的代码审查、日志过滤等问题。 文章像一本详尽的参数手册,却比手册更易读,因为它把每个抽象参数都落到了具体命令和输出结果上。无论你是刚接触grep的新手,还是想挖掘更多高级用法的老手,都能从中找到立即可用的技巧。

本机暂存
IT 2013-05-01 22:38:40 / 累计浏览 8,744

推荐一些socket工具,TCP、UDP调试、抓包工具

这篇讲的是作者从自己推荐HTTP调试工具的过往经验出发,引出了对Socket、TCP/UDP调试及抓包工具的系统推荐。作者作为一名“工具控”,不仅介绍了像Wireshark这样公认的网络抓包神器——它功能强大但偶尔会“自作聪明”地按端口号解码协议,也重点安利了一款国人开发的跨平台工具sokit,它能方便地模拟分包粘包,支持客户端、服务器、代理三种模式,不过作者也分享了一个在发送二进制数据包时因空格导致发送异常的小坑。 文章还列举了TCP/IP Builder、TCPView等其他几款各有侧重的工具。其中,TCPView尤其适合用于监控系统当前的TCP/UDP连接状态,甚至能帮助排查一些异常连接。作者最后也坦言,对于简单的调试需求,自己动手写脚本同样便捷。 这些工具基本覆盖了从数据包捕获、协议分析到连接状态监控的常见场景,适合在不同环节辅助开发者进行Socket通信的调试与排查。

本机暂存
IT 2013-05-01 22:34:51 / 累计浏览 5,043

HTTP 正向代理与反向代理

这篇讲的是代理技术中正向与反向的核心区别。作者从大家最熟悉的“翻墙”场景切入,解释了正向代理由客户端主动设置(比如配置VPN),用于突破访问限制或进行网络管控,就像通过一台能上网的“网管”机器连接外部世界。 而反向代理则完全不同,它部署在服务器端,用户毫无感知。文中特别指出,反向代理主要用于两件事:负载均衡,以及通过地理位置优化提升性能——比如电信用户通过代理服务器经内部光纤访问网通资源,速度会快得多。 文章用电信用户获取文件的对比例子,清晰说明了反向代理如何通过服务器端的资源整合来改善用户体验。最后总结道,两者最根本的差异在于:正向代理由客户端配置,反向代理则由服务端对服务器间通信进行代理,实现负载分配与访问加速。 文末提到作者参考了《HTTP权威指南》,其个人对“防火长城”作用的理解也为我们提供了一个观察网络代理不同角色的有趣视角。

本机暂存
IT 2013-05-01 22:31:58 / 累计浏览 4,505

Nginx 响应 400 的处理

作者从实际生产环境出发,剖析了Nginx返回400 Bad Request的几种隐蔽原因。除了常见的请求头过大,端口探测工具或LVS等负载均衡设备的健康检查也会导致大量400错误,日志里全是空行非常干扰排查。 文章深入分析了这类日志的特征:请求里连HTTP方法(如GET)或协议版本(HTTP/1.1)都没有,导致它们根本匹配不到任何常规的location规则。作者尝试用`if`指令过滤协议版本,但发现这无法阻止日志产生。 最终,他给出了一个简洁有效的方案:通过配置一个监听默认端口、主机名为空的`server`块,并直接关闭其访问日志(`access_log off`),将这些“无效”请求全部吸收并静默处理。这个方法从源头上解决了日志污染问题,干净利落。

本机暂存
IT 2013-05-01 22:29:00 / 累计浏览 5,922

计算机网络协议包头赏析-UDP

这篇讲的是网络协议中那位“低调的幕后英雄”——UDP。作者从它和TCP的兄弟关系切入,点明两者虽同处传输层,但性格迥异:UDP更像随性的文科生,不追求严格顺序,换取了简单与高效,因此在语音、视频、DNS查询等对延迟敏感但能容忍少量丢包的场景下大显身手。 文章的核心是“赏析”其精巧的8字节包头。与TCP冗长的20字节头部相比,UDP头只包含源/目的端口、长度和校验和,这直观体现了它的设计哲学:轻量化、低开销。作者还特别解释了“用户数据报长度”字段的含义,并引用了一个极其实用的结论:在以太网环境下,UDP数据载荷最好控制在1472字节以内,以避免IP分片带来的风险;而在复杂的互联网环境中,这个安全值则建议在548字节左右。 这些从底层协议特性推导出的具体数字建议,让这篇赏析不止停留在概念层面,为实际的网络编程提供了清晰的参考尺度。

本机暂存
IT 2013-05-01 22:27:35 / 累计浏览 1,303

PFIF网上寻人协议

这篇讲的是PFIF协议在灾难救援中的诞生与演进。从911事件时25个寻人网站各自为战,到卡特里娜飓风期间志愿者手动整合数据的艰难,催生了用标准格式统一信息交换的需求。PFIF协议通过为每条记录附加唯一ID,让不同站点的数据能自动合并与同步。 文章重点梳理了协议从1.1到1.4的关键迭代:1.2版为适应国际救援增加了国家代码、性别等字段;1.3版引入有效期以解决隐私与过期数据问题;1.4版则支持网络身份链接与多照片,进一步便于人员匹配。作者在四川地震后,观察到国内多家企业匆忙上线独立寻人平台,再次面临信息分散的旧问题,由此引出PFIF协议的现实意义。 核心观点是,在突发灾害面前,一个开放的技术标准能有效打破数据孤岛,让各方力量快速协同。文章通过历史案例与具体协议设计,说明了标准化如何将混乱的个体行动,转化为可扩展、可协作的救援网络。

本机暂存
IT 2013-05-01 18:41:08 / 累计浏览 5,983

DNS解析过程及DNS TTL值

这篇从DNS劫持和解析错误这些常见痛点出发,系统拆解了域名背后的运作机制。文章首先明确了全球仅13台根域名服务器的核心地位,任何域名解析都需从这里获取顶级索引。 接着,它用六个步骤清晰复现了从客户机发起请求到本地DNS服务器完成查询的全过程。其中,递归查询与迭代查询的差异被直观呈现:前者是本地DNS一路负责到底,后者则是逐级向下获取地址。 文章重点阐述了DNS TTL(生存时间)的概念——这条记录在各级DNS服务器中的缓存时长。针对域名解析IP变更后如何加速更新的问题,作者给出了一个实用的分步操作建议:先将TTL值调至最低(如60秒),等待各地缓存过期后再修改解析记录,最后恢复正常TTL。这种从理论到实践的过渡,让技术原理落到了具体操作层面。文末配合的全球根服务器分布图与解析流程图,也帮助读者建立了直观的理解。

本机暂存
IT 2013-05-01 18:07:24 / 累计浏览 2,882

Perl 实现 Flash 的 Socket Policy 服务器

这篇讲的是作者从一个误解出发,折腾出一个轻量解决方案的实践经历。起初,为了支持Flash P2P功能的测试,作者需要提供Socket策略文件。他最初错误地以为只需用HTTP服务器响应,直到被合作方提醒,才明白Flash Player的机制:在建立Socket连接前,它会主动向服务器的843端口发送一个 `` 字符串以请求策略文件。 理解了这个机制后,作者利用Perl的AnyEvent框架,仅用几分钟就实现了一个TCP服务器来响应这个请求。核心代码展示了AnyEvent::Handle的强大:它让服务器可以简洁地监听连接,并依据自定义规则(此处是收到特定字符串)进行读写。收到请求后,服务器直接返回预设的 `crossdomain.xml` 内容并主动断开连接,完美符合协议要求。作者也借此引出了AnyEvent在快速构建高性能TCP服务上的便利性。 文章最后,作者提到自己后来发现GitHub上已有类似实现,相当于“重复造了个轮子”。但整个过程清晰地记录了问题排查、机制理解和代码实现的完整链条,对需要处理类似Flash Socket安全策略的开发者,是一个直接而有用的参考。

本机暂存
IT 2013-05-01 17:44:21 / 累计浏览 5,767

whatsapp深度使用Erlang有感

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

本机暂存
IT 2013-05-01 17:42:26 / 累计浏览 1,243

从Moco谈程序库设计

这篇讲的是Moco这个Mock服务器框架背后的设计思考,核心问题是如何让一个程序库既强大又易用。 作者从Moco的两个基本任务切入:如何启停服务器,以及如何设置请求与响应。在启停服务器上,Moco没有让用户在每个测试中手动写try-finally来管理生命周期,而是通过一个`running`方法将细节封装,让接口保持简洁。 在设置请求响应时,作者非常强调DSL(领域特定语言)的价值。为了让API读起来像自然语言,Moco使用了`uri`、`method`这样的函数来包装对象创建,避免直接使用`new`打断表达的连贯性。同时,为了处理复杂的请求条件匹配,文章引入了“函数组合”的思路。在Java没有一等函数的情况下,Moco利用函数对象(functor)以及`and`、`or`运算符,让用户可以像搭积木一样组合多个匹配条件。 此外,文章还分享了利用类型系统进行安全设计的实践。例如,通过引入`ContentResource`子类型来区分需要与不需要Content Type的场景,让错误在编译期暴露。另一个巧妙之处是分离了公开接口`Setting`与内部实现`BaseSetting`,通过隐藏实现方法来防止用户误操作。 文章最后总结,好的程序库设计应当致力于简化用户接口、精心设计DSL、充分利用静态类型系统,并清晰地区分公开与内部接口。这些原则都是为了降低使用者的心智负担,提升开发体验。

本机暂存
IT 2013-05-01 17:40:52 / 累计浏览 5,471

简单理解Memcached的Slab Allocation

这篇讲的是Memcached如何用Slab Allocation机制管理内存。作者从内存分配的基本问题切入,解释了这套机制的核心:它预先将内存划分为大小固定的Page(默认1MB),再将每个Page切成相同尺寸的Chunk,相同尺寸的Chunk集合就构成了一个Slab。 这种预分配和分组的方式,能有效减少动态分配内存时产生的碎片。文章进一步指出,通过启动参数`-f`可以调整Growth Factor(默认1.25),它决定了相邻Slab中Chunk尺寸的倍增关系。不过,Slab Allocation并非完美:当实际数据尺寸与Chunk大小不匹配时,会产生内部碎片;当一个Slab无法被其Chunk大小整除,或是某些尺寸的Slab根本没被使用时,也会造成内存浪费。 文章通过结构图和工具截图,直观展示了Slab、Page与Chunk的关系,以及Growth Factor对不同Slab中Item尺寸的影响,清晰剖析了这个内存管理方案的利与弊。

本机暂存
IT 2013-05-01 17:38:27 / 累计浏览 3,724

“C++的数组不支持多态”?

这篇博客澄清了一个关于“C++数组不支持多态”的常见误解,作者从微博上的一场讨论切入。文章指出,争议的核心在于对C/C++内存布局的理解差异。当使用 `Base* p = new Derived[n]` 时,删除操作能否正确调用派生类析构函数,并非语言本身的缺陷,而是涉及指针类型转换后,数组步长与对象内存布局是否匹配的根本问题。 作者通过对比C和C++进行了深入分析。在C语言中,不同大小的结构体数组被强制转型会导致严重的内存访问越界和数据混乱,这纯粹是内存模型问题。但在C++中,由于编译器通常将虚函数表指针置于对象起始位置,并且在内存对齐规则下,只要派生类大小不小于基类,数组的物理步长就是安全的。文章通过具体的代码示例和内存调试,展示了在特定内存布局下(例如派生类大小不超过基类),上述C++代码反而能正确执行。 最终,文章揭示了所谓“坑”的本质:它混淆了C语言中数组指针转换的危险性和C++对象模型的特殊性。关键在于理解对象的内存布局,而非简单断言语言特性的有无。这提醒开发者,需要扎实掌握底层内存知识,才能准确区分语言设计、编译器实现和编码错误之间的边界。

本机暂存
IT 2013-05-01 17:36:13 / 累计浏览 3,086

使用 AnyEvent 来实现同一个端口跑二种服务

这篇讲的是一个非常实际的网络访问问题:当 Linode 的 SSH 端口(22)被 GFW 过滤后,如何利用仍然开放的 80 端口,让同一台服务器同时提供 HTTP 和 SSH 两种服务。作者从这个痛点出发,实现了一个基于 Perl AnyEvent 库的协议识别与转发代理。 核心方案在于对连接建立时发送的初始数据包进行嗅探。对于 HTTP 请求,开头通常包含“GET”、“POST”等关键字;而对于 SSH 连接,像 SecureCRT 或 Bitvise 这样的客户端会主动发送包含“SSH”字样的协议头。程序根据这个特征,将连接动态转发到本地对应的 80 或 22 端口后端服务。作者基于国外一个 Perl 实现进行了重写和封装,利用 AnyEvent 的事件循环特性来构建高性能的异步代理。 最终效果就是,作者现在浏览的网页和远程管理都是通过这同一个 80 端口完成的。这个方案虽然牺牲了使用 CDN 的可能性,但在特定网络环境下,提供了一种巧妙且有效的端口复用思路。

本机暂存
IT 2013-04-07 13:11:07 / 累计浏览 1,561

分享两个强符号,弱符号引起的编译问题

这篇文章从两个真实的编译问题出发,剖析了C++开发中一个隐蔽的“坑”:强符号与弱符号机制在debug和release模式下可能引发截然不同的结果。 作者分享了两个具体案例:一是模板类的静态函数特例化,在release模式下由于符号未被正确声明为弱符号而丢失,导致只执行了默认实现;二是在cpp文件内部定义的内联函数,release模式下因内联展开而在外部符号表中找不到定义。这些问题在debug时一切正常,却在上线前的关键阶段暴露。 文章指出,根因在于编译优化(release模式)改变了符号的属性与生成规则。随后,作者系统梳理了强符号与弱符号的定义、链接规则及其实际用途——弱符号允许重定义和可选覆盖,是实现类似“插件”式扩展的基础。最后,文章还以一个Zookeeper日志函数的弱符号改写为例,展示了如何利用这一特性优雅地解决实际工程问题。 这类问题的隐蔽性很强,只有深入理解底层的链接机制,才能在开发和构建阶段主动规避风险。

本机暂存
IT 2013-04-07 13:04:38 / 累计浏览 3,320

使用tcpdump搞定一个替换问题

这篇讲的是如何在不直接修改数据库的情况下,动态替换服务器渲染输出中的链接。作者面临的背景问题是代码混乱,无法快速定位哪些接口需要修改,暴力查找效率低下。 他找到了一个巧妙的解法:使用 `tcpdump` 抓取服务器的出口流量,并过滤包含问题链接的响应。为了进一步定位具体是哪个请求路径,文章给出了两个实用技巧:在PHP中利用 `auto_prepend_file` 或在Nginx中利用 `add_header`,为每个响应统一注入一个 `X-Request-URI` 头部。这样,在过滤出的内容中就能直观看到对应的地址,让替换工作变得精准。 虽然Nginx有专门的Substitution模块可以完成替换,但作者认为在本例中这种方案显得过重。最终,这个案例展示了一个道理:即便是简单的替换问题,选择合适的方法能极大影响效率,值得我们多思考一步。

本机暂存
IT 2013-04-06 23:17:19 / 累计浏览 6,240

移动互联网创业公司的服务器选择

这篇讲的是早期移动互联网团队,在预算和人力有限的情况下,如何务实选择服务器。作者从网络、硬件到软件,结合自己踩过的坑,给出了具体建议。 网络方面,他指出国内网络成本高,要先分析用户地域集中度来省钱,并强调机房在搜索引擎的“能见度”至关重要,否则用户手机根本访问不了。前期租用双线机房是更经济的选择。 硬件部分,他点明了几个容易被忽略但关键的细节:配内存条要匹配主板通道(比如三通道主板用三条相同内存)、务必检查RAID卡电池并开启缓存(对MySQL性能提升明显)、以及SSD应优先给数据库服务器使用,应用服务器则不需要。 软件选型上,他根据社区调查推荐CentOS,并特别提到移动互联网的协议选择。由于手机网络环境复杂,建议用HTTP协议并设置特定Header(如声明为JSON),来防止运营商劫持注入广告。 总的来说,这篇文章像一份为初创团队准备的、从基础设施到代码层面的实战避坑指南,每一条建议都直指小团队资源有限的痛点。

本机暂存
IT 2013-03-11 13:40:08 / 累计浏览 5,202

网络栈内存不足引发进程挂起问题

这篇讲的是高并发场景下,一个隐蔽但影响巨大的“坑”:当服务器需要支撑C1M(百万)级别连接时,TCP服务可能出现超时,甚至高达100ms的延迟。 问题的根源往往在于Linux内核的网络栈内存。文章开篇就点明,TCP的发送和接收缓冲区并非“想设多大就多大”,它们受到一系列sysctl参数(如net.ipv4.tcp_mem)的全局控制。这些内存是不可交换的物理内存,用一点少一点,系统默认值通常偏保守。在连接数暴涨时,可供分配的内存很快耗尽。 一旦内存不足,进程向socket写入数据时,内核就会将其挂起(阻塞),并调用 `sk_stream_wait_memory` 函数等待内存释放。文章直接展示了如何用SystemTap脚本精准定位这一过程——脚本输出会清晰地显示进程“blocked on full send buffer”和“recovered”的时间点,这就是导致应用层超时的直接证据。 最后,文章给出了行动指南:如果观测到了这种内存等待,就需要着手调整协议栈的内存限制参数。它通过一个具体的案例强调,面对复杂的网络问题,定量的工具与分析比猜测更可靠。

本机暂存