杜架的技术月刊(202210期)

杜架的技术月刊,主要关注计算机领域,记录本月看到的有价值的信息,主要包含:碎片化思考,阅读笔记分享,开源项目(软件)介绍。内容主题可能有极大的个人喜好偏向,努力做个输出的人,爱我所爱,想我所想,写我所写。

austin-schmid-qXkfoiTV6nY-unsplash (1).jpg
岁月无痕,流光难驻。用笔印证心灵的虹影,用心感悟时代的呼声,让过往的岁月留存,让看过的世界被更多的人知晓,爱我所爱,想我所想,写我所写,这便是创刊的情和志。

思考

做事

学习任何事务首先要学会基本的规则,然后才能知道什么时候去打破规则。这个原则放在很多地方都能适用
例如:如何成为一个厉害的程序员,刚入行,大佬会告诉你先按这样写,而这样就是规则,新人最容易创新,但也最容易出错,往往忽略规则,忽略约定成俗,你的视野决定了你看问题的高度,当你掌握基本规则,那么我相信你的很多新奇的想法就可以实现了。为什么大佬告诉你程序员要懂设计原则设计模式,我想这个应该算是程序员世界的规则吧。

世界的本质是数学

人类孜孜不倦的探索着世界的本质,或者说一个物体的本质,原子核,质子,电子,夸克,这些都可以用数学公式来解释,人的认知能力是有限的,想象力也只局限于三维世界,这些都可以用数学来描述,数学可以让我们看的更远,看到一些我们无法想象的事。三个苹果+两个苹果等于五个苹果,三个桃+两个桃等于五个桃子,抛开外在干扰,3+2=5,这个是本质。外在因素再变化,这个数学本质没有变化,所以我想说未来对世界的探索可能还会有新的发展,新的变化,但数学一定是永恒的。

团队工程经验

一份团队工程经验(新人指导)可以极大的提升团队协作能力,代码质量,生产效率等等方面,而不是手把手教每一个新人。这个其实是做事的第一个阶段,经验文档化,方案演进化。整理了一个思维图:
image.png

笔记

虚拟线程的意义

Java 高并发革命!JDK19 新特性——虚拟线程(Virtual Threads)

这里的虚拟线程是指 JDK19 新特性(Virtual Threads), 虚拟线程并不是更快的线程ーー它们运行代码的速度并不比平台线程快。它们的存在是为了 提供规模(更高的吞吐量)而不是速度(更低的延迟) 。它们的数量可能比平台线程多得多,因此根据 Little’s Law,它们 能够实现更高吞吐量所需的更高并发性
换句话说,虚拟线程可以显著提高应用程序的吞吐量,在如下情况时:

  • 并发任务的数量很多(超过几千个)
  • 工作负载不受 CPU 限制,因为在这种情况下,比处理器核心拥有更多的线程并不能提高吞吐量

结构化并发

Java 19 发布,Loom 怎么解决 Java 的并发模型缺陷?

虚拟线程解决某些场景吞吐量问题,结构化并发来解决复杂并发编写复杂性问题。
如下为结构化并发 StructuredTaskScope.ShutdownOnFailure 使用案例

1
2
3
4
5
6
7
8
9
10
11
12
13
void handleOrder() throws ExecutionException, InterruptedException {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<Integer> inventory = scope.fork(() -> updateInventory());
Future<Integer> order = scope.fork(() -> updateOrder());

scope.join(); // Join both forks
scope.throwIfFailed(); // ... and propagate errors

// Here, both forks have succeeded, so compose their results
System.out.println("Inventory " + inventory.resultNow() + " updated for order " + order.resultNow());
}
}

  • 基于短路的错误处理:如果 updateInventory()或 updateOrder()失败,另一个将被取消,除非它已经完成。这是由 ShutdownOnFailure()实现的取消策略来管理的,我们还可以使用其他策略。
  • 取消传播:如果运行 handleOrder()的线程在调用 join()之前或调用过程中被中断的话,当该线程退出作用域时,两个分支(fork)都会被自动取消。
  • 可观察性:线程转储文件将清楚地显示任务层次,运行 updateInventory()和 updateOrder()的线程被显示为作用域的子线程。

架构

关于架构的一些理解

  • 架构师永远要在 Reuse 高耦合和 Repeat 低耦合之间做一个权衡。这种权衡就是 Reuse 和 Repeat 的中庸之道。
  • 重复能够解耦。

根据企业中职责的划分,我们往往可以将软件架构,及关联的架构师划分为以下几类:

  • 业务架构/解决方案架构:核心是解决业务带来的系统复杂性,了解客户/业务方的痛点,项目定义,现有环境;梳理高阶需求和非功能性需求,进行问题域划分与领域建模等工作;沟通,方案建议,多次迭代,交付总体架构。
  • 应用架构:根据业务场景的需要,设计应用的层次结构,制定应用规范、定义接口和数据交互协议等。并尽量将应用的复杂度控制在一个可以接受的水平,从而在快速的支撑业务发展的同时,在保证系统的可用性和可维护性的同时,确保应用满足非功能属性要求(性能、安全、稳定性等)。
  • 数据架构:专注于构建数据中台,统一数据定义规范,标准化数据表达,形成有效易维护的数据资产。打造统一的大数据处理平台,包括数据可视化运营平台、数据共享平台、数据权限管理平台等。
  • 中间件架构:专注于中间件系统的构建,需要解决服务器负载,分布式服务的注册和发现,消息系统,缓存系统,分布式数据库等问题,同时架构师要在 CAP 之间进行权衡。
  • 运维架构:负责运维系统的规划、选型、部署上线,建立规范化的运维体系。
  • 物理架构:物理架构关注软件元件是如何放到硬件上的,专注于基础设施,某种软硬件体系,甚至云平台,包括机房搭建、网络拓扑结构,网络分流器、代理服务器、Web 服务器、应用服务器、报表服务器、整合服务器、存储服务器和主机等。

关于应用架构,推荐大家阅读 COLA 4.0:应用架构的最佳实践应用架构就是要解决代码要如何被组织的问题,希望给阅读的你带来一些帮助。我会更简单的将架构分为:应用架构,业务架构,技术架构。

架构设计原则

原则是指导思想,就像听党指挥能打胜仗一样,需要熟记于心,做方案评估时挨个对照,看是否满足,以下基本原则很是认可。

  • 合适优于领先
  • 演进优于快成
  • 简单优于复杂

老杨说

老杨说

一件事情:
你必须把它抽象化,
因为抽象化以后才可以简化,
简化后才可以标准化,
标准化的事情才能自动化,
自动化的事情才能规模化。

数据湖 vs 数据仓库

7000 字,详解湖仓一体架构!


什么是湖仓一体化?
湖仓一体是一种结合了数据湖和数据仓库优势的新范式,在用于数据湖的低成本存储上,实现与数据仓库中类似的数据结构和数据管理功能。“湖仓一体”并不等同于“数据湖”+“数据仓”,这是一个极大的误区

有人把“湖仓一体”做了形象的比喻,就好像湖边搭建了很多小房子,有的可以负责数据分析,有的来运转机器学习,有的来检索音视频等等,而这些数据源流,都可以从数据湖里轻松取得。

HBase 实现 TopN

一款视频 APP 的播放行为统计数据,需要查询每天每个视频类型播放量 TopN 的视频(播放量从高到低排序),如何设计 rowkey?

需求分析: 首先我们存储的数据是每个视频在某天的播放量统计数据,我们读取数据的场景是获取某天某个视频类型的播放量 TopN(可以是 Top10、Top100、Top200 等)视频列表,那么我们的设计思路可以是将 RowKey 分为三段,第一段存储播放日期,第二段存放视频类型,第三段存储倒排的播放量。这样在检索时,我们可以设置过滤 RowKey 前缀是播放日期+视频类型,然后提取前 N 条记录。

参考示例: key_day + content_type + (99999999-play_num)

说明: key_day 是播放日期,content_type 是视频类型,play_num 是视频的播放量,用(9999999999-play_num)是为了反转排序,将播放量大的视频排在前面。需要注意的是,RowKey 每段的长度一定要保持一致,如果长度不够,需要用其他字符补足位数。
这样设计 rowkey 就可以满足每天每个视频类型的 TopN 查询,查询的时候要配合前缀过滤器 PrefixFilter 进行升序排序,得到的就是一个播放量倒排的视频列表。

个人成长模型

一个程序员的成长之路

  • 第一阶段,一技之长。就是深耕你的专业技能,你的专业技术。
  • 第二阶段,独立做事。当你的一技之长达到一定深度的时候,需要开始思考如何独立做事。
  • 第三阶段,拥有事业。选择一份使命,带领团队实现它。

fdcon2018.023.jpeg

gRPC vs REST

作为两种 api 风格,在微服务领域都有各自存在的意义和价值,目前来说 REST 还是业界主流。简单对比一下,方便未来选型。

特点 gRPC REST
Http1.1 vs Http2 遵循基于 Http2 的客户端-响应通信模型,支持流通信和双向流 一般遵循 Http1.1 的请求-响应通知模型
浏览器支持 有限支持,gRPC 需要 gRPC-web 和一个代理层来处理 Http1.1 和 Http2 之间的转换 均支持
负载数据结构 默认使用 Protocol Buffers 来序列化负载数据 主要依赖 json 和 xml 来交换数据
应用场景 一般局限在内部/私有系统
对性能有极致追求 内部/外部系统
优点 性能不错,跨语言,双工流 简单,可读,运维方便,可观策性强
缺点 需要服务注册与发现,重客户端,可维护性差,版本性差 性能较 gRPC 差

借用同事的一句话总结:通常南北流量走 REST,东西走 RPC(南北就是内部和外部的交互,东西就是纯内部的交互)。

推荐文章

  1. 甲骨文新微服务框架 Helidon Níma:使用虚拟线程实现高性能
  2. 信心是最大的资产
  3. COLA 4.0:应用架构的最佳实践
  4. 如何减少软件设计和实现之间鸿沟
  5. 软件架构万字漫谈:业务架构、应用架构与云基础架构
  6. 东方证券:我们如何成功实施微服务
  7. 5 千字深度解析 B 端产品的美即适用效应
  8. Culture Docs: Facebook, Netflix and Valve

开源项目(软件)

Event Ruler

https://github.com/aws/event-ruler
亚马逊云科技最近宣布开源Event Ruler,一个管理 EventBridge 路由规则的组件。对于需要几乎实时为任意数量事件匹配大量模式、策略或表达式的开发人员来说,这个项目是一个值得考虑的新选择。

Event Ruler 使用 Java 开发,提供了用于声明模式匹配规则、显示数据记录(事件)和大规模查找匹配每个事件规则的 API,帮助开发人员构建出以每秒几十万个事件的速度匹配任意数量规则与事件的应用程序。

事件和规则都是 JSON 对象,规则还可以通过内置的查询语言(可用于描述自定义匹配模式)来表示。
例如事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"version": "0",
"id": "ddddd4-aaaa-7777-4444-345dd43cc333",
"detail-type": "EC2 Instance State-change Notification",
"source": "aws.ec2",
"account": "012345679012",
"time": "2017-10-02T16:24:49Z",
"region": "us-east-1",
"resources": [
"arn:aws:ec2:us-east-1:123456789012:instance/i-000000aaaaaa00000"
],
"detail": {
"c-count": 5,
"d-count": 3,
"x-limit": 301.8,
"source-ip": "10.0.0.33",
"instance-id": "i-000000aaaaaa00000",
"state": "running"
}
}

规则:Prefix matching

1
2
3
{
"time": [ { "prefix": "2017-10-02" } ]
}

它还包含了很多匹配模式,具体信息详见项目介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
public static ValuePatterns exactMatch(final String value);
public static ValuePatterns prefixMatch(final String prefix);
public static ValuePatterns suffixMatch(final String suffix);
public static ValuePatterns equalsIgnoreCaseMatch(final String value);
public static ValuePatterns wildcardMatch(final String value);
public static AnythingBut anythingButMatch(final String anythingBut);
public static AnythingBut anythingButPrefix(final String prefix);
public static ValuePatterns numericEquals(final double val);
public static Range lessThan(final double val);
public static Range lessThanOrEqualTo(final double val);
public static Range greaterThan(final double val);
public static Range greaterThanOrEqualTo(final double val);
public static Range between(final double bottom, final boolean openBottom, final double top, final boolean openTop);

我们有个项目 EventHub,其中也升级到事件匹配,功能上基本类似,但我们做的比较粗糙,性能也很差。目前该项目还未发布到 maven 中央仓库,未来有机会,可以将我们这部分转为使用 event ruler。
总结:Event Ruler 是一个提供 json 规则匹配的 java sdk(类库)。

PowerToys

微软出品,已经使用两年多了,作为 windows 增强工具集,必备软件。我常用来管理全局快捷键,分屏,文件预览,查找鼠标等功能。
https://github.com/microsoft/PowerToys
搜狗截图20221010153106.png

windows clock

image.png
windows 自带的 clock 可以用来作为简洁版番茄闹钟,番茄闹钟的好处不必多说,在工作效率上会有一定的提升,可以让我们专注工作,注意休息,休息的时候可以用来站立,喝水等。

idea 插件

image.png

美食

相信美食是不分职业的,技术群体爱吃美食的也大有人在,所以我增加一个飞行主题:美食。是我在这个月吃到的,觉得推荐的,或者有想分享的。

烧饼

作为一个来自晋南资深烧饼爱好者,所有美食里烧饼绝对能放在首位,是那种刻在记忆深处的爱,它的味道算不上多姿多彩,油盐面,纯粹的美食,一定对得起肚子。烧饼,又名火烧,顾名思义碳火烧的艺术。味蕾最深处的记忆是劳作后吃着刚出炉的烧饼,顶饱,那种吞咽感也有极大的满足感。
最爱的是晋南油酥饼,在碳火的炙烤下,外焦里嫩。它的大概做法是油,茴香,盐在内部分层,一层层的卷,恰到好处的按压,最后放在类似汽油桶的炉子上先在外层烙,再放内部烧烤。晋南做饼最出名的是稷山饼。大致有:圆油酥饼,三角油酥饼,月牙饼。把圆形和三角单独分开是因为做法和味道还是有一些区别,只是很久没有吃到家乡的饼了。
切记:刚出炉 5 分钟内味道最佳
微信图片_20221010145229.jpg

微信图片_20221010145234.jpg

京津芝麻烧饼
最近在西安尝到一家还不错的烧饼,大众点评可以搜到。排队人也挺多,在我的 10 分制打分系统里,我给打 7 分,比及格线高一点,没有我第一次在北京吃的那么惊艳!但也值得推荐!
微信图片_20221010145219.jpg
黄桥烧饼
很脆,不过感觉没有京津芝麻烧饼好吃。
image.png

桃酥

泸溪河的桃酥,值得推荐,吃一口会掉渣。
微信图片_20221010145225.jpg

说明

月刊相关信息:

🙌 如果你阅读到这里,相信我们一定是同道中人,有任何想法,欢迎私聊我,微信号:trumandu007
💡 如果你也是在西安地区从事 IT 相关工作,欢迎私信加入我建的 『西安 IT 技术圈』微信群,我们是一个什么样的群体? 为什么要做『西安 IT 技术圈』
👬🏻 朋友,都看到这了,确定不关注一下么 👇

参考资料

  1. Java 高并发革命!JDK19 新特性——虚拟线程(Virtual Threads)
  2. Java 19 发布,Loom 怎么解决 Java 的并发模型缺陷?
  3. 老杨说
  4. 7000 字,详解湖仓一体架构!
  5. 一个程序员的成长之路