NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

空降 CTO 接手“烂摊子”:技术连续踩坑,创业公司没几个月就倒闭了

  • 2023-02-03
    北京
  • 本文字数:5965 字

    阅读完需:约 20 分钟

空降CTO接手“烂摊子”:技术连续踩坑,创业公司没几个月就倒闭了

初创公司在技术上到底要踩多少“坑”?


Egor Romanov 曾被朋友邀请到一家初创公司担任 CTO,他先组建了一支工程师团队,然后着手构建后端、Web 管理门户和移动应用,并决定使用微服务架构来构建后端。不幸的是,这个初创业务未能获得市场关注,公司也在几个月后就宣布倒闭。回顾整个创业历程,Egor Romanov 总结了一些经验与教训。以下为他的自述。

空降 CTO 接手“烂摊子”


第一次受邀到初创公司担任技术主管的时候,我基本压根不清楚自己要做的是哪一行,但朋友的盛情实在难却。我认真审查了之前技术负责人和开发者着手构建的解决方案,他们做得不错,但受种种原因影响吧,大家最终决定退出项目。所以我得迎难而上,接手一款刚开发的产品,而且团队里根本没人可用。


这家初创公司开发的是一款应用程序,号称能帮助用户找到最划算的交易和合作企业,高效运用自己的时间和资金资源。这款应用程序预期把用户跟非旺季时段的库存或者产能过剩的公司对接起来,既帮助买方享受折扣、又帮助卖方回流资金。


项目要求在 iOS 和 Android 平台开发移动应用,还要搭配一套 Web 管理门户,供企业主管理产品、开展客户沟通。另外,所有采购行为必须通过我们的应用,不可私下交易。


因为团队不给力加上期限紧迫,我知道自己必须抓点紧了。


于是,我先组建了一支工程师团队,着手构建后端、Web 管理门户和移动应用。虽然我们已经拥有明确的开发目标和愿景,也制定了可靠的计划,但我知道愿景和计划肯定是会变的。另外,招聘合格工程师耗费的时间也比我预期中要多,所以得随时灵活调整推进策略。好在,我最终还是建立起了一支既有执行力和战斗力,又能不断适应环境变化的优秀队伍。

使用微服务构建可扩展后端


在刚开始构建后端时,我就知道可扩展性和适应性是其中的关键。经过广泛搜索,我找到了一位真正精通 Node.js 技能的后端开发人员。经过商议,我们决定使用微服务架构来构建后端。达成共识之后,我们开始根据业务要求和动态特性,逐步招聘移动和 Web 开发人员。


我在基础设施方面已经积累了一定经验,所以承担起了云、Kubernetes 集群、监控与日志记录,还有编码基础设施的设置任务。我们用 GitLab 进行版本控制,并使用 CI/CD 管线实现了构建、测试与部署流程的自动化。我们选择 JSON-RPC 作为通信协议,并指定 Node.js 作为后端。我们的后端开发人员又决定使用 MongoDB 数据库——虽然我个人更偏好 Postgres。


最终,我们定下了以下几项微服务:


  • Products:这项微服务用于管理由合作伙伴提供的产品和交易、他们的零售地点和促销活动信息。通过 Products,用户可以创建、更新和管理这些条目。另外,Products 还负责处理促销活动的启动与中止。

  • Business Users:这项微服务的作用,是在管理面板中管理 Auth 服务下的企业及其员工和数据。

  • Orders:负责实现订单的购物车和生命周期,并与支付系统相集成。

  • Gate:这项微服务位于从客户端到后端(也就是从移动设备到管理面板)的两个入口点处。它维护着客户端到后端之间的 websocket 连接,负责将请求定向至身份验证服务或者外观。

  • Admin Façade 和 User Façade 是后端的外观微服务。它们将来自客户端的请求分发给服务,负责封装系统的内部结构,而且会根据可用方法为客户端授权访问权限。

  • Auth:这项微服务负责用户的身份验证和授权。

  • File:这项服务负责管理静态资源(例如产品照片或者与合作伙伴的法律文件),而且跟 Yandex 集成以存储数据。

  • App Users:这项微服务负责管理移动应用用户。除其他事项外,它还存储用户的相关元信息:最后一次上线时间、好友等。

  • Settings:这项服务负责管理应用程序的设置。

  • Marketing:这项微服务负责管理营销/促销活动和推荐列表。

  • Email、Push 和 SMS 通知服务各自与对应的供应商集成。整个平台涉及多个外部集成:面向供应商 CloudPayments 的支付功能,用于 Push/SMS/Email 的通知服务,还有把静态文件(例如图片)匹配至 Yandex 云对象存储的功能。


我们的架构


我们用了两、三个月时间才找到一位移动/Web 开发人员。但我们没有浪费掉这段时间,坚实的后端基础设施在此期间已经成功建立了起来。我们在开发过程中多次调整过概念和需求,而微服务架构大大降低了后端的调整难度。


得夸一句,我们的移动开发者非常棒。经过多次重新设计,最终移动应用充分满足了我们 CEO 和设计团队提出的每个新愿景。客户端应用程序和后端间的通信,通过使用 json-rpc 协议的 websocket 实现。前端使用的是 Vue.js,移动端使用的是 React Native,这有助于团队保持一致性和代码共享能力。


总的来说,我们几乎在一切可能的地方都在用 JavaScript,它能帮助工程师轻松理解同事编写的代码,并在必要时灵活更新服务和移动/Web 应用程序的通信方式。

可能正确的答案 —Supabase


在当初建立这家初创公司时,我们发过一篇博客,讲述了我们在此期间面临的挑战。我们从社区收到了不少反馈,其中有些比较消极,但也有不少颇具建设性。对我来说,印象最深的一条反馈就是建议用Firebase这类服务来简化我们的后端


当时,我个人觉得用 Firebase 不行,因为这可能引发严重的供应商锁定,没准会导致我们失去对数据和基础设施的控制权。(注:几个月后,我们的初创业务未能获得市场关注,因此被迫放弃。在此期间,我在翻看 Y Combinator 时偶然发现了 Supabase。事后来看,可能最适合当初创业需求的就是 Supabase。)


这是个开源平台,想帮助开发者简化为 Web/移动应用程序构建安全可扩展后端的过程。它以 Postgres 为基础,提供一系列工具和服务来管理数据库、身份验证、实时数据同步和存储对象,同时仍保证用户能控制自己的数据和基础设施。它的主要功能包括:


  • 自动生成 API:Supabase 能自动为 Postgres 数据库生成 REST、GraphQL 和实时 websocket 通知,帮助用户便捷访问来自 Web 和移动应用程序的数据。

  • 用户身份验证和授权:Supabase 内置支持用户身份验证和授权,能轻松保护应用程序和敏感数据。

  • 实时性:Supabase 能让 Web/移动应用程序同数据库保持同步,无需手动刷新数据。

  • 存储:用户可以存储大型对象,例如图像或文档,还可以通过请求调整图像大小。

  • 可扩展性与安全性:Supabase 构建在 Kubernetes 之上,具备自动扩展与高可用性,同时提供静态加密和传输中加密等安全功能。


总之,Supabase 堪称初创企业和小型团队的绝佳选择,能帮助用户轻松快捷地构建后端,而且不必费力设置和维护整个复杂的基础设施。即使身在大型公司,各位在推出新服务时也不妨考虑使用 Supabase 或者类似的开源项目。

如果我们当初选了 Supabase 会怎样?


下面我们就大开脑洞,畅想如果从一开始就选择了 Supabase,我们的初创公司会有怎样的不同。


首先,我们可以节省下来的业力投入到真正重要的工作中:关注用户、关注产品,而不是花几个月时间来构建微服务。从基础设施身上省下的时间不光能用于招聘移动开发人员,也能用来打磨后端。


Supabase 大大降低了数据库的设置和管理难度,它丰富的内置功能可以直接替代我们的大多数微服务。节约下来的不只有时间,更有宝贵的资金和精力。有了它,我们没准能保持住适应变化和需求的能力,这也是我们当初最引以为傲的本钱。但很遗憾,当时我们根本没听说过 Supabase——现在屏幕前的你知道了,它也许能改变你的创业故事。


如果用上了 Supabase,我们来看看原本的架构会发生怎样的变化。


Auth


首先,Supabase 的内置身份验证和用户管理服务,可以直接替代我们的独立身份验证和用户管理微服务。它将为我们提供开箱即用的用户注册、登录以及用户角色/权限管理方案。另外,Supabase 还支持基于角色的访问控制(RLS),所以我们完全可以对数据进行细粒度访问。比如,用户只能查看自己的订单,企业主可以编辑自家产品,管理员则可以访问所有数据。



在 Supabase 中创建一项 RLS 策略,这样企业主就能轻松管理全体员工


存储


使用 Supabase 的内置文件存储,可以简化文件上传、下载和管理的整个流程,不需要依赖任何单独的存储解决方案。不同于独立的 File 微服务,Supabase 的内置文件存储直接提供功能,例如调整产品图像的大小,并允许用户动态创建预览。另外,我们也能用 Supabase 的文件存储安全存储和管理业务用户签署的法律文件,无需额外第三方服务即可将这些重要文件集中起来存储和访问。


// Request a small resized image of a product from Supabase Storage:await storage.from('mama_jane').download('pizza.jpeg', {      transform: {        width: 200,        height: 200,        format: 'origin',      },})
复制代码


Gateways 与 Facades


使用 Supabase,Gateway 和 Façade 这两项负责处理移动应用和 Web 应用同其他微服务间通信的设计也就不需要了。Supabase 的自动 PostgREST 和 GraphQL API 能够完全承担起这方面需求,让我们专注于其他更有价值的工作。


# Retrieve a feed with products from app using Supabase generated GraphQL API{  retailersCollection(    filter: {active: {eq: true}},  ) {    edges {      node {        name        productsCollection {          edges {            node {              id              title              imageUrl              price            }          }        }      }    }  }}
复制代码


Products


关于 Product 和 Settings 微服务,它们主要是充当数据所有者,处理关于产品的各项 CRUD 操作。但如果能使用 Supabase,我们可以直接跳过这些麻烦事、享受 Postgres 的强大功能。这样,我们就能直接在数据库中处理其他更复杂的操作,例如涉及交易事务的产品更新。而且 Supabase 还提供内部 hook 和 cron 作业,并全面支持 pg_cron、触发器、webhook 以及无服务器函数等。


Notifications


我们可以用 Supabase 提供的表上无服务器函数和触发器,顺利替代当初设置的 Push、SMS 和 Email 通知微服务。例如,我们可以在订单表上设置触发器,确保订单确认时立即向用户发送推送、短信或者电子邮件通知。我们可以使用触发器在某些事件发生时延动怒出消息,例如创建用户账户或添加新产品。


这将大大降低整体架构的复杂性,使其更易适应不断变化的需求。想象一下,如果我们的营销经理想要组织一场促销,并向过去 30 天内从未下单的用户发送推送通知。利用 Supabase,只需在订单表上创建一个简单的触发器即可轻松实现。


营销活动


前面的例子同时证明,我们的 marketing 服务也没必要独立存在了。因为我们可以设置由特定操作触发的自动营销活动,或者引入名为 marketing_campaigns 的新表。之后,营销经理只需要向表内插入一个带有参数的新行——比如作为通知目标的用户。表上的触发器将自动调用无服务器函数以发出推送通知。


--Trigger to send push notifications after the--marketing specialist adds a marketing campaign to the database.create or replace function insert_marketing_campaign() returns trigger as $$begin    insert into marketing_campaigns (message, user_group, start_date)    values (new.message, new.user_group, new.start_date);    perform send_push_events();    return null;end;$$ language plpgsql;
create trigger insert_and_send_pushafter insert on marketing_campaignsfor each rowexecute function insert_marketing_campaign();Admin studio
复制代码


回想起来,为企业客户专门构建自定义管理门户可能也不是什么好主意。虽然我当初提出过反对,但合作伙伴那边坚持说有必要。而事实证明,我们的客户并没有做好迎接这样一套新的、完全陌生的界面的准备。Supabase 仪表板允许销售团队轻松管理各企业客户的产品。也许我当初该再加把劲,劝合作伙伴在吸引到更多用户并切实了解他们的需求之前,先别急着搞一套独立的定制化管理门户。


Orders


最后要聊的是 Orders 服务。单从技术上讲,我们本可以用无服务器函数加触发器来替代,但我还是选择用老办法。原因是我这人就这样,比较敏感守旧。但即使如此,如果选择 Stripe 作为支付供应商,我们也能用上 Supabase 的打包器新功能。


此功能使用 postgres_fdw 从 Postgres 直接向 Stripe 发送查询,由此轻松完成交易。如果还有额外的时间和余力,我们还可以针对 Stripe 开发自己的打包器并把它跟 Supabase 整合起来。


// Listen for stripe events using Supabase Edge Functions // (to keep track of invoice-paid events, for example)serve(async (request) => {  const signature = request.headers.get("Stripe-Signature");  const body = await request.text();
let receivedEvent; try { receivedEvent = await stripe.webhooks.constructEventAsync( body, signature!, Deno.env.get("STRIPE_WEBHOOK_SIGNING_SECRET")!, undefined, cryptoProvider ); } catch (err) { return new Response(err.message, { status: 400 }); }
console.log(receivedEvent); return new Response(JSON.stringify({ ok: true }), { status: 200 });});
复制代码


更多想法


我们这家初创公司还高度依赖于地理数据。我们本可以使用 PostGIS(Postgres 的空间数据库扩展程序)的强大功能处理全部地理数据需求,这样就能轻松将基于位置的搜索和映射等功能整合到业务应用程序当中。


总的来说,使用 Supabase 加 PostgreSQL 这套强大组合,将大大简化我们的业务架构,让我们腾出时间和精力专注开发应用程序的核心功能。使用 Supabase 稻可能改变我们这家年轻企业的命运——虽然不一定保证获得商业成功,但至少能节约下可观的开发和基础设施运营资金。


如果使用 Supabase,那我们的架构可能会是这个样子:



更重要的是,我不用担心供应商锁定问题了。用户可以配合多种编程语言使用 Supabase,包括 JavaScript、Dart、Python 或者 Go,极大提高应用程序的构建和维护灵活度。另外,Supabase 在设计上很重视扩展需求,既适合小型初创公司、也能满足大型企业客户。它同时支持云端和本地环境,还能跟其他开源项目集成,这就为应用程序构建和部署工作赋予了极高的自定义空间和灵活性。

写在最后


回顾整个初创历程,我们意识到构建微服务架构是个既充满挑战又成本高昂的决定。但是,Supabase 提供了一种更简单、更具成本效益的替代方案,其内置功能完全可以满足典型初创企业对多种微服务的需求。从用户管理到文件存储、再到实时 API 和自动数据管理,Supabase 有望帮助大家显著节约时间和资金。


虽然我当初没能在自己的初创公司中使用 Supabase,但我希望自己的这段惨痛教训能给大家带来一点启示,特别是认真考虑 Supabase 在公司业务环境中的可行性。诚然,Supabase 不可能是所有项目的最佳选项,但至少值得一试,而且大家最好能在市场上广泛物色可能更适合需求的其他替代方案。在我看来,Pocketbase 在某些方面可能表现更好(比如某些涉及大量自定义 Golang 代码的基础设施开发项目),但总体上 Supabase 更适合大多数项目。


原文链接:


https://egor-romanov.medium.com/building-a-startup-from-scratch-my-mistakes-as-cto-b20b463e0058

2023-02-03 14:1210003

评论 4 条评论

发布
用户头像
简化后端对初创公司确实很重要,毕竟人力财力都有限。我们团队现在在用一个国内的工具叫飞布,有点类似Supabase,用起来挺顺手的https://www.fireboom.io/
2023-02-22 18:56 · 江苏
回复
用户头像
初创公司没必要一开始就采用微服务架构,使用单机服务方式,快速出产品市场试水更重要。接手烂摊子,建成卖不去的别墅区。
2023-02-07 10:44 · 浙江
回复
深以为然
2023-02-10 11:17 · 北京
回复
经验教训。遇到过大公司出来的人,来中小公司提出一套高大上的技术架构,把小公司折腾的够呛,后面推到重来,5年过去了还在还技术债。
2023-02-13 09:45 · 浙江
回复
没有更多了
发现更多内容

一文了解游戏美术开发流程,以及可能遇到的问题

龙智—DevSecOps解决方案

perforce Helix Core Helix DAM

卷入上海疫情,被封40天,我的一点心得

大数据梦想家

程序员 程序人生 疫情防控

市场份额不断提升,百度智能云稳居金融云解决方案市场第一阵营

百度开发者中心

《银行保险机构消费者权益保护管理办法》,如何影响行业与个人?

易观分析

金融消费

错过了太后悔,九大绝招大公开,详解华为低时延技术

华为云开发者联盟

云计算 音视频 华为云

TDengine 社区问题双周精选 | 第一期

TDengine

数据库 tdengine

ShardingSphere 在金融支付场景下的实践与调优

SphereEx

Apache 数据库 开源 ShardingSphere SphereEx

2022年中国互联网母婴行业年度分析

易观分析

母婴产品

物联网时代,如何保障嵌入式系统安全?

龙智—DevSecOps解决方案

klocwork perforce Helix QAC

ironSource开通业内首家微信客户服务平台, 为中国客户提供本地支持

Geek_2d6073

如何 DIY 一款属于自己的【3D 重力感应 动态壁纸 】,看完这篇文章你也可以学会

呆呆敲代码的小Y

android Unity 壁纸 动态壁纸

敏捷团队教练工作坊 (Coaching Agile Teams) | 6月11日

ShineScrum捷行

敏捷 教练 敏捷教练 cat 高管教练

编写实用有效的产品帮助文档,提升客户满意度

小炮

帮助文档

7 款最棒的 React 移动端 UI 组件库 - 特别针对国内使用场景推荐

蒋川

UI 前端框架 React 移动端 组件库

极客星球 | 机器学习赋能商业地产决策进阶

MobTech袤博科技

如何实现客户自助服务?打造产品知识库

小炮

知识库

微信小程序和 uniapp 的区别是什么?

CRMEB

为什么要上云,您的团队适合上云吗?Atlassian白皮书给你答案

龙智—DevSecOps解决方案

Atlassian atlassian云版

如何提高团队的工作效率?

ShineScrum捷行

Scrum 敏捷 团队效率

静亦求精,罗技MX高性能键鼠组合上市!

Geek_2d6073

打开人工智能“黑盒”,发展可解释、可扩展、可信赖、安全可靠的人工智能

博文视点Broadview

乏善可陈的Neuralink

图灵教育

易安联参编《SASE技术与应用场景白皮书》正式发布

权说安全

网络安全 sase

域成员服务器怎么会突然脱域?

BUG侦探

脱域 域信任关系 windows更新

手把手教你如何高效落地单项目管理 | 一看既会

阿里云云效

云计算 阿里云 项目管理 敏捷开发 单项目管理

关于2022年12代C/C++Linux服务器开发高级架构师课程体系分析

C++后台开发

后端开发 Linux服务器开发 C++后台开发 Linux后台开发 服务器开发架构师

达人专栏 | 还不会用 Apache Dolphinscheduler?大佬用时一个月写出的最全入门教程【三】

Apache DolphinScheduler

Apache 大数据 开源 DolphinScheduler workflow

云原生架构及演进

云智慧AIOps社区

云原生 k8s 构架

leetcode 69. Sqrt(x) x 的平方根(简单)

okokabcd

LeetCode 查找

Jira工时管理插件线上安装量过百,龙智产品赢得全球企业信赖

龙智—DevSecOps解决方案

Jira插件 龙智 龙智自研插件

百度吴甜提出大模型落地关键路径 业内首发行业大模型

百度开发者中心

空降CTO接手“烂摊子”:技术连续踩坑,创业公司没几个月就倒闭了_语言 & 开发_Egor Romanov_InfoQ精选文章