2024-12-27 18:29:00
马尔科姆·格拉德威尔的“一万小时定律”指出,持续投入一万小时的努力,足以使人在某个领域达到专家水平。
按照每周20小时的练习量计算,每天大约需要投入3小时,十年左右才能达成这一目标。
从我写下第一行C代码算起,至今已超过十年。
期间,我编写了超过三十万行代码,其中一部分在微信编写的代码,曾服务过超过一亿的用户。
尽管写了这么多代码,我仍不敢自诩为专家。
但多年的“打工”生涯,日复一日地敲代码,也让我积累了不少感悟。
“工多艺熟”,这些感悟既是对编程技术的思考,更是对职场人生的体味。
毕竟,除了最初在学校学习的几年,我的编程生涯几乎都伴随着“打工”的酸甜苦辣(多是苦辣)。
虽然大学是从C语言入门编程的,但是我在大学时主修的语言是Java
,毕竟Java是门非常成熟的工业语言,有非常丰富的框架,在国内的企业非常受欢迎,工作岗位也多。
我当时从Java Servlets入门Web开发,再学习了非常流行的JavaEE 企业开发框架SSH, 即 Structs2 1+ Spring 2+ Hibernate 3, Struct2 负责控制逻辑关系,Spring 负责解耦, Hibernate 负责操作数据库.
而到我开始找工作时,SSH的概念就变了, Struct2 被SpringMVC 4所取代, SSH 变成了 SpringMVC + Spring + Hibernate.
到我实习入职蚂蚁金服的时候,发现组里代码库操作数据库的ORM框架用的并不是Hibernate,而是 Ibatis 5, 后面又切换成了新的 MyBatis 6
而蚂蚁金服内部使用的也并不是Spring/SpringMVC, 而是自主研发出发的 Sofa框架 7, Spring 社区后来觉得Spring框架过于重量级,不利于快速开发,又开发了更轻量级的 SpringBoot 8, 而蚂蚁内部又推出了Sofa版本的 Sofaboot 9
去了微信支付后,前期都是在写C++, 使用微信内部自研的svrkit 框架,到后期因为负责数据治理相关项目的缘故,开始使用 Spark + Python + Hive SQL
现在在AWS S3, 因为业务对性能和资源使用有非常高的要求,又开始使用Rust, 而历史业务又是使用Java, 兜兜转转之后,又回到Java的路子上。
细数下来, 这些年来,我写过Java,C++,Python,Rust,Javascript/Typescript 这些语言的生产代码.
除去工作之外, 我还因为学习SICP 学习了Scheme, 因为使用Emacs 而学习了Emacs Lisp, 想做独立开发赚钱学习了Swift, 想感受Ruby on Rails的魅力而学习的Ruby, 还有以前为了压测写的Golang, 还有各种语言对应的框架和库.
自我学习编程以来,学过的编程语言没有10种也有半打了.
我也从来不会把自己定义为某门语言的程序员,如Java程序员,C++程序员等等, 我只叫自己做Software Development Engineer. 语言从来只是工具,只要你持续学习,遇到新的场景,自然就会学习新的编程语言了.
计算机的世界日新月异,可能几个月就会出个新框架,几年又会流行一门新语言,只有持续学习,才能持续保持自己的竞争力。
领袖常说,「东升西降」,虽然不知道此种变化何时才能实现,但起码说明,目前是「西尚在上,东尚在下」,在计算机领域,尤其如此。
最前沿的技术都是英文资料,英语又是世界通行的语言,来自不同国家的开发者又会不约而同地使用英语来交流,
因此学好英语既可以了解最新的技术潮流,又可以融入社区,建立自己的影响力。
疫情之后,越来越多的公司都开始推行远程办公,从全世界招聘开发者.
这就意味着如果你英文过硬,甚至可以离开一线城市,避免高额的生活开销,在老家工作,陪伴在父母身边,同时赚取外汇;这对于饱受996困扰的程序员来说,未尝不是一条出路.
于我个人而言,坚持学习英语可能是我收获最大的投资之一。
熟悉我的朋友,尤其是我的高中同学可能知道,十年以前,我的英文可以说着实挺烂的:
满分150分的英语,只考个及格的90分可谓是家常便饭,后来也只会笨学英语,到高三的时候能考个120分已经是巅峰水平。
但上大学之后,我也没有就此懈怠放下英语,大一还每天去晨读英语。
没有口语交流的条件,就自己创造,去网上找人聊天, 当时还在一个叫 Interpals 10 聊天网站认识了全世界好多的人, 其中还有一个是年龄相仿的土耳其女孩,我们还加了Facebook, 经常用Skype 视频聊天.
大学毕业后就没有那么多的时间闲聊后就断了联系, 最近看Facebook的动态,看她也穿上婚纱了.
工作后也一直阅读英文的技术文章,用英文搜索内容,在Stackoverflow 和 GitHub 用英文回答问题,在Discord 的英语学习频道找人聊天, 把电脑和手机系统语言都换成英文的,从学习英语变成用英语。
后来在机缘巧合之下,从国内找到了加拿大AWS的工作,幸而有机会来加.
人们常说,路应该要越走越宽,而不是越走越窄;
而在我看来,英语就是夜里走路时手上拿着的手电筒,可以让我们走自己的路的同时,
扫一下旁边那条道的情况,需要时及时转向,不至于一条路走到黑.
微信以前一直有发最新iPhone手机的传统,但是那已经是4年前的美好时光了。
记得2021年是小龙明确年会不会发手机的第一年,他当时透露,那一年会发个铝片。
当时同事之间还在讨论,iPhone也是一块铝片冲压而成的嘛,那发的是否还是iPhone呢,不发手机只是烟雾弹?
拆开年会礼物之后发现,的确是一块铝片,上面写着「2022保持独立思考」.
{{< figure src="/ox-hugo/think_independently.jpg" >}}
小龙一直强调「独立思考」对微信的重要性,认为如果要选择一个最重要的品质,他会选择「独立思考」。
上级说的不一定是对的,老师说的不一定是对,学术机构说的也不一定是对,媒体说的也不一定是对,声音大的更不一定是对,毕竟有理不在言高。
比如微服务架构非常流行,许多公司都在搞微服务,那么单体架构是否就应该不使用?
作为初创公司或小团队,新业务是否要上微服务架构呢?还是先使用单体架构,业务发展起来再迁移到服务呢?
开发过程免不了要做各种决策,比如技术选型,针对你的需求,你可能会找到一打「看似」符合要求的组件,
可能还会去网上找找对各个组件的评价,会发现众说纷纭,就需要自己独立对每个组件做出分析,找出其优劣,再结合自身团队的特点,做出决策.
关于独立思考,我最喜欢的是一句话是HBO出品短剧《切尔诺贝利》里面,
科学家瓦列里·列加索夫希望克格勃释放调查真相同事乌拉娜·霍缪克的要求,说可以保证她是没问题的,克格勃头子回答的那句话:
Trust, but verify.(相信,但要核实)
这句话还有一个广为人知的变种:「又不是不能用」
很多的程序员都是完美主义者,尤其是读过《重构》和《设计模式》的程序员,会倾向于把很多时间来优化代码,做重构。
以前的我也会有类似的冲动,总会想时间去优化代码, 但是项目肝多了之后,有种强烈的感觉,还是先把MVP上线,及早让用户体验。
如果没有用户使用,再好再漂亮的代码也没有任何意义了。
所以经常看到社区有人问做副业的时候,应该用什么语言和框架,PHP/Python/Ruby 会不会太慢,我的观点一直都是,先做个原型跑起来,先找到第一个用户再说。
当运行速度成为瓶颈时, 你的业务已经非常大,肯定有足够的钱可以招一打的程序员把你的项目换成Golang/Java了。
对此,我很赞同坐我旁边大佬关于代码质量的说法:
make it run, make it fast, make it beautiful.
最近在做副业的尝试,有个深刻的体会,技术可能是商业里面最不重要的。
从零把产品做出来,推广给用户,用户只会关注你的产品是否好用,能否解决他们的问题.
他们既不会关注你是用C++/Java还是Javascript 写的,也不会关注你代码写得是否优雅,与其执着于技术选型,不如先把产品干出来让用户试用。
经常会看到有人在社区提问,什么语言最好,什么框架最好,什么编辑器最好,什么操作系统最好。
「最好」是个相当主观的结论,也并没有针对所有场景的「最好」的解决方案, 但是经常能看到社区有人因为哪个语言更好而吵起来.
或者有人在分享A的时候,有人会在下面回复B/C/D更好, 然后又争吵起来.
让不禁让我想起《社会性动物》这本著名的社会心理学著作里面提到的团队认同现象,
当球迷与某支球队产生强烈的认同感后,会将球队视为自我认同的一部分,这里他们会:
如果有人问我这个问题,我会回答「你顺手熟悉的工具的最好」。
即使是出于乐趣,编程的目的还是利用计算机解决问题,而解决问题最好的工具就是你最熟悉的工具。
除非你了解的工具不适用于你的问题,那么自然就需要一个新工具,也不要削足适履,矫枉过正。
当然,如果是为了满足求知欲而想去学习一个新的语言,那选择你感兴趣的就可以了。
当初在2017年学习Rust, 也只是因为大四没有课,时间充裕, 想学点有趣的新东西,那时候Rust1.0才发布2年, 可没指望能靠Rust找到工作
记不清在哪里看过的一段话:
我也曾问过自己类似的问题:
- 是不是好的东西就能流行?不一定
- 是不是我喜欢的东西就是好的东西?不一定
- 我会不会花时间精力在一个不一定会流行但是我喜欢的东西上?会
程序员固然是和机器打交道,但是本质解决的还是人的问题.
当初学习编程的时候,曾经有个误区,认为自己只要把技术搞好,就可以不去关心什么「人情世故」。
因此初入职场之后,我既是这么持有这样的想法,又是这样行动的,虽然不至于对其他人冷脸相对,但是难免会如好友形容那般:「孤傲」
但是被毒打时间久了才会发现,无论是在国内或国外,都难免会有「人情世故」,用英文来说,那叫 network and connection.
即使我技术能力过硬,也需要被人见到才行,和同事领导相处关系好,才可以在做出成绩的时候,「花花轿子被众人抬」。
所以我现在都是有事没事都和同事们聊天,既可以提升下熟悉度,也可以了解到许多部门八卦,
还可以从同事们抱怨中找到潜在优化点,践行自己「Work hard and be nice to people」的理念.
这行做久了,会发现软件工程其实说到底,就是人的系统工程。
程序写多了之后就会有种幻觉,就是觉得什么事情都可以用代码来解决。
手里拿着锤子的时候,把什么都当成钉子来砸。
被毒打多才认清的事实就是,有很多事情是无法用代码来解决,代码只是个工具,只能在个合适的场景使用, 避免路径依赖.
酒香也怕巷子深,只会写代码没啥用,还要写文章,在公司内部做分享,让别人能「看到你」。
编程肝项目的专业能力固然重要,但是也要有营销自己的软实力,就像一位长者说的那样: 两手抓,两手都要硬.
不知道是中国人讲究谦虚内敛的品质,还是程序员「木讷呆板」的刻板印象,导致大家都不怎么营销自己。
有事没事和老板聊下天,增进下交流,经常露个脸,可能比肝十个项目还有用。
从业多年,去过蚂蚁金服,微信支付和AWS 搬砖, 和各种各样的同事都共事过,有个越发强烈的感悟:
要与优秀的人共事
不仅能从他们身上学到非常到的优点,提升技术能力,可以学到最佳实践和工程经验,在Code Review 的时候可以学到更好的编程方式,遇到问题时又有靠谱的队友帮忙和指导。
由优秀的程序员开发出来的系统的独特之处,知道什么叫简单好用的系统,形成自己的技术品味。
品味与美感这个词是很抽象,但是用过了好用的系统,自然就不会对那些粗制滥造,还靠老板背书强行推广的系统感兴趣。
而提高技术品味在提高我们的技术认知的前提下,又能反过来帮我们提高设计能力.
和优秀的同事共事的另外一个好处是可以建立高质量的人脉网络,利于职业发展,跳槽换赛道也多个选择。
虽然初始公司也有优秀的开发者,但是平均而言,大公司优秀程序员的比例会更高,毕竟他们更有竞争力的薪资福利,自然也有更高的招聘门槛。
比如微信就有所谓的面试委员会,除了招聘部门的面试官之外,还要通过面委面试官的考核,避免为了快速招人而降低标准。
所以个人建议应届毕业生,有机会还是去大公司,见识下。
虽然离职微信快两年了,我仍然想念当初同组共事的同事们,他们真的是技术过硬,人又超nice, 还乐于帮忙.
正如孔子所言:与善人居,如入兰芷之室,久而不闻其香,则与之化矣;与恶人居,如入鲍鱼之肆,久而不闻其臭,亦与之化矣
编程这么多年,落下一堆的职业病。
大学时候就有的鼠标手(腱鞘炎), 工作几年之后「喜提」腰椎间盘突出,久坐下半身会麻痹,还有我曾经浓密黝黑的头发,现在也日渐凋零。
因为腾讯总部有免费的健身房,所以我基本工作日都会去健身房薅公司羊毛,2天有氧慢跑,2天无氧器械,坚持了快3年。
也开始注意自己的饮食,尽量少油少糖不喝酒。
健身虽然不是包治百病,但是起码人显得有精神了,也有精力应付高强度的工作了。
只有失去才会懂得珍惜,也真的只有在开始吃药,去医院复诊,才会开始注意身体。
虽然编程很有趣,虽然养家很重要,但是还是要注意身体,毕竟身体是一切的本钱,垮就没有其他的精彩故事了。
无论是编程,还是其他的技能,我感觉都是「马太效应」,你学得越多,你懂得越多,再学新的东西,你就会学得越快。
代码写多了才意识到,程序员的竞争力并不是写代码,也并不是哪门语言或者框架,
其核心竞争力是通过技术解决问题的能力,又何必再去拘泥于哪门具体的编程语言或技术呢。
希望编程十年只是个起点,十年后可以再写一篇「编程二十年的感悟」
旅加经历
历史思考
工具流分享
职场思考
软件工程
来源 编程十年的感悟
作者 Ramsay
2024-12-27 18:19:00
计划进行一系列 AI Agent 实验,欢迎交流。
app:
description: ''
icon: 🤖
icon_background: '#FFEAD5'
mode: agent-chat
name: 城市天气画报
use_icon_as_answer_icon: false
kind: app
model_config:
agent_mode:
enabled: true
max_iteration: 5
prompt: null
strategy: function_call
tools:
- enabled: true
provider_id: gaode
provider_name: gaode
provider_type: builtin
tool_label: 天气预报
tool_name: gaode_weather
tool_parameters:
city: ''
- enabled: true
provider_id: dalle
provider_name: dalle
provider_type: builtin
tool_label: DALL-E 3 绘画
tool_name: dalle3
tool_parameters:
n: ''
prompt: ''
quality: ''
size: ''
style: ''
annotation_reply:
enabled: false
chat_prompt_config: {}
completion_prompt_config: {}
dataset_configs:
datasets:
datasets: []
reranking_enable: true
retrieval_model: multiple
top_k: 4
dataset_query_variable: ''
external_data_tools: []
file_upload:
allowed_file_extensions:
- .JPG
- .JPEG
- .PNG
- .GIF
- .WEBP
- .SVG
- .MP4
- .MOV
- .MPEG
- .MPGA
allowed_file_types: []
allowed_file_upload_methods:
- remote_url
- local_file
enabled: false
image:
detail: high
enabled: false
number_limits: 3
transfer_methods:
- remote_url
- local_file
number_limits: 3
model:
completion_params:
stop: []
mode: chat
name: gpt-4o-mini
provider: openai
more_like_this:
enabled: false
opening_statement: 回复 1 开始创作今日城市天气画报。
pre_prompt: '查找城市 {{city}} 今天的天气情况,生成一段简单的话描述这个场景,提供给 dalle 绘制一幅图片。
'
prompt_type: simple
retriever_resource:
enabled: true
sensitive_word_avoidance:
configs: []
enabled: false
type: ''
speech_to_text:
enabled: false
suggested_questions: []
suggested_questions_after_answer:
enabled: false
text_to_speech:
enabled: false
language: ''
voice: ''
user_input_form:
- text-input:
default: ''
label: 城市
max_length: 48
required: true
variable: city
version: 0.1.5
界面:
生成效果:
仅展示效果,为了让更多人体验到效果,请勿滥用。
链接:https://dify.skybyte.me/chat/eg0ZPHqgCyeWF1Mb
iframe 插入不太正常,先不放了。
2024-12-24 19:23:18
这个看似简单的编辑器为用户提供了许多易于学习和使用的命令。
这款产生自资源极其有限时期的产物,似乎还很有助于理解vi/vim
和emacs
的一些设计。
GNU ed
命令是一个行编辑器。它被认为是标准的 Unix 文本编辑器,因为它是首个出现在 Unix 的文本编辑器,并且它曾经无处不在,你在任何一个 POSIX 系统中都能找到它(通常来说,你现在也可以)。在某种程度上,你可以很容易看出来它是第一个文本编辑器,因为它在许多方面的功能都十分基础。和其他大多数的文本编辑器不同,它不会打开一个属于自己的窗口或显示区域,事实上,在默认情况下,它甚至不会提示用户输入文字。从另一个方面来说,它在交互功能上的缺失也可以成为一个优点。它是一个多功能的编辑器,你可以用简短的命令控制它,无论是在交互式的命令行中,还是在编写的 shell 脚本里。
如果你正在使用 Linux 或者 BSD 的话,你很可能已经默认安装了 ed
(在 Linux 上是 GNU 版 ed
,而在 BSD 上是 BSD 版 ed
)。但是,一些极简的环境可能没有包括 ed
,这也没关系,你的发行版的软件仓库中很可能有 ed
可供下载。macOS 默认安装了 BSD 版 ed
。
# archlinux
$ sudo pacman -S ed
当你启动 ed
的时候,你的终端提示符不见了,看起来好像是 ed
停止运行了。其实它没有,它只是在等待你输入指令而已。
$ ed
为使 ed
显示更详细的信息,你可以输入命令 p
让它返回一个提示符:
$ ed
p
?
这个问号(?
)是默认的 ed
提示符。
当 ed
激活时,你其实是在和一个叫 缓冲区buffer 的东西打交道。缓冲区是内存中的一块区域。你并不会直接编辑文件,而是在编辑它对应的缓冲区。当你退出 ed
却没有把修改保存到磁盘的文件上时,所有的修改都会丢失,因为它们只在缓冲区里存在。(这对于一个已经习惯了初始的 草图缓冲区scratch buffer 的资深 Emacs 用户可能很耳熟。)
启动 ed
后,你处于命令模式。这意味着你可以向编辑器发送指令,比如让它显示一个提示符,而不是空白区域。你可以使用 a
命令开始附加文本到当前的缓冲区,使用一个实心的点 .
来终止输入。比如,下面的这个例子往缓冲区里附加了两行文字(“hello world” 和 “hello ed”):
?
a
hello world
hello ed
.
使用点 .
终止输入后,你将回到命令模式。
怎样查看当前缓冲区里都有什么呢?你可以输入想要查看的行号,也可以使用 ,p
命令来显示所有的行:
?
1
hello world
2
hello ed
,p
hello world
hello ed
如果你现在对文本很满意,你可以使用 w
命令把缓冲区写入到文件中,后面跟上目标文件名:
?
w example.txt
19
写操作后显示的那个数字代表着写入到文件中的字符数。
除了使用 ed
来读取文本,你也可以使用 r
命令把一个已经存在的文件加载到到缓冲区里:
?
r myfile.txt
另外,你也可以在启动 ed
时,在它后面加上你想要加载到缓冲区里的文件名:
$ ed myfile.txt
鉴于 ed
是一个文本编辑器,你当然可以使用一种特殊的语法来编辑缓冲区里的文本。使用 sed
或 vim
的用户或许会觉得这个语法很熟悉。假设现在缓冲区里已经加载了一个文件:
$ ed myfile.txt
,p
This is an example document.
There is some text, but not much.
There is some errors, but not much.
如果你要把第一句话中的 document
修改为 file
,你可以先选择目标行(1
),然后使用 s
命令调用搜索函数,后面跟着搜索文本和替换文本:
?
1
This is an example document.
s/document/file/
1
This is an example file.
如果你要编辑其他行,步骤也是一样的,只需提供一个不同的行号即可:
?
3
There is some errors, but not much.
s/is/are/
s/much/many/
你可以使用 ,p
命令来看到你对缓冲区的历史编辑记录:
This is an example file.
There is some text, but not much.
There are some errors, but not many.
当然,这些修改只存在于缓冲区里。你如果在 ed
编辑器外查看这个文件,你只会看到原始的文本:
$ cat myfile.txt
This is an example document.
There is some text, but not much.
There is some errors, but not much.
如果你要把这些修改保存回文件中,使用 w
命令即可:
w myfile.txt
258
如果想要得到一个新的缓冲区,以此来打开一个新的文件,或者把一个新的文件加载到不同的环境中,你可以使用 c
命令。使用这个清空缓冲区后,什么也不会输出,因为缓冲已经是空的了:
c
,p
如果要退出当前的 ed
会话,你可以使用 q
命令。它并不会给你一个保存缓冲区的机会,所以你要确保自己在这之前执行了保存操作。
ed
还可以做到很多事情,学习 ed
可以让你知道它和部分的 vim
是如何工作的。我并没有尝试使用 ed
来写这篇文章,老实说,我也不认为它是通常意义上的最佳文本编辑器。但是,ed
仍然是一个出色的编辑器。通过阅读它的文档,你可以很轻松地学会它。在 GNU 系统上,你可以使用 info ed
来查看它的操作手册。
2024-12-24 19:23:04
来源:Buildah 简明教程:让镜像构建更轻量,告别 Docker 依赖
Buildah 是一个专注于构建 OCI 镜像的工具,Buildah CLI 工具使用底层 OCI 技术实现(例如 containers/image1 和 containers/storage2)。
OCI 三剑客包括:
这三者一起形成了一个 Dockerless 的容器生态,支持构建、管理、推送和操作镜像和容器,且不依赖 Docker 守护进程。
注意:三者之间功能是有一定重复的,特别是 Buildah 和 Podman,不过各自专注点不同,建议合理搭配使用。
Buildah 是一个专注于构建 OCI 镜像的工具,Buildah CLI 工具使用底层 OCI 技术实现(例如 containers/image3 和 containers/storage4)。
官方描述原文:
A tool that facilitates building OCI images.the Buildah command line tool (CLI) and the underlying OCI based technologies (e.g. containers/image5 and containers/storage6)
Buildah CLI 工具则基于这些项目实现了构建、移动、管理镜像的功能:
containers/image
project provides mechanisms to copy (push, pull), inspect, and sign container imagescontainers/storage
project provides mechanisms for storing filesystem layers, container images, and containers那么问题来了:构建镜像已经有 Docker 了为什么还需要 Buildah?
Buildah 是无守护进程以及可以 rootless 运行的,相比于 docker 更加轻量级。
如果使用 Buildah 来代替 Docker 镜像构建能力,由于可以无守护进程以及可以 rootless 运行,因此即使在容器中使用也非常方便,对于 Devops 来说是一个很好的选择。
即:相较于现有的构建工具, Buildah 更轻量级,做到了 Dockerless 和 Rootless。
官方文档:buildah#install.md7
Buildah 为各大发行版都提供了对应的 Package,可以方便的通过 yum
、apt-get
、dnf
等等工具安装,当然也可以通过源码编译安装。
推荐使用发行版自带的包管理工具安装:
# CentOS
sudo yum -y install buildah
# Ubuntu 20.10 and newer
sudo apt-get -y update
sudo apt-get -y install buildah
# Fedora
sudo dnf -y install buildah
Demo 用的 Ubuntu22.04
sudo apt-get -y update
sudo apt-get -y install buildah
查看 Buildah 版本
ps:系统版本比较低,所以安装的 buildah 也比较旧
root@builder-ubuntu:~# buildah version
Version: 1.23.1
Go Version: go1.17
Image Spec: 1.0.1
Runtime Spec: 1.0.2-dev
CNI Spec: 0.4.0
libcni Version:
image Version: 5.16.0
Git Commit:
Built: Thu Jan 1 08:00:00 1970
OS/Arch: linux/amd64
BuildPlatform: linux/amd64
Buildah 相对于 Dockerfile 提供了强大的命令式构建方式,将 Dockerfile 指令变成一条一条的命令,为我们构建镜像提供了新的选择:
# 拉取镜像,类似 Dockerfile 中的 FROM
container=$(buildah from nginx)
# 类似 Dockerfile 中的 RUN
buildah run $container -- bash -c 'echo "hello world" > /usr/share/nginx/html/index.html'
# 提交保存镜像
buildah commit $container nginx-hello
输出如下:
[root@builder ~]# container=$(buildah from nginx)
[root@builder ~]# buildah run $container -- bash -c 'echo "hello world" > /usr/share/nginx/html/index.html'
[root@builder ~]# buildah commit $container nginx-hello
Getting image source signatures
Copying blob c0f1022b22a9 skipped: already exists
Copying blob fc00b055de35 skipped: already exists
Copying blob 2c3a053d7b67 skipped: already exists
Copying blob b060cc3bd13c skipped: already exists
Copying blob 8aa4787aa17a skipped: already exists
Copying blob c28e0f7d0cc5 skipped: already exists
Copying blob d32d820bcf1c skipped: already exists
Copying blob c6a7a8084917 done |
Copying config 19de2f1f4a done |
Writing manifest to image destination
19de2f1f4afc6e0ff9da11e9dfb988619f4bcd1d388ea4c18413ab574487a0d4
查看到刚才构建的镜像
[root@builder ~]# buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/nginx-hello latest 19de2f1f4afc 22 seconds ago 196 MB
当然,Buildah 也支持通过 Dockerfile 构建镜像,这个应该是比较常见的用法。
准备一个 Dockerfile
FROM nginx
RUN echo "Hello World" > /usr/share/nginx/html/index.html
EXPOSE 80
使用 buildah 构建镜像
buildah build -t nginx-hello2 .
输出如下
[root@builder ~]# buildah build -t nginx-hello2 .
STEP 1/3: FROM nginx
STEP 2/3: RUN echo "Hello World" > /usr/share/nginx/html/index.html
STEP 3/3: EXPOSE 80
COMMIT nginx-hello2
Getting image source signatures
Copying blob c0f1022b22a9 skipped: already exists
Copying blob fc00b055de35 skipped: already exists
Copying blob 2c3a053d7b67 skipped: already exists
Copying blob b060cc3bd13c skipped: already exists
Copying blob 8aa4787aa17a skipped: already exists
Copying blob c28e0f7d0cc5 skipped: already exists
Copying blob d32d820bcf1c skipped: already exists
Copying blob eec64f0b2723 done |
Copying config 1b63bdb270 done |
Writing manifest to image destination
--> 1b63bdb270c1
Successfully tagged localhost/nginx-hello2:latest
1b63bdb270c1066520a5ae37dcea3d5c3b9c5e9af581e76bf1287f9f79f77f03
用法和 Docker build 基本一致,迁移的话也没有太多学习成本。
同为 OCI 三剑客,Podman 、Buildah 配置文件也是通用的。
您可以在以下目录中找到默认的 Podman
、Buildah
的配置文件:
/etc/containers/
~/.config/containers/
ps:会优先使用用户配置文件,若没有则使用全局配置文件。
即:不同用户都可以单独指定自己的配置文件
在/etc/containers
目录下,包括多种配置文件:
各个文件的具体配置可以参考:Podman&Buildah 配置文件说明8
作为使用者,主要关系 registries.conf 配置,因此重点分析。
vi /etc/containers/registries.conf
/etc/containers/registries.conf
完整内容如下:
unqualified-search-registries = ["registry.access.redhat.com", "registry.redhat.io", "docker.io"]
# 配置为 Docker.io 仓库的镜像源
[[registry]]
prefix = "docker.io"
location = "registry-1.docker.io"
# 为 Docker.io 配置镜像源
[[registry.mirror]]
location = "mirror.gcr.io"
[[registry.mirror]]
location = "mirror2.gcr.io"
# 配置为私有仓库 10.10.10.49:5000 的镜像源
[[registry]]
prefix = "10.10.10.49:5000"
location = "10.10.10.49:5000"
insecure = true
# 配置私有仓库镜像源
[[registry.mirror]]
location = "mirror.gcr.io"
short-name-mode = "permissive
大致可以分为以下几部分:
不同仓库配置使用 [[registry]]
块进行区分。
注意:下面这样的配置是 V1 版本,已经废弃了,虽然还可以使用,但是不推荐。
[registries.search]
registries = ['registry1.com', 'registry2.com']
[registries.insecure]
registries = ['registry3.com']
[registries.block]
registries = ['registry.untrusted.com', 'registry.unsafe.com']
官方文档:containers-registries.conf.5.md9
unqualified-search-registries
是一个配置项,用来指定当拉取一个 没有指定完整路径(即不包含域名和路径) 的镜像时,应该尝试哪些仓库(注册表)。这通常适用于 “没有指定镜像仓库” 的情况。
unqualified-search-registries = ["registry.access.redhat.com", "registry.redhat.io", "docker.io"]
一句话描述:在拉取没有指定完整路径(即不包含域名和路径) 的镜像时,应该尝试哪些仓库(注册表)。
short-name-mode
选项定义了如何处理不带仓库路径的镜像名(例如,golang:1.20
)。有三种模式:
默认值就可以了,不用改。
short-name-mode = "permissive
Registry 块下的 prefix 用于匹配在拉取镜像时会用那个 Registry 块里的配置,只会使用最长匹配的 Registry 块。
假设有下面这样的配置,包含两个 Registry 块
[[registry]]
prefix = "docker.io"
[[registry]]
prefix = "docker.io.example.com"
当我们拉取镜像docker.io.example.com/library/busybox:latest
时,根据镜像完整命令中解析得到一个域名,然后和我们的配置文件中的 prefix 进行匹配,最终会匹配到第二个 Registry 块,这样就会使用该 Registry 块中的配置。
一句话描述:一般填写 Registry 地址即可,但是需要按照 *.example.com
格式,或者就是指定 location。
Registry 块中的 location 用于指定最终拉取镜像时访问的地址。
我们在拉取镜像时指定的是 docker.io/library/busybox:1.36
,但是最终会去 registry-1.docker.io
这个地址拉取。
对于 docker.io 来说,就需要以下配置文件:
[[registry]]
prefix = "docker.io"
location = "registry-1.docker.io"
还有就是 prefix 不是*.example.com
格式时,也必须指定 location,内容和 prefix 一致就行。
一句话描述:用于指定真正拉取镜像的地址,例如 registry-1.docker.io,或者当 prefix 不是*.example.com
格式时,也必须指定 location,内容和 prefix 一致就行。
registry 块下的 Insecure 参数比较常见,就是配置使用 http 访问该仓库,一般自建私有仓库会用到该配置。
# 配置为私有仓库 10.10.10.49:5000 的镜像源
[[registry]]
prefix = "10.10.10.49:5000"
location = "10.10.10.49:5000"
insecure = true
官方解释是这样的: If true, pulling images with matching names is forbidden.
默认是 false,配置为 true 之后就不能冲对应 Prefix 指定的镜像仓库中拉取镜像了。
# 配置为私有仓库 10.10.10.49:5000 的镜像源
[[registry]]
prefix = "10.10.10.49:5000"
blocked = false
一句话描述:用于关闭某些禁止使用的仓库。
对于部分无法拉取或拉取慢的仓库,可以配置 mirror 仓库。
# 配置 Docker 的镜像源
[[registry]]
prefix = "docker.io"
location = "registry-1.docker.io"
[[registry.mirror]]
location = "docker.m.daocloud.io"
registry.mirror 块放在那个 Registry 块下面就是为哪个仓库配置的 Mirror。
以下就是一个比较常用的配置文件 Demo,包括了 location、mirror、insecure 等配置,增加其他镜像仓库时可以做参考。
unqualified-search-registries = ["docker.io"]
short-name-mode = "permissive"
# 配置 Docker 的镜像源
[[registry]]
prefix = "docker.io"
location = "registry-1.docker.io"
[[registry.mirror]]
location = "docker.m.daocloud.io"
# 配置为私有仓库 "172.20.150.222" 的镜像源
[[registry]]
prefix = "172.20.150.222"
location = "172.20.150.222"
insecure = true
这里主要分享一些进阶的用法,包括:
多阶段构建是一种优化镜像大小的常用手段,通过将程序编译环境和运行环境分开来降低最终镜像大小。 用一个简单的 Go 程序演示一下多阶段构建。
使用 net/http 启动一个 http 服务。
// main.go
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
多阶段构建核心其实是 Dockerfile,可以看到当前 Dockerfile 有两个 FROM 语句,分别对应到编译阶段和运行阶段。
# Stage 1: Build stage (builder)
FROM golang:1.20-alpine as builder
# Set the Current Working Directory inside the container
WORKDIR /app
# Copy the source code into the container
COPY . .
# Build the Go binary
RUN CGO_ENABLED=0 go build main.go
# Stage 2: Runtime stage
FROM alpine:latest
# Install the necessary libraries to run the binary (if any)
RUN apk --no-cache add ca-certificates
# Set the Current Working Directory inside the container
WORKDIR /root/
# Copy the compiled binary from the builder stage
COPY --from=builder /app/main .
# Expose port 8080
EXPOSE 8080
# Run the Go application
CMD ["./main"]
buildah build -t server:v0.0.1 .
输出如下:
[root@builder ~]# buildah build -t server:v0.0.1 .
[1/2] STEP 1/4: FROM golang:1.20-alpine AS builder
[1/2] STEP 2/4: WORKDIR /app
[1/2] STEP 3/4: COPY . .
[1/2] STEP 4/4: RUN CGO_ENABLED=0 go build main.go
[2/2] STEP 1/6: FROM alpine:latest
Resolved "alpine" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/alpine:latest...
Getting image source signatures
Copying blob 38a8310d387e done |
Copying config 4048db5d36 done |
Writing manifest to image destination
[2/2] STEP 2/6: RUN apk --no-cache add ca-certificates
fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/community/x86_64/APKINDEX.tar.gz
(1/1) Installing ca-certificates (20241010-r0)
Executing busybox-1.37.0-r8.trigger
Executing ca-certificates-20241010-r0.trigger
OK: 7 MiB in 16 packages
[2/2] STEP 3/6: WORKDIR /root/
[2/2] STEP 4/6: COPY --from=builder /app/main .
[2/2] STEP 5/6: EXPOSE 8080
[2/2] STEP 6/6: CMD ["./main"]
[2/2] COMMIT server:v0.0.1
Getting image source signatures
Copying blob 3e01818d79cd skipped: already exists
Copying blob 529cb79624ea done |
Copying config 8d0a6344f5 done |
Writing manifest to image destination
--> 8d0a6344f55c
Successfully tagged localhost/server:v0.0.1
8d0a6344f55c0611c94b23f2571adb0ba1ce98ee1d5009c79fd656fd42247c1b
很多应用程序和服务都需要在不同架构的机器上运行,如 amd64 和 arm64,但我们不可能为每一个架构都准备一台专门的机器。
之前主要用的是 Docker Buildx,不过 Buildah 也是支持多架构构建的。
ps:当然了,都要借助 qemu
buildah
使用 qemu
来模拟不同架构。
首先需要确保你的系统上安装了 qemu
。
ps:经过测试,如果你的 Dockerfile 中没有 RUN 命令去执行某些操作其实不需要 qemu 也能正常构建多架构镜像。
直接包管理工具安装:
# Ubuntu
sudo apt-get install qemu-user-static
# Fedora
sudo dnf install qemu-user-static
和 Docker buildx 一样,Buildah 也通过 --platform
参数来指定要构建的架构。
不过 Buildah 没有 --push
参数,不能在构建完成后自动生成 manifest 并推送,因此需要手动创建一个 manifest 并将构建的镜像和 manifest 绑定并手段推送到最终镜像仓库。
整体流程大致分为三步:
Command 如下:
PUSH_WAY=172.20.150.222/lixd/nginx-hello:v0.0.2
# 创建 manifest
buildah manifest create ${PUSH_WAY}
# 构建
buildah build --manifest ${PUSH_WAY} --platform linux/amd64,linux/arm64 .
# 推送
buildah manifest push ${PUSH_WAY} --all "docker://${PUSH_WAY}"
定义了一个简单的脚本来实现构建多架构镜像,build.sh 完整内容如下:
# Set the required variables
export REGISTRY="172.20.150.222"
export REPOSITORY="lixd"
export IMAGE_NAME="server"
export IMAGE_TAG="v0.0.1"
export BUILD_PATH="."
# Platforms to build for
export PLATFORMS="linux/amd64,linux/arm64"
PUSH_WAY="${REGISTRY}/${REPOSITORY}/${IMAGE_NAME}:${IMAGE_TAG}"
MANIFEST_NAME=$PUSH_WAY
echo $PUSH_WAY
# Create a multi-architecture manifest
### Infact,this command can be ignore,when build will creates manifest list if it does not exist
buildah manifest create ${MANIFEST_NAME}
# Build the container for all platform
### Note: When more than one platform,use manifest to instead of tag flag.
buildah build \
--manifest ${MANIFEST_NAME} \
--platform ${PLATFORMS} \
${BUILD_PATH}
# Push the full manifest, with both CPU Architectures
### If Push To Docker Hub or Gitlab Registry,need add flag:--format v2s2,Default Is oci
buildah manifest push --all \
${MANIFEST_NAME} \
"docker://${PUSH_WAY}"
就以上一步的 Go Demo 编译生成一个多架构镜像:
bash build.sh
输出如下:
root@builder-ubuntu:~/multistage# bash build.sh
172.20.150.222/lixd/server:v0.0.1
e6ba6ec459a1fd7303c19242ab0d85c7c23af8cb156ce348928e2a4135327f15
# amd64
[linux/amd64] STEP 1/4: FROM golang:1.20-alpine AS builder
[linux/amd64] STEP 2/4: WORKDIR /app
[linux/amd64] STEP 3/4: COPY . .
[linux/amd64] STEP 4/4: RUN CGO_ENABLED=0 go build main.go
[linux/amd64] STEP 1/6: FROM alpine:latest
[linux/amd64] STEP 2/6: RUN apk --no-cache add ca-certificates
[linux/amd64] STEP 3/6: WORKDIR /root/
[linux/amd64] STEP 4/6: COPY --from=builder /app/main .
[linux/amd64] STEP 5/6: EXPOSE 8080
[linux/amd64] STEP 6/6: CMD ["./main"]
# arm64
[linux/arm64] [1/2] STEP 1/4: FROM golang:1.20-alpine AS builder
[linux/arm64] [1/2] STEP 2/4: WORKDIR /app
[linux/arm64] [1/2] STEP 3/4: COPY . .
[linux/arm64] [1/2] STEP 4/4: RUN CGO_ENABLED=0 go build main.go
[linux/amd64] [2/2] STEP 1/6: FROM alpine:latest
[linux/arm64] [2/2] STEP 3/6: WORKDIR /root/
[linux/arm64] [2/2] STEP 4/6: COPY --from=builder /app/main .
[linux/arm64] [2/2] STEP 5/6: EXPOSE 8080
[linux/arm64] [2/2] STEP 6/6: CMD ["./main"]
[linux/arm64] [2/2] COMMIT
# push
Getting image source signatures
Copying blob 977340364f39 skipped: already exists
Copying blob d8b4b7adc1e8 done
Copying config d97c60d03e done
Writing manifest to image destination
Storing signatures
--> d97c60d03e8
d97c60d03e822bb29c02c6b5c2c51b0f47871e52bc8c210c1e6324863797ce64
Getting image list signatures
Copying 4 of 4 images in list
Writing manifest list to image destination
...
这里以 Github Action 为例,演示如何使用 Buildah 构建多架构镜像。
源码:lixd/github-action-lab[11]
Dockerfile 和 main.go 和之前一样,就不贴了,感兴趣的同学可以调整 Github 查看~
Workflow 就是最终执行的 Pipeline,分为几个步骤:
name: Build and Push Multi-Arch Image
on:
push:
env:
IMAGE_NAME: test-multi-arch
IMAGE_TAG: latest
IMAGE_REGISTRY: docker.io
IMAGE_NAMESPACE: lixd96
jobs:
build:
name: Build and Push Multi-Architecture Image
runs-on: ubuntu-20.04
steps:
# Checkout the repository
- name: Checkout repository
uses: actions/checkout@v2
# Set up QEMU for cross-platform builds
- name: Set up QEMU for multi-arch support
uses: docker/setup-qemu-action@v1
# Build the Docker image using Buildah
- name: Build multi-architecture image
id: build-image
uses: redhat-actions/buildah-build@v2
with:
image: ${{ env.IMAGE_NAME }}
tags: ${{ env.IMAGE_TAG }}
archs: amd64,ppc64le,s390x,arm64 # Specify the architectures for multi-arch support
dockerfiles: |
./Dockerfile
# Push the built image to the specified container registry
- name: Push image to registry
id: push-to-registry
uses: redhat-actions/push-to-registry@v2
with:
image: ${{ steps.build-image.outputs.image }}
tags: ${{ steps.build-image.outputs.tags }}
registry: ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAMESPACE }}
username: ${{ secrets.REGISTRY_USERNAME }} # Secure registry username
password: ${{ secrets.REGISTRY_PASSWORD }} # Secure registry password
# Print the image URL after the image has been pushed
- name: Print pushed image URL
run: echo "Image pushed to ${{ steps.push-to-registry.outputs.registry-paths }}"
提交代码后,Workflow 会自动运行,到 Dockerhub 查看镜像是否成功推送
可以看到,指定的 4 个架构都成功构建并推送过来了。
Buildah 提供了一种灵活且高效的镜像构建方式,无需 Docker 依赖,且支持 rootless 安全模式,适用于各种 DevOps 和 CI/CD 环境。它支持命令式和 Dockerfile 构建方式,还能进行多阶段构建和多架构镜像构建。
2024-12-24 00:17:44
Gartner研究副总裁高挺(Arnold Gao)表示:“今年的重要战略技术趋势涵盖了AI的必要事项和风险,以及计算技术和人机协同等前沿趋势。追踪这些趋势将帮助IT领导者以负责任、和合乎道德的创新方式塑造企业机构的未来。”
以下是 2024 年 10 月 22 日 Gartner 发布的 2025 年重要战略技术趋势:
代理型AI通过自主规划和采取行动实现用户定义的目标。代理型AI为实现能够分担和补充人类工作的虚拟劳动力带来了希望。Gartner 预测,到2028年,至少15%的日常工作决策将由代理型AI自主做出,而2024年这一比例为0%。这项技术的目标导向型功能将实现适应性更强、能够完成各种任务的软件系统。
代理型AI有望实现企业首席信息官(CIO)提高生产力的愿望。这一动机促使企业与厂商探索、开创和建立能够提供稳健、安全和可信的代理型AI所需的技术和实践。
行业应用:
随着AI的广泛应用,模型偏见、不透明性等问题对信任构成威胁。AI治理平台将通过模型透明度、道德审查和可解释性提升信任度,防止生成有害或不道德的内容输出。
技术落地:
Gartner预测,到2028年,采用综合AI治理平台的企业将比没有这类系统的企业减少40%与AI相关的伦理事件。
虚假信息安全是一个新兴技术类别。该技术能够系统地辨别信任度,旨在提供一个能够确保信息完整性、评估真实性、防止冒名顶替和追踪有害信息传播的方法体系。Gartner预测,到2028年,将有50%的企业开始采用专为应对虚假信息安全用例而设计的产品、服务或功能,而目前这一比例还不到 5%。
AI和机器学习工具的广泛可用性和高级状态被用于恶意目的,预计将增加针对企业的虚假信息事件数量。如果这种趋势不被加以控制,那么虚假信息可能会对企业造成重大且持久的损害。
应用场景:
后量子密码学能够保护数据免受量子计算解密风险。根据量子计算过去几年的发展情况,目前广泛使用的几种传统加密技术将被淘汰。由于改变加密方法并非易事,企业必须有更长的准备时间,才能为一切敏感或机密信息提供强有力的保护。
行业影响:
Gartner预测,到2029年,量子计算技术的进步将使大多数传统的非对称加密技术变得不安全。
环境隐形智能是由成本极低、体积小巧的智能标签和传感器实现的,这些传感器能够提供大规模、经济实惠的的追踪和传感。长远来看,环境隐形智能将使传感器和智能技术无缝融入我们的日常生活中。
典型应用:
到2027年,环境隐形智能的早期示例将以解决当前问题为主,例如零售库存检查或易腐货物物流等,通过实现低成本的实时物品追踪和感知来提高可见性和效率。
IT以多种方式影响可持续性。在2024年,碳足迹是大多数IT组织的首要考虑因素。计算密集型应用,例如AI训练、模拟、优化和媒体渲染等由于能耗最高而可能成为企业碳足迹“大户”。
发展方向:
预计从2020年代末开始将出现一些新的计算技术,如光学、神经形态和新型加速器等。这些新技术将被专门用于特殊任务,例如AI和优化,并显著降低能耗。
新的计算范式正在不断涌现,包括中央处理单元、图形处理单元、边缘、特定应用集成电路、神经形态以及经典量子计算、光学计算范式。混合计算结合不同的计算、存储和网络机制解决计算问题。这种计算形式能够帮助企业探索和解决问题,使AI等技术能够突破当前的技术限制。混合计算将被用来创建比传统环境更高效的变革性创新环境。
未来计算体系将整合CPU、GPU、边缘计算、量子计算、光学计算等多种技术,实现协同计算。组织需要评估并部署最适合其需求的计算框架。
应用趋势:
空间计算利用增强现实和虚拟现实等技术,以数字方式增强物理世界。它将实体和虚拟体验之间的交互提升到一个新的级别。在未来五到七年内,空间计算的使用将通过简化工作流程和增强协作能力来提高企业效率。
前景展望:
Gartner 预测,到2033年,空间计算市场将从2023年的1100亿美元增长至1.7万亿美元。
多功能机器人能够执行多项任务,它们正在取代为重复执行一种任务而专门设计的特定任务机器人。这种新型机器人的功能性能够提高效率和投资回报率(ROI)。多功能机器人可以与人类一起协作,能够快速部署和轻松扩展。
技术进展:
Gartner预测,到2030年,80%的人类将每天与智能机器人打交道,而目前这一比例还不到10%。
神经增强利用读取和解码大脑活动的技术提高人类的认知能力。这项技术能够使用单向脑机接口或双向脑机接口(BBMI)读取人的大脑,在人类技能提升、下一代营销和提升表现这三个主要领域具有巨大潜力。神经增强将提高人类的认知能力,帮助品牌了解消费者的想法和感受并增强人类的神经功能,从而获得最佳的结果。
Gartner预测,到2030年, 30%的知识工作者将通过BBMI等技术(资金来源包括雇主和个人)提升自己的能力,并凭借这些技术来适应工作场所中AI的崛起。这一比例在2024年还不到 1%。
潜在价值:
今年的重要战略技术趋势强调了那些将在未来10年内给CIO和其他IT领导人带来重大变革与机遇的趋势。
2024-12-24 00:02:46
Gartner建议企业评估每个技术趋势的影响和收益,明确哪些创新技术或组合将对企业的成功产生最显著影响。
AI Trism 指“AI Trust,Risk,Security Management”,是一组关于AI信任、风险、安全管理的架构性趋势,比较简单的说法是“AI治理”。
越来越多的人工智能成为工作中不可或缺的一部分,尤其是在生成式人工智能爆火的今天。一旦我们缺乏对人工智能模型有效的治理,实际上就存在人工智能技术“失控”的风险。对于企业来说,人工智能在整个生命周期中可能都会有一些安全风险,从最早的“训练数据投毒”,到应用生成式人工智能时的“提示词攻击”,从各个方面来讲,人工智能有很多风险敞口。
基于这样的现实情况,Gartner提出这套“AI Trust”框架。它关注的是人工智能模型的治理,以及公平性、可解释性、透明度、数据保护等,由6个模块组成,分别是:模型运维(ModelOps)、主动数据保护、AI特定安全、模型监控(包括对数据漂移、模型漂移和/或意外结果的监控)以及第三方模型和应用输入与输出风险控制工具。这是AI Trism连续第二年入选“十大趋势”。
CTEM指“Continuous Threat Exposure Management”,是Gartner提出的安全态势修复和改进的框架,其与传统安全技术的区别在于:
不是指单纯从技术上去修复一个安全漏洞,而更加关注业务层面的风险暴露面,包含五个模块:Scoping(范围界定)、Discovery(发现)、prioritization(优先级排序)、Validation(验证)、Mobilizatlon(动员)。
可持续技术是一个数字解决方案框架,其用途是实现能够支持长期生态平衡与人权的环境、社会和治理(ESG)成果。人工智能、加密货币、物联网、云计算等技术的使用正在引发人们对相关能源消耗与环境影响的关注。因此,提高使用IT时的效率、循环性与可持续性变得更加重要。
Gartner预测,到2025年,75%的组织都会面临持续的电力短缺,这种电力短缺会加速推动可持续IT技术的发展。到2027年,25%的CIO(首席信息官)的个人薪酬将与他们对可持续技术的影响挂钩。
平台工程指的是通过一系列工具和流程,为企业的软件开发团队提供一个自助开发门户,或者称之为内部开发平台。这个平台可以涵盖应用程序整个生命周期里所有的操作,但它需要由一个专门的平台工程团队去创建和维护。
这跟传统的开发有什么区别呢?传统开发都是项目制,很多开发人员是根据业务部门的需求做定制化开发。这导致了一个问题,比如一个企业开发了3个应用,3个应用里有很多功能是类似的,那么就会有重复开发的资源浪费问题。
平台工程更像是开一家自助餐厅,顾客可以根据自己的要求去挑选合适的菜品,就是所谓的“自助式服务”。这样可以在短时间内满足需求、提升开发效率,同时可以比较大限度地规避菜品重复的浪费问题。餐厅里的厨师就变成了“平台工程师”,这也是为什么平台工程要有一个专门的团队去维护。
平台工程有3个关键词:可组装、可复用、可配置。本质上它背后的思想就是把软件开发从项目管理的思维转化到产品管理的思维,把本来相对独立的开发项目流程模块化和集中化。
AI增强开发指使用生成式人工智能、机器学习等AI技术协助软件工程师进行应用设计、编码和测试。主要包括:AI代码生成、AI增强测试、从设计到代码的过程。
在第一个模块里进行“AI代码生成”,对于下面几种场景特别有帮助:样板代码、重构代码,以及对旧的框架或编程语言进行学习。
“AI增强测试”即会有很多测试任务逐渐被AI开发替代,主要集中在3个方面:编写测试代码、生成测试数据、生成单元测试中的“测试桩”。
从设计到代码,在某种意义上是人工智能参与整个开发全生命周期的过程。目前还没有完全实现,属于对未来的展望。
Gartner预测,到2027年,将有超过70%的企业使用行业云平台(ICP)加速其业务计划,而2023年的这一比例还不到15%。ICP通过可组合功能将底层IaaS(基础设施即服务)、PaaS(平台即服务)、SaaS(软件即服务)服务整合成全套产品,推动与行业相关的业务成果。这些功能通常包括行业数据编织、打包业务功能库、组合工具和其他平台创新功能。
换句话讲,即在传统的“云”上加一层“业务模块层”。它之所以会成为趋势,因为现在企业更关注在“云”投资可以如何产生可量化的商业价值,而不是像以前只是为了达到技术和基础设施改进的目的。“行业云平台”有两大特征:可组装、模块化。
它实际上是把一些通用的业务能力模块化之后放在“公有云”上,然后让它重新排列组合进行组装。根据现在的整理,我们在超过20个行业当中找到了大概有超过270个“行业云平台”,以下是大致的分布。
Gartner将智能应用中的“智能”定义为自主做出适当响应的习得性适应能力。在许多用例中,这种智能被用于更好地增强工作或提高工作的自动化程度。作为一种基础能力,应用中的智能包含各种基于人工智能的服务,如机器学习、向量存储和连接数据等。
在2023年Gartner首席执行官(CEO)和业务高管调查中,26%的CEO认为对企业机构破坏力最大的风险是人才短缺。吸引和留住人才是CEO在人力资源方面的首要任务,而人工智能被认为是未来3年对他们所在行业影响最大的技术。
其目标是最终成为可以像人类一样去思考、判断和适应环境的应用。这种智能应用自适应的学习能力,背后实际上是包含各种基于人工智能的服务,如机器学习、语意引擎、连接数据等。比如苹果手机或苹果手表有一个“优化充电”的功能,即根据用户每天的充电习惯,通过机器学习的方式找到规律,比如起床时间、出门时间,然后在你出门之前一个小时左右才充电到100%。
这就是通过“学习适应的模式”去改变,让手机寿命更长一点。像辅助驾驶/自动驾驶,包括一些做机器人的公司,如特斯拉的AI机器人,本质上也是一种智能应用。
一个有意思的例子是“AI读心术”。在2023年5月,美国得克萨斯州的奥斯汀分校研究团队在《自然·神经科学》杂志上发表文章,公布了一个基于AI预训练大模型的大脑活动解码器,它可以将大脑活动转化为连续的文本流,通过一种非侵入式的方法学会“读心术”。实际上目前的识别率虽然不算特别高,但还是很有意思。
生成式人工智能应用可以让企业用户访问并使用大量内部和外部信息源,这意味着生成式人工智能的快速采用将极大地促进企业知识和技能的全民化。
Gartner预测:到 2026年超过80%的企业将使用生成式人工智能的API(应用程序编程接口)或模型,或在生产环境中部署支持生成式人工智能的应用,而在2023年初这一比例不到5%。
未来生成式人工智能平台的入门门槛会变得非常低,几乎可以为所有人提供“生成、创造、编写数字内容”的能力。入门门槛低,意味着成本也低。这个“低成本”实际上还能够提高生产力,取代或辅助一些工作,用来研发一些新的产品。
举个例子,二手车零售商CarMax用微软Azure OpenAI的服务,把万余条“客户评论”汇总成一个简短的描述,包括它库存里每种汽车的品牌、型号、年份,以及一些关键评论的要点。
对于商业用户来说,如果我们将来可以无处不在地获取以前不可能获得的知识和技术,那么这预示着一波新的生产力浪潮即将到来。“云”和“开源”的融合会使生成式人工智能更加民主化,会超越只是某些大型科技巨头能够掌握这件事的局限性。但它也有一个问题,即这种不受限制地获取知识和技能的方式,必须以治理和风险管理作为基础。
增强型互联员工队伍(ACWF)是一种优化员工价值的战略。ACWF使用智能应用和分析,提供助力员工队伍体验、福祉和自身技能发展的日常环境与指导。
其关键的核心在于提供员工的数字体验。如何用人工智能“增强”?它指的是,对从终端应用知识库甚至是员工情绪中提取出的数据进行接近实时的处理和反馈。比如,企业从员工在线工作的时间,包括邮件里的措词、访问各个应用的数据,分析出员工目前的工作状态和压力。另外一个角度是,从员工在某些系统里逗留的时间、所做的操作,可以看到企业里需要改善的流程,甚至找到一些“员工的离职倾向”等。这里要考虑“安全和隐私”问题。但它的一个要点是用人工智能的方式对员工进行关怀,人工智能最后不会取代人类的关怀,但是可以增强,至少给人类提供一些数据方面的支撑。
机器客户(也被称为“客户机器人”)是一种可以自主协商并购买商品和服务以换取报酬的非人类经济行为体。到2028年,将有150亿台联网产品具备成为机器客户的潜力,这一数字还将在之后的几年增加数十亿。到2030年,该增长趋势将带来数万亿美元的收入,其重要性最终将超过数字商务的出现。
在战略上应考虑为这些算法和设备提供便利甚至创造新型客户机器人的机会等。Gartner预测:到2027年,超过50%的销售和服务中心将接听机器客户的电话。
这个“机器客户”当然不是一蹴而就的,它的整个进化过程分成3个阶段:
第一,人类主导,由机器通过一定的规则去购买特定的商品。
第二,人类和机器共同主导,优化购买的选择,最终由机器根据规则执行购买操作。第一个阶段已经实现了,第二个阶段也已经实现了一部分了。
第三,机器推测人类的需求,根据规则、场景和偏好进行自主化购买。
一个有意思的案例是,前不久OpenAI的一位创始人发表TED演讲,演讲之前他做了一件事:用聊天机器人ChatGPT和文生图工具Dall·E帮他准备晚餐的菜单,然后用Dall·E把晚餐的菜单文字转化为图片的请柬,最后用ChatGPT创建一个“购物清单”。
每个趋势都与以下一个或多个关键主题相关:
为确保技术投资持续创造价值,企业需要:
该主题相关的IT趋势包括:
通过以下方式激发开发者社区的创造力:
该主题相关的IT趋势包括:
通过以下方式提升利益相关方体验,拓展收入增长渠道:
该主题相关的IT趋势包括: