N26:构建无缝体验的平台工程之路-Part 2
在第一部分,我们介绍了 N26 团队为达成 “在 Day 1 实现轻松部署” 的目标而设定的战略规划和开发人员体验图,在这一部分,我们将带您了解该团队如何构建最简可行平台以及该平台如何运作。
01 计划构建最简可行平台
我们通过采用 Story Workshop,将功能分解为三个层级,以洞察其基本特征和范围大小,并更好地确定优先级。
在研讨会中,我们深刻认识到软件工程的复杂性。我们讨论了一些简单问题,比如数据库迁移和日志记录,也讨论了更高级的问题,比如在软件交付生命周期(SSDLC)中确保安全性,再比如在分期付款计算和信贷融资等操作中采用 Money 模式来避免四舍五入错误。这些问题的代价不容忽视,而且发生的频率比我们想象的更高。
软件开发的残酷事实:永远没有足够的人力、时间和资金来构建你想要的一切。因此,关键是确定重点和优先顺序。而这正是 Story Workshop 的优势所在,因为它能帮助我们定义 “最简可行平台”(TVP)。
在某些情况下,TVP 可能是作为软件开发构件的组件或服务文档。尽管如此,定义 TVP 还是很重要的,因为软件工程师喜欢构建技术性的东西,如果没有重点,就有可能交付一个忽视开发人员体验的复杂平台。这里我们将着重关注在 TVP 中实现哪些功能,目标是设计一个能够在一周内运行的配置流程,初始功能集将为我们构造平台的基础。
因此,我们优先安装了 Kubernetes、编排自动化(我们将其命名为 “项目引导器”)和服务架构。但是在没有任何数据库支持的情况下,如何交付呢?我们告诉团队,他们可以使用内存存储库来实现这些目的。TVP 发布后不久,平台团队发布了数据库配置功能。自此产品团队可以在生产中部署完全可运行的服务。
对于从事平台工程的人来说,这是一堂重要的产品管理课。通过发布产品,可以部分解决问题。要计划减少构建量,并为用户和利益相关者提供替代方案。在解决临时问题时,协调和沟通非常重要。
从那时起,我们的平台发生了翻天覆地的变化。但每一个进步都离不开平台团队的辛勤工作,他们始终计划以迭代的方式推进平台的功能。这一过程的核心是了解业务目标、产品工程师的需求和监管要求,优先考虑能为公司带来价值的功能。
02 我们的平台如何运行
转眼到了2023年7月。我们平台日益壮大,不断优化协同工作,使每个人的工作都更加便捷。开发一项全新的服务时,产品工程师需要复制和管理基础架构的资源库,并运行make
命令:
$ git checkout -b overnight
$ make create-team spaces
该命令提供了一个目录,产品工程师团队将在该目录中编辑一个配置文件来启动新服务。该文件允许配置服务级别目标(SLO)和数据库集群大小等内容:
locals {projects = {overnight = {description = "Calculate the balances' CDI-indexed yield."repository = {bootstrap = truelanguage = "kotlin"}service = {bootstrap = true}monitoring = {bootstrap = trueerror_rate = "0.5"read_latency = "0.4"write_latency = "4"apdex = "0.94"}database = {bootstrap = trueinstance = "db.r6g.large"replicas = 4engine = "aurora-postgresql"}queues = {bootstrap = truenames = ["invoice-paid", "yield-calculated"]}logs = {archive = true}cdn = {bootstrap = false}}}
}
然后,产品工程师提交文件并创建拉取请求,由平台团队进行审核。我们制定了一项政策来防止微服务失败。作为领域驱动设计(Domain-Driven Design)的实践者,我们更倾向于围绕有边界的上下文设计服务,只有经过深思熟虑后才能拆分服务,平台团队才会审查是否符合政策。
拉取请求获得批准后,就会触发编排。编排:
- 在 AWS IAM 中为应用程序创建服务用户。
- 创建启用水平和垂直 pod 自动分级器的 Kubernetes 服务。
- 将API 网关与 Kubernetes 入口集成,以公开服务的 API。
- 在 AWS RDS 中创建 Aurora集群,并启用水平自动扩展。
- 创建消息队列/主题。
- 创建与内容分发网络(CDN)集成的 S3 目录。
- 在机密管理系统中存储凭证(API 密钥、数据库密码等)。
- 使用 service chassis 引导新服务代码库。
- 在BitBucket 中创建新的服务存储库。
- 配置 BitBucket 资源库变量。
- 创建 CI/CD 流水线。
- 配置质量和安全网关。
- 运行服务的首次部署。
- 在 Datadog 中创建服务级别目标 (SLO)。
- 在 Datadog中配置服务警报。
- 运行健康检查以确保供应工作。
这里的 service chassis 是一个基于 Ktor 的框架,其封装了细致的开源库和内部开发的组件,以减少对持久性和日志记录等问题的认知负荷。
配置完成后,产品工程师会克隆存储库并开始开发新服务。service chassis 会自动生成 Docker Compose 文件,来支持本地开发。所有项目共享相同的引导结构,方便产品工程师在项目间切换。此外,更少的可变性意味着平台工程师在增强工程团队使用的底层工具时,可以加快优化周期。
产品工程师可以在早期监控应用性能,并排除查询速度慢和 Apdex 分数低等问题。警报会自动配置并发送到标准化的 Slack 频道(每个团队都有一套标准的 Slack 频道,其中一个专门用于可观察性警报)。
为了微调可用算力,产品工程师可以更新配置文件,增加运行服务所需的 Kubernetes pod 数量。从产品工程师的角度来看,建立生产环境的唯一方法就是通过这个抽象了底层云基础设施的配置文件。这就保证了对生产环境的所有更改都会受到全面的审计。
同时,我们还有一系列需要人工操作但必须遵循准则或标准的工作。有些指南是在同行评审过程中产生的,比如 API 设计评审。我们努力从语义上设计 API。目前我们团队遵循设计文档中的规则。
强调文档的重要性也是我们一直在做的事。文档记录了产品工程师工作中最关键的部分,包括整个软件开发生命周期(SDLC)。例如,产品工程师可以通过阅读文档了解如何创建新凭证并将其机密存储在我们的云环境中,或者如何调整警报阈值。自动化流程和文档是自助服务平台的基础。
当新人加入我们的团队时,identity provider 会发送一封欢迎电子邮件,告知如何激活笔记本电脑。当然笔记本电脑是已完全配置好的,并更新到最新版本的操作系统和开发工具。软件工程师需要做的唯一工作就是克隆资源库,并运行 README 文件中提供的启动脚本(通常是 Docker Compose 命令)。
为了让我们基于网络的工具(如 Rancher、Datadog、Jira、Confluence、1Password、Slack)随时可用,我们使用 Okta 来提供身份管理。只需一个密码,用户就能解锁笔记本电脑并访问所有工具。将我们的平台范围扩大到访问管理和笔记本电脑设置等问题,有助于我们实施工程范围内的变更,如滚动工具更新和增强,而无需中断人员手动运行设置向导。
03 总结
N26 的平台工程之路漫长而曲折。从定制的协调工具到手动流程的标准化,我们致力于让开发人员在 Day1 就能够轻松部署。在此过程中,我们消除了对第三方基础设施的依赖,从而使应用程序接口延迟大大降低。最终开发人员生产率大幅提高。
通过构建内部平台,我们深刻体会到战略性地管理平台的重要性。除了充足的人力、时间和资金,还需要建立许多其他要素。其中,最重要的是产品思维,可以利用现有工具,特别是开源工具,来缩小开发范围;要关注开发者体验以及公司的目标成果。
相关文章:

N26:构建无缝体验的平台工程之路-Part 2
在第一部分,我们介绍了 N26 团队为达成 “在 Day 1 实现轻松部署” 的目标而设定的战略规划和开发人员体验图,在这一部分,我们将带您了解该团队如何构建最简可行平台以及该平台如何运作。 01 计划构建最简可行平台 我们通…...
【Hadoop-Distcp】通过Distcp的方式进行两个HDFS集群间的数据迁移
【Hadoop-Distcp】通过Distcp的方式进行两个HDFS集群间的数据迁移 1)Distcp 工具简介及参数说明2)Shell 脚本 1)Distcp 工具简介及参数说明 【Hadoop-Distcp】工具简介及参数说明 2)Shell 脚本 应用场景: 两个实时集…...

【Linux】使用Bash和GNU Parallel并行解压缩文件
介绍 在本教程中,我们将学习如何使用Bash脚本和GNU Parallel实现高效并行解压缩多个文件。这种方法在处理大量文件时可以显著加快提取过程。 先决条件 确保系统上已安装以下内容: BashGNU Parallel 你可以使用以下命令在不同Linux系统上安装它们&am…...

T天池SQL训练营(五)-窗口函数等
–天池龙珠计划SQL训练营 5.1窗口函数 5.1.1窗口函数概念及基本的使用方法 窗口函数也称为OLAP函数。OLAP 是OnLine AnalyticalProcessing 的简称,意思是对数据库数据进行实时分析处理。 为了便于理解,称之为窗口函数。常规的SELECT语句都是对整张表进…...
道可云元宇宙每日资讯|上海市区块链关键技术攻关专项项目立项清单公布
道可云元宇宙每日简报(2023年12月11日)讯,今日元宇宙新鲜事有: 上海市2023年度区块链关键技术攻关专项项目立项清单公布 据上海市科学技术委员会近日发布通知,上海市2023年度“科技创新行动计划”区块链关键技术攻关…...

大语言模型有什么意义?亚马逊训练自己的大语言模型有什么用?
近年来,大语言模型的崭露头角引起了广泛的关注,成为科技领域的一项重要突破。而在这个领域的巅峰之上,亚马逊云科技一直致力于推动人工智能的发展。那么,作为一家全球科技巨头,亚马逊为何会如此注重大语言模型的研发与…...

RabbitMQ-学习笔记(初识 RabbitMQ)
本篇文章学习于 bilibili黑马 的视频 (狗头保命) 同步通讯 & 异步通讯 (RabbitMQ 的前置知识) 同步通讯:类似打电话,只有对方接受了你发起的请求,双方才能进行通讯, 同一时刻你只能跟一个人打视频电话。异步通讯:类似发信息,…...
SQL Update语句
SQL Update语句 大家好,我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! SQL Update语句:数据库操作高招解析 数据库是我们搭建查券返利机器人的重要组成部分&…...

C语言-WIN32API介绍
Windows API 从第一个32位的Windows开始就出现了,就叫做Win32API.它是一个纯C的函数库,就和C标准库一样,使你可以写Windows应用程序过去很多Windows程序是用这个方式做出来的 main()? main()成为C语言的入口函数其实和C语言本身无关&…...

TFIDF、BM25、编辑距离、倒排索引
TFIDF TF刻画了词语t对某篇文档的重要性,IDF刻画了词语t对整个文档集的重要性...

MySQL之DML语句
文章目录 DML语句创建表添加表字段**插入数据**查询数据更新数据替换数据删除数据清除表数据删除表 DML语句 数据操作语言DML(Data Manipulation Langua) 是SQL语言的一个分类,用于对表的数据进行增,删,改,…...
kubernetes集群常用指令
目录 1.1 基础控制指令 1.2 命令实践 1.3 备注 1.1 基础控制指令 # 查看对应资源: 状态 $ kubectl get <SOURCE_NAME> -n <NAMESPACE> -o wide # 查看对应资源: 事件信息 $ kubectl describe <SOURCE_NAME> <SOURCE_NAME_RANDOM_ID> -n <NAMES…...

PyQt6 QTreeView树视图
锋哥原创的PyQt6视频教程: 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili QTreeView类,它是树控件的基类,使用时,必须为其提供一个模型来与之配合。 QTreeView类的常用方法: 方法…...

链表|148. 排序链表
148. 排序链表 题目:给你链表的头结点 head ,请将其按升序排列并返回排序后的链表。 题目链接: 148. 排序链表 时间复杂度:快排 O(n^2) 超出时间限制 class Solution {public ListNode sortList(ListNode head) {if(headnull)…...

如何解决5G基站高能耗问题?
安科瑞 须静燕 截至2023年10月,我国5G基站总数达321.5万个,占全国通信基站总数的28.1%。然而,随着5G基站数量的快速增长,基站的能耗问题也逐渐日益凸显,基站的用电给运营商带来了巨大的电费开支压力,降低5…...

PyTorch实现逻辑回归
最终效果 先看下最终效果: 这里用一条直线把二维平面上不同的点分开。 生成随机数据 #创建训练数据 x torch.rand(10,1)*10 #shape(10,1) y 2*x (5 torch.randn(10,1))#构建线性回归参数 w torch.randn((1))#随机初始化w,要用到自动梯度求导 b …...

什么是FPGA原型验证?
EDA工具的使用主要分为设计、验证和制造三大类。验证工作贯穿整个芯片设计流程,可以说芯片的验证阶段占据了整个芯片开发的大部分时间。从芯片需求定义、功能设计开发到物理实现制造,每个环节都需要进行大量的验证。 现如今验证方法也越来越多ÿ…...

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十四:系统设置模块相关功能实现
一、本章内容 本章使用已实现的公共组件实现系统管理中的系统设置模块相关功能,包括菜单管理、角色管理、日志管理、用户管理、系统配置、数据字典等。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 3.1 B站视频地址:...

使用Visual Studio(VS)创建空项目的Win32桌面应用程序【main函数入口变WinMain】
前言 在Visual Studio中直接新建Windows桌面应用程序会有很多多余的代码生成,本文将提供从空项目创建Win32项目的方法,解决新建空项目直接使用WinMain代码编译报错的问题 例如:LNK2019 :无法解析的外部符号 参考博客࿱…...

基于自动化脚本批量上传依赖到nexus内网私服
前言 因为某些原因某些企业希望私服是不能连接外网的,所以需要某些开源依赖需要我们手动导入到nexus中,尽管nexus为我们提供了web页面。但是一个个手动导入显然是一个庞大的工程。 对此我们就不妨基于脚本的方式实现这一过程。 预期效果 笔者本地仓库…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...

Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...

uni-app学习笔记三十五--扩展组件的安装和使用
由于内置组件不能满足日常开发需要,uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件,需要安装才能使用。 一、安装扩展插件 安装方法: 1.访问uniapp官方文档组件部分:组件使用的入门教程 | uni-app官网 点击左侧…...