我的碎碎念

不为繁华易匠心,不舍初心得始终。

0%

近期因工作和出海业务需要,开始研究一些方便部署云服务的平台。

之前有接触过vercel,sealos等平台,但是vercel对中文用户不友好,sealos费用又比较高。综合评估下来, 最后深入使用了zeabur平台。下面简单把自己对zeabur的使用体验发表成文。

什么是zeabur?

zeabur是台湾公司出品的一套部署服务的平台,支持各种编程语言和开发框架。对比传统的部署方式,Zeabur 可以在几分钟内完成部署,不需要花费大量的时间去学习部署的相关知识,把时间精力专注于产品的开发。

并且zeabur也很注重中国市场,除了支持信用卡付费以外,也支持支付宝付费,使用的是stripe支付平台。

三步快速在zeabur部署服务

第一步,你需要创建一个zeabur帐号。

可以点击这个链接创建一个,zeabur目前支持邮箱和github社交认证。

第二步,就是创建项目。

登录成功后,你会被自动重定向到 Zeabur 的控制台页面。 点击右上角的【创建项目】按钮创建一个新的项目。之后你会看到一个弹窗来供你选择你的项目所在的区域。

第三步:部署服务。

点击你刚刚创建的项目,Zeabur 会为你打开该项目的详情页面。

最后选择你要部署的服务部署就行。

更多细节可以参考我如何在zeabur部署hexo博客

zeabur的付费方案有哪些?

zeabur目前有3种类型的方案:免费方案、开发者方案和团队方案。我目前使用的是开发者方案,每月需要5美元,换算成人民币就是35块。和各大云厂商的每月基础版的云主机价格相差不大。

这5美元也是你当月的免费使用额度,超出的用量另外计算。我部署的一个基于python的AI音乐web服务,经过优化后,每天用量是在0.04-0.05美元之间,30天最多是花费1.5-1.6美元之间。如果用量大不,还可以多部署2个这样的docker web服务。

某服务zeabur资源近七天用量图

但是,你除了可以在zeabur部署docker服务以外,还可以在zeabur部署serverless服务!

zeabur是怎么部署服务的?

zeabur提供两种部署机制,一个是docker容器机制,另一个是serverless机制。

什么是serverless?对于zeabur的使用者来说,serverless是一个无状态的部署方式,当有请求来时才启动你的服务,没有请求时则暂停,不消耗任何资源,并且收费也是根据你的使用资源来衡量。也就是按需使用,按需付费。

docker机制对于开发者应该很熟悉了。zeabur的docker机制是长时间运行的服务,如果你的服务应用是有状态的,需要长时间运行的,那么可以使用docker机制来部署,同时每分钟每小时都会计算你的使用资源。

但比较可惜的是,截至2024年10月,zeabur的serverless还不支持python的异步服务器(asgi server),因此也不能部署fastapi框架的服务,只能使用docker机制部署。

zeabur支持多种部署代码来源,包括:

  • 从github仓库部署
  • 从模板部署
  • 直接部署数据库,比如mysql或mongodb
  • 从本地上传源码部署
  • 从docker镜像部署
  • 等等

我最常用的有三个:自己的项目是上传到github,然后从github仓库部署;需要数据库什么的,就直接从官方提供的资源部署数据库;如果是某些web服务别人已经创建好模板了,就会从模板部署。

如果你也对zeabur服务平台有兴趣了,可以点击下面链接尝试体验:https://zeabur.com?referralCode=AngelLiang

AI编程课二期第一次答疑,有位同学提出了一个重量级的问题:「感觉 Python 不是很适合编写程序,因为有全局解释锁的存在和动态编译导致的性能问题,后续如何学习 c 语言或者 JAVA?」

我第一眼看到这个问题也头痛,如果我来回答,会分为两部分:Python的性能问题和如何学习其他语言,我这篇文章只针对前者进行探讨。

追求速度是人类的天性。Python在性能这一块指标肯定是拿不到前三名的,但不代表不能在TIOBE编程语言排行榜拿下每月第一名。回想起在AI时代的智识四课阅读课中,有一本最经典的计算机书籍——保罗·格雷厄姆在2004年出版的《黑客与画家》——这本书里面的一些观点就可以很好地解答Python到底适不适合写程序。我把书中几个观点提取出来,并结合自己的开发经历,略和大家讨论一二。

必须承认,如果你关注运行速度,最好使用接近机器的语言

我大学所学的电子信息工程专业,学习的第一门语言就是C语言,在我专业中需要对一些资源很小的芯片进行编程,简称单片机开发,需要使用的语言就是C语言。虽然也有些人移植了Python到单片机,但是对于商业化电子产品来说,可能并不会真正使用高级语言去开发单片机。

一个原因就是高级语言运行速度太慢,单片机是一个硬件资源受限制的开发环境,本身CPU运算速度根本达不到GHz级别,有些小家电的单片机的运行速度可能只有12MHz,如果再跑一个Python虚拟机,再在上面运行字节码,恐怕运行速度会很慢。并且这种开发更多的是属于制造业领域,需要考虑硬件成本,那么为了在单片机上跑Python,就需要好一点的芯片,于是硬件成本就上升了。

另外不喜欢用高级语言开发单片机的原因是,由于高级语言做了一层封装,所提供的接口没有C语言的SDK多,以至于没有把一些硬件资源引出来,无法进行控制,最后明明芯片是支持的功能,却无法使用。

当然,还有一些其他领域会使用C语言,比如web服务最常见的代理网关nginx,以及机器学习领域常用的numpy库的底层实现,都是使用C语言开发的。它们使用C语言不外乎以上两点原因,提高运行速度或调用硬件资源。

对于半路出家学习编程的同学来说,大多数还是做应用开发。此时,程序员的时间比计算机的时间昂贵得多

应用开发是需要编写大量的业务代码的。对于开发者来说,首先是收到需求(哪怕是自己想的灵感,也可以算是一种需求);然后理解需求,如何把这个需求进行分解,需要实现几个功能模块,有没有可以直接调用的库,还是要自己编写;最后才是实现需求,写下一行行代码。

低级语言,比如C语言和汇编语言,运行速度是很快,也能直接调用硬件资源。但是,使用它们开发效率会非常低。你需要编写大量的代码才能实现一些功能,而使用高级语言就很简单,比如同样是编写一个Hello World程序:

C语言版本的Hello World

1
2
3
4
5
6
#include <stdio.h>

int main() {
printf("Hello World\n");
return 0;
}

Python版本的Hello World

1
print("Hello World")

你看!Python是多么的简洁。此时该语言的优点就来了,开发者可以直接思考如何实现业务功能,不需要更多的心思去想语法细节。开发者的时间就这么节省出来了。

另外,保罗·格雷厄姆说:「一个功能所需的代码越多,就越难避免bug,也越难发现它们。」。写过C语言的人都知道,有时自己的程序运行达不到预期,排查来排查去,发现就是某行末尾少了一个分号。Python则没有这些问题,Python是以缩进规则表示代码块的开始或结束,而不是花括号或分号。也不会有类似Java的空指针问题,或者忘记回收内存导致内存泄漏。这些很底层的问题,Python解析器都帮你解决好了。

确实有的语言内核设计并不是很好,比如Python的全局解释锁。但是,Python有很多很强大很有用的函数库,可以用来解决开发者很多问题。在编程开发中,总有一些很琐碎普遍的问题,开发者需要花费大量的时间去解决,但是有了函数库之后,解决起来就变得容易多了。所以这些函数库比语言的核心还重要,也就是这个语言的生态。

Python是动态类型语言,也就是说,你可以给一个变量赋予整数类型,然后这个变量再赋值字符串类型,甚至一个函数也是可以的。而静态类型语言,比如C语言,则不允许你这样做,你在声明变量的时候,就需要确定好是整数类型还是字符串类型。

虽然使用静态语言这样可以防止bug,也可以帮助编译器生成更快的代码;但是这样也对程序构成了限制,无法更自由的编写程序。

自由是一把双刃剑。在Python界有一句名言:动态一时爽,重构火葬场。使用Python编写代码确实很爽,你不需要考虑任何数据类型,直接声明一个变量就可以使用,但是这个也给后期维护代码带来了麻烦。人是善忘的,前一秒你传入了字符串类型,下一秒你却当整型来处理,不怕开发时Python发出尖叫告诉你这里有bug,就怕在生产环境中直接掉进bug坑里出不来。

因此,Python在其3.5版本加入了类型提示的功能,可以给一些静态分析工具进行类型检查。之后一些优秀的函数库,比如Pydantic,你使用的时候强制需要你定义类型,也是为了保护好代码的可维护性。

与其争辩Python的性能,不如跳出圈外,关注点其他方面,比如面向对象编程

什么是面向对象编程?它和函数式编程相对应。一个程序员在接到一个要编写「毁灭地球」的任务的时候,他不会直接编写一个「毁灭地球」的函数,而是编写一个「毁灭行星」的函数,然后把「地球」传参进去。这个就是函数式编程。而面向对象编程,就是把「毁灭行星」这个函数,作为「宇宙」这个类的方法。

1
2
3
class Space:
def destroy_planet(self, planet):
...

面向对象编程的优点在于,如果你需要添加「毁灭恒星」的功能,那么只需要添加相应的方法就可以了,甚至可以不修改程序其他部分。

编程语言有静态和动态之分,对于面向对象编程,编程语言只有程度之分。目前只有两种程度的面向对象编程语言,一种是允许你面向对象编程,另一种是强迫你必须面向对象编程,比如Java,Java版本的Hello World,你必须先写一个Main的类,再写一个main方法,最后才能打印Hello World

1
2
3
4
5
public class Main {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

保罗·格雷厄姆认为后一种语言是不可取的,我也是这么认为的。最好的方案是使用允许你面向对象编程的语言,最后编写代码的时候到底用不用,则是另外一个问题。这也是接下来我想探讨的。

在AI编程首期,我遇到了这么一个问题:「什么时候使用类去编程,什么时候使用函数去编程?」

我回答是,在我的开发经历当中,有几个地方是必须使用面向对象编程的。

第一个是编写ORM的代码的时候,就必须使用面向对象去编程。什么是ORM?就是数据库中的一张表映射为代码中的一个类,之后你对这个类的对象进行操作,就相当于操作这张表的数据了。

另一个是需要继承框架的一些方法才能运行的时候,比如使用PyQt编写桌面端应用程序,必须继承它的QtWidgets类,才能编写一个组件显示在界面上。

那么什么时候使用函数去编程?除了以上两种场景,其他情况都可以使用函数去编程。在web开发中,我更喜欢使用函数去实现HTTP接口,而不是类。除了实现接口,一些辅助函数,我也习惯使用函数去实现。但是如果遇到了复杂的业务规则,我就会使用类和方法来实现。因此我的一个准则是:简单的功能用函数实现,复杂的功能用类与方法来实现。

除了类与方法,还需要关注的最重要的一点就是数据库。面向对象编程可以跨语言讨论,但是SQL语言除外。千万不要拿面向对象编程的思维去设计数据表。

Python的ORM工具极其强大,你可以直接使用面向对象编程的方式,去设计一个个数据表对象,然后再迁移到数据库。但是,这是有害的!长期使用面向对象编程的思维方式去设计数据表,会忘记数据库的本质。

数据库的设计不讲究封装和继承那一套。更多考你的是如何把高维的业务规则,变为一张张二维数据表的名称和字段,以及如何更高效地查出数据,或者如何更有效地写入数据。

而且,大多数Web应用程序的并发性能压力,不是在Web框架,而是在数据库。这是你使用面向对象编程的思维方式无法解决的问题,也不是任一一个编程语言的问题。

写了那么多,如果要重点提醒初学者什么内容的话,那就是:对于半路出家学习编程的同学来说,不需要考虑Python的性能适不适合写程序这个问题。如果需要更快更强,必然是选择接近机器的语言。Python可以是你入门的第一门编程语言,但不是最后一个。除了性能,你需要更多考虑的是你的开发时间,你的数据库设计,你的软件作品。