• 两千多个挺正常的,你 nginx 和 puma 是跑在同一台机器上的,nginx 每次转发请求实际上都会创建新的 TCP 连接,连接没有被复用后面就 timewait 了。如果并发量高的话确实会出问题,upstream 就会连不上,sourceIP:Port -> DesIp:Port 耗尽了。

    一般有几个解决方案:

    • 把可用随机端口调大 net.ipv4.ip_local_port_range
    • 后端多搞几个 upstream
    • Nginx 在 upstream 中用长连接
    • 开 tcp_tw_reuse 和时间戳 并且限制 timewait 的总数量,当触发上限时就会剔除旧的
    • nginx 和 puma 在同一台机器上时可以用 unix socket 避开 tcp 协议栈
  • 关于散列表的一些思考 at 2019年03月13日

    棒!

    可以继续解释一下哈希如何存放不同类型的 key 和 value

  • 18 年三月份刚来上海面的第一家就是薄荷,宝贵的经历啊。

    由于当时经验不足,也没有”证据“证明自己是谁 (底气很虚),然后被问了两个简单的工程应用问题,仓皇之下答的一塌糊涂。回去了解了一下就是简单的乐观锁应用和 feed 流的知识,听到 vincent 叹息了声”时间过的好快“(面试时),当时就意识到没戏了。面试前准备了许久了数据结构/算法/redis 底层/tcp/LB 等知识完全没被问到,当时也不太懂要引导面试官往自己熟悉的方向走,或者争取机会在其他方面证明自己。

    vincent 当时出于礼貌 (自己感觉当时该立即埋头出门的),带我逛了一下薄荷,个人感觉薄荷还是不错的!

    在经历了一系列类似的场景后,让我蓄积了大量动力去尝试写技术文章。认识到构建个人对外的沟通界面真是太重要了。

    还在路上的菜鸟在此表示感谢!

  • 从上帝视角看微服务 at 2019年03月05日

    描述系统混乱程度的经典概念。维基百科

  • 什么是 RPC? at 2019年01月31日

    角色扮演游戏?作为游戏盲又了解了一个概念···

  • 有个简单的方案:

    功能有这几个重点:

    • 竞拍,更新状态 (价格/截止时间等)
    • 到点后自动结束竞拍

    有两个对象:(名字随意取的)

    • 被竞拍物 (Goods)
    • 竞拍物状态 (GoodsStatus)

    每次有人出更高的价格,其实就是在更新 GoodsStatus,可以为每次出价都持久化一条数据,核心字段是价格截止时间竞拍人,并将 Goods 对应到最新的 GoodsStatus。

    每次竞拍都往 sidekiq 中插入一条定时任务,任务执行时检查当前 GoodsStatus 是否是最新的,不是的话直接退出。如果是最新的话就结束竞拍。

    用 sidekiq 的时候需要注意的是,sidekiq 取定时任务的时间点并不精准,可能会有数秒的误差 (可以配置),sidekiq 里面的任务本质上是一个个被取出处理的,要保证 sidekiq 的处理能力足够强,避免当竞拍任务过多时,任务延迟过多。

    竞拍应该还有个大盘,大盘在”轮询“的时候,也可以检查时间点,做结束竞拍的动作。

  • 文章不错,聊一点个人拙见。

    更喜欢将本文标题理解为:开发者如何变得更加优秀、能创造更大的价值?

    之所以这样理解,是因为很多人像我一样现在只是一个普通的开发者,但我相信很多年后,随着不断地积累,我们这帮人会慢慢从开发者的角色逐渐分化,变成一个复杂的综合体,也只有这样,才能够真正地实现更大的价值创造,分化的方向大概是:

    • 拥有产品经理的能力
    • 拥有项目经理的能力
    • 拥有 leader 的能力 (判断力、打造团队等)
    • 拥有开发者的能力
    • 拥有搞定人的能力
    • ···

    多年后,从开发大军中脱颖而出的人,都会拥有上面这些方向的素质,成为一个复合体。放眼望去,在大的团队或项目中产生核心价值的人,都是这种复合体。大部分节点上的螺丝钉都只是螺丝钉而已,当然这些螺丝钉的价值总和还是会非常大的,只不过均分到人头上就不见得了。

    不过,除了上面的分化,部分在技术圈备受崇敬的人还有另一种发展方向,就是成为能搞定高难度技术点的精英,他们会在相对单纯的技术环境下创造价值。不过大部分这种人才其实也具备产品经理和项目经理的能力。

    能吃透行业,在某个方向上有深耕的复合体,具有很大的单点价值。

    Matz 是开发者吗?不是,他是一名拥有开发能力的和项目管理能力的产品经理。他的核心价值在于设计了 Ruby 这款解放程序员的产品,并在带领开发者迭代 ruby 这个项目。

    马化腾是开发者吗?不是,他早期是拥有开发能力的产品经理,现在应该算是懂技术、产品、项目管理、市场···的 leader。

    ···

    一个人只有两只手,一天能写的代码量太有限,高价值的代码更有限。何况岁数变大,体能还在下降····

  • 说实话,这个代码我不能快速看懂。“冗长”点的代码更容易理解吧。文章里代码写的糙,将就点看😂

  • 从上帝视角看微服务 at 2019年01月02日

    技术的应用肯定是有很大价值的,从有些角度来看技术的应用比其本身更有价值。不过这个价值是大部分是由企业家/产品经理来引导,”架构师“来选型做抽象,剩下的那些价值就不大了,可替代性太强了,很多是框架下简单的重复而已。

  • 从上帝视角看微服务 at 2019年01月02日

    移动互联网催生了微服务这类的效率改善措施,业界有很非常多好的正面的有指导意义的微服务例子。有人浑水摸鱼,或者胡搞一通,以某项技术来获取利益,这也挺正常,每项技术出来都会被炒,不过这是人或做事方式的问题,和技术本身关系不大。

    ServiceMesh 由谁来做,也许对大多数码农来说没有区别。把大多数显得牛逼的项目中的开源组件拿掉,可以发现很多码农的核心价值趋近于零。不过这些牛逼的开源组件确实是部分码农搞出来的,总有人在做有挑战的事情。

  • 厉害!我差点用排列组合来换字符的位置穷举所有可能,再用 Base64 解密,想想真是蠢。你的答案给了我灵感。

  • Ant Design 错了吗? at 2018年12月26日

    简单复述一下自己对这件事的掌握:

    框架的核心开发者在代码中埋了一个逻辑:在圣诞期间会触发一个“彩蛋”,这个彩蛋的触发引起了广大人民群众的的抵触。进而在舆论上造成了一些风波。

    应该就是这么个事情。

    在我个人看来(个人观点),这件事情根本不应该被拿出来说。 发展到现在的“状况”的根本原因是,互联网的“羊群效应”和利用羊群效应挣钱的媒体的精彩表现。这个彩蛋给谁造成了伤害?给谁造成了损失?心理上?身体上?都没有。

    核心问题是该核心贡献者的“审美”和大众有些距离,如果是个优美的彩蛋,现在应该是一片掌声。

    对于至于软件代码质量和交付过程的批评,可能有些苛责阿里巴巴了。没有谁有义务在一个免费的开源项目上化大的精力和时间像保证商业产品质量那样去付出,商业社会这是不现实的。况且这个彩蛋真的是没有造成什么损害。(本人能力有限,非阿里职员,也没能在开源项目的贡献者,仅仅客观评价)

    至于那些在 github 上喷人的我就不在这里骂它们了,理解点开源精神都不会那样做。

    跳的高的,喊的厉害的,都不过是被操控的玩偶而已,你没看到有很多人在欣赏着自己的“操控能力”,另一方面在开心的数钱。

  • Ruby 2.6.0 已发布 at 2018年12月25日

    求教,为什么 JIT 比原来的堆栈式更快?该如何理解这个点呢

  • 拼写检查的四种实现 at 2018年12月25日

    把约束去掉,约束是根据场景人为加上去的。B 树也是一个多叉树,多叉树都能实现拼写检查,差别只是子节点的储存方式,Trie 是通过一个 hash 或数组来存,B 树根据范围条件来放(按某种顺序对字符排序),当然可能就不需要叶子了,但也会觉得就不是 B 树了。

    所以认为 B 树不适合或不行,我也是认同的。

  • 拼写检查的四种实现 at 2018年12月24日
    • Trie 能给出拼写建议,类似搜索引擎上搜索词提示,当然也能检查词汇是否存在。很节约储存空间。
    • HashTable 只能判断词汇是否存在,不能给出拼写建议
    • 布隆过滤器用多个哈希函数将结果映射在 bitmap 上,用来判断词汇是否存在,不能给出拼写建议。节约空间,速度也快。
    • B 树也能实现 trie 树的效果,且几乎没有差别(不限制子节点数量)。只不过 B 树为磁盘读取量身定做,可按操作系统页的大小来存数据,尽量减少磁盘 IO 次数,更加强大复杂。

    拼写检查用 Trie 有好处,因为在你还没写完某个词汇时,就可能判断出这个词汇不存在,不用写完了才告诉你。

  • 从上帝视角看微服务 at 2018年12月24日

    本质上为了 解耦/转移复杂度,为了提升效率。

    继续往下想想,为什么要用微服务?微服务本质上就是用来提升效率的,当年的 SOA,企业服务总线等等都是这样。它们都只是工具,手段而已。

    是为了使用微服务才提出 ServiceMesh,还是为了进一步提升效率而提出 ServiceMesh 呢?假设某一天不使用微服务了,ServiceMesh 依然有它的价值,不会受影响,只是可能会微调。

    我是在说 ServiceMesh 的理念,讨论的可能不是同一个。

  • 从上帝视角看微服务 at 2018年12月23日

    我觉得可以。微服务的理解有很多差别,我个人认为:微服务本质是在互联网时代提升产品交付效率的一种理念级的手段。

    往技术上扯就是当前的微服务架构,为当前互联网大型项目量身定做的一种方案,通过三个方面来提升效率:

    • 减熵。复杂度转移,大目标拆小,实践起来就是拆服务、ServiceMesh(将各个服务面临的网络复杂度转移给 ServiceMesh) 等等
    • 解耦。降低各个服务间的相互影响,使各自的工作可以并发且独立
    • 融入自动化,降低错误率,减少人力参与,提升产品的稳定性

    这一切本质上都是在提升效率,这是软件工程的主要目标之一吧,特别是前几天看了阿里提出的2-1-1(两周内交付 85% 的需求),感触尤其深。

    梳理完这几点,再回头看像 SpringCloud 全家桶那些东西,全部都是围绕上面三点来的。至于现在概念很火爆的 ServiceMesh,其实也是这样,只不过它似乎将解耦、复杂度转移、自动化一起同时实践了。门外汉看热闹,我就不继续瞎扯了。

  • 从上帝视角看微服务 at 2018年12月20日

    熵用来描述系统的混乱程度,是非常非常棒的一个概念。说大点,脑力劳动所做的一切都是在减熵,减熵能力越强,所产生的价值越大,剩下的都是随时可替换的体力活,这是大部分只重视应用的码农的最终归宿。

    自勉,希望多年以后我能真正在减熵的路上走好,而不是成为干体力活的“全栈工程师”。

  • 从上帝视角看微服务 at 2018年12月20日

    所以说是 递弱代偿,要量力而行,选择当下合适的方案,逐步演化。(希望后面我真正开始完备实践的时候,能不激进踏实地这么走。)

  • 从上帝视角看微服务 at 2018年12月14日

    文章关注本质,serviceMesh 只是一种解耦的方式而已,是微服务理念的部分实践,相信随着技术发展,还会出现更多的解耦方式。

  • 图解 Unicorn 工作原理 at 2018年12月07日

    golang 是这样的。

    • 本身很快,可以自己做 http 协议解析
    • 并发行好,accept 得到一个新连接后,可以丢到一个 gorouting 里面执行 socket 操作和业务逻辑
    • gorouting 本身很轻量,可以同时开非常多个,彼此之间可以实现并行执行

    到处都在处理 error,所以程序的健壮性可以得到保障。一般应用引入一个 http 包,就可以简单地实现应用服务器的功能了。

  • puts caller
    
  • 这种方式要判断当前连接是否处于事务中,重连后原连接持有的锁等信息会被丢掉,如果应用程序还在按照事务进行操作的话可能会出问题。 https://dalibornasevic.com/posts/77-auto-reconnect-for-activerecord-connections,建议楼主参考这个。

  • DHH 在 Railfconf2018 中很自豪的说: “我们不招聘 DBA,数据库不分库分表,只用一个主实例和其他 slave,怎么省事怎么来”

    其实就是 Basecamp 量小,业务不够复杂而已。

  • Ruby 的好朋友 -- jemalloc at 2018年11月08日

    这是用动态配置的方式让应用使用 jemalloc 吧,不想用时可以动态修改环境变量来控制。重新编译就没这个灵活性了。https://github.com/jemalloc/jemalloc/wiki/Getting-Started

  • 小规模数据可以这样:

    • 按照 created_at 分区 (partition)。例如三个月或一年一个区 (看具体情况),这个最简单。数据分布情况对应用透明,最近的查询会自动落到最新的分区上(得带上分区字段的查询条件)。
    • 按照某字段分表。例如,可以是 created_at,三个月或一年一个表 (看具体情况),分表的情况由应用自己维护。在查询时先按照 created_at 计算一下是在哪个表,然后就直接从对应表拿数据。
  • Ruby 的好朋友 -- jemalloc at 2018年11月04日

    我看到的解释和你接近。对于 jemalloc 持谨慎态度的人一般是两个原因:

    对于 glibc malloc,它为了减少多线程环境下,申请内存所产生的锁竞争,将可分配的 arena 数量放的比较大,这导致了严重的内存碎片,也是因为它本身不是为多线程环境而设计的。将 MALLOC_ARENA_MAX 调小,可以减轻这种情况,但是会使得线程间的竞争变得严重,内存碎片是降低了,但是性能会受影响。

  • Ruby 的好朋友 -- jemalloc at 2018年11月01日

    清洗是对于脏页 (dirty page) 进行的回收、合并等操作,是增加可用内存和减少碎片的操作,并不会有大量的内存移动之类的操作。具体的过程有点复杂,可以参考下附录中的这篇文章

  • Ruby 的好朋友 -- jemalloc at 2018年11月01日