12 Factor 方法论合并知识图谱 / 分组目录 / 12 Factor App 体系 / 端口绑定

端口绑定

App 体系基础方法原则GA · 12 Factor App 体系

What · 是什么

通过端口绑定自含导出服务,不依赖注入的 Web 服务器
web 应用有时在 webserver 容器内执行:PHP 应用作为 Apache HTTPD 内的模块运行,Java 应用跑在 Tomcat 内。
十二要素应用完全自包含,不依赖运行时注入 webserver 到执行环境来创建面向 web 的服务。
web 应用通过绑定端口把 HTTP 作为服务导出,并监听该端口上到来的请求,契约简单清晰,这正是端口绑定模型的自包含体现。
本地开发中开发者访问如 http://localhost:5000/ 的服务 URL 来使用应用导出的服务。
部署中由 routing layer 处理从公开主机名到端口绑定 web 进程的请求路由,应用无需关心。
典型实现:用依赖声明把 webserver 库加入应用,如 Python 的 Tornado、Ruby 的 Thin、Java/JVM 的 Jetty。
webserver 库完全在 user space(应用代码内部)运行,与运行环境的契约就是绑定端口服务请求。
HTTP 不是唯一可经端口绑定导出的服务:几乎任何服务器软件都能经进程绑定端口等待请求,如 ejabberd(XMPP)、Redis(Redis 协议)。
端口绑定还意味着一个应用可成为另一应用的 backing service:把 backing app 的 URL 作为消费方 config 中的资源句柄即可。

Why · 为什么

原理 · Principle

避免依赖运行时注入的 webserver 容器,使执行环境契约简洁统一,部署形态一致,这正是端口绑定模型的自包含体现。

契约即绑定端口提供服务,跨环境(本地/云平台)可移植,无需环境特化,使应用在任何执行环境都能以同一方式对外服务。

服务可嵌套:应用经端口绑定成为别的应用的 backing service,组合自由度高,是十二要素可移植性与环境契约简洁性的保障。

How · 怎么做

经依赖声明引入 webserver 库(Tornado/Thin/Jetty)进 user space,随应用一起构建。
进程启动即绑定端口并监听请求,作为对运行环境的服务契约,无需外部注入,这正是端口绑定模型的自包含体现。
本地经 http://localhost:端口 访问,生产由 routing layer 从公开主机名路由到端口绑定进程。
把某应用的 URL 作为另一应用 config 的资源句柄,实现服务嵌套消费,使应用在任何执行环境都能以同一方式对外服务。

案例 · Cases

代表性案例
Tornado:Python webserver 库,作为依赖加入应用自包含运行,这正是端口绑定模型的自包含体现。
Thin:Ruby webserver 库;Jetty:Java/JVM webserver 库,均可经依赖引入。
ejabberd:经端口绑定导出 XMPP 服务,非 HTTP 服务的端口绑定例子,使应用在任何执行环境都能以同一方式对外服务。
Redis:经端口绑定导出 Redis 协议服务,同样遵循端口绑定模型,是十二要素可移植性与环境契约简洁性的保障。
http://localhost:5000/:本地开发访问自含应用,无需外部 webserver,服务组合与嵌套因此变得自由而清晰。
PHP 模块在 Apache HTTPD 内、Java 应用在 Tomcat 内——容器注入的反例。

反模式 · Anti-patterns

相关边

实践资源 · 源码引用

路径说明
08-source/app-content-en/port-binding.mdVII. Port binding 原文:自包含/端口绑定契约/webserver 库/user space/routing layer/服务嵌套
08-source/app-content-en/dependencies.mdwebserver 经依赖声明引入的交叉引用
08-source/app-content-en/backing-services.md端口绑定服务可作为 backing service 的交叉引用
08-source/app-deploy/Procfile实例:web: ruby web.rb -p $PORT 启动即绑定 $PORT