Morden Javascript Tutorial Chapter 1 - An Introduction

An Introduction to JavaScript Let’s see what’s so special about JavaScript, what we can achieve with it, and what other technologies play well with it. Why is it call JavaScript? JavaScript initially called “Live Script”. But Java was popular at that time, so it was decided that positioning a new language as a “younger brother” of Java would help. But as it evolved, JavaScript became a fully independent language with its won specification called ECMAScript, and now it has no relation to Java at all. ...

September 15, 2025 · 3 min · 622 words · Starslayerx

Service Implementation Patterns for Microservice

Hexagonal architectures for microservices 微服务的六边形架构 六边形架构 Hexagonal Architecture 也被称为接口与适配器架构 Prots and Adapters Architecture, 是一种软件架构模式, 旨在实现高内聚、低耦合和可测试性的应用程序设计. 该架构由 Alistair Cockburn 发明, 他是敏捷宣言的签署者之一. 该架构是说, 在任何应用程序中, 都有一个核心逻辑实现服务, 并且在该服务周围"附加"上一些接口, 用于核心与外部组件的交互. 例如, 一个 web API 就是一个适配器 adapter, 帮助核心逻辑与互联网上的 web 客户端交流. 对于数据库也是一样的, 其也是一个外部组件, 帮助服务维护数据. 如果我们需要, 应该要能迁移到其他的数据库, 并且服务仍然是相同的. 因此, 数据库也是一个适配器 adapter. 上述架构可通过在核心业务逻辑层与适配器之间构建接口 ports 来实现. 在处理核心业务逻辑与适配器之间的关系时, 应用依赖反转原则 dependency inversion principle: 高层模块不应该依赖底层细节. 相反, 两者都应该依赖抽象. 以数据存储为例, 我们应当通过统一的接口进行操作, 无需理解数据库的具体实现细节. 无论是 SQL 数据库、NoSQL 数据库还是缓存存储系统, 都应该使用相同的接口规范. 抽象不应依赖于具体实现, 而具体实现应依赖于抽象. 以业务层与数据层之间的接口设计为例, 必须确保接口不会因数据库实现细节的变动而修改, 相反地, 我们通过调整数据层实现来适配接口规范.这意味着数据层依赖于接口定义, 而非接口依赖于数据层实现. 依赖反转的概念经常同控制反转与依赖注入的概念一同出现, 这些是相关但是不同的概念. ...

September 10, 2025 · 1 min · 76 words · Starslayerx

Docker - Images

每个 Linux 容器都基于一个镜像, 镜像重新构建运行中容器的底层定义. 要启动一个容器, 需要下载公共镜像或者创建自己的镜像. 每个镜像由一个或多个相互关联的文件系统层 layer 组成, 这些层通常与创建镜像的每个构建步骤大致一一对应. 由于镜像由独立的层构建而成, 这就对 Linux 内核提出了特殊要求: 内核必须提供 Docker 所需的驱动, 以便运行存储后端. 在镜像管理, Docker 高度依赖这个存储后端, 该后端通过与底层 Linux 文件系统通信, 用来构建并管理多个层并将它们组合成一个可用的镜像. 主要支持的后端存储有以下类型: Overlay2 B-Tree File System Device Mapper 每一个后端都提供一个快速的 copy-on-write (CoW) 系统用于镜像管理. 包含: Building images Uploading (pushing) images to an image registry Downloading (pulling) images from an image registry Creating and running containers from an image Anatomy of a Dockerfile | 剖析 Dockerfile 这个文件描述了所有构建一个容器所需的步骤, 并且通常存储在项目源码的根目录里. 一个典型的 Dockerfile 看起来像下面这样, 这里是创建一个 Node.js 的应用镜像: ...

September 7, 2025 · 18 min · 3803 words · Starslayerx

Docker - Workflow

The Docker Workflow 这篇文章介绍 Docker 工作流 Revision Control 版本控制 Docker 有两种版本控制方式. 一个是用来跟踪文件系统层 layers (每个镜像的组成), 另一个是 tagging 标签系统. Filesystem layers 文件系统层 Linux 容器由堆叠文件系统层组成, 每一层由一个唯一的哈希标记, 每次 build 都在之前的修改之上. 这意味着, 每次 build 只需要重新构建修改过的层. 这节省了时间和网络带宽. Image Tags 镜像标签 第二种版本控制回答了一个问题: 之前部署的应用版本是? 非容器化应用的解决方案有很多种, 从 Git 发布标签到部署日志. Docker 有一个内置的处理机制: 每次 build 都有一个镜像标签. latest 经常被用来表示最新版本, 但由于这是一个浮动的标签, 因此在生产中使用并不好. 正确的做法应该是使用一个特定的版本. Building 构建镜像 Docker 的命令行工具包含一个 build 标志, 它会读取 Dockerfile 并产生一个 Docker 镜像. Dockerfile 中的每一条指令都会在镜像中生成一个新的层, 因此仅通过查看 Dockerfile 就能比较容易的推断出构建会做什么. 这样标准化的好处是, 任何熟悉 Dockerfile 的工程师都可以直接上手并修改任何其他应用的构建. Dockerfile 通常会提交到版本控制系统, 这也简化了对构建变更的追踪, 现代的多阶段构建还运行将构建环境与最终镜像分离, 为构建环境提供了像生产容器那样强大的可配置性. ...

September 6, 2025 · 2 min · 368 words · Starslayerx

Docker - Images and Registeries

The Docker Images | Docker 镜像 Image、OCI Image、Docker Image、Container Image 都是指同一个概念镜像的不容叫法. 镜像是一个轻量、只读且不可变的蓝图, 指定了应用运行所谁要的一切, 以及在 Docker 系统上如何运行. 就像是一份配方, 包括所有必要的原料, 诸如依赖、配置、环境设置和你的应用代码, 以及确保应用每次都能稳定运行的详细指令. 可以把镜像类比为面向对象编程中的类: 定义结构和行为, 但不能直接与类交互, 需要创建实例. Pulling and Inspecting an Image 拉取并查看镜像 镜像其实就是一个 JSON 对象, 可以这样拉取一个镜像 % docker pull celery:latest latest: Pulling from library/celery ef0380f84d05: Pull complete ada810c79ed7: Pull complete 4608a1c4fe47: Pull complete 58086cbb21fb: Pull complete a7bccb4a3faa: Pull complete 9de06a08ec25: Pull complete ad6feb8c6a6b: Pull complete 7568ca85d492: Pull complete 2d6f458f7411: Pull complete Digest: sha256:5c236059192a0389a2be21fc42d8db59411d953b7af5457faf501d4eec32dc31 Status: Downloaded newer image for celery:latest docker.io/library/celery:latest What's next: View a summary of image vulnerabilities and recommendations → docker scout quickview celery:latest 现在查看镜像信息 ...

September 5, 2025 · 5 min · 890 words · Starslayerx

Docker - Engine and Netowrking

Docker 引擎(Docker Engine), 顾名思意,是 Docker 的核心. 它为 Docker 提供动力, 并承担所有繁重的工作. 本文将深入探讨这一关键组件的内部运作, 以便了解 Docker 在内核下是如何工作的. The Evolution of the Docker Engine | Docker 引擎的演进 Docker 最初是一个巨大的单体(monolith), 所有代码都塞在同一个项目里. 对于 dotCloud来说, 这种方式一开始是可行的. 实际上, 这个方向运作得非常好, 以至于他们放弃了其他服务、把所有赌注都押在 Docker 上, 甚至把公司重命名为 Docker, Inc. 一开始, Docker 是一个又大又混乱的单体应用. 随着时间推移, Docker, Inc. 发现这种做法不可持续, 他们需要把系统拆分出来: 各个部分可以独立成长 更容易升级某些部分 - 可以替换旧组件而不影响整体 让社区更容易参与贡献 - 更小的组件意味着更多人能参与进来 更易跨平台 - 他们想要 Docker 在每个平台上运行, 而不只是 Linux 拆分的第一步是把客户端 client 剥离出来. 把客户端从大应用中抽出, 赋予它新职责: 把用户命令翻译成 Docker 引擎能理解的指令(也就是原来单体里"内核部分"的接口) 此时, Docker 引擎主要有两部分: ...

September 4, 2025 · 4 min · 653 words · Starslayerx

Docker - History

The Docker Story - Part1: Docker History docCloud - 也就是开发 Docker 的公司, 最初是一家 PaaS(平台即服务)公司, 他们在 PaaS 领域并没有太大的成功, 但他们构建了一个可以无缝管理客户系统与架构的工具: Docker. 2013 年, 他们决定放弃 PaaS 服务, 将全部精力投入到 Docker 这款产品上. Containers 容器 Docker 公司并没有发明容器这个概念. 实际上, 容器的概念已经演进了十多年, 很多参与者都做出了贡献, Linux 基金会和 Google 是推动整个生态走向成熟的重要力量. 假如你在运营一家公司, 希望将应用上线, 以前需要做的事大概是: 购买一台服务器 安装所有必要的应用和依赖 配置环境以匹配你的开发设置 部署应用 把服务器对外开放 看起来很简单, 但实际操作会很复杂: 要手动跟踪并更新每个依赖和配置 如果出问题, 需要手动去修复 基础设施团队需要估算服务器规格(内存、CPU 等) — 为了防止流量高峰崩溃, 通常会配置更高的规格(过度配置) 那台高配服务器大多数时间只是闲置着, 做最少量的工作 不能轻易扩展或在同一服务器上运行多个应用, 因为每个应用都需要独立的运行环境 总之, 非常混乱 后来出现了虚拟机(VM), 情况有了改善. 使用 VM 可以: 在同一台服务器上运行多个隔离的环境 为 VM 做快照并在不同服务器间复用 不再重复重复地搭建环境,这是一个很大的进步 但 VM 也有缺点: ...

September 3, 2025 · 2 min · 289 words · Starslayerx

Redis Ordered Set

Redis 的有序集和(ordered set)同时具有"有序"和"集和"两种性质, 这种结构中每个元素都由一个成员和一个与成员相关联的分值组成, 其中成员与字符串方式存储, 而分值以64位双精度浮点数格式存储. 例如下面一个记录薪水的集和: 成员 分值 “perter” 3500 “bob” 3800 “jack” 4500 “tom” 5000 “mary” 5500 与集和一样, 有序集和中的元素都是唯一的, 同时, 成员将按照分值大小进行排序. 有序集和分值除了可以是数字外, 还可以是字符串 “+inf” 或者 “-inf”, 这两个特殊值分别表示无穷大和无穷小. 虽然有序集和的成员不可相同, 但是分值可以是相同的, 当两个或多个成员拥有相同的分值时,Redis 将按照这些成员在字典序中的大小对其进行排列. 有序集合是Redis提供的所有数据结构中最为灵活的一种, 它可以以多种不同的方式获取数据, 比如根据成员获取分值、根据分值获取成员、根据成员的排名获取成员、根据指定的分值范围获取多个成员等. ZADD: 添加或更新成员 ZADD sorted_set socre number [score number ...] 默认情况下, ZADD 命令将返回成功添加的新成员数量作为返回值, 对于更新操作会返回0(未添加新成员). 使用 XX | NX 选项来显示地指示命令 只更新 或 只添加操作 ZADD sorted [XX|NX] socre member [socre member ...] 若要返回所有被修改的成员数量(新添加 + 更新数量), 可使用 CH 选项 ZADD sorted_set [CH] socre number [score number ...] 复杂度: O(M * log(N)) 其中 M 为给定成员数量, N 为有序集和的成员数量 ...

August 30, 2025 · 4 min · 646 words · Starslayerx

Redis Set

Redis 的集和 set 键允许用户将任意多个不同的元素存储到集和中, 既可以是文本数据, 也可以是二进制数据. 其与列表有以下两个明显的区别: 列表可以存储重复元素, 而集和只存储非重复元素 列表以有序方式存储元素, 而集和则以无序方式存储元素 下面介绍结合键的各个命令 Set 集和 SADD: 将元素添加到集和 SADD set element [element ...] 返回成功添加的新元素数量作为返回值, 由于集和不存储相同元素, 所以会自动忽略重复的元素 SREM: 从集和中移出元素 SREM set element [element ...] 返回被移除的元素数量, 同样的, 不存在的元素会被忽略 SMOVE: 将元素从一个集和移动到另一个集和 SMOVE source target element 移动操作成功时返回1, 若不存在于源集和, 返回0. 如果 source 的元素不存在, 则返回0表示失败. 如果 target 的元素已存在, 则会覆盖该元素. 从结果来看, 并不会导致 target 中元素变化, 但是会导致 source 中的该元素消失. SMEMBERS: 获取集和包含的所有元素 SMEMBERS set 由于集和是无序的, 且 SMEMBERS 命令不会进行任何排序操作, 所以根据元素添加的顺序不同, 含相同元素的集和执行该命令结果可能不同. SCARD: 获取集和包含的元素数量 SCARD set SISMEMBER: 检查给定元素是否存在于集和 ...

August 26, 2025 · 4 min · 780 words · Starslayerx

Redis List

List 列表 Redis 的列表是一种线性的有序结构, 可以按照元素被推入列表的顺序来存储元素, 这些元素即可以是文字顺序, 也可以是二进制顺序, 且元素可重复出现. LPUSH: 将元素推入列表左端 LPUSH list item [item item ...] LPUSH 命令会返回当前元素数量 RPUSH: 将元素推入列表右端 RPUSH list item [item item ...] LPUSHX, RPUSHX: 只对已存在的列表执行推入操作 上面两条命令, 在列表不存在的情况下, 会自动创建空列表, 并将元素推入列表中. 且上面命令每次只能推入一个元素 LPOP: 弹出列表最左端的元素, 并返回被移出的元素 POP list 空列表 POP 会返回空值 (nil) RPOP: 弹出列表最右端的元素 RPOP list RPOPLPUSH: 将列表右端弹出的元素推入列表左端 RPOPLPUSH source target source 和 target 可以是相同列表, 也可以是不同列表. 但不能为空列表, 否则会返回空(nil) 示例: 先入先出队列 许多电商网站都会在节日时推出一些秒杀活动, 这些活动会放出数量有限的商品供用户抢购, 秒杀系统的一个特点就是短时间内会有大量用户进行相同的购买操作, 如果使用事务或者锁去实现秒杀程序, 那么会因为锁和事务的重试性而导致性能低下, 并且由于重试的存在, 成功购买商品的用户可能并不是最早购买操作的用户, 因此这种秒杀系统并不公平. 解决方法之一就是把用户的购买操作都放入先进先出队列里面, 然后以队列的方式处理用户购买操作, 这样的程序就可以不使用锁或者事务实现秒杀系统, 且更加公平. ...

August 24, 2025 · 3 min · 489 words · Starslayerx