Server饭-用API发微信通知或用微信控制你的服务器

大家好,这是又一个向微信发通知的服务。这样的服务其实不少,一定是有新的特色我才好意思来介绍。 Server饭不仅可以给微信发通知,还能反过来用微信和服务器产生交互。大概像下面这样: 好了,还是先介绍基础功能吧。 主动发送通知 给自己发消息是最常用的功能。 拉到文末扫码关注服务号,或者在微信搜索 “LetServerRun” 这个服务号关注。 在服务号发送 token 命令查看自己的用户 token 。 使用用户 token,您就可以用 API 向公众号发警告消息了: curl "https://api.letserver.run/message/info?token=YOUR-TOKEN&msg=hello" 这个 GET 接口是为了调试和轻量使用场景的,在程序中使用的话有一系列接口和SDK。 反向控制服务器 Server饭的特色功能是用微信控制服务器做简单的事情。就像一开始的图里那样。 放心,不需要你提供ssh密钥,为了安全,命令能做什么完全由你定义。 实现的原理是在服务号中你发的命令会被存储在云端, Agent 每分钟向云端发起请求检查一次,如果有命令则拉回来执行它。 执行完成之后可以返回成功或者失败的结果,你就会在微信服务号上看到。 Agent 哪里来呢?有这么几种选择: 最自由:调用我们的API自己写 省事点:调用 SDK 自己写 够用就好:直接用我们几个开源的方案 这里我们先使用一个开源的通用 Agent来上手。 它可以帮你在服务器执行特定的命令。后面我们可以根据需求,自己通过 API 或 SDK,集成 Agent 或自己编写。 假设你的服务器是 Debian/Ubuntu ,如果是别的请参考 安装通用Agent 如果您本身就是 root 用户,麻烦去掉所有命令中的 sudo # 注册仓库 curl -1sLf \ 'https://dl.cloudsmith.io/public/hackfan/skadi/setup.deb.sh' \ | sudo -E bash # 更新 apt update # 安装 apt install skadi 在安装后,因为还没有 Token,所以并没有自动启动。 Token 哪来的呢?在服务号输入命令: agent add 名字 (名字是要你给它取个简单的名字,以后每次都要用它发命令) 然后将得到的 Token 写入配置文件,像下面这样。 你也可以编辑 /etc/skadi/skadi.yml 这个文件自己写入。 ...

2021年5月6日 · 1 分钟 · Hyacinthus

Docker 重要更新: 原生支持多阶段构建(multi-stage build)

Docker 的口号是 Build, Ship, and Run Any App, Anywhere. 但是我们在应用过程中会遇到一个问题,我们在 build 的时候,把源码也 build 进去了。 然后就继续把源码 Ship 出去吗?这可不行。所有的编译型语言都面临这个困扰。 即使是脚本型语言,build 的时候也会使用很多上线时用不到的构建工具, 而我们希望减小生产镜像的体积,这样我们的小鲸鱼才能多拉一点集装箱嘛。 传统做法 我们最终的目的是要将编译好的可执行文件复制到 alpine 这样的迷你镜像里, 那么该怎么弄到编译好的文件呢?基于 Docker 的思想,我们肯定需要在一个标准容器中编译, 这样这个过程才是标准化的,再说,你在 Ubuntu 编译出一个二进制文件在 alpine 也运行不了。 于是我们先需要准备一个编译用的自定义镜像。一般是用相应语言的 alpine 基础镜像, 把编译项目额外需要的各种工具打包进去,比如 golang 目前没有官方的包管理, 你就需要把你用的包管理工具装进去。 然后我们需要在运行 container 时把主机的一个目录通过 -v 挂载到 container上, 让它把编译的结果输出到这个挂载的目录,这样我们就在主机上拿到这个文件了。 最后,我们用一个最小的 alpine 镜像,把二进制文件复制进去。 可能你还需要设置一下时区之类的。 持续集成 上面的流程,在用持续集成工具时又变成了一个问题。你会发现每一家 CI 提供商都不太一样。 你未必有权限控制 CI 时的宿主机。 比如 Docker Cloud,你需要定义 pre-build 的 hook 去完成这个工作, 在 SEMAPHORE,你发现你有了一台宿主机,这下和我们在本地的做法可以一样了。 在更多的提供商,你会发现他们只是能根据 git 仓库和 Dockerfile 构建镜像, 你用他们的系统甚至没办法做出一个最小镜像…… 中国的 DaoCloud 其实挺先进的,很早就推出了安全镜像的概念,让你的构建通过两步完成。 但是,那个配置的内容太多让不太懂的人看了直接晕掉。 ...

2017年4月14日 · 1 分钟 · Hyacinthus

对 echo 框架进行统一的自定义错误处理

借助移动端的增长,如今 RESTful 风格的 API 已经十分流行, 用各种语言去写后端 API 都有很成熟方便的方案,用 golang 写后端 API 更是生产力的代表, 你可以用不输 python/ruby 这类动态语言的速度,写出性能高出一两个数量级的后端 API 。 ECHO 框架 由于 golang 的标准库在网络方面已经很完善,导致框架发挥余地不大。很多高手都说, 用什么框架,用标准库就写好了,框架只是语法糖而已,还会限制项目的发展。 不过我们并不是高手,语法糖也是糖,用一个趁手的框架还是能提高不少效率的。 要是在半年前,你让我推荐框架,我会说有很多,都各有优缺点,除了 beego 随便选一个就可以。 但是来到2017年,一个叫 Echo 的框架脱颖而出。这是我目前最推荐的框架。 Echo 的宣传语用的是 “高性能,易扩展,极简 Go Web 框架” 。它的一些特性如下图所示: 这些特性里,HTTP/2,Auto HTTPS,听着很熟?这是我之前介绍的 Caddy 也有的特性, 因为 golang 实现这些太容易了。还有 Middleware 里的一大堆功能也差不多。 我们在做微服务的时候,这些通用的东西由 API Gateway 统一实现就好了, 如果你写的是个小的独立应用的后端,这些开箱即用的功能倒是能提供很大的帮助。 其实今天我主要想说说最后一个特性里提到的,“中心化的 HTTP 错误处理”。 RESTful API 错误返回 一个团队应当有一份 RESTful API 的规范,而在规范中应该规范响应格式,包括所有错误响应的格式。 比如微软的规范, jsonapi.org 推荐规范等等。 大部分时候我们不需要实现的那么繁琐,我们规定一个简单的结构: STATUS 400 Bad Request { "error": "InvalidID", "message": "invalid id in your url query parameters" } 传统的错误响应可能只有一个伴随 HTTP Status code 的 string 类型的 message, 如今我们把正常的响应格式变成了 JSON ,那么把错误返回也用 JSON 吧。 除了用 JSON 之外,我们又增加了一个 error 字段, 这个字段是一个比 Status code 要详细一个级别的 Key, 消费端可以用这个约定的 Key 做更为灵活的错误处理。 ...

2017年4月10日 · 3 分钟 · Hyacinthus

使用 caddy 作为微服务的 API gateway

背景 大家都知道,Docker这些年让IT界产生了深刻的变革, 从开发到测试到运维,处处都有它的身影。 它同时也和微服务架构相互促进,并肩前行。 在最新版的 Docker(CE 17.03) 里,随着 swarm mode 的成熟, 在较简单的场景里已经可以不再需要专门的基础设施管理, 服务编排,服务发现,健康检查,负载均衡等等。 但是API gateway还是需要一个的。或许再加上一个日志收集, 你的微服务架构就五脏俱全了。 我们知道Nginx Plus是可以很好的胜任 API gateway 的工作的, 但它是商业软件。Nginx我们不说认证啊限流啊统计啊之类的功能, 单就请求转发这一点最基本的就出了问题。 我们知道Docker是用DNS的方式,均衡同一名称的服务请求到不同的node, 但是Nginx为了速度,在反向代理的时候会有一个不可取消的 DNS Cache, 这样我们Docker在根据容器的扩展或收缩动态的更新DNS,可Nginx却不为所动, 坚持把请求往固定的IP上发,不说均衡,这个IP甚至可能已经失效了呢。 有一个配置文件上的小Hack可以实现Nginx每次去查询DNS,我本来准备写一篇文章来着, 现在看来不用了,我们找到了更优雅的API gateway, Caddy 。 我上篇文章也写了一个它的简介。 接下来的所有代码,都在这个demo中, 你可以clone下来玩,也能在此基础上做自己的实验。 应用 我们先用golang写一个最简单的HTTP API,你可以用你会的任何语言写出来, 它为GET请求返回 Hello World 加自己的 hostname . package main import ( "io" "log" "net/http" "os" ) // HelloServer the web server func HelloServer(w http.ResponseWriter, req *http.Request) { hostname, _ := os.Hostname() log.Println(hostname) io.WriteString(w, "Hello, world! I am "+hostname+" :)\n") } func main() { http.HandleFunc("/", HelloServer) log.Fatal(http.ListenAndServe(":12345", nil)) } Docker 化 我们需要把上面的应用做成一个docker镜像,暴露端口12345。 接着才有可能使用Docker Swarm启动成集群。 本来做镜像特别简单,但我为了让大家直接拉镜像测试时快一点,用了两步构建, 先编译出应用,然后添加到比较小的alpine镜像中。大家可以不必在意这些细节。 我们还是先来看看最终的docker-compose.yml编排文件吧。 ...

2017年3月16日 · 1 分钟 · Hyacinthus

新兴的web服务器caddy

caddy 是一个像 Apache, nginx, 或 lighttpd 的web服务器。 你要问nginx已经很好了,为什么要用caddy呢? 我觉得caddy最大的特点是用起来简单, 然后呢,它还有下面这些开箱即用的特性: HTTP/2 全自动支持HTTP/2协议,无需任何配置。 Auto HTTPS Caddy 使用 Let’s Encrypt 让你的站点全自动变成全站HTTPS,无需任何配置。当然你想使用自己的证书也是可以的。 Multi-core 因为caddy是golang写的,所以当然可以合理使用多核啦。 IPv6 完全支持IPv6环境. WebSockets Caddy 对WebSockets有很好的支持. Markdown 自动把md转成 HTML ,当然,我后续要给大家介绍更强大的hugo来干这个事情. Logging Caddy 对log格式的定义很容易,更好的满足你日志收集的需求。 Easy Deployment 得益于go的特性,caddy只是一个小小的二进制文件,没有依赖,很好部署。 那么在什么场景下适合尝试使用caddy呢,我推荐从以下场景开始: 作为静态页面的webserver 转发 fastcgi 请求到 php-fpm 服务,比如替换apache或nginx作为wordpress的server 反向代理,管理多个站点 微服务的 API gateway ,我会专门写一篇文章。 有些在nginx上难以开发的需求,为caddy写插件太方便了。 入门 安装caddy 下载 caddy 把caddy放到系统的PATH中,让其可以直接执行。比如Linux中一般习惯放到 /usr/local/bin 简单测试 找一个做测试的临时目录,生成一个测试主页。echo "hello world">index.html 执行 caddy 在另一个终端 curl localhost:2015 或在浏览器访问 (http://localhost:2015) Caddyfile caddy的一个特色就是配置简单,nginx的配置文件群已经越看越晕了。我们来试试: 在当前目录创建这样一个叫Caddyfile的文件: localhost:2020 gzip 这次,我们改变了端口,并且启用了gzip自动压缩数据。运行caddy,去你指定的地址看看吧。 ...

2017年3月12日 · 1 分钟 · Hyacinthus