有状态扩展:Kubernetes 集群中的 Laravel 会话管理

最后更新于

Stateful Scaling: Laravel Session Management in Kubernetes Clusters image

Kubernetes 是扩展 Laravel 应用程序 的绝佳选择。Kubernetes 提供可扩展性、高可用性、服务发现和负载均衡。特别是在 Laravel 部署方面,Kubernetes 可以帮助实现无状态水平扩展、轻松管理后台处理以及存储灵活性。

但它也会带来成本。Kubernetes Pod 的短暂性以及它们的扩展方式使得在 Laravel 中进行会话管理变得很困难。使用默认的文件会话驱动程序会导致在 Pod 重启或被替换时丢失数据,因此开发人员必须转向不同的机制。

在这里,我们想带您了解一些在迁移到 Kubernetes 部署时,在 Laravel 会话管理中会遇到的陷阱。好消息是,只要了解容器化的内部机制,这些问题都是可以解决的。

将 Kubernetes 与 Laravel 一起使用的好处

让我们从为什么你可能想这样做开始。您可以以多种不同的方式部署 Laravel 应用程序,那么为什么要选择一个会立即给你带来这种会话问题的方法呢?嗯,在 Kubernetes 上部署 Laravel 应用程序的核心优势是

  1. **无状态水平扩展。** Laravel 本质上被设计为对大多数组件(如果本地存储会话和缓存除外)都是无状态的。这种设计与 Kubernetes 的扩展能力相得益彰。当您 Laravel 应用程序的流量增加时,Kubernetes 可以快速生成更多 Laravel 应用程序的副本以处理负载,反之亦然,当流量减少时,Kubernetes 可以快速生成更多 Laravel 应用程序的副本以处理负载,反之亦然,当流量减少时,Kubernetes 可以快速生成更多 Laravel 应用程序的副本以处理负载,反之亦然。
  2. **后台处理。** Laravel 的作业和队列系统基于 Laravel Horizon 等工具构建,可以从 Kubernetes 的部署策略中获益。例如,工作器容器可以独立于主应用程序进行扩展,从而有效地处理排队的作业。
  3. **配置管理。** Laravel 的配置系统很大程度上依赖于环境变量。Kubernetes 的 ConfigMaps 和 Secrets 使得在不同环境(开发、登台、生产)中一致且安全地管理和注入这些环境变量变得容易。
  4. **存储灵活性。** 如果您的 Laravel 应用程序需要文件存储(例如,用于用户上传),Kubernetes 提供了持久卷声明 (PVC),它们抽象了底层存储后端。这意味着您的 Laravel 应用程序可以无缝地存储文件,无论您是在云对象存储、块存储设备还是网络文件系统上。
  5. **服务网格集成。** 如果您在 Kubernetes 上的 Laravel 应用程序中采用 Istio 等服务网格,您将获得增强的可观察性、流量管理和安全功能,而无需修改 Laravel 应用程序本身。

但是,虽然 Kubernetes 提供了这些好处,但也引入了复杂性,会话管理成为了这种复杂性的牺牲品。上面提到的好处之一是导致会话管理问题的罪魁祸首——无状态水平扩展。这会通过引入 Laravel 应用程序的多个副本,而这些副本可能不会天生共享会话状态,从而导致会话管理问题。

在传统的单服务器设置中,用户的会话数据通常存储在本地,使其可以立即用于来自该用户的后续请求。在 Kubernetes 中,由于多个副本处理请求,用户每次请求都可能由不同的副本提供服务。

Laravel 和 Kubernetes 的会话管理挑战

因此,会话管理的挑战来自三个对 Kubernetes 工作方式至关重要的因素。

首先,需要会话持久性。当会话存储在 Pod 中的本地时,转到不同副本的请求将无法访问之前的会话数据,从而导致用户体验破损。这种不一致会导致用户随机注销或需要帮助保留应用程序状态等问题。

其次是 Pod 的短暂性。Kubernetes 中的 Pod 可以随时终止和替换,尤其是在它们变得不健康或在更新期间。如果会话存储在 Pod 内的本地,并且该 Pod 被终止,则会话数据将丢失,从而影响用户体验。

第三,虽然 Kubernetes 确实提供了跨 Pod 的负载均衡,但在没有会话亲和性配置的情况下,来自同一用户的后续请求可能会落在不同的副本上。如果没有集中式会话存储,这会导致不可预测的行为。

所有这些都会导致数据同步开销和延迟增加,因为尝试通过同步或其他非集中式方法管理会话可能会在请求中引入延迟。这会损害用户体验,尤其是在响应时间至关重要的应用程序中。

为了应对这些挑战,在 Kubernetes 上部署 Laravel 的开发人员有两个选择

  1. 利用 Kubernetes 的会话亲和性功能,确保来自用户的请求始终落在同一个副本上。
  2. 将会话存储在 Redis 或数据库等分布式系统中,确保会话数据集中化并可供所有副本访问。

让我们分别介绍每个选项以及它们在 Laravel 中的工作原理。

粘性会话

会话亲和性,也称为“粘性会话”,在部署有状态应用程序或工作负载的场景中至关重要,您希望来自特定客户端的所有请求始终转到同一个 Pod。在 Kubernetes 中,您可以使用服务会话亲和性来实现这一点。

在传统的单体架构中,应用程序通常运行在单个服务器上,会话数据存储在本地。此模型确保来自特定用户的后续请求始终可以访问该用户的会话数据。但是,在 Kubernetes 等容器编排环境中,您的应用程序可能运行在分布在不同节点上的多个 Pod 中。在这种情况下,没有内在的保证,用户后续的请求每次都会命中同一个 Pod。

这就是粘性会话发挥作用的地方。对于特定的应用程序,用户的请求必须始终落在同一个 Pod 上,才能维护应用程序状态、提供一致的用户体验或有效地利用本地缓存。

Kubernetes 提供了会话亲和性的概念,使您能够指定来自特定客户端的所有请求都应路由到同一个 Pod。这是通过使用 Cookie 或 IP 来实现的。

当您根据客户端的 IP 地址配置会话亲和性时,Kubernetes 会检查传入请求的源 IP,并将其定向到与来自该 IP 的先前请求相同的 Pod。如果会话亲和性基于 Cookie,Kubernetes 将确保所有具有特定 Cookie 的请求都定向到同一个 Pod。

在您服务的 YAML 定义中,您必须指定会话亲和性类型。例如

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
sessionAffinity: ClientIP

在上面的配置中,sessionAffinity 字段设置为 ClientIP,这意味着 Kubernetes 服务将使用客户端的 IP 地址来确保来自该 IP 的所有请求都将定向到同一个 Pod。

如果您想对会话亲和性进行更多控制,可以使用 sessionAffinityConfig。例如,要为会话亲和性设置超时时间

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 3600

虽然粘性会话可以解决一些问题,但它们并不总是合适的。如果处理粘性会话的 Pod 不堪重负或关闭,用户可能会遇到性能问题或中断。

仅依赖粘性会话也会导致 Pod 之间的流量分配不均匀,尤其是在某些客户端进行更频繁或资源密集型请求的情况下。对于许多用例而言,与粘性会话相比,Redis 等集中式会话存储可能更具可扩展性和容错性。因此,让我们看看这个选项。

使用 Redis 的分布式会话存储

Laravel 中的 Redis 等分布式会话存储允许您在多个应用程序实例之间共享会话数据。这在 Kubernetes 等可扩展环境中尤其有用,在这些环境中,您的应用程序可能运行在多个 Pod 中,并且这些 Pod 中的任何一个都可以为用户请求提供服务。

Redis 由于以下原因是理想的选择:

  1. 性能。Redis 是一个内存中的数据结构存储,提供快速的数据访问。这使其非常适合会话管理,在会话管理中,快速读写操作对于维护无缝的用户体验至关重要。
  2. 可扩展性。Redis 支持水平分区或分片,使其能够跨多台机器进行扩展。在高流量场景中,单个 Redis 实例可能会成为瓶颈,此时您可以将数据分布在多个 Redis 实例中。
  3. 持久性。虽然 Redis 主要是一个内存存储,但它提供了将数据持久保存到磁盘的机制,而不会影响太多性能。这确保了如果 Redis 服务重新启动,会话数据不会丢失。
  4. 数据结构。Redis 不仅仅是一个简单的键值存储。它支持各种数据结构,如字符串、哈希、列表和集合。这种灵活性对于更复杂的与会话相关的操作非常有利。

Redis 在粘性会话方面也有一些优势。由于任何实例都可以处理请求,因此流量在所有 Pod 之间更均匀地分布。如果一个 Pod 出现故障,用户会话不会丢失。另一个 Pod 可以接管请求并从 Redis 中获取会话数据。随着流量的增长,您可以根据需要独立地扩展应用程序和 Redis 实例。

让我们逐步了解如何在 Laravel 中将 Redis 设置为会话驱动程序。首先,您需要安装所需的包

composer require predis/predis

然后,您可以更新 Laravel 的 .env 文件以指向 Redis 进行会话管理

SESSION_DRIVER=redis
REDIS_HOST=your_redis_server
REDIS_PASSWORD=your_redis_password
REDIS_PORT=6379

在 Laravel 中,您需要更新您的 config/session.php 以使用 .env 文件中的会话驱动程序

'driver' => env('SESSION_DRIVER', 'file'),

然后,确保 config/database.php 中的 Redis 配置如下所示

'redis' => [
'client' => 'predis',
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
],

接下来,您需要一个表来存储会话。Laravel 提供了一个命令来生成此表

php artisan session:table

这将创建一个迁移文件。运行迁移以创建 sessions 表

php artisan migrate

完成上述配置后,Laravel 将自动使用 Redis 处理会话,而无需在您的应用程序中编写任何特定代码。例如,当您设置一个会话变量时

session(['key' => 'value']);

此值将存储在 Redis 中。要检索它

$value = session('key');

当您调用这些函数时,Laravel 会自动使用 Redis 作为后端来管理会话数据。

要在 Kubernetes 中部署 Redis,您需要使用 Helm 在您的 Kubernetes 集群中部署 Redis 实例

# Add the Bitnami repository which has the Redis chart
helm repo add bitnami <https://charts.bitnami.com/bitnami>
 
# Install Redis using Helm
helm install my-redis bitnami/redis

请务必记下安装过程中 Helm 提供的 Redis 实例的密码。然后,创建一个 Kubernetes 服务清单文件。我们将其命名为 redis-service.yaml

apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
selector:
app: redis
ports:
- protocol: TCP
port: 6379
targetPort: 6379

您可以应用 Kubernetes 服务清单以创建服务

kubectl apply -f redis-service.yaml

然后验证服务是否正在运行

kubectl get svc redis-service

最后,通过更新您的 Laravel .env 文件或配置以使用在 Kubernetes 中创建的 Redis 服务,将 Laravel 指向 Kubernetes Redis 服务

REDIS_HOST=redis-service
REDIS_PORT=6379

redis-service 是主机,因为它是在 Kubernetes 服务的名称,Kubernetes 内部 DNS 将解析此名称到服务的适当 IP 地址。

恭喜,您已将 Redis 与 Laravel 集成,并确保 Laravel 应用程序与部署在 Kubernetes 中的 Redis 实例通信。这确保会话数据在分布式环境中得到有效存储和管理。

使用 Laravel 和 Kubernetes 实现可扩展的会话

使用会话亲和性和分布式会话存储,您的 Laravel 应用程序可以存储和持久保存所有应用程序实例都可以访问的会话数据。然后,您可以扩展您的应用程序,确保所有用户都保留其会话数据,而无论应用程序的哪个实例处理其请求。在 Kubernetes 环境中,Pod 可能短暂存在,用户请求可以路由到任何 Pod,这些选项对于维护用户会话一致性至关重要。

随着技术的不断发展,确保无缝的用户体验变得至关重要,尤其是在 Kubernetes 等分布式和可扩展的环境中。通过利用 Laravel 的固有适应能力和 Kubernetes 的强大功能,开发人员可以解决会话管理的挑战。这种组合不仅增强了应用程序的弹性,而且还为未来的可扩展性铺平了道路,而不会影响用户体验。

立即尝试 Scout APM

Sarah Morgan photo

Sarah 在软件行业拥有超过 18 年的经验。除了她目前担任 Scout 的高级产品经理一职外,她还是 Product School 的特邀演讲者,也是 Tapple.io 的产品战略顾问。

归档于
Cube

Laravel 新闻

加入 40,000 多名其他开发人员,绝不错过新的提示、教程等。

Laravel Forge logo

Laravel Forge

轻松创建和管理您的服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成和本地和生产环境的即时反馈进行修补。

Tinkerwell
No Compromises logo

无妥协

Joel 和 Aaron,两位来自 No Compromises 播客的经验丰富的开发者,现在可以为您的 Laravel 项目提供服务。 ⬧ 每月固定价格 7500 美元。 ⬧ 没有冗长的销售流程。 ⬧ 没有合同。 ⬧ 100% 退款保证。

无妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,以确保您的 Web 应用程序取得成功。

Kirschbaum
Shift logo

Shift

正在运行旧版本的 Laravel?即时、自动化的 Laravel 升级和代码现代化,使您的应用程序保持新鲜。

Shift
Bacancy logo

Bacancy

每月仅需 2500 美元,即可使用经验丰富的 Laravel 开发人员(拥有 4-6 年的经验)为您的项目增光添彩。获得 160 小时的专业技能和 15 天的无风险试用。立即预约电话!

Bacancy
Lucky Media logo

Lucky Media

现在就来 Lucky - Laravel 开发的理想选择,拥有十多年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar:Laravel 电子商务

Laravel 的电子商务。一个开源软件包,为 Laravel 带来了现代无头电子商务功能的强大功能。

Lunar:Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 职位招聘网站

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit:Laravel SaaS 启动套件

SaaSykit 是一个 Laravel SaaS 启动套件,它包含运行现代 SaaS 所需的所有功能。支付、漂亮的结账、管理面板、用户仪表板、身份验证、现成组件、统计信息、博客、文档等等。

SaaSykit:Laravel SaaS 启动套件
Rector logo

Rector

您的无缝 Laravel 升级合作伙伴,降低成本,加速创新,为成功的企业提供支持

Rector
MongoDB logo

MongoDB

通过 MongoDB 和 Laravel 的强大集成来增强您的 PHP 应用程序,使开发人员能够轻松高效地构建应用程序。支持事务性、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。了解 MongoDB 的灵活、现代数据库如何改变您的 Laravel 应用程序。

MongoDB

最新消息

查看全部 →
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的零依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

将 Swagger UI 添加到您的 Laravel 应用程序

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel Prompts 构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的站点搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 包将评论添加到您的 Laravel 应用程序

阅读文章