文章

从阿里云迈向Cloudflare与无服务器计算的一些思考 From Aliyun Towards Cloudflare and Thinkng About ServerLess

出于一些安全、政策以及海外访问方面的考虑,我将intmian.com的DNS从阿里云迁移到Cloudflare。

本文将记录下过程并对Cloudflare提供的serverless系列服务展开研究。

For reasons of security, policy, and overseas access, I migrated the DNS of intmian.com from Aliyun to Cloudflare.

This article will document the process and explore the serverless services offered by Cloudflare.

迁移流程 Migration Process

虽然域名商往往提供默认的解析服务,并且将更改DNS服务隐藏的非常深。但是其实这两者是分离的,可以将域名的解析托管到别的供应商。

Although domain registrars often provide default DNS services and deeply hide the ability to change DNS settings, these two functions are actually separate. You can host the domain's DNS with another provider.

关于DNS的基础知识 Basic Knowledge of DNS

DNS(Domain Name System) 是互联网的“电话簿”,它将域名(如 www.example.com)解析成计算机可以理解的 IP 地址(如 192.168.1.1)。每当用户访问一个网站时,浏览器需要通过 DNS 查询获取该网站的 IP 地址,然后与服务器建立连接。

域名解析的流程:

  1. 用户在浏览器中输入网址(如 www.example.com)。
  2. 浏览器首先检查本地缓存中是否已有该域名的 IP 地址。
  3. 如果没有,浏览器会向 DNS 服务器发起请求。
  4. DNS 服务器会从根 DNS 服务器开始,逐级查询权威 DNS 服务器,直到找到域名对应的 IP 地址。
  5. 浏览器获取到 IP 地址后,就可以与目标服务器建立连接,加载网页。

这里的权威服务器指的就是域名管理者在平台指定的DNS服务器。我们在DNS解析平台里操作的记录本质上就是权威服务器提供的应答。

域名托管平台向上层提供对应的顶级域名的权威DNS服务器,用户经过种种流程最终向权威服务器查询对应域名的解析服务。例如用户请求www.intmian.com,上层系统根据intmian.com找到域名托管平台指定的DNS服务器,DNS服务器根据内部规则提供对应的IP。

因为DNS服务器可以非常智能地提供IP,所以可以实现非常复杂的功能,例如对大陆IP的用户提供cn.intmian.com的C记录,从而嵌套解析到大陆的IP,对香港的用户提供hk.intmian.com的C记录,从而嵌套解析到香港的IP。甚至可以实现任播、负载均衡等高级功能,这里不做展开。

DNS (Domain Name System) is the "phone book" of the internet, converting domain names (like www.example.com) into IP addresses (like 192.168.1.1) that computers can understand. Whenever a user visits a website, the browser queries DNS to obtain the website’s IP address and then establishes a connection with the server.

The process of domain resolution:

  1. The user enters a URL (e.g., www.example.com) in the browser.
  2. The browser first checks if the IP address for the domain is in its local cache.
  3. If not, the browser sends a request to a DNS server.
  4. The DNS server starts from the root DNS servers and queries authoritative DNS servers step by step until it finds the corresponding IP address.
  5. Once the browser obtains the IP address, it can establish a connection with the target server and load the webpage.

The authoritative server refers to the DNS server specified by the domain registrar. The records we manipulate in the DNS resolution platform are essentially responses provided by the authoritative server.

The domain hosting platform provides authoritative DNS servers for the corresponding top-level domain. After a series of processes, the user queries the authoritative server for the corresponding domain resolution. For example, when a user requests www.intmian.com, the upper-level system identifies the DNS server specified by the domain hosting platform for intmian.com, and the DNS server provides the corresponding IP based on its internal rules.

Since DNS servers can intelligently provide IP addresses, they can enable complex functionalities, such as providing cn.intmian.com C-records for users in mainland China, resolving to IPs in China, or providing hk.intmian.com C-records for users in Hong Kong, resolving to IPs in Hong Kong. Advanced features like Anycast and load balancing can also be implemented, though I won’t elaborate here.

为什么迁出,为什么Cloudflare Why Migrate and Why Cloudflare

阿里云的DNS之前其实挺好用的,有很多(虽然我用不上的)高级功能。但是因为一些人的滥用,目前一些复杂的功能需要付费才能获得,也没有了免费的海外的解析服务器。同时出于一些政治与监管上的担忧,我就想将阿里云的DNS服务逐渐迁出。

因为Cloudflare提供了很多免费的强大功能以及具备非常强大的企业信用,我最终决定将域名香港迁移到Cloudflare。本来打算直接将域名转移到Cloudflare,但是经过研究后发现仅仅托管(指更改解析服务器)就可以达到预期的功能。这样的话也更为灵活,也方便后期改回。

转移域名是个很笨重的行为,甚至需要额外缴纳一年的域名费用来在新平台续费。

Aliyun’s DNS used to be quite useful, with many advanced features (though I didn’t use most of them). However, due to abuse by some users, some complex features now require payment, and the free overseas resolution servers are no longer available. Additionally, due to political and regulatory concerns, I decided to gradually migrate away from Aliyun’s DNS services.

Because Cloudflare offers many powerful free features and has strong enterprise credibility, I ultimately decided to migrate my Hong Kong domain to Cloudflare. I originally planned to transfer the domain to Cloudflare entirely, but after researching, I realized that simply hosting (i.e., changing the resolution server) would achieve the desired functionality. This approach is more flexible and allows for easier reversal later.

Transferring a domain is a cumbersome process and even requires an additional year's domain renewal fee on the new platform.

将阿里云平台的DNS平台改到Cloudflare Change DNS Platform from Aliyun to Cloudflare

前往域名管理界面,选择对应域名的管理。Go to the domain management interface and select the domain to manage.

image-20241219144617537.png

侧边栏选择DNS修改。In the sidebar, select DNS modification.

image-20241219143651525.png

在这个界面输入下文中获取的DNS地址。In this interface, input the DNS addresses obtained in the following section.

image-20241219143724315.png

托管到Cloudflare Hosting on Cloudflare

登录Cloudflare,选择网站->添加域 Log in to Cloudflare, select "Website" -> "Add Domain."

image-20241219173135002.png

输入域名并选择free套餐。此时会显示您的流量几乎已准备好使用代理,并且允许快速导入扫描到的记录.这里不要勾选直接选择继续前往激活。Enter the domain name and choose the free plan. At this point, it will show "Your traffic is almost ready to use proxy," and allow you to quickly import scanned records. Do not check any options, just proceed to activation.

image-20241219144108081.png

将这里获得的DNS服务器按照顺序填入上文的阿里云DNS服务器配置中。Fill in the DNS servers obtained here into the Aliyun DNS server settings mentioned earlier.

image-20241219144214107.png

在阿里云确认后,点击立即检查名称服务器。等待十几到几十分钟后就成功将域名托管在Cloudflare了。After confirming in Aliyun, click "Check Name Servers Now." After waiting for a few minutes to tens of minutes, the domain will be successfully hosted on Cloudflare.

导入DNS记录 Import DNS Records

在托管后,所有的原来的解析记录都会处于不可访问的状态,因为新的权威DNS服务器没有记录,此时我们需要从阿里云导出DNS记录。

选择阿里云域名控制台中的解析

After hosting, all the original resolution records will be inaccessible because the new authoritative DNS server has no records. At this point, we need to export the DNS records from Aliyun.

Select the "Resolution" section in Aliyun's domain console.

image-20241219144617537.png

image-20241219144705677.png

image-20241219144652545.png

选择导出zone记录,这是一个exe文件。在Cloudflare中选择导入

Select "Export Zone Records," which will provide an exe file. Then, choose to import these records on Cloudflare.

image-20241219144807093.png

就可以将原来的解析记录全部导入。但是此行为会导入两个NS记录,指定由阿里云服务器解析,这里不用管阿里云,删掉就好了。

如果用户使用的是特殊区域的受限互联网,请注意解析设定一定不要启动CDN,仅在解析时启动DNS功能。特别是你的服务器也接入特殊区域的受限互联网,会在分配CDN时产生非常离谱的网络问题。例如请求者在中国大陆,服务器也在中国大陆,但是CDN在美国洛杉矶……

This will import all the original resolution records. However, this process will also import two NS records specifying Aliyun's servers for resolution. You can ignore these and simply delete them.

If users are in regions with restricted internet access, ensure that CDN is not activated in the DNS settings—only DNS functionality should be enabled. This is especially important if your server is also in a restricted region, as assigning a CDN could cause absurd network issues. For example, the requester is in mainland China, the server is also in mainland China, but the CDN is in Los Angeles, USA…

一些有趣的Cloudflare功能 Interesting Features of Cloudflare

Cloudflare提供一些很方便的小功能用于建站。

  1. DNS 解析服务:提供全球范围快速的 DNS 解析,减少访问延迟。
  2. CDN(内容分发网络):将网站内容缓存到全球服务器,提升加载速度。有传统CDN缓存和全向反代的CDN和隧道,便于隐藏真实IP避免攻击。
  3. Web 应用防火墙(WAF):阻止常见的 Web 攻击(如 SQL 注入、XSS)。
  4. DDoS 防护:自动防护基本的分布式拒绝服务(DDoS)攻击。
  5. SSL/TLS 加密:免费提供 SSL 证书,保障网站数据加密传输。可以快速为传统HTTP网站添加HTTPS。
  6. 性能优化:自动压缩和优化图像、CSS、JavaScript 提升加载速度。提供一些图片操作API。
  7. 访问0控制与安全:可以控制哪些 IP 或国家可以访问网站。
  8. 页面规则:设置 URL 重定向和自定义缓存规则。
  9. 分析和报告:提供网站流量分析和性能报告。
  10. Always Online:当原服务器宕机时,展示缓存的静态页面。
  11. 文件系统:提供大量免费的OSS额度。
  12. 邮件:可以快速为域名添加证明邮件可信的MX记录,并提供邮件服务。支持创建邮件账号并转发邮件到设定的账户。

Cloudflare offers some very convenient features for building websites.

  1. DNS Resolution Service: Offers fast global DNS resolution, reducing access latency.
  2. CDN (Content Delivery Network): Caches website content to global servers, improving loading speed. Offers traditional CDN caching, full-proxy CDN, and tunneling, making it easier to hide the real IP address and avoid attacks.
  3. Web Application Firewall (WAF): Blocks common web attacks such as SQL injection and XSS.
  4. DDoS Protection: Automatically protects against basic distributed denial-of-service (DDoS) attacks.
  5. SSL/TLS Encryption: Offers free SSL certificates to secure encrypted data transmission on websites. Quickly adds HTTPS to traditional HTTP sites.
  6. Performance Optimization: Automatically compresses and optimizes images, CSS, and JavaScript to improve loading speed. Also provides some image processing APIs.
  7. Access Control and Security: Allows control over which IPs or countries can access the website.
  8. Page Rules: Set URL redirects and custom caching rules.
  9. Analytics and Reporting: Provides traffic analysis and performance reports for your website.
  10. Always Online: Displays cached static pages when the origin server is down.
  11. File System: Offers a large amount of free OSS (object storage) credits.
  12. Email: Quickly adds MX records to verify email domain credibility and provides email services. Supports creating email accounts and forwarding emails to designated accounts.

使用Cloudflare搭建无服务器计算(ServerLess)Building Serverless Computing with Cloudflare

自从AWS在15年提出了ServerLess以后,似乎这个概念先是兴盛继而转向衰败,并未如同预期的彻底取代传统服务器部署服务的模式。

我之前也觉得这个和Web3.0一样,就是些技术装逼爱好者口中的空泛概念。但是随着技术阅历的增长,我也改变了我的一部分观念。似乎现在前后端分离的SAP(单页应用)为前端的应用特别适合ServerLess,或者确切说,适合将部分模块转入ServerLess。

将前端放在Cloudflare Page(类似于GIthub Page),后端的部分放在Worker,持久化部分放在D1 SQL数据库,缓存放在KV数据库,一部分公开数据放在R2对象存储。其实就是个相当完备的ServerLess系统。用户访问Cloudflare Page,Page请求Worker和R2,Worker访问D1读取状态并将修改后的数据持久化到D1。在部分情况下这个是可行的,以下我进行讨论。

Since AWS introduced the concept of ServerLess in 2015, it initially gained popularity but later seemed to decline. It has not entirely replaced the traditional server deployment model as originally anticipated.

I used to think this was like Web 3.0—just a nebulous concept hyped up by tech enthusiasts. However, as my technical experience grew, my perspective changed. It seems that single-page applications (SPAs) in a front-end and back-end separated architecture are particularly well-suited for ServerLess, or more precisely, for moving certain modules into ServerLess environments.

The front-end can be hosted on Cloudflare Pages (similar to GitHub Pages), the back-end on Workers, persistent storage on the D1 SQL database, cache on the KV database, and some public data on R2 Object Storage. This essentially forms a complete ServerLess system.

When users access Cloudflare Pages, the Pages send requests to Workers and R2. The Workers query D1 for the current state, modify it, and persist the changes back to D1. In some scenarios, this setup is feasible, as I’ll discuss below.

前端部分 Front-end

能否部署在在Page取决于前端应用是否可以独立打包成一个静态文件夹,且有一个index入口。

  • 静态网页一般都可以。例如早期的真正意义上的静态网页,或者hexo等打包转换出的静态网页包。
  • react等前后端分离的项目如果可以通过vite打包成一个前端包也可以,可以将后端的请求处理成请求worker。
  • PHP、ASP或者Django返回的前端界面:这种浏览器访问框架,框架通过模板模板生成出的前端是不可以的。

对比传统nginx部署+CDN的方式,虽然可控性并没有传统方式好,但是相对更加灵活,性能理论上也更高一些。

Whether the front-end can be deployed on Pages depends on whether the application can be independently packaged into a static folder with an index entry point.

  • Static websites generally work, such as early truly static websites or static site bundles generated by frameworks like Hexo.
  • React and other front-end and back-end separated projects can also work if they can be bundled into a front-end package using tools like Vite, with back-end requests handled by Workers.
  • PHP, ASP, or Django-generated front-end pages are not compatible, as these frameworks generate front-end code dynamically through templates.

Compared to traditional nginx deployment + CDN setups, this approach offers less control but is relatively more flexible and theoretically higher-performing.

后端部分 Back-end

丑化说在前面 The Downsides First

后端其实不太适合完全托管成ServerLess。

  • ServerLess的服务,一旦复杂了以后,需要非常强的架构设计能力,因为这个是本质上需要将程序设计为纯无状态的,每个请求是独立的,仅依靠KV数据库的锁实现同步管理。如果业务逻辑非常复杂,甚至这种架构是无法设计与实现的。
  • 受限于非常复杂的ServerLess底层架构和一些设计的缺陷,服务的延时、可靠性是很难保证的。这导致了ServerLess其实不太适合游戏等对延时、可靠性要求比较高的业务。
    • 只能使用解释型语言,虽然方便了ServerLess平台端设计,但是会导致运行效率较低,虽然可以通过无限扩容实现极高并发,但是单个请求的延时会偏高,特别是执行非常复杂的计算的情况下。
    • 传统服务器可以在内存里保存非常复杂的状态或保存一个非常复杂的系统,ServerLess只能访问KV数据库。KV数据库不仅仅带来了网络延时,也没法做到如同原生数据结构一样的性能。KV数据库提供的数据结构就这么几种,无法覆盖所有的需求,也无法自己实现。
    • 分布式的环境下,R2、D1、KV的请求是极为高度复杂的,涉及到缓存的穿透和跨大洲级别的网络成本,但是传统服务器可以很好的通过运维提前部署,做到reddis、数据库都能以极低延时被逻辑服务器访问,且可以通过集群做到高可用、高性能。更何况依赖于别人封装好的东西也会有可用性的问题,传统方案最起码替换魔改数据库是可行的,数据的流向和请求的逻辑都是透明可见的。
    • 如果业务依赖的状态非常大,每一次执行都会拉去非常大的依赖,其实性能问题是很大的。特别是有些有些游戏后端,需要对人工配置的东西进行复杂的二次加工。
    • 就算KV在最理想的情况下工作,能够媲美redis局域网工作的性能,也难以做到内存直接共享。
  • 很多时候我们不需要那么高的可用,也不适合为了高可用投入过多的心智成本。越复杂的东西维护成本其实也就越高,且越容易出问题。这体现在ServerLess平台本身其实有时都会出现高可用性的问题。
  • 非用户请求被动触发的逻辑其实是很难做的,例如cron定时等,要么以很扭曲的形式实现,要么就是干脆实现不了。
  • ServerLess中能使用的js、ts、python其实很难使用第三方库或者复杂的本地依赖。很多依赖于原生系统环境的应用根本是没办法部署的,例如ai的框架和依赖只能调用Cloudflare本身的工具进行拼积木。
  • 类似于微服务,这种流通很复杂的东西万一出问题了确认dump和调试都是比较困难的。
  • 因为系统比较复杂,所以成本的预估可能充满了困难,甚至由于很多细节是不透明的原因,。
  • 不可控的处于黑盒的细节太多了,就算服务商宣传的可靠性里面的9很多,也难以使真正的决策者安心。

而后端的无限伸缩或者高可用性很多时候其实可以通过k8s+docker或者简单的负载均衡+准无状态(尽量将状态以合理的设计放在reddis)实现,以锁或者hash环的方式保证同步异步和一些涉及多个用户的设计,不需要依赖如此复杂的方案。

综上如果业务小似乎不用上这个ServerLess,如果业务大似乎不太适合上ServerLess,总的来说只能算是一个很“有趣”的技术选型。

Backend is actually not very suitable for being fully managed as Serverless.

  • Serverless services, once they become complex, require very strong architectural design capabilities because, at its core, the program must be designed to be stateless. Each request is independent and relies solely on KV database locks for synchronization. If the business logic is very complex, this architecture may even be impossible to design and implement.
  • Due to the complex underlying architecture of Serverless and some design flaws, the latency and reliability of the service are hard to guarantee. This makes Serverless unsuitable for businesses with high demands on latency and reliability, such as gaming.
    • Only interpreted languages can be used, which, although convenient for the Serverless platform design, leads to lower execution efficiency. While infinite scalability can achieve extremely high concurrency, the latency for individual requests tends to be higher, especially when performing complex calculations.
    • Traditional servers can store very complex states or systems in memory, but Serverless can only access KV databases. KV databases not only introduce network latency but also lack the performance of native data structures. The few data structures provided by KV databases cannot meet all the requirements, and it's not possible to implement them independently.
    • In a distributed environment, requests to R2, D1, or KV are extremely complex, involving cache penetration and the network costs of cross-continent communications. In contrast, traditional servers can be efficiently deployed in advance through operations and maintenance, ensuring low-latency access to Redis and databases via logic servers, and can achieve high availability and high performance through clustering. Moreover, relying on encapsulated solutions from others introduces availability issues, while traditional solutions can at least replace or modify databases, with the data flow and request logic being transparent and visible.
    • If the business relies on very large states, and each execution pulls large dependencies, performance issues become significant. This is particularly true for some game backends, where complex post-processing of manually configured elements is required.
    • Even if KV works in the best-case scenario and matches the performance of Redis in a local network, it's still hard to achieve direct memory sharing.
  • Many times, we don't need such high availability and shouldn't invest excessive mental cost into achieving it. The more complex something is, the higher the maintenance cost, and the easier it is to encounter problems. This is reflected in the fact that even the Serverless platform itself sometimes faces availability issues.
  • Logic triggered passively, not by user requests, is difficult to implement, such as cron jobs, which are either implemented in a convoluted way or simply cannot be done.
  • The JavaScript, TypeScript, and Python environments available in Serverless are hard to integrate with third-party libraries or complex local dependencies. Many applications that rely on the native system environment can't be deployed at all. For example, AI frameworks and dependencies can only use Cloudflare's native tools to "piece together" functionalities.
  • Similar to microservices, if something goes wrong in a system with complex communication flows, confirming dumps and debugging can be difficult.
  • Due to the complexity of the system, cost estimation can be very challenging, especially since many details are opaque.
  • There are too many uncontrollable, black-box details, and even though the reliability claimed by service providers may include many 9s, it is difficult to reassure decision-makers.

On the other hand, backend scalability or high availability can often be achieved through K8s + Docker or a simple load balancing + quasi-stateless architecture (by placing states in Redis with a reasonable design), using locks or hash rings to ensure synchronization and asynchronous processes in designs involving multiple users. There's no need to rely on such complex solutions.

In conclusion, for small businesses, Serverless may not be necessary. For large businesses, Serverless may not be suitable. Overall, it can only be considered a very "interesting" technology choice.

然而 However

以上都是“丑话说在前面”的内容。坦白的说,也许是出于某些偏见或者惯性我其实对于这种花里胡哨的东西是比较难以接受,所以丑话写的特别的长:)。但是其实如果满足一定的情况,很多应用却很适合放在worker上面。

一些逻辑相对简单,涉及到的状态和同步异步流程都很少甚至没有的服务完全可以放在worker上,例如只是打开时去数据库查询一下统计数据,就不需要自己弄一套服务器同时部署后端,直接修改worker代码虽然协作上可能有点问题,但是一定是更加灵活了

一些纯前端功能,出于安全和开发便利性考虑可以拆分敏感部分在worker。很多时候如果只是简单的做一些供个人或者小范围使用的业务快速开发,全栈开发者会倾向于将逻辑全部放在前端,例如我对于memos的二次开发全部挂靠在platform的前端,因为业务简单,做界面的时候顺手就做了。反正无论如何前端都是要写的,如果逻辑很简单加上节约交互成本的考虑完全可以把功能做成纯前端的。这样也可以更好的节约服务器资源。这种情况下就很适合将秘钥或者ID等敏感数据或者不希望用户看见或者明文存储在本地的东西放在worker或者通过worker存储在在线的基础设施内。就算用户自己没有管理好电脑的权限,有人通过f12或者本地的形式读取量cookie或者storage也不会酿成进一步后果,用户改个密码就行了。

一些非常简单的应用如果做成ServerLess可以节约大量的传统意义的开发成本和运维成本。特别是前后端分离的应用,如果确定后端的api都是可以被替换成worker的,那就可以可以做成ServerLess。但是所谓少即使多,如果之后应用复杂到一定的程度,那反而会吞噬掉一切人员的一切心智,需要开发者进行权衡

在全栈开发的一些情况,开发者有时会全用同一种语言开发前后端,类似前端React,后端Next.js。这种情况迁移后端到ServerLess的成本相对较低,如果有额外的好处可以考虑下。

当然也可以渐进式的将一部分后端替换为worker,一部分请求依然是传统地请求后端api,或者将后端api由worker代理,做到彻底隔离后端,这也是隐藏后端的一种方式,相对也会更加灵活。

The above is all the “downsides first” content. Honestly, perhaps due to some biases or inertia, I find it hard to embrace such fancy concepts, so I wrote an especially long section on the drawbacks. :) But in reality, many applications are well-suited for Workers if certain conditions are met.

Services with relatively simple logic and minimal or no state or synchronization/asynchronous processes can be entirely placed on Workers. For example, if a service only queries the database for statistics upon being opened, there’s no need to set up a separate server for the back-end. Directly modifying Worker code may have some collaboration issues, but it’s undoubtedly more flexible.

Some purely front-end functionalities can separate sensitive parts into Workers for security and development convenience. Often, for quick development of applications for personal or small-scale use, full-stack developers prefer placing all the logic in the front end. For example, in my secondary development of Memos, I attached everything to the platform's front end because the logic was simple, and it was convenient to handle while working on the interface. After all, the front end needs to be written anyway. If the logic is simple, it’s perfectly feasible to implement the functionality entirely in the front end, reducing interaction costs and saving server resources. In such cases, it is ideal to place keys, IDs, or other sensitive data—anything you don’t want users to see or store as plain text locally—in a Worker or store them in online infrastructure through a Worker. Even if the user fails to secure their device and someone accesses cookies or local storage via F12 or similar methods, the consequences won’t escalate; the user simply needs to change their password.

Some very simple applications can save considerable traditional development and operational costs by being implemented as ServerLess. This is particularly true for front-end and back-end separated applications, where the back-end APIs can all be replaced by Workers. However, the saying "less is more" applies here—if the application grows complex enough later, it may instead consume all the mental energy of your team. Developers must weigh this trade-off carefully.

In some full-stack development scenarios, developers may use the same language for both front-end and back-end, such as React for the front-end and Next.js for the back-end. In such cases, migrating the back-end to a ServerLess architecture has relatively low costs, and it’s worth considering if there are added advantages.

Of course, it’s also possible to gradually replace parts of the back-end with Workers while keeping some requests directed to traditional back-end APIs. Alternatively, Workers can be used to proxy back-end APIs, completely isolating them. This also serves as a way to hide the back-end and provides greater flexibility.

后言 Conclusion

本来只是打算简单的写一些关于Cloudflare的内容。但是仔细研究了Page和worker,感觉又有了研究的热情,加上想到哪写到哪,就有点写多了,而且写的很杂乱:)。看来除了技术,语文也是一门我需要研究的学问。

顺带一提,我放弃谷歌广告了,牛皮癣广告有违我的分享初衷,同时为了更更多人能够看见这些文章,提供了英文版本。

Originally, I only planned to write something simple about Cloudflare. However, after diving into Pages and Workers, I found renewed interest in exploring these technologies. As I wrote, I kept following my train of thought, which resulted in a lengthy and somewhat disorganized piece. :) It seems that, besides technology, writing is another skill I need to study further.

By the way, I've given up on Google ads. The intrusive ads go against my original intention of sharing, and in order for more people to see these articles, I have provided an English version.

The English part is translated by OpenAI

License:  CC BY 4.0