软件工程的本质复杂度和次要复杂度
本质:如何从抽象的问题,发展出具体的概念上的解决方案(业务问题)
次要:指实现它的过程(技术手段)
过去解决了的次要复杂度(提升研发效率)
高级语言
分时系统
开发环境(ide)
什么是云的原生编程模型?怎么样做到在云上的应用开发效率得到10倍的提升?
我想并行处理n个文件该怎么做?
- 编写处理文件的代码
- 创建包含工作队列的线程池,提交任务
本质复杂度:
- 实现文件处理程序
次要复杂度;
- 实现线程池
- 高性能的工作队列
- 线程池资源管理
- 操作系统调度
扩展这个问题,让这个处理程序是分布式的,应该怎么做?
问题:
- 需要多少台server
- 如何处理宕机
- 文件的大小不同如何实现负载均衡
- 怎么确保不同机器上的任务被可靠地执行
- ....
本质复杂度:
- 实现文件处理程序
次要复杂度:
- server相关的操作(类似自己实现线程池的这类问题)
对于分布式应用来说,这个程序的复杂度和汇编语言类似,次要复杂度>>本质复杂度
如何减少次要复杂度?
- 使用消息队列、函数等更高抽象原语设计解决方案
- 使用serverless计算服务,自动启动、调度实例
- 使用全托管对象存储服务,用于存储
- 上传代码包/镜像,调用任务,查看结果,查看日志,暂停/终止服务
去除掉server概念
云计算和Serverless
云计算的发展史就是serverless的兴起史
物理机时代=>虚拟机时代=>容器时代=>serverless时代
物理机时代
物理机时代面临的最大的问题是服务器硬件问题、维护问题、人力问题
虚拟机时代
iaas解决了物理机时代的硬件问题,paas解决了维护问题,单机应用也升级成了群体应用,服务器负责计算,paas中间件负责存储、调度等功能,同时也出现了新的问题,多台机器下环境的一致性
容器时代
容器时代解决了统一运行环境的问题,同时又出现了新的问题,需要规划节点pod中cpu、内存、磁盘的资源,需要编写复杂的yaml去部署pod,需要学习专业的运维知识。
serverless时代
serverless指构建和运行不要服务器管理的一种概念
前面三种架构都是属于serverful,就像第一节中提到的,需要处理各种次要复杂度,像是用汇编语言进行编程。而serverless架构就像用python等高级语言进行编程
目前serverless的实现 faas + baas
faas: 提供运行函数代码的能力,并具有自动弹性伸缩
baas: 将后端能力封装成服务,并以接口的形式提供服务
serverless的出现让我们可以不再关心传统的运维工作,专注解决业务实现,以更快的速度更低的成本完成应用的开发迭代,进而创造出更大的价值,
Faas、Baas
特点:
- 不用运维
- 事件驱动
- 按量付费
- 弹性伸缩
- 无状态
云原生指的是原生为云的设计架构模式,serverless是云原生的一种实现,k8s是云原生的另一种实现。
serverless的缺点:
- 云厂商绑定
- 底层硬件多样性(看你的代码是否依赖底层硬件)
- 冷启动有时间
- 函数通信效率低
- 开发调试较复杂
尝试第一个云函数
这里尝试的是阿里云的云函数,使用的是阿里云牵头的serverless-devs框架来部署。对比腾讯云的serverless-cli,erverless-devs号称是更具有通用性,无云厂商绑定。但其实所有的兼容都是有代价的,serverless-devs就依赖对其他云厂商组件的兼容,腾讯云的代码上次更新还是21年,自家的最近更新是今年,懂得都懂。
serverless-devs提供了整个云函数的生命周期方法,部署镜像时会先build再push到你的镜像仓库,还是非常方便的。同时也提供的CI/CD的配置。(说是通用,但非常依赖他的组件代码,若想在腾讯云上实现自动推镜像拉取部署,建议还是用腾讯云的serverless-cli)
yaml
# ------------------------------------
# If you need English case, you can refer to [s_en.yaml] file
# ------------------------------------
# 欢迎您使用阿里云函数计算 FC 组件进行项目开发
# 组件仓库地址:https://github.com/devsapp/fc
# 组件帮助文档:https://www.serverless-devs.com/fc/readme
# Yaml参考文档:https://www.serverless-devs.com/fc/yaml/readme
# 关于:
# - Serverless Devs和FC组件的关系、如何声明/部署多个函数、超过50M的代码包如何部署
# - 关于.fcignore使用方法、工具中.s目录是做什么、函数进行build操作之后如何处理build的产物
# 等问题,可以参考文档:https://www.serverless-devs.com/fc/tips
# 关于如何做CICD等问题,可以参考:https://www.serverless-devs.com/serverless-devs/cicd
# 关于如何进行环境划分等问题,可以参考:https://www.serverless-devs.com/serverless-devs/extend
# 更多函数计算案例,可参考:https://github.com/devsapp/awesome/
# 有问题快来钉钉群问一下吧:33947367
# ------------------------------------
edition: 1.0.0
name: hello-world-app
# access 是当前应用所需要的密钥信息配置:
# 密钥配置可以参考:https://www.serverless-devs.com/serverless-devs/command/config
# 密钥使用顺序可以参考:https://www.serverless-devs.com/serverless-devs/tool#密钥使用顺序与规范
access: "yaods-aliyun-fc"
vars: # 全局变量
region: "cn-hangzhou"
service:
name: "widget-api"
description: 'hello world by serverless devs'
services:
widget: # 业务名称/模块名称
# 如果只想针对 helloworld 下面的业务进行相关操作,可以在命令行中加上 helloworld,例如:
# 只对helloworld进行构建:s helloworld build
# 如果不带有 helloworld ,而是直接执行 s build,工具则会对当前Yaml下,所有和 helloworld 平级的业务模块(如有其他平级的模块,例如下面注释的next-function),按照一定顺序进行 build 操作
component: fc # 组件名称,Serverless Devs 工具本身类似于一种游戏机,不具备具体的业务能力,组件类似于游戏卡,用户通过向游戏机中插入不同的游戏卡实现不同的功能,即通过使用不同的组件实现不同的具体业务能力
actions: # 自定义执行逻辑,关于actions 的使用,可以参考:https://www.serverless-devs.com/serverless-devs/yaml#行为描述
pre-deploy: # 在deploy之前运行
- component: fc build --use-docker --dockerfile ./code/Dockerfile # 要运行的组件,格式为【component: 组件名 命令 参数】(可以通过s cli registry search --type Component 获取组件列表)
# - run: docker build xxx # 要执行的系统命令,类似于一种钩子的形式
# path: ./src # 执行系统命令/钩子的路径
# - plugin: myplugin # 与运行的插件 (可以通过s cli registry search --type Plugin 获取组件列表)
# args: # 插件的参数信息
# testKey: testValue
# post-deploy: # 在deploy之后运行
# - component: fc versions publish # 要运行的命令行
props:
region: ${vars.region} # 关于变量的使用方法,可以参考:https://www.serverless-devs.com/serverless-devs/yaml#变量赋值
service: ${vars.service}
function:
name: "custom-python39-event-function"
description: 'hello world by serverless devs'
caPort: 9000
memorySize: 128
timeout: 60
runtime: custom-container
customContainerConfig:
image: "registry.cn-hangzhou.aliyuncs.com/yaods/widget:latest"
codeUri: ./code
triggers:
- name: httpTrigger
type: http
config:
authType: anonymous
methods:
- GET
customDomains:
- domainName: auto
protocol: HTTP
routeConfigs:
- path: /*
methods:
- GET
- POST
# next-function: # 第二个函数的案例,仅供参考
# # 如果在当前项目下执行 s deploy,会同时部署模块:
# # helloworld:服务widget-api,函数cpp-event-function
# # next-function:服务widget-api,函数next-function-example
# # 如果想单独部署当前服务与函数,可以执行 s + 模块名/业务名 + deploy,例如:s next-function deploy
# # 如果想单独部署当前函数,可以执行 s + 模块名/业务名 + deploy function,例如:s next-function deploy function
# # 更多命令可参考:https://www.serverless-devs.com/fc/readme#文档相关
# component: fc
# props:
# region: ${vars.region}
# service: ${vars.service} # 应用整体的服务配置
# function: # 定义一个新的函数
# name: next-function-example
# description: 'hello world by serverless devs'
思考
无论是serverless还是最近的人工智能,对于实现本质问题的效率会越来越高,成本越来越低,你会用这些去做什么呢?