使用Apache APISIX+Nginx实现地理路由 - frankel

22-11-07 banq

地理路由是根据用户的物理位置转发 HTTP 请求,从他们的 IP 推断。这样做的原因有很多,这里有几个:
有些应用程序确实随着业务的发展而增长。当这种情况发生时,就会出现对国际化和本地化的需求。
i18n应该由技术栈原生处理,例如在Java中。l10n更多是临时性的,但也不应该是一个问题。

当业务规则因国家而异时,问题就会出现,主要是由于法律的原因。其他原因包括伙伴关系。想象一下,一个在许多国家有分支机构的电子商务商店。你可以选择交付伙伴,但根据不同的国家,可用的合作伙伴是不同的。虽然保持单一代码库总是一个明智的选择,但即使是最好的设计也只能减缓许多业务规则带来的混乱。在某一时刻,将上帝应用程序拆分成多个依赖国家的应用程序是不可避免的。

有时,你甚至没有选择。一个国家决定你必须在他们的领土上存储你的数据库,所以你不能再分享它,必须把存储和应用程序都拆开。2015年,我在俄罗斯亲眼目睹了这一点:我们不得不为俄罗斯部署一个定制版本的电子商务应用程序。

最后,你也可能想只为一个国家部署一个新的应用程序版本。在这种情况下,你不应该(只)监测技术指标,而是随着时间的推移监测业务指标。然后,你将决定是否根据这些指标将新版本扩展到其他国家,或者在进一步部署之前对最新版本进行更多的工作。

为地理路由设置 Apache APISIX
Apache APISIX 不提供地理路由,但它建立在 Nginx 之上。后者提供了地理路由功能,尽管不是默认的。
以下说明基于 Docker,以允许每个人都遵循它们,而不管他们的平台如何。
我们需要几个步骤来在 Apache APISIX 上设置地理路由:

  1. 创建自定义 Docker 映像
    • 添加所需的库模块
    • 添加其依赖项
  • 配置 Apache APISIX

    Nginx 地理路由需要该ngx_http_geoip_module模块。但是如果我们尝试通过包管理器安装它,它也会安装nginx,这与nginx嵌入在 Apache APISIX 中的实例冲突。由于我们只需要这个库,我们可以从相关的 Docker 镜像中获取它:

    FROM nginx:1.21.4 as geoiplib
    
    FROM apache/apisix:2.15.0-debian
    
    COPY --from=geoiplib /usr/lib/nginx/modules/ngx_http_geoip_module.so \      
                         /usr/local/apisix/modules/ngx_http_geoip_module.so
    


    常规包安装会安装所有依赖项,甚至是我们不想要的依赖项。因为我们只复制库,所以需要手动安装依赖。这很简单:

    RUN apt-get update \
     && apt-get install -y libgeoip1
    


    Nginx 提供了两种激活模块的方法:通过命令行或在nginx.conf配置文件中动态激活。前者是不可能的,因为我们无法控制,所以后者是我们唯一的选择。为了在启动时使用模块更新 Nginx 配置文件,Apache APISIX 在其配置文件中提供了一个钩子:

    /usr/local/apisix/conf/config.yaml

    nginx_config:
      main_configuration_snippet: |
        load_module     "modules/ngx_http_geoip_module.so";
    


    以上将生成以下内容:

    /usr/local/openresty/nginx/conf/nginx.conf
    # Configuration File - Nginx Server Configs
    # This is a read-only file, do not try to modify it.
    master_process on;
    
    worker_processes auto;
    worker_cpu_affinity auto;
    
    # main configuration snippet starts
    load_module     "modules/ngx_http_geoip_module.so";
    
    ...
    


    GeoIP 模块依赖于Maxmind GeoIP 数据库。我们在上一步中隐式安装了它;我们必须配置模块指向它:

    /usr/local/apisix/conf/config.yaml
    nginx_config:
      http_configuration_snippet: |
        geoip_country   /usr/share/GeoIP/GeoIP.dat;
    



    从此时起,通过 Apache APISIX 的每个请求都是地理定位的。它翻译为 Nginx 添加额外的变量。根据文档:

    使用此数据库时可以使用以下变量:
    • $geoip_country_code两个字母的国家/地区代码,例如"RU", "US"。
    • $geoip_country_code3三个字母的国家代码,例如"RUS", "USA". $geoip_country_name国家名称,例如"Russian Federation", "United States"。


    结论
    地理路由是成功的应用程序和业务的必要条件。Apache APISIX 没有提供开箱即用的功能。在这篇文章中,我展示了如何使用 Nginx 的强大功能进行简单的设置。
    这篇文章的完整源代码可以在Github上找到。