您现在的位置:首页
--> 系统架构
常规的单机软件升级, 一般认为是一个原子操作, 也就是说, 软件会在"瞬间"完成升级, 即使不能在"瞬间"完成升级, 也要中断服务, 等升级完成后再提供服务.
对于需要中断服务的情况, 在分布式系统中是不能接受的. 同时, 分布式系统的升级永远不可能在"瞬间"完成. 因此, 分布式系统升级会面临一个长时间的中间态, 新旧版本的软件同时运行, 这就涉及到兼容性问题.
广义的可靠通信不限于计算机网络通信, 只要两个物体具有发送和接收能力, 或者两个物体之间有发送和接收动作, 均属于通信范畴. 例如人于人的声音对话, 身体语言等等. 可靠通信至少包括三项要求:
不丢包
不重复
完整性(原子性)
为了达到这三项要求, 对应有三条定理:
定理一(丢包定理): 确认和重传是解决丢包的问题唯一正确方法
定理二(去重定理): 排队(串行化)是解决去重问题的唯一正确方法
定理三(原子定理): 单点标记或者自校验是实现完整性(原子性)的唯一正确方法
有些同学可能对排队理论有怀疑, 表示搞一个全局位图(标记集合)也能解决去重问题. 如果深究, 判断标记和修改标记是独立的两步操作, 这两步操作就遇到去重问题, 也即, 对标记集合的操作本身也需要排队. 当然, CAS 是一种解决方案, 但 CAS 的实现内部本质也是排队.
• 初识前端智能化
虽然接触推荐算法是2009年,第一次组建人工智能团队却在2014年底。在经历了应用发行、广告、信息流和浏览器等业务,看到人工智能给业务带来的巨大价值,因参与其中而被彻底征服。那时起我就坚定认为,人工智能是继计算机以来最强大的力量,将会从每个角落彻底改变世界。
从32k猫和网页三剑客开始,一直热爱着前端,看着人工智能时代到来,萌发了帮助前端进入人工智能领域的愿望。2018年4月在前端委员会的共创会上,提出“前端智能化”方向。设计和规划直到推动这个方向落地,已经一年多。我在实践中发现,对前端智能化不理解、不会做,是阻碍前端工程师参与其中的最大障碍。
不理解主要是因为缺乏前端智能化的定义,大家不懂我在说什么、做什么,很多听过我分享的朋友都强烈要求我给大家提供一些学习建议和资料。曾尝试写过一些文档,但总觉得无法简单把前端智能化讲清楚,有必要把自己的实践经验和思考总结都梳理一下,供大家参考。
• 裁剪和空间管理
今天想谈谈游戏引擎中 Culling 模块。
当场景中的可渲染对象很多,而当前会被渲染的对象相较甚少的时候,我们通常会启用一个 culling 的过程。Culling 会想办法剔除一些当前不必渲染的对象,避免这些对象提交到 GPU ,让 GPU 承担剔除的过程。这样可以减少 CPU 到 GPU 的带宽。
最基本的 Culling 是用相机的视锥体和对象做一个相交测试,如果对象和视锥体不相交,则可判定它不必渲染;复杂的 Culling 还包括遮挡测试,如果一个对象完全被墙体挡住,那么也不必渲染。这篇只谈前者。
我们在开发软件的过程中,总有一些模块的需求是普遍的,除了自己开发,使用一个具备合适的 License 的开源项目也是个不错的选择。
在一个程序员的职业生涯中,总会有那么一个阶段,不太愿意使用别人开发的代码。如果不是受项目进度压力所迫,宁愿自己实现。这并非是因为相信自己总能做得更好,而是希望少受牵制,能够自由发挥。而且,写代码往往比理解代码更简单。整合多块不同团队开发的代码也更难保证项目各个部分的一致性。
• 内存的惰性初始化
我们公司上海的工作室的一个 MMO 项目做服务器压力测试。谈及优化,涉及到服务器中使用的 C 模块。他们把同一套 C++ 加上 namespace 编译了很多份,供多个服务使用。我很好奇,一般来说,Lua 的 C 模块是可以供多个 vm 共用的,并不需要实际链接很多份。仔细探究发现,原来这个代码中用到了一些全局对象(singleton 模式)。
我本能的觉得全局对象的设计中透着糟糕的味道,在逐个分析每个全局对象的必要性时,发现了一个有趣的东西:寻路模块。
寻路模块本身的实现是没有持久状态的,场景地图的障碍信息是独立出去的静态不变数据,全局共享,这是合理的设计。但是一个无状态的 pathfinding 对象却被实例化了很多份,供不同的服务独立使用。
Google 在十年前提出了一套名为 BeyondCorp 的零信任网络的安全方案。这套方案想要完整地实现还是有一定门槛的,在这种模型下,企业内网不再作为一个安全边界存在,相反即使在内网进行的访问也必须进行和外网同样的鉴权与访问控制。最终的改造方向是内网不再是一个特权网络,每个终端上部署的客户端证书主要是作为一项身份信息来使用。
随着 Web 应用复杂程度越来越高,以及 NodeJS 大规模投入生产环境,许多 Web 应用都会长时间运行, JavaScript 的内存管理显得更为重要。
JavaScript 具备自动回收垃圾的机制, 执行环境会负责管理代码在执行环境过程中使用的内存,将某些不再被使用的的变量所占用的内存释放掉,正因如此,大多数情况我们在前端开发的时候,并不是那么关注我们的页面用了多少内存,是否合理,需不需要优化。
JavaScript 基础中有很多重要的知识点是和内存相关的,比如深拷贝和浅拷贝、闭包、原型、引用数据类型和引用传递等。
最近我们在开发引擎时遇到一个和操作系统有关的问题,想了个巧妙地方法解决。我感觉挺有意思,值得记录一下。
在 ios 上,如果你的程序没能及时处理系统发过来的消息(比如触摸消息等),系统有机会判定你的程序出了问题,可能主动把进程杀掉。
完全自己编写的应用程序,固然可以把处理消息循环放在最高优先级。即使有大量耗时操作,也可以通过合理的安排代码,不让消息处理延后。但作为引擎,很难阻止使用者阻塞住主线程做一些耗时的操作。所以,通常我们会把窗口消息循环和业务逻辑分离,放到两个不同的线程中。这样,消息处理线程总能及时的处理系统消息。
近年来,互联网上安全事件频发,企业信息安全越来越受到重视,而IDC服务器安全又是纵深防御体系中的重要一环。保障IDC安全,常用的是基于主机型入侵检测系统Host-based Intrusion Detection System,即HIDS。在HIDS面对几十万台甚至上百万台规模的IDC环境时,系统架构该如何设计呢?复杂的服务器环境,网络环境,巨大的数据量给我们带来了哪些技术挑战呢?
经过长时间的思考和实践,最近一个多月,我们的 ECS 框架做了较大的调整。其中一部分工作已经在前一篇消息发布订阅机制中介绍,另一部分工作其实开展的更早,但因为我想多沉淀一段时间再写。到本周基本基本改动完毕,可以总结一下了。
ECS 框架几乎只在游戏开发领域提出,我认为这主要是因为目前只有在游戏领域,周期性的大量对象的状态变换才是主流行为。而在其它人机交互领域,响应外部事件才是主流。这是为何 System 在游戏领域如此重要的原因。
我们上周在游戏引擎上面的工作中遇到一些 bug ,涉及到过去的一些设计问题。维持讨论了几天解决该问题的方案。今天终于把最终方案确定了下来,值得做一个记录。
bug 出在游戏资源文件的转换上面。
游戏里用到的资源通常需要一个导入资源库的过程,例如你的原始贴图是一个 png 文件,但是引擎需要的是对应运行平台的压缩格式,windows 上是 dxt ,手机上是 ktx 等等。这个过程,在 Unity 等商业引擎中,是放在资源导入流程中。
我们的引擎把这个转换过程放在虚拟文件系统这个层次。这个设计决策是因为,我感觉统一导入资源是个痛点,用的人通常需要等待导入过程。Unity 用了 cache server 来解决这个痛点,但我认为 cache server 也存在一些设计问题 ,这个会在后面再展开一次。
我们在实践 ECS 框架时发现,之所以 ECS 的概念诞生于游戏领域,是因为游戏程序往往都在周期性的处理一批对象,进行运算,根据上个周期的状态得到下个周期的状态。而传统人机交互的应用则是响应型的:即一个外部请求触发一系列的业务运作。
如果你把游戏业务塞到响应型框架中,就会发现,不得不用时间去触发,业务响应的是 timer 。但这种情况下,timer 几乎没有携带任何状态,对单个 timer 的响应,是不可能做成无状态的:它本身就是整个游戏世界对上个状态的迭代。
这种情况下,响应式框架就很低效。
但是,如果框架完全做周期性自迭代,对外部输入事件的处理又远不如响应式框架灵活。
如果只是简单的操作输入还好,比如手柄,我们可以每帧把手柄各个按键的状态置入世界,那么 System 在不断迭代时,直接把这些状态当作世界中某个单例的状态就好了。但更复杂的输入就没那么好做了。
总有一些看不见的手在控制着软件的世界,就像CAP定理,第一次听到这个词竟然是在面试场合,真的是汗颜,回来之后数次尝试去理解这个定理。英文原文理解不透,中文介绍更是百花齐放百家争鸣,总是感觉一知半解。痛定思痛,决定好好研究一番,并用更加通俗的言语进行解释。
协程会在低CPU系统中获得不少易于编程的好处,但是当系统总CPU上去后就需要付出等价于甚至大于多线程编程中的代价。
实现分布式锁目前有三种流行方案,分别为基于数据库、Redis、Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开。我们来看下使用Zookeeper如何实现分布式锁。
交易系统中,对账是一个大问题。对账处理不好,不但需要花费大量的人力去处理账簿,还要承担很大的线上修改账簿的风险。
如果系统能自动化保证账簿每时每刻100%准确,不能说一劳永逸地解决了所有问题,至少解决了绝大部分问题。
如何对账,能时刻确保账簿100%准确?
断点单步跟踪的交互式调试器是软件开发史上的一项重大发明。但我认为,它和图形交互界面一样,都是用牺牲效率来降低学习门槛。本质上是一种极其低效的调试方法。
曾经写过一点关于代码评审(code review)的文章,比如这篇和这篇,现在觉得关于它的认识又有了不少更新。软件工程的技术和实践分成两部分,一部分是和书本知识一致的,大约占一半,这部分基本上在大学里就可以学,自学只要方法得当、刻苦努力也可是途径;但是第二部分来自于实际团队、经验,内容通常无法从书本当中获得,而且难说对错,不同的人和不同的经历造就了不同的认识。代码评审就是第二部分颇具槽点,可以大加讨论的典型。
虽然可以列举了不少 HDFS 的缺点,不过不得不承认,HDFS 仍旧是“计算存储融合”阵营的定海神针,甚至可以说,在大部分大数据玩家眼中,HDFS 才是正统。不过,我们也在 Hadapter 上看到了“计算存储分离”的新未来。目前 UMStor 团队正主力打造 Hadapter 2.0,希望能带来更好的兼容性以及更强的读写性能。
近3天十大热文
- [69] Twitter/微博客的学习摘要
- [65] IOS安全–浅谈关于IOS加固的几种方法
- [62] 如何拿下简短的域名
- [61] Oracle MTS模式下 进程地址与会话信
- [61] Go Reflect 性能
- [60] android 开发入门
- [58] 【社会化设计】自我(self)部分――欢迎区
- [57] 图书馆的世界纪录
- [57] 流程管理与用户研究
- [57] find命令的一点注意事项
赞助商广告