使用 Encore.ts 构建事件驱动的 Uptime Monitor:从 0 到云端的完整实战教程
【免费下载链接】encoreThe infrastructure platform for the intelligence era项目地址: https://gitcode.com/GitHub_Trending/encor/encore
本教程将基于开源仓库 encore 提供的 Encore.ts 开发框架,从零构建一个事件驱动架构的网站可用性监控系统(Uptime Monitor)。你将掌握 Encore.ts 的服务定义、API 端点、SQL 数据库迁移、Cron 定时任务、Pub/Sub 消息解耦、Secrets 密钥管理以及一键云端部署的完整实战能力,全部代码仅约 300 行。
1. 我们要构建什么
当你的网站宕机时,你希望第一时间收到通知,而不是等用户来抱怨。这就是 Uptime Monitor 存在的意义。
本教程将使用 Encore.ts 构建一个完整的上线监控系统,最终形态包含三个后端服务(site、monitor、slack)、两个 SQL 数据库、一个每小时触发的 Cron 任务、一个 Pub/Sub 主题及其订阅者,以及通过 Slack Webhook 发送告警的能力。
整个系统采用事件驱动架构:monitor服务周期性检查所有被监控站点,当某个站点从"在线"变为"离线"(或反之)时,向 Pub/Sub 主题发布一条消息;slack服务订阅该主题,自动把状态变更推送到 Slack 频道。架构图(由 Encore 自动生成的 Flow 图)中,白色盒子是服务,黑色盒子是 Pub/Sub 主题,可以参考 encore-flow 说明 了解这一可视化能力。
2. 创建 Encore 应用
🥐 首先创建一个新的 Encore 应用。教程提供了包含现成前端页面的起始分支,直接克隆即可:
$ encore app create uptime --example=github.com/encoredev/example-app-uptime/tree/starting-point-ts如果你是第一次使用 Encore,会提示创建一个免费账号。这在后续需要 Encore 托管 secrets 或执行云端部署时是必需的。
💡 提示:本教程使用 🥐 标记每一个需要你亲手完成的操作步骤,跟着走即可。
创建完成后,应用目录内会有一个encore.app文件(这个文件持有应用的唯一 ID,用于将应用与 Encore 平台关联,后续部署时不要替换它)。
3. 创建 monitor 服务:编写第一个 API 端点
Encore.ts 中,服务是一个目录及其所有子目录的集合,通过一个名为encore.service.ts的文件来声明。
🥐 创建monitor目录和它的服务定义文件:
$ mkdir monitor $ touch monitor/encore.service.ts-- monitor/encore.service.ts -- import { Service } from "encore.dev/service"; export default new Service("monitor");从源码看,Service 类 的注释明确说明:它必须在名为encore.service.ts的文件中调用,以便 Encore 高效识别服务定义;服务的范围就是其所在目录及其全部子目录。构造函数还接受可选的cfg参数(目前支持配置middlewares中间件)。
3.1 编写 ping 端点
🥐 在monitor目录下创建ping.ts,定义pingAPI 端点:接收一个 URL,返回该站点当前是否在线:
-- monitor/ping.ts -- // Service monitor checks if a website is up or down. import { api } from "encore.dev/api"; export interface PingParams { url: string; } export interface PingResponse { up: boolean; } // Ping pings a specific site and determines whether it's up or down right now. export const ping = api<PingParams, PingResponse>( { expose: true, path: "/ping/:url", method: "GET" }, async ({ url }) => { // If the url does not start with "http:" or "https:", default to "https:". if (!url.startsWith("http:") && !url.startsWith("https:")) { url = "https://" + url; } try { // Make an HTTP request to check if it's up. const resp = await fetch(url, { method: "GET" }); // 2xx and 3xx status codes are considered up const up = resp.status >= 200 && resp.status < 300; return { up }; } catch (err) { return { up: false }; } } );这里用到了api()这个 Encore.ts 的核心 API。查看 api/mod.ts 中的 APIOptions 定义,可以深入理解本例中几个选项的含义与更多可选配置:
path:路由路径。使用:定义单段路径参数(如/ping/:url),使用*匹配任意多段。如果不指定path,默认值是/<服务名>.<端点名>(例如本端点未指定时会是/monitor.ping)。method:HTTP 方法,可以是单个方法、方法数组,或"*"匹配所有方法。本教程后续的site服务会展示 POST/GET/DELETE 的用法。expose:是否将端点暴露为公网可访问。默认为false,此时端点只在 Encore 内部网络可达(这非常适合服务间调用,如后面monitor服务调用site服务)。auth:是否要求请求携带有效认证信息,默认为false。bodyLimit:请求体大小上限(字节),默认 2MiB,设为null则不限。tags、sensitive:分别用于客户端生成过滤和从 trace 中剔除敏感请求信息。
3.2 在本地运行并测试
🥐 运行encore run启动应用,然后打开本地开发仪表盘 http://localhost:9400,在 API Explorer 中调用monitor.ping,传入google.com。你也可以直接查看请求的响应、日志和调用链(trace)。
如果更喜欢命令行,在另一个终端执行:
$ curl http://localhost:4000/ping/google.com返回结果:
{"up": true}再试试负面用例httpstat.us/400和some-non-existing-url.com,应返回{"up": false}——测试负面用例永远是值得养成的习惯。
3.3 为 ping 端点编写自动化测试
🥐 创建monitor/ping.test.ts,防止端点日后被改坏:
-- monitor/ping.test.ts -- import { describe, expect, test } from "vitest"; import { ping } from "./ping"; describe("ping", () => { test.each([ // Test both with and without "https://" { site: "google.com", expected: true }, { site: "https://encore.dev", expected: true }, // 4xx and 5xx should considered down. { site: "https://not-a-real-site.xyz", expected: false }, // Invalid URLs should be considered down. { site: "invalid://scheme", expected: false }, ])( `should verify that $site is ${"$expected" ? "up" : "down"}`, async ({ site, expected }) => { const resp = await ping({ url: site }); expect(resp.up).toBe(expected); }, ); });🥐 运行encore test:
$ encore test DEV v1.3.0 ✓ monitor/ping.test.ts (4) ✓ ping (4) ✓ should verify that 'google.com' is up ✓ should verify that 'https://encore.dev' is up ✓ should verify that 'https://not-a-real-site.xyz' is down ✓ should verify that 'invalid://scheme' is down Test Files 1 passed (1) Tests 4 passed (4) Start at 12:31:03 Duration 460ms (transform 43ms, setup 0ms, collect 59ms, tests 272ms, environment 0ms, prepare 47ms) PASS Waiting for file changes...4. 创建 site 服务:用 Knex.js 管理被监控站点
下一步需要维护"要监控哪些网站"的列表。由于大部分接口是简单的 CRUD(增删改查),教程选用 Knex.js 这个 ORM 库来简化开发。
4.1 定义服务与数据库迁移
🥐 创建site服务:
$ mkdir site # Create a new directory in the application root $ touch site/encore.service.ts-- site/encore.service.ts -- import { Service } from "encore.dev/service"; export default new Service("site");🥐 为site服务添加 SQL 数据库。创建site/migrations目录,并在其中放置一个迁移文件1_create_tables.up.sql。文件名有讲究,必须形如1_<名字>.up.sql:
-- site/migrations/1_create_tables.up.sql -- CREATE TABLE site ( id SERIAL PRIMARY KEY, url TEXT NOT NULL UNIQUE );🥐 安装依赖:
$ npm i knex pg4.2 编写 CRUD 端点
🥐 创建site/site.ts:
-- site/site.ts -- import { api } from "encore.dev/api"; import { SQLDatabase } from "encore.dev/storage/sqldb"; import knex from "knex"; // Site describes a monitored site. export interface Site { id: number; // ID is a unique ID for the site. url: string; // URL is the site's URL. } // AddParams are the parameters for adding a site to be monitored. export interface AddParams { // URL is the URL of the site. If it doesn't contain a scheme // (like "http:" or "https:") it defaults to "https:". url: string; } // Add a new site to the list of monitored websites. export const add = api( { expose: true, method: "POST", path: "/site" }, async (params: AddParams): Promise<Site> => { const site = (await Sites().insert({ url: params.url }, "*"))[0]; return site; }, ); // Get a site by id. export const get = api( { expose: true, method: "GET", path: "/site/:id", auth: false }, async ({ id }: { id: number }): Promise<Site> => { const site = await Sites().where("id", id).first(); return site ?? Promise.reject(new Error("site not found")); }, ); // Delete a site by id. export const del = api( { expose: true, method: "DELETE", path: "/site/:id" }, async ({ id }: { id: number }): Promise<void> => { await Sites().where("id", id).delete(); }, ); export interface ListResponse { sites: Site[]; // Sites is the list of monitored sites } // Lists the monitored websites. export const list = api( { expose: true, method: "GET", path: "/site" }, async (): Promise<ListResponse> => { const sites = await Sites().select(); return { sites }; }, ); // Define a database named 'site', using the database migrations // in the "./migrations" folder. Encore automatically provisions, // migrates, and connects to the database. const SiteDB = new SQLDatabase("site", { migrations: "./migrations", }); const orm = knex({ client: "pg", connection: SiteDB.connectionString, }); const Sites = () => orm<Site>("site");注意其中最关键的一行:new SQLDatabase("site", { migrations: "./migrations" })。这是 Encore.ts 的数据库声明方式——Encore 会自动完成数据库的供给(provision)、迁移(migrate)和连接(connect),你无需关心连接串管理。SiteDB.connectionString提供了运行时连接信息,可以无缝接入任意 ORM(这里是 Knex)。
4.3 验证数据库与端点
🥐 确保本机已安装并运行 Docker,然后重启encore run,Encore 会自动创建site数据库。可以在本地开发仪表盘(localhost:9400)的 Flow 架构图中确认数据库已出现,并通过 Service Catalog 调用site.add端点。
也可以通过终端调用:
$ curl -X POST 'http://localhost:4000/site' -d '{"url": "https://encore.dev"}' { "id": 1, "url": "https://encore.dev" }5. 记录每次检查结果:monitor 数据库与 check 端点
要在站点宕机(或恢复)时发出通知,必须先记录它上一次的状态。
5.1 添加 checks 表
🥐 同样为monitor服务添加数据库。创建monitor/migrations目录及迁移文件:
-- monitor/migrations/1_create_tables.up.sql -- CREATE TABLE checks ( id BIGSERIAL PRIMARY KEY, site_id BIGINT NOT NULL, up BOOLEAN NOT NULL, checked_at TIMESTAMP WITH TIME ZONE NOT NULL );每次检查都会向checks表插入一行记录。
5.2 编写 check 端点
🥐 这次改用 Encore 原生的SQLDatabase类(与上一节的 Knex 形成对比,展示两种写法)。创建monitor/check.ts:
-- monitor/check.ts -- import { api } from "encore.dev/api"; import { SQLDatabase } from "encore.dev/storage/sqldb"; import { ping } from "./ping"; import { site } from "~encore/clients"; // Check checks a single site. export const check = api( { expose: true, method: "POST", path: "/check/:siteID" }, async (p: { siteID: number }): Promise<{ up: boolean }> => { const s = await site.get({ id: p.siteID }); const { up } = await ping({ url: s.url }); await MonitorDB.exec` INSERT INTO checks (site_id, up, checked_at) VALUES (${s.id}, ${up}, NOW()) `; return { up }; }, ); // Define a database named 'monitor', using the database migrations // in the "./migrations" folder. Encore automatically provisions, // migrates, and connects to the database. export const MonitorDB = new SQLDatabase("monitor", { migrations: "./migrations", });这里有两个值得注意的 Encore.ts 特性:
~encore/clients类型安全的服务间调用:import { site } from "~encore/clients"是由 Encore 自动生成的客户端引用,让你像调用本地函数一样调用其他服务的端点(site.get),并且全程类型安全、自动集成分布式追踪。这里site.get没有设置expose却仍被调用,正是因为内部网络调用不需要 expose。- SQL 模板字符串:
MonitorDB.exec\...`是 Encore 提供的类型安全 SQL 查询方式,参数通过${}` 插值并以参数化形式传给数据库,天然防止 SQL 注入。
🥐 重启encore run创建monitor数据库。在 Flow 图中可以看到monitor与site服务之间新增的依赖关系。然后调用monitor.check端点(使用上一步得到的 id1),并在 trace 中查看数据库交互。
也可以直接用命令行检查数据库内容:
$ encore db shell monitor psql (14.4, server 14.2) Type "help" for help. monitor=> SELECT * FROM checks; id | site_id | up | checked_at ----+---------+----+------------------------------- 1 | 1 | t | 2022-10-21 09:58:30.674265+00看到这条记录,说明一切正常。
6. 用 Cron 任务定时检查所有站点
现在要定期检查所有被追踪站点。先把check端点的核心逻辑抽取成可复用的doCheck函数:
-- monitor/check.ts -- import {Site} from "../site/site"; // Check checks a single site. export const check = api( { expose: true, method: "POST", path: "/check/:siteID" }, async (p: { siteID: number }): Promise<{ up: boolean }> => { const s = await site.get({ id: p.siteID }); return doCheck(s); }, ); async function doCheck(site: Site): Promise<{ up: boolean }> { const { up } = await ping({ url: site.url }); await MonitorDB.exec` INSERT INTO checks (site_id, up, checked_at) VALUES (${site.id}, ${up}, NOW()) `; return { up }; }6.1 新增 checkAll 端点
🥐 在monitor/check.ts中添加checkAll端点,列出所有站点并全部检查一遍(用Promise.all并行执行):
-- monitor/check.ts -- // CheckAll checks all sites. export const checkAll = api( { expose: true, method: "POST", path: "/check-all" }, async (): Promise<void> => { const sites = await site.list(); await Promise.all(sites.sites.map(doCheck)); }, );6.2 定义每小时触发的 Cron 任务
🥐 定义一个 Cron 任务 自动调用checkAll(作为示例,每小时一次即可):
-- monitor/check.ts -- import { CronJob } from "encore.dev/cron"; // Check all tracked sites every 1 hour. const cronJob = new CronJob("check-all", { title: "Check all sites", every: "1h", endpoint: checkAll, });对照 CronJob 的源码定义,配置项说明如下:
endpoint:要定时调用的 API 端点(必填);every:间隔时长(DurationString,如"1h"、"30m");schedule:与every二选一,直接写 cron 表达式;title:任务的人类可读标题。
⚠️ 注意:Cron 任务在本地开发运行应用时不会被触发,只有部署到云环境后才生效。这是为了避免本地开发时产生困惑。
6.3 status 端点:聚合展示当前状态
前端需要一个接口来列出所有站点及其当前在线状态。
🥐 创建monitor/status.ts:
-- monitor/status.ts -- import { api } from "encore.dev/api"; import { MonitorDB } from "./check"; interface SiteStatus { id: number; up: boolean; checkedAt: string; } // StatusResponse is the response type from the Status endpoint. interface StatusResponse { // Sites contains the current status of all sites, // keyed by the site ID. sites: SiteStatus[]; } // status checks the current up/down status of all monitored sites. export const status = api( { expose: true, path: "/status", method: "GET" }, async (): Promise<StatusResponse> => { const rows = await MonitorDB.query` SELECT DISTINCT ON (site_id) site_id, up, checked_at FROM checks ORDER BY site_id, checked_at DESC `; const results: SiteStatus[] = []; for await (const row of rows) { results.push({ id: row.site_id, up: row.up, checkedAt: row.checked_at, }); } return { sites: results }; }, );SQL 中的DISTINCT ON (site_id)配合ORDER BY site_id, checked_at DESC,正是"取每个站点最近一次检查记录"的标准写法。这里也展示了MonitorDB.query与queryRow(后面会用到)这类流式查询 API。
后端完成!打开 http://localhost:4000/ 即可看到配套前端页面。
7. 部署(可选:先让系统真正跑起来)
一个还没部署的系统称不上真正的监控系统。Encore 提供两种部署方式:
方式一:自托管(Self-hosting)
Encore 支持直接从 CLI 构建 Docker 镜像,然后部署到任意自有基础设施。由于应用使用了 SQL 数据库等基础设施资源,需要为 Docker 镜像提供运行时配置。
🥐 在项目根目录创建infra-config.json:
{ "$schema": "https://encore.dev/schemas/infra.schema.json", "sql_servers": [ { "host": "my-db-host:5432", "databases": { "monitor": { "username": "my-db-owner", "password": {"$env": "DB_PASSWORD"} }, "site": { "username": "my-db-owner", "password": {"$env": "DB_PASSWORD"} } } } ] }这些值只是示例,请替换为你真实数据库的地址与凭据。密码通过
{"$env": "DB_PASSWORD"}从环境变量注入,避免硬编码。更完整的示例可参考在 DigitalOcean 上部署带 PostgreSQL 的 Encore 应用。
🥐 构建 Docker 镜像:
$ encore build docker uptime:v1.0该命令会在宿主机上编译应用,并产出一个包含编译后应用的 Docker 镜像。
🥐 将镜像上传到你选择的云厂商并运行。
方式二:Encore Cloud(免费)
Encore Cloud 提供自动化的基础设施与 DevOps 能力,可以部署到免费开发环境,或你自己的 AWS/GCP 账号。
创建账号:如果还没有账号,运行encore app create并在提示时选择Y创建。创建新应用时选择empty app模板,然后把项目文件复制进新应用目录——注意不要替换encore.app文件(它持有连接应用与平台所需的唯一 ID)。
提交代码:Encore 自带 CI/CD,部署流程简单到一次git push(也可以集成 GitHub,详见 CI/CD 文档)。
🥐 部署到 Encore 免费开发云:
$ git add -A . $ git commit -m 'Initial commit' $ git push encoreEncore 会自动构建并测试应用、供给所需基础设施、然后部署到云端。触发部署后,你会得到一个形如https://app.encore.dev/$APP_ID/deploys/...的链接来查看进度。在 Cloud Dashboard 中你还可以查看指标、手动触发 Cron 任务、查看调用链,以及后续接入自己的 AWS/GCP 账号。
🥐 部署完成后,访问https://staging-$APP_ID.encr.app体验真实的 uptime monitor。
8. 用 Pub/Sub 发布站点状态变更事件
一个不会通知你站点宕机的监控系统是没用的。现在为系统添加 Pub/Sub 主题:每当站点从在线变为离线(或反之)时,发布一条消息。
8.1 定义 Topic
🥐 在monitor/check.ts中定义主题:
-- monitor/check.ts -- import { Subscription, Topic } from "encore.dev/pubsub"; // TransitionEvent describes a transition of a monitored site // from up->down or from down->up. export interface TransitionEvent { site: Site; // Site is the monitored site in question. up: boolean; // Up specifies whether the site is now up or down (the new value). } // TransitionTopic is a pubsub topic with transition events for when a monitored site // transitions from up->down or from down->up. export const TransitionTopic = new Topic<TransitionEvent>("uptime-transition", { deliveryGuarantee: "at-least-once", });查看 Topic 源码 与TopicConfig类型,可以看到:
deliveryGuarantee支持"at-least-once"(至少一次,吞吐无限制)与"exactly-once"(精确一次,但吞吐受限:AWS 每主题约 300 msg/s,GCP 每区域至少 3000 msg/s,且订阅延迟更高,建议处理器保持幂等);- 还可选
orderingAttribute设置消息顺序键,保证相同键的消息按发布顺序投递(本地开发时该项暂不生效)。
8.2 对比前后状态并发布消息
🥐 添加getPreviousMeasurement函数,查询该站点上一次的在线状态:
-- monitor/check.ts -- // getPreviousMeasurement reports whether the given site was // up or down in the previous measurement. async function getPreviousMeasurement(siteID: number): Promise<boolean> { const row = await MonitorDB.queryRow` SELECT up FROM checks WHERE site_id = ${siteID} ORDER BY checked_at DESC LIMIT 1 `; return row?.up ?? true; }🥐 修改doCheck,仅在状态发生翻转时发布消息:
-- monitor/check.ts -- async function doCheck(site: Site): Promise<{ up: boolean }> { const { up } = await ping({ url: site.url }); // Publish a Pub/Sub message if the site transitions // from up->down or from down->up. const wasUp = await getPreviousMeasurement(site.id); if (up !== wasUp) { await TransitionTopic.publish({ site, up }); } await MonitorDB.exec` INSERT INTO checks (site_id, up, checked_at) VALUES (${site.id}, ${up}, NOW()) `; return { up }; }🥐 重启encore run并打开本地开发仪表盘的 Flow 架构图,你会看到 Pub/Sub 主题以黑色盒子的形式出现在图中。注意观察:现在监控系统发布消息时并不知道也不关心谁在听——这正是事件驱动架构的松耦合精髓。
9. Slack 通知:订阅主题并发送告警
"真相是,目前还没有人订阅这些消息。" 现在就来修复这个问题。
9.1 创建 slack 服务
🥐 创建slack服务:
$ mkdir slack # Create a new directory in the application root $ touch slack/encore.service.ts-- slack/encore.service.ts -- import { Service } from "encore.dev/service"; export default new Service("slack");9.2 用 Secrets 安全存储 Webhook URL
🥐 创建slack/slack.ts:
-- slack/slack.ts -- import { api } from "encore.dev/api"; import { secret } from "encore.dev/config"; import log from "encore.dev/log"; export interface NotifyParams { text: string; // the slack message to send } // Sends a Slack message to a pre-configured channel using a // Slack Incoming Webhook (see https://api.slack.com/messaging/webhooks). export const notify = api<NotifyParams>({}, async ({ text }) => { const url = webhookURL(); if (!url) { log.info("no slack webhook url defined, skipping slack notification"); return; } const resp = await fetch(url, { method: "POST", headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ content: text }), }); if (resp.status >= 400) { const body = await resp.text(); throw new Error(`slack notification failed: ${resp.status}: ${body}`); } }); // SlackWebhookURL defines the Slack webhook URL to send uptime notifications to. const webhookURL = secret("SlackWebhookURL");这里展示了 Encore 的 Secrets 机制。查看 secrets.ts 源码 可知:secret("SlackWebhookURL")返回一个类型安全的可调用对象,每次调用取当前值;Encore 会周期性刷新密钥值。本地开发时如果密钥未设置,会返回空字符串而不报错(方便本地调试);而在云端环境未设置则直接抛错。这样webhookURL()为空时优雅跳过通知的逻辑,正是针对本地场景设计的。
9.3 设置 Secret 并测试
🥐 去一个有创建 Incoming Webhook 权限的 Slack 社区,创建 webhook 后设置为 Encore secret:
$ encore secret set --type dev,local,pr SlackWebhookURL Enter secret value: ***** Successfully updated development secret SlackWebhookURL.🥐 用 cURL 测试slack.notify端点:
$ curl 'http://localhost:4000/slack.notify' -d '{"text": "Testing Slack webhook"}'你指定的 Slack 频道应出现Testing Slack webhook消息。
9.4 订阅状态变更事件
🥐 添加 Pub/Sub 订阅者,让 Slack 通知全自动:
-- slack/slack.ts -- import { Subscription } from "encore.dev/pubsub"; import { TransitionTopic } from "../monitor/check"; const _ = new Subscription(TransitionTopic, "slack-notification", { handler: async (event) => { const text = `*${event.site.url} is ${event.up ? "back up." : "down!"}*`; await notify({ text }); }, });new Subscription(TransitionTopic, "slack-notification", { handler })将slack服务与monitor服务解耦:monitor只负责发布事件,slack只负责消费事件并发通知。两者之间唯一的"约定"就是TransitionEvent的消息结构。
10. 部署完整版 Uptime Monitor
现在你的系统已经完整,可以部署了。
自托管
由于新增了基础设施(Pub/Sub 主题、订阅者、Slack 密钥),需要更新infra-config.json,把新的 Pub/Sub 主题与订阅、以及SlackWebhookURL密钥的注入方式都配置进去。
🥐 更新infra-config.json以反映新的基础设施。
🥐 构建镜像并部署:
$ encore build docker uptime:v2.0🥐 上传镜像到云厂商并运行。
Encore Cloud(免费)
🥐 和之前一样,一行命令完成部署:
$ git add -A . $ git commit -m 'Add slack integration' $ git push encore🎉 庆祝一下
应用已在云端运行。在 Cloud Dashboard 中按Cmd + K(Mac)或Ctrl + K(Windows/Linux)打开 Command Menu(从这里可以快速访问所有 Cloud Dashboard 功能,例如直接跳到 Service Catalog 中的某个服务、查看指定端点的调用链)。
🥐 在 Command Menu 中输入fireworks并回车,坐下欣赏这场烟火秀吧。
11. 总结
回顾一下,我们用极少的代码完成了一个功能完整的 uptime 监控系统:
- 构建了三个服务:
site(站点管理)、monitor(检查调度)、slack(通知投递); - 添加了两个数据库(
site与monitor服务各一个),分别存放被监控站点与检查结果,全部由 Encore 自动供给、迁移、连接; - 添加了每小时自动检查所有站点的 Cron 任务;
- 设置了一个 Pub/Sub 主题,将监控系统与 Slack 通知彻底解耦;
- 接入 Slack 集成,用 Secrets 安全存放 webhook URL,通过订阅状态变更事件自动发送通知。
这一切只用了 300 多行代码。核心秘诀在于 Encore.ts 把服务定义(Service)、端点(api)、数据库(SQLDatabase+ 迁移)、定时任务(CronJob)、消息总线(Topic/Subscription)和密钥(secret)都变成了声明式的基础设施原语——你描述意图,Encore 负责供给与运维。接下来,你可以基于应用结构、数据库与 Pub/Sub等文档继续扩展,比如加入更精细的告警策略、Telegram/邮件通知渠道,或者把检查频率提高到分钟级。从今往后,再也不必担心网站悄然宕机而无人知晓了。
【免费下载链接】encoreThe infrastructure platform for the intelligence era项目地址: https://gitcode.com/GitHub_Trending/encor/encore
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考