Kubernetes集群中有状态扩展的Laravel Session会话管理
Laravel  /  管理员 发布于 1年前   278
Kubernetes 是扩展 Laravel 应用程序的绝佳选择。Kubernetes 提供了可扩展性、高可用性、服务发现和负载平衡。
具体到 Laravel 部署,Kubernetes 可以帮助实现无状态水平扩展、后台处理的轻松管理和存储灵活性。
https://scoutapm.com/frameworks/laravel-monitoring?utm_source=laravelnews&utm_medium=affiliate&utm_campaign=q1_2024&utm_content=stateful_scaling_laravel_blog
但这也是有代价的。Kubernetes pod 的短暂性及其扩展方式使得 Laravel 中的会话管理变得困难。
如果重新启动或替换 pod,使用默认的文件会话驱动程序可能会导致数据丢失,因此开发人员必须转向另一种机制。
在这里,我们将带你了解在转向 Kubernetes 部署时,Laravel 会话管理会遇到的一些问题。
好消息是,只要了解容器化的内部运作,这些问题都是可以解决的。
在 Laravel 中使用 Kubernetes 的好处
先说说为什么要这么做。
你可以用无数种不同的方式部署 Laravel 应用程序,那么为什么要选择一种会让你立即头疼的方式呢?
在 Kubernetes 上部署 Laravel 应用程序的核心优势如下:
1.无状态水平扩展。
Laravel 本身的大部分组件(不包括会话和本地存储的缓存)都是无状态的。
这种设计与 Kubernetes 的扩展能力相得益彰。
当 Laravel 应用程序的流量增加时,Kubernetes 可以快速生成更多
Laravel 应用程序的副本来处理负载,反之亦然。
2.后台处理。
围绕 Laravel Horizon 等工具构建的 Laravel 作业和队列系统,
可以从 Kubernetes 的部署策略中获益。
例如,工作容器可以独立于主应用程序进行扩展,从而有效处理队列作业。
3.配置管理。
Laravel 的配置系统在很大程度上依赖于环境变量。
Kubernetes 的配置地图(ConfigMaps)和秘诀(Secrets)可以轻松地管理和注入这些环境变量,
并在不同环境(开发、暂存、生产)中保持一致和安全。
4.存储灵活性。
如果你的 Laravel 应用程序需要文件存储(例如用户上传),
Kubernetes 可提供持久卷声明(Persistent Volume Claims,PVC),对底层存储后端进行抽象。
这意味着你的 Laravel 应用程序可以在云对象存储、块存储设备或网络文件系统上无缝存储文件。
5.服务网格集成。
如果你在 Kubernetes 上的 Laravel 应用程序中采用 Istio 这样的服务网格,
就能在不修改 Laravel 应用程序本身的情况下,获得增强的可观察性、流量管理和安全功能。
不过,Kubernetes 在带来这些好处的同时,也带来了复杂性,会话管理就是复杂性的牺牲品。
上述优势之一就是导致会话管理问题的罪魁祸首--无状态水平扩展。
这会导致会话管理问题,因为它引入了多个 Laravel 应用程序副本,而这些副本可能无法共享会话状态。
在传统的单服务器设置中,用户的会话数据通常存储在本地,以便该用户的后续请求可以立即使用。
在 Kubernetes 中,由于有多个副本处理请求,用户的每次请求都可能由不同的副本处理。
会话管理对 Laravel 和 Kubernetes 的挑战
会话管理的挑战来自 Kubernetes 工作方式中不可或缺的三个因素。
首先,需要会话持久性。
当会话存储在 pod 的本地时,转到不同副本的请求将无法访问之前的会话数据,从而导致用户体验崩溃。
这种不一致性会导致用户随机注销或需要帮助保留应用程序状态等问题。
其次是 pod 的短暂性。
Kubernetes 中的 Pod 可以随时终止和替换,尤其是在它们变得不健康或更新期间。
如果会话存储在本地 pod 中,而 pod 被终止,会话数据就会丢失,从而影响用户体验。
第三,虽然 Kubernetes 确实提供了跨 pod 的负载平衡,但如果没有会话亲和性配置,
同一用户的后续请求可能会落到不同的副本上。
如果没有集中的会话存储,这可能会导致不可预测的行为。
这些都会导致数据同步开销和延迟增加,因为试图通过同步或其他非集中方法管理会话会给请求带来延迟。
这会影响用户体验,尤其是在对响应时间要求极高的应用程序中。
为了应对这些挑战,部署 Kubernetes 的 Laravel 开发人员有两种选择:
利用 Kubernetes 的会话亲和性功能,确保用户的请求始终落在同一个副本上。
将会话存储在分布式系统(如 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 是一个理想的选择,因为性能。
Redis 是一种内存数据结构存储,可提供快速的数据访问。
这使其非常适合会话管理,快速的读写操作对保持无缝的用户体验至关重要。
可扩展性。Redis 支持水平分区或分片,因此可在多台机器上进行扩展。
在高流量场景中,单个 Redis 实例可能会成为瓶颈,这时您可以将数据分布到多个 Redis 实例上。
持久性。
虽然 Redis 主要是内存存储,但它提供了在磁盘上持久化数据的机制,而不会对性能造成太大影响。
这可确保会话数据不会在 Redis 服务重启时丢失。
数据结构。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
这将创建一个迁移文件。运行迁移,创建会话表:
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 的健壮性,开发人员可以应对会话管理的挑战。
这种组合不仅增强了应用程序的弹性,还为未来的可扩展性铺平了道路,同时不会影响用户体验。
122 在
学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
Copyright·© 2019 侯体宗版权所有·
粤ICP备20027696号