我的博客变迁史
本科毕业以后就很少有时间来折腾自己的网站了,大部分时间里都是 ssh
到服务器上随便搭好一个服务后就任其自由生长,即便是服务挂掉了之后也没有太在意——毕竟是自己用的东西,对于网站的用户而言:ABSOLUTELY NO WARRANTY。不过随着网站近来的用户数量呈现难以置信的增长势头(虽然什么也没干),自然也就难免希望让网站变得更加「可靠」。
作为 2020 年的最后几项 TODO,我终于在圣诞节休假的第一周的前三天完成了整个 changkun.de[1] 的「架构升级」,从原来组织混乱、依赖复杂的 Native Nginx + Docker + tmux served binary + Jupyter notebook + hypervisor + crontab + ... 等等依赖 C/C++/Python/Node.js/Go/... 以及数不胜数的第三方依赖全面转向了以「尽可能自研、能不依赖就不依赖、 即使以来也要依赖使用 Go 开发的依赖」为指导思想的纯 Go 的后端结构。
这篇文章就介绍了 changkun.de[2] 作为个人网站,从最初的每年不到一百的活跃用户到现在的每月上万活跃用户这个过程中究竟积累并承载了哪些(公开的、但不那么可见的)个人以及面向公共的服务,以及它背后的迁移故事。
迁移历史
博客 blog.changkun.de[3] 的每次「重大」迁移,其实都有文章记录,在这里[4]可以找到。
回顾过去来看,changkun.de[5] 其实有相当长的迁移历史。从最早的内容散落在各种 BBS(贴吧、新浪博客、QQ 空间)、到后来本科时期 Wordpress(2012-2015)再到到后来初次迁移到 Hexo 的第一、二版(2015-2017)以及沿用至今的 Hexo 第三版(2017-2020)和刚刚上线的纯 Go 应用版(2021-至今)。
蛮荒纪元(2008-2013):BBS
在 2013 年以前,我还是一个彻头彻尾的不知计算机技术为何物的纯数学爱好者(高中),对计算机技术曾嗤之以鼻。混迹在诸如几何吧、数学吧、猫扑天涯这类早期的 BBS 与人版聊数学,自然也不懂建站为何物。很多早期的内容都散布于此,博客里面很多早期的文字都是从这些地方后续搜集得来,具体的历史几乎不可考究,那时候还没有注册changkun.de[6] 这个域名。
远古纪元(2013-2015):Wordpress (LAMP Stack)
本科本以为稳稳的数学系结果误打误撞来到了计算机系,才开始真正开始学习计算机科学,入学一年后,在沉迷旁听各种数学系课程的过程中,花费了极少的时间掌握了各种 C 语言的奇淫巧技(比如熟读 C 和指针、C 专家编程这类书籍)后大致建立了对计算机科学在研究什么样的问题这一基本概念后,而完成了第一次的建站。那时候的博客所注册的域名并不是现在这个域名(如今我也不再拥有该域名,所以这里就不提了)。早在 2013 年的时候并没有如今 Docker 这种便利的工具,想要独立建站,不外乎以下这些步骤:购买域名和服务器
手动在服务器上编译源码并安装 MySQL
手动在服务器上安装 Wordpress
没有 HTTPS
第一纪元(2015-2016):Hexo + GitHub Pages
本科三年很快就结束了,我也从那个对计算机一无所知成长为了一个能够用 C 语言徒手撸 parser 的萌新,可惜还没来得及进入职场就已经在 2015 年的下半年应差阳错的来到了德国开启了半年的留学访问之旅。但那时并没有对 Web 技术有多少了解,直到我旁听了一门 Online Multimedia 的课,才了解到了这个世界上还有 Polymer、Angular 这样的前端技术、以及 MongoDB 这样的非关系型数据库,就像开启了新世界的大门。由于开始尝鲜各种 Web 技术,了解到了静态博客的概念,发现了相对成熟的 Hexo 的存在。
考虑到博客作为一个年活跃不超过 100 个用户的自留地,继续使用 Linux+Apache+MySQL+PHP 这样的组合无疑是愚蠢而笨重的。与此同时因为当时的服务器在国内阿里云,而我身在德国直接 SSH 上服务器通常敲几个命令就会掉线,做不了任何事情。于是狠下心来决定将网站迁移到 GitHub Pages 上,这次迁移的工作包括:
从 Wordpress 将文章从 MySQL 中导出并转化为 Markdown 的格式
在本地编译博客静态文件,手动 push 到 GitHub
继续没有 HTTPS
第二纪元(2016-2017):Hexo + Git Server + HTTPS
第一纪元的的开启意味着整个网站从繁重的 LAMP 栈中摆脱出来,直接削减为了零成本的「Serverless」计算。
但这并不是没有缺点,其实当时整个网络环境并不如今天这么好,我早年的 Wordpress 站点曾被搜索引擎索引得很好,也有相当的流量从搜索引擎直接倒入。但由于 GitHub 自身优化的原因,博客部署到 GitHub Pages 之后便再没有被搜索引擎给索引,相当于整个站点从互联网上直接就消失了。另一个缺点是当时的 GitHub Pages 也还不支持配置 HTTPS,虽然说作为一个静态博客这种东西没有必要,但那时候能够启用 HTTPS 已经是一种尊贵的象征。
推动整个互联网向 HTTPS 迈进的一个历史性的关键节点是苹果的 iOS 开始强制应用 API 必须使用 HTTPS 协议,当时移动互联网热潮翻涌,我也非常热衷于希望给自己的博客开发一个 APP,如果还有博客的早期读者在的话应该还记得,这个博客曾经是有桌面客户端(基于 Electron)和移动客户端(基于 ReactNative)[7] 支持的, 而且为了能够支持 API 访问,我编写过 Hexo RESTful API Generator[8] 这种东西。
所以,这次迁移的工作包括:
在服务器上配置好 Nginx 网关
设置 Git 服务器,配置 post-hook 脚本
在本地编译博客静态文件,手动 push 到 Git 服务器并触发 post hook 来更新 /www/blog 下的静态文件
启用 HTTPS
值得一提的是,这个时候(2016)年还没有 LetsEncrypt,而自签名的证书并不会被主流浏览器判断为可靠证书,所以当时还花了一些时间来寻找可靠且免费的 SSL 证书。
第三纪元(2017-2020):Hexo + GitHub + Travis CI + VPS
第二纪元的做法并不安全,而且相当依赖本地原始文件的安全性,如果本地文件丢失,那么从编译好的 HTML 中恢复 markdown 将是不小的工作量(图片、公式的处理)。此外,每次向服务端 Push 编译后的静态文件严重依赖本地和服务器之间的传输速度,这对于纯文本的更新还好,但一旦需要向服务器 Push 图片、文件等内容时,将是巨大的灾难。我至今仍然记得为了更新一篇博客,敲完 push 后开着电脑等待一小时的尴尬场景(当时德国向国内阿里云华南地区服务器上传速度仅为 10kb/s 左右)。
为了解决网速缓慢的问题,于是这个博客开始引入 CI/CD 系统,核心目的其实是当 push 完毕后, CI 系统能够自动帮我完成编译、上传的过程,这样每次更新博客的流程就简化为了为博客源码提交一个 commit。虽然引入 CI 并没有彻底解决向国内阿里云服务器上传文件的速度问题,但这个上传过程是异步的,总体上是能接受的。
当时比较主流的 CI/CD 系统是 TravisCI,于是很快就用上了。这次迁移的工作虽然不多,但是期间花了很多时间将整个流程进行调优,例如使用 gulp (早于 Webpack 的一种打包工具)对 assets 中的文件进行 minify、图片压制等等。这些操作在今天看来无非就是引入一个基本的依赖,但当时做起来并不简单。
除此之外,有一个比较特别的地方,那就是路由管理。当时网站的路由被设计成了:
页面:
/archives/{{year}}/{{month}}/{{id}}
图片:
/images/posts/{{id}}/{{image}}.{{format}}
其中的 ID 是文章的全局 ID,但因为 Hexo 这样的工具并不像数据库那样为文章分配全局的 ID,所以当时还专门写了一个脚本:
import yaml
import glob
import timePOST_DIR = 'source/_posts/'def loader():posts = glob.glob(POST_DIR + '*.md')settings = []for post in posts:raw = open(post).read()head = raw.split('---')[1]try:setting = yaml.load(head)if set(['title', 'date', 'tags', 'id']).issubset(setting):setting['path'] = postsettings.append(setting)else:print('YAML parsing error: ', post)except Exception as e:print('YAML head not avaliable: ', post)return len(settings) == len(posts), settingsdef id_repair():all_correct, settings = loader()if all_correct:print('ALL SUCCESS')fixed = sorted(settings, key=lambda head: head['date'])for index, fix in enumerate(fixed):fix['id'] = index + 1return fixed, settingselse:print('PLEASE FIX YAML HEAD FORMAT FIRST')def id_writer():# goal:# repair id: ../images/posts/old/* => /images/posts/fixed/*fixed, old = id_repair()for i, fix in enumerate(fixed):try:with open(fix['path'], 'r', encoding='utf-8') as f:raw = f.read()try:content = raw.split('---', 1)[1].split('---', 1)[1]content = content.replace('](../images/posts/', '](/images/posts/')content = content.replace('/images/posts/' + str(old[i]['id']), '/images/posts/' + str(fix['id']))except Exception as e:print('ERROR: ', fix['path'])print(e)with open(fix['path'], 'w', encoding='utf-8') as f:f.write('---\n')stream = yaml.dump(fix, default_flow_style=False, allow_unicode=True)f.write(stream.replace('\n- ', '\n - '))f.write('---')f.write(content)f.close()print('SUCCESS: ', fix['path'])except Exception as e:print('FAILED: ', fix['path'])print('REASON: ', e)def main():id_writer()if __name__ == '__main__':main()
这个脚本的主要功能就是遍历所有文章,然后将文章按发表时间排序,然后按时间顺序依此为文章分配 ID。这样做的原因有:
可能要在某个旧时间节点上插入新的文章(例如找到了一些新的散落在 BBS 值得回收的文章)
文章编写过程中使用图片的相对路径可以方便预览,生成后通过替换图片的 URL 来保证图片能够被正确的路由。
现在回想起来这种 /year/month/id 的路由简直反人类,因为这样的路由并没有提供任何有用的信息。但当时可能只是因为防止爬虫能够轻易爬取,现在想来真是没有必要,反倒给现在的迁移带来了麻烦。
进行迁移的动机
这次的迁移的第一大原因是由数据驱动的。上面提到过,这个博客曾经只有不到一百的年活跃用户,但如今却已经成长为了每月上万的活跃用户了,这真是着实令我吃惊。
当然,这得益于今年莫名其妙的几次匿名推广,例如我本科时期写的蹩手蹩脚的 C++ 教程被国内知名公众大号机器之心在没有联系我的情况下直接推广[9] 等等。让我一跃晋升为坐拥 11k+ Star GitHub 项目的「大V」。如果有读者看到那个教程里 typo 百出,我很是抱歉,但无论如何看到自己的作品被他人认可还是很开心的。
进行迁移的第二个原因是我已经越来越难在新的机器上直接顺利编译整个基于 Hexo 的博客了。通常我的个人习惯会将所有的打包步骤封装到一个 make
命令。但随着时间的推移,我越发的发现 Hexo 及其所围绕的生态开始不断的进行破坏性的更改:
gulp 的打包脚本已经无法顺利执行,breaking changes 的修复需要重新熟悉 gulp 的工作机制并重写打包脚本
无法将博客顺利的升级到 Hexo 5.0 之后的版本
所依赖的主题 hexo-theme-next 的源仓库早已停止维护
自己定制的版本 changkun/hexo-theme-next 包含了太多主题上的定制
...
等等的这些原因让我开始觉得整个 Node.js 生态变得无比的不可靠,加之近几年对 Go 的使用愈发的频繁,并且开始被 Go 所崇尚的 New Jersey Style 的魅力而吸引,相比野蛮生长的 Node.js 和参差不齐的 NPM 生态,我更愿意相信 Go 的作者们,这也就成为了这次迁移定下了一个很好的目标:
到底能不能将这些混合了 C/C++/Python/JS/Go 的个人网站改造并简化为一个由纯 Go 驱动的网站?
正如你看到了这篇文章的那样,答案当然是可以的。
迁移的成本
进行迁移自然会问自己这样的问题:都 2020 年了,你怎么还没用上 Kubernetes ?诚然,个人网站充当的是技术的试验场,早年折腾自己博客的主要目的就是做各种各样的技术试验,所以我并不是没有想过,而且我为了能够用上 Kubernetes 和诸多 Cloud Native 生态,在 2018 到 2020 年期间为了这个小小的静态博客网站曾三次尝试向其靠拢,但如今的我的回答依然是:如无必要,勿增实体(Occam's Razor 原则)。显然 Kubernetes 很好,它有它专注解决的领域问题,但个人网站自然有其发展的需要。
迁移前,我的所有服务都搭建在一个 $5/月 的 Digital Ocean[10] 的 Droplet。我们不妨来计算一下为了用上 Kubernetes,需要花费多少成本:
Kubernetes Cluster:
$30
/月(1 Worker Node =$10
/月,3x)Container Registry:
$5
/月(Basic Plan,5 Repo,5GB Storage)Spaces:
$5
/月(250GB)
当然我不是没有考虑过其他的云,但大都比 DO 的开销更大(比如 GCP)。当然,并不是因为负担不起这笔费用,换做是本科时期对用上一些潮流技术极度痴迷的我,肯定早就换过去了。但随着自己「阅历」的增加,逐渐开始在这一方面变得越来越保守。
第一个原因是因为见过了一定数量轮替:比如早年我是 Evernote 的重度用户,但如今大热的 Notion 在我看来无非是资本狂欢下的又一个 Evernote,而且我现在也已经不再使用 Evernote,将里面的笔记整理迁移出来也成为了我一个非常头疼的待办事项。当然这样的例子还有很多,这里就不一一列举了;第二个原因是在我看来:技术的本质或者原理并没有发生变化,所谓的新生事物对我而言无非是新瓶装旧酒。与其追逐一些洪流,不如安下心来读一读 paper 并问问自己能够推导并实现多少个需要用到数学的算法。
那么就还是回到了刚才的问题,在 2020 年的今天究竟什么样的 Go 技术栈才适合个人网站?
新纪元(2021-)
从 Hexo 迁移到 Hugo
想要迁移到 Go 的第一个重大的转变就是摆脱 Hexo。这个要求其实并不简单,虽然我可以彻彻底底的将之前的 Next 主题抛弃,但毕竟这个主题用了这么多年我还是很希望能够在 Hugo 上找到同类主题,不出意料,果然已经有人做过了: xtfly/hugo-theme-next[11]。
不过可惜位老哥做主题也是给他自己用的,没有太多迁移支持,初次尝试下来这个主题还有很多问题:
动画闪屏:这似乎是 Next 主题的老毛病,估计这位老哥是直接将 Next 主题的 JS 脚本直接搬了过来
多余的特性:比如边栏中的地理位置追踪,比如文章分类(我个人倾向于直接使用 Tag)等等
需要额外的定制:Footer 的 Powered by XYZ 改为 Copyright Changkun Ou 等等
前面提到了第三纪元中网站路由的智障设计,因此这次迁移还需要对路由进行迁移,将博客的文章路由统一为 /posts/:slug
的格式。好在 Hugo 提供链接别名的功能,可以在一篇文章的 YAML Header 中指定别名链接,当访问到这些链接时可以跳转到 slug 指定的路由页面:
---
-date: 2020-03-08 21:56:31
+date: "2020-03-08 21:56:31"
+toc: true
id: 264
-path: source/_posts/2020-03-08-我为什么不再写博客了?.md
+slug: /posts/why-i-stopped-blogging
+aliases:
+ - /archives/2020/03/264/
tags:
- - 随笔
+ - 随笔
+ - 博客
title: 我为什么不再写博客了?
---
当然这个功能并不是手动完成的,为此我用 Go 编写了一个简单的脚本:
type oldh struct {Date string `yaml:"date"`ID int `yaml:"id"`Path string `yaml:"path"`Tags []string `yaml:"tags"`Title string `yaml:"title"`
}
type newh struct {Date string `yaml:"date"`TOC bool `yaml:"toc"`ID int `yaml:"id"`Slug string `yaml:"slug"`Aliases []string `yaml:""`Tags []string `yaml:"tags"`Title string `yaml:"title"`
}
func main() {filepath.Walk("../../content/posts", func(path string, info fs.FileInfo, err error) error {if info.IsDir() { return nil }b, err := os.ReadFile(path)if err != nil { panic(err) }ss := strings.Split(string(b), "---")header := []byte(ss[1])var old oldherr = yaml.Unmarshal(header, &old)if err != nil {log.Fatalf("cannot parse configuration, err: %v\n", err)}dd, err := time.Parse("2006-01-02 15:04:05", old.Date)if err != nil {panic(err)}newHeader := newh{Date: old.Date,TOC: true,ID: old.ID,Slug: fmt.Sprintf("/posts/%s", strings.Replace(strings.ToLower(old.Title), " ", "-", -1)),Aliases: []string{fmt.Sprintf("/archives/%d/%02d/%d/", dd.Year(), dd.Month(), old.ID),},Tags: old.Tags,Title: old.Title,}b, err = yaml.Marshal(newHeader)if err != nil {panic(err)}ss[1] = string(b)err = os.WriteFile(path, []byte(strings.Join(ss, "---\n")), os.ModePerm)if err != nil {panic(err)}return nil})
}
当对路由进行迁移时,还需要在 Disqus 中对文章的评论进行迁移,Disqus 提供了这样的迁移功能,可以通过指定路由映射表来迁移博客的评论,例如:
https://blog.changkun.de/archives/2020/01/262/, https://blog.changkun.de/posts/2018-2019-reading/
https://blog.changkun.de/archives/2020/02/263/, https://blog.changkun.de/posts/2019-summary/
https://blog.changkun.de/archives/2020/03/264/, https://blog.changkun.de/posts/why-i-stopped-blogging/
https://blog.changkun.de/archives/2020/03/265/, https://blog.changkun.de/posts/setup-wordpress-in-10-minutes/
https://blog.changkun.de/archives/2020/09/266/, https://blog.changkun.de/posts/eliminating-a-source-of-measurement-errors-in-benchmarks/
https://blog.changkun.de/archives/2020/11/267/, https://blog.changkun.de/posts/pointers-might-not-be-ideal-for-parameters/
综上所述,最终迁移到 Hugo 之后的博客使用的是我自己 Fork 并维护一份主题,有兴趣的读者可以在博客的源码中找到我自己定制的版本,其中着重修复前面提到的问题,并增加了这些特性:
Drak Mode
支持了 Disqus,删除了一些无用的百度、微信、多说(现已倒闭)分享等功能
增加了友链
标签按频次大小进行缩放
...等等
利用 Go 1.16 新特性进行编译
在 Go 的 1.16 中有一项新特性,能够将文件整个打包到二进制的执行文件中。
这段代码展示了如何利用 Go 1.16 的特性将生成的位于 public/*
文件夹中的静态文件统一打包到一个二进制文件中。
package mainimport ("embed""io/fs""net/http""os""path"
)//go:embed public/*
var public embed.FS// blogFS implements fs.FS
type blogFS struct {content embed.FS
}// Open opens a given filename from the public folder.
func (b blogFS) Open(name string) (fs.File, error) {return b.content.Open(path.Join("public", name))
}func main() {r := http.NewServeMux()r.Handle("/", http.FileServer(http.FS(blogFS{public})))const addr = "0.0.0.0:9129"s := &http.Server{Addr: addr, Handler: r}if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {panic(fmt.Sprintf("cannot listen on %s, err: %v\n", addr, err))}
}
容器化轻量级编排
我们已经决定了要将网站整个切换到纯 Go 的技术栈,那么我们就需要考虑要做那些变更。既然我们决定了不用 Kubernetes,那要不要考虑削弱版的 Docker Swarm?很明显也没有必要。但容器化是肯定的,容器化带来的打包和分发的便利性、以及运行时的隔离性、多重 replica 的特点对日后管理带来的方便远远大于其他缺点。同时考虑到 Docker 也是 Go 开发的项目(政治正确 应该叫 Moby),配合 Docker Compose 进行管理是再好不过了。
我个人喜欢 Go 的很大一个原因是他近乎完美的编译特性,一个简单的 go build
几乎解决所有的依赖问题,不需要静态链接更不需要运行时的动态链接。虽然编译过程中会有这些步骤,但这些步骤并不需要作为用户的我来操心,这也就让整个打包流程变得异常的简洁:
NAME=main
VERSION = $(shell git describe --always --tags)
build:CGO_ENABLED=0 GOOS=linux go build # 交叉编译docker build -t $(NAME):$(VERSION) -t $(NAME):latest -f Dockerfile .
Dockerfile 只需将打包好的二进制文件扔进 alpine 即可:
# 拷贝二进制文件即可
FROM alpine
COPY main /app/main
CMD ["/app/main"]
Docker compose 的编写也非常简单:
version: "3"
services:main:build:context: .dockerfile: Dockerfilerestart: alwaysimage: main:latestdeploy:replicas: 3
监控报警和其他服务
除了主网站和博客之外,还有一些其他的服务也运行中在服务器上。为了保证稳定性,我们需要对这些运行的服务进行监控,一旦出现问题就需要进行提醒,虽然个人网站自用的目的性更强,也就不会有 SLA 保障,但掉线好几天的对于网站的浏览者来说还是很不好的体验。个人使用的监控可以做得非常简陋:使用 crontab 不断的 curl 某个接口,当接口不可用时就触发某个邮件脚本,也可以做得非常花哨,比如用上 Prometheus 和 Grafana 等甚至对 CPU 和内存使用率进行监控。确实也可以,但作为个人网站,从历史经验来看,只有自己写的东西才能长久且兼容的维护下去。
所以,在这次的升级过程中,我顺手为 changkun.de[12] 编写了一个监控服务 upbot,并接入了邮件服务 mailgun,间隔固定的周期像某个服务发起请求来监视服务的可用性,当不可用时候给我发邮件报警。
除了监控服务外,changkun.de[13] 还运行了几个自己使用的服务,例如:
midgard:一个跨平台的剪贴板服务,可以在 Linux、Mac 和 iOS 之间自动同步剪贴板、快速为剪贴板中的内容或者本地的文件创建一个公开的链接等等功能(开发这个服务的原因是自身需要 ,但个服务搭建起来可能相对复杂,改天有时间录个使用教程吧 Orz 挖坑)
occamy:一个通用远程桌面服务,支持 VNC/RDP/SSH 三种协议的转译
redir:一个短链接服务,支持 PV/UV 统计
限于篇幅,这里就不详细介绍了,我们以后有机会再表,有兴趣的读者可以在文后找到链接。
当然网站上其实还有一些自己在用但没有公开提供的服务,比如服务器上还运行了一个 Jupyter 的 Server 等等。这些服务其实早年要么是直接一个 python3 -m http.server
直接跑在 Tmux 上,要么是用 hypervisor 挂起(部署方式取决于部署时的心情)。这次也一并统一给清理和容器化了。
最后,既然有这么多服务跑在服务器上,还需要反向代理的支持,虽然也可以自己写一个,而且 Go 的标准库中有 httputil.ReverseProxy[14]接口,但实现相对可靠、功能完善的反向代理的复杂性要比写一个简单的监控服务复杂得多(?) (至少在我看来还需要实现请求截断、重试、缓存、日志等等特性)。从远古纪元的 Apache、到第三纪元的 Nginx,既然我们的目标是至少用上 Go 编写的服务,那么 从 Cloud Native 生态发展而来的 Traefik 就是不二之选了,使用上非常傻瓜,看文档就能秒懂,也就不再进一步展开了。
回顾
这篇文章首先介绍了 changkun.de[15] 作为个人网站的迁移历史,以及每次迁移过程中的遇到的问题和决策,并据此展开了最近一次迁移过程中带来的「架构」升级,同时介绍了由于迁移需求而「自研」并正在运行的线上服务。此次迁移的亮点是目前整个网站完全依靠 Go 进行支撑,并从某种意义上实现了微服务。除此之外,文章还顺带介绍了如何利用 Go 1.16 带来的 embedded files 特性将网站的静态文件一并编译到用于分发的二进制文件中。
目前 changkun.de[16] 这个网站的整体结构如图所示:
这些服务都是用 Go 编写并开源的,感兴趣的读者可以在下面的链接中找到:
https://changkun.de/s/main
https://changkun.de/s/blog
https://changkun.de/s/midgard
https://changkun.de/s/redir
https://changkun.de/s/upbot
https://changkun.de/s/occamy
https://changkun.de/s/modern-cpp-tutorial (这是个例外 :)
除了这些之外,还有这些运行在 golang.design[17] 上的服务:
https://changkun.de/s/go-under-the-hood
https://changkun.de/s/go-history
https://changkun.de/s/gossa
https://changkun.de/s/code2img
他们也曾早期部署在 changkun.de[18] 上,算是由他孵化的新生儿吧。第三纪元的设计使用了三年左右的时间,希望这次的「组织架构」能够借助 Go 的兼容性稳定的服务超过三年。
欧长坤
2020 年 12 月 24 日 于 慕尼黑
参考资料
[1]
changkun.de: https://changkun.de
[2]changkun.de: https://changkun.de
[3]blog.changkun.de: https://changkun.de
[4]这里: http://localhost:9219/tags/%E5%8D%9A%E5%AE%A2/
[5]changkun.de: https://changkun.de
[6]changkun.de: https://changkun.de
[7]桌面客户端(基于 Electron)和移动客户端(基于 ReactNative): https://github.com/changkun/changkun-blog-clients
[8]Hexo RESTful API Generator: https://github.com/changkun/hexo-generator-restful
[9]推广: https://www.jiqizhixin.com/articles/2020-10-17-5
[10]Digital Ocean: https://www.digitalocean.com/?refcode=834a3bbc951b&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=CopyPaste
[11]xtfly/hugo-theme-next: https://github.com/xtfly/hugo-theme-next
[12]changkun.de: https://changkun.de
[13]changkun.de: https://changkun.de
[14]httputil.ReverseProxy: https://golang.org/pkg/net/http/httputil/#ReverseProxy
[15]changkun.de: https://changkun.de
[16]changkun.de: https://changkun.de
[17]golang.design: https://golang.design
[18]changkun.de: https://changkun.de
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 速石找人 | 工程师/市场/销售,12个职位,一起来搞云啊
这是一个招聘帖。 听说最近不景气,我们却在大量招人。 前端,后端,测试,解决方案,市场,销售,12个职位,统统在找人。 职位一:初级开发工程师——后端 职位二:高…...
2024/5/4 17:06:52 - 基于SSH框架的电影订票系统网站的设计与实现
源码及论文: 源码及论文下载:http://www.byamd.xyz/tag/java/开发计划 1. 甘特图 2. 开发计划简述 如图所示在项目初期阶段,首先开始需求调研。 需求调研阶段,我们将首先根据初期的会议内容考虑市场需求以及基本的市场现状&…...
2024/4/21 14:59:47 - 做完双眼皮脸变大了
...
2024/5/4 17:10:22 - 做完双眼皮来月经肿
...
2024/4/28 19:42:36 - 如何在Chrome中调试Angular2
参考:https://stackoverflow.com/questions/35856926/how-to-debug-angular2-in-chrome转载于:https://www.cnblogs.com/Ceri/p/7750720.html...
2024/4/21 14:59:43 - angular 调试工具安装谷歌浏览器插件Batarang
第一步,到github上面搜索一下batarang,或者直接到https://github.com/angular/batarang/releases去下载batarang,我选择为了最新版本的v0.10.9的zip进行下载,解压, 运行 npm install 注意,我运行了好几次都报错&#x…...
2024/4/21 14:59:42 - 做完双眼皮可以睡觉么
...
2024/4/21 14:59:41 - 做完双眼皮可以抽烟么
...
2024/4/21 14:59:40 - 做完双眼皮可以侧睡吗
...
2024/5/1 4:37:43 - 程序员资料整理
资料篇 技术站点 在线学习:Coursera、edX、Udacity、MIT公开课、MOOC学院、慕课网 Hacker News:非常棒的针对编程的链接聚合网站 Techmeme:美国知名科技新闻和博客聚集网站,类似的还有(Panda, Hacker & Designer…...
2024/4/21 14:59:39 - 分页查询
AngularJSBootstrap 分页功能实现,同时支持模糊查询分页 发表于2017/9/11 20:18:56 209人阅读 因为项目的需要需要实现页面的分页功能,需要用到AngularJSBootstrap来实现页面的分页功能,同时支持模糊查询分页。 思考了一下需要确定要完成以下…...
2024/4/20 15:09:24 - 做完双眼皮会冻么
...
2024/4/20 15:09:23 - 做完双眼皮画眼线就
...
2024/4/20 4:44:22 - 做完双眼皮后眼皮跳动
...
2024/4/27 12:18:00 - AngularJS实际项目应用——程序入口启动
一步一步看程序怎么启动的,angularjs是单页应用,基本就一个页面,页面主要结构如下: <div class"body-wrap"><!-- body--><div class"content-wrap" ui-view></div> </div> 页面…...
2024/4/21 14:59:37 - 做完双眼皮后眼睛小了
...
2024/4/21 14:59:37 - 做完双眼皮后眼睛干涩
...
2024/5/2 6:44:31 - 做完双眼皮后眼睛变小
...
2024/4/21 14:59:35 - 做完双眼皮后脸部肿了
...
2024/4/21 14:59:35 - SSH网上商城颗粒归仓【五.后端控制权限访问】
背景 这次在项目中遇到关于struts拦截的问题,背景是在用户执行实际的处理逻辑之前我们首先执行权限检查逻辑,使拦截器来进行检查,这让我们想起了angular4中的拦截器,当时候angular4拦截器的时候,我们可以在他之前进行…...
2024/4/21 14:59:33
最新文章
- KMP算法--C语言实现
#include <stdio.h> #include <assert.h> #include <string.h> #include <stdlib.h>void GetNext(char* sub, int next[]) {int lenSub strlen(sub);next[0] -1; // 初始第一个为 -1 第二个为 0next[1] 0;int i 2;int k 0;while (i < lenSub){…...
2024/5/5 0:10:57 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - Python读取文件里内容
如果要读取一个文件里的内容是 # 文件名:db.txt 1 2 3 4代码如下 import requests f open("db.txt", mode"rb") content f.read() f.close()data content.decode(utf-8)# 存到 list 里 data_list data.split(\r\n) print(data_list)# 结果…...
2024/5/3 15:30:08 - WIFI驱动移植实验:WIFI从路由器动态获取IP地址与联网
一. 简介 前面两篇文章,一篇文章实现了WIFI联网前要做的工作,另一篇文章配置了WIFI配置文件,进行了WIFI热点的连接。文章如下: WIFI驱动移植实验:WIFI 联网前的工作-CSDN博客 WIFI驱动移植实验:连接WIF…...
2024/5/4 17:27:10 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/4 23:54:56 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/4 23:54:56 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/5/4 23:54:56 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/4 23:55:17 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/5/4 23:54:56 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/5/4 23:55:05 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/5/4 23:54:56 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/5/4 23:55:16 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/5/4 23:54:56 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/4 18:20:48 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/5/4 23:54:56 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/5/4 23:55:17 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/5/4 23:55:06 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/5/4 23:54:56 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/4 23:55:06 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/5/4 2:59:34 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/5/4 23:55:16 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/5/4 23:54:58 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/4 23:55:01 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/5/4 23:54:56 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57