Skip to main content
Photo from unsplash: https://cdn.moeyy.cn/img/202309172109595.png/moeyy_webp

使用 fly.io 实现负载均衡和自动弹性伸缩

Moeyy 发布于 September 17, 2023

5 min read

前言

fly.io 是一个现代的应用程序交付平台,提供了负载均衡和自动弹性伸缩功能,保证应用程序的可靠性和性能。

根据 fly.io 负载均衡 的文档,可以知道 fly.io 支持通过请求书或者 tcp 连接数来进行自动扩容,因为前段时间我朋友的 API 被攻击了,然后服务器直接死亡,又因为他的 api 都是在非浏览器下使用,比如一些应用程序,脚本什么的不好做防御策略,所以我推荐他迁移到 fly.io 上

配置

首先把程序打包成 docker,然后部署到 fly.io 上,我使用的是 2H512M 的配置,并且创建了 11 台的实例。

然后通过 fly.toml 进行配置每一台实例的最高连接数,使用 [services.concurrency],参考配置:

# fly.toml app configuration file generated for cheat-show-backend on 2023-09-15T18:53:53-05:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#
 
app = "XXXXXXXXXXXX"
primary_region = "lax"
swap_size_mb = 1024
 
[http_service]
  internal_port = 8080
  force_https = false
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0
  processes = ["app"]
  [services.concurrency]
    type = "connections"
    hard_limit = 10000
    soft_limit = 1200
 
[build]
dockerfile = "Dockerfile"
 

soft_limit 是软限制,fly.io 会判断这个连接数从而限制每台实例,如果单台超出这个连接数则会启动其他实例,从而实现自动扩容。使用 wrk 测试后可以得出,我们部署的服务单台可以支撑 2k 的并发,为了给他足够的时间扩容,我把它的限制改成 1200,如果低于这个值,fly.io 只会启动一台机器,如果超过这个值,则根据连接数启动多台。

hard_limit 是硬限制,单台实例超过这个数值会返回 503。

压测

默认状态

连接数巨增状态 (wrk 5000 线程)

正常情况下只会开启一台,按分钟计费,一台跑一个月 3.8 刀,如果在连接数下降后会自动缩放至一台,停止状态的实例不会收费。

关于一些坑

fly.io 的负载均衡是就近回源。如果我有一台实例在纽约,有一台在洛杉矶,我默认想洛杉矶开着,纽约当后备的话需要一台洛杉矶的服务器进行反向代理 fly.io,如果直接访问的话会导致 fly.io 就近启动实例,比如纽约用户访问它会启动纽约的实例,即使连接数只有 1 也会启动。所以我还在 fly.io 的洛杉矶地区部署了 3 台 nginx 反向代理实例,使用 3 台 1h256m 的实例做负载均衡,经过优化后单台并发可以达到 1w+。

更新:好像修复了同地区自动弹性的问题,之前同地区的情况下会开启所有机器默认负载均衡,弹性只对跨地区起作用,这个坑已经没了,目前对同地区也生效。

优化后的 Dockerfile

FROM nginx
RUN sed -i 's/worker_processes auto;/worker_processes 8;/' /etc/nginx/nginx.conf
RUN sed -i 's/worker_connections [0-9]*;/worker_connections 9999999;/' /etc/nginx/nginx.conf
COPY nginx.conf /etc/nginx/conf.d/nginx.conf

nginx.conf

server {
  listen 8080 default_server;
  listen [::]:8080 default_server;
  server_name         api.test.com;
  keepalive_timeout   75s;
  keepalive_requests  100;

  location / {
      proxy_pass            http://ip:80;
      proxy_set_header      Host $host;
      proxy_set_header      Upgrade $http_upgrade;
      proxy_http_version 1.1;
  }
}

即可实现低成本的服务自动弹性扩容

成本问题

用于部署 nginx 的 3 台实例免费,后端实例基本上只有一台在开启,每个月 3.8 刀,不开启的不会收费。