news 2026/9/9 22:54:22

云原生大模型部署实战:K8s GPU调度与vLLM弹性伸缩全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
云原生大模型部署实战:K8s GPU调度与vLLM弹性伸缩全攻略

把大模型服务从“脚本启动”搬到云原生环境,这个事我最近刚好完整做了一轮,踩了不少坑,也理顺了不少逻辑。今天这篇就围绕云原生环境中的大模型部署策略展开,把我实际用到的方案、踩过的雷、反复调过的参数,全部整理出来。

这篇内容适合三类人:一是正在做AI平台或模型服务化的工程师,二是想把本地Ollama部署升级成生产级API服务的同学,三是刚接触Kubernetes但想搞清楚“GPU调度到底怎么玩”的运维。我会从部署形态选型、K8s GPU调度、弹性伸缩、常见故障排查这几个维度讲,尽量做到可以直接抄作业。

先说一个核心结论:云原生部署大模型,真正的难点不是“把模型塞进容器”,而是显存调度、弹性伸缩、流量治理、模型更新这些工程化的事情。模型推理快不快,取决于GPU和推理引擎;模型服务稳不稳、省不省成本、能不能扛住流量波动,才取决于云原生这套架构。

1. 为什么我建议把大模型推理服务迁到Kubernetes

1.1 单机部署大模型的三个真实痛点

很多人最开始部署大模型,都是在一台GPU服务器上跑脚本,用nohup或者systemd把推理服务拉起来。这个方法在开发验证阶段完全够用,但一旦要面对多个模型、多个业务方、流量忽高忽低的情况,问题就接踵而来。

第一个痛点是显存利用率低。我团队早期有两台GPU服务器,一台跑了LLM推理,一台跑了Embedding模型,显存分配都是写死的。结果LLM那台晚高峰排队,Embedding这台一整个白天几乎闲置。后来想把Embedding模型挪过去和LLM混布,又担心相互干扰,最后只能继续闲置着。

第二个痛点是模型更新必须停服。旧模型要换新版本,先杀掉旧进程,再拉新镜像,再启动服务。如果是工作日白天操作,业务方直接投诉“API又挂了”。这种更新方式在单机环境里几乎没法做到平滑。

第三个痛点是故障恢复全靠人。GPU卡偶发异常、显存被某个进程吃满、进程僵死,都需要人工登服务器排查。晚上两三点被告警叫醒,然后手动重启服务,这类经历相信不少人都体会过。

1.2 云原生到底解决了什么问题

云原生给大模型部署带来的核心能力,可以概括成四个词:编排、调度、弹性、可观测。

编排解决的是“多副本如何管理”。同一个推理服务可以跑多个副本,滚动更新时先起新Pod、再杀旧Pod,请求不中断。调度解决的是“模型跑到哪块GPU上”。通过节点标签、亲和性、资源请求,可以把不同模型合理地分配到不同GPU节点上。

弹性解决的是“流量多了怎么办、流量少了怎么办”。Kubernetes自带的HPA加上自定义指标,可以实现基于GPU利用率或请求队列长度的自动伸缩。业务高峰多拉起几个推理副本,低峰自动缩容,省下的GPU资源可以给其他任务用。

可观测解决的是“服务出了什么状况”。通过Prometheus采集指标、Grafana展示面板、Loki收集日志,GPU利用率、请求延迟、显存占用这些指标都可以一目了然。

但这里我必须泼一盆冷水:云原生本身不是性能加速器。它不会让你的模型推理变得更快,它的价值在于让已有的GPU算力被更高效地组织、更稳定地输出。如果你只有一台服务器、一个模型、几十个日活调用方,直接上K8s反而增加运维复杂度,不一定划算。

1.3 部署策略的整体链路

我习惯把云原生大模型部署拆成三条线来看:资源层、服务层、流量层。

资源层解决的是GPU怎么管。包括GPU设备插件、显存切分方案、节点池划分、资源配额。服务层解决的是模型怎么跑。包括推理引擎选型、模型加载方式、副本管理、更新策略。流量层解决的是请求怎么进。包括Ingress网关、路由规则、限流熔断、灰度发布。

三层各司其职,但又是联动的。比如某业务方流量大增,流量层先做限流保护,然后HPA根据指标扩容服务层副本,服务层扩容前资源层要保证节点池里有可调度的GPU资源。这三条线都理顺了,整个部署策略才算闭环。

2. 选型对比:Ollama和vLLM到底该怎么选

2.1 先分清你处在哪个部署阶段

现在开源推理工具非常多,很多人一上来就懵。我给大家一个判断框架:先分清你是“本地私有部署”还是“生产对外服务”。

本地私有部署,典型场景是个人电脑或内网服务器上跑一个私有模型,自己用、小团队用、或接Open WebUI这类前端。这时候追求的是快速启动、操作简单、模型管理方便。Ollama是这类场景的不二之选,一条命令就能拉模型、起服务,API也简单,还有配套的模型仓库管理。

生产对外服务,典型场景是多个业务方调用API,有并发、有SLA要求、需要压测、需要监控。这时候追求的是高吞吐、低延迟、稳定的显存控制和高级调度能力。Ollama就略显吃力,vLLM、TensorRT-LLM、TGI这类专门的推理引擎才是正解。

我见过不少团队把Ollama直接暴露到生产环境,前期没问题,流量一起来就各种超时、OOM、排队。不是说Ollama不行,而是它设计的定位就不是高并发推理服务。工具选型一定要匹配场景,这一点非常重要。

2.2 主流推理引擎横向对比

这里我列一个实际对比表格,都是我自己部署过的引擎,参数和表现基于实测:

引擎定位核心优势主要短板适用场景
Ollama本地/私有快速部署安装简单、模型管理方便、依赖少高并发吞吐偏弱、调度能力有限开发验证、内网小范围使用、个人电脑
vLLM生产级高吞吐推理PagedAttention显存效率高、兼容OpenAI API、支持Prefix Caching部署配置项多、学习曲线稍陡对外API服务、GPU集群、高并发场景
HuggingFace TGI生产级推理HuggingFace生态紧密、动态批处理成熟部分新模型适配慢、调优依赖经验与HF生态深度绑定的团队
TensorRT-LLM极致性能推理NVIDIA硬件上性能天花板最高模型编译复杂、构建时间长、灵活性低固定模型+固定硬件、极致性能诉求
SGLang高性能结构化推理结构化输出支持好、调度灵活社区相对新、资料较少需要复杂结构化输出的场景

从这个表能看出来,没有哪个引擎是绝对王者,关键看你的调用模式和硬件事态。

2.3 我的选型建议

如果你是刚开始,我的建议是分两步走。第一步:先用Ollama在本地把模型跑通,验证模型效果、调prompt、测业务逻辑。第二步:确认模型效果没问题、要上生产了,再用vLLM搭建正式API服务,配合K8s做云原生部署。

整个流程里,模型权重是共享的,不会因为换了推理引擎就需要重新下载模型。

关于vLLM,它最打动我的一点是PagedAttention,它把KV Cache拆成块来管理,大幅度减少了显存碎片,这让它在大并发场景下能塞入更多请求。另外它还提供了兼容OpenAI的API接口,迁移成本很低,原来的openai客户端改一下base_url就能直接对接。

如果你用的是NVIDIA A100/H100这类专业卡,TensorRT-LLM确实能榨出更高性能,但它引入的复杂度不容小觑。模型需要编译优化,每次换版本都要重新构建。个人建议,除非你对单卡吞吐有极致的追求,否则先用vLLM把业务跑起来,性价比最高。

3. K8s部署大模型推理服务:一份能直接抄的YAML

3.1 GPU资源管理:整卡、MIG、共享显存怎么选

Kubernetes默认只认识“整张GPU卡”,通过nvidia.com/gpu这个资源名来调度。一台8卡机器,nvidia.com/gpu: 1就是分配一张完整的显卡给某个Pod。这种方式简单粗暴,适合大模型这种独占显存需求明显的场景。

但实际部署中我发现一个问题:并不是所有模型都需要一整张卡。一个7B模型量化后显存占用可能只要8GB左右,但整卡40GB显存(A100)大部分时间是闲置的。这时候有两个选择,一个是NVIDIA MIG,把物理GPU切成多个独立的GPU实例;另一个是GPU Sharing,用第三方插件实现显存共享。

MIG只支持A100、H100这类高端卡,切分后每个实例有独立的显存和计算资源,隔离性最好,但配置稍麻烦,而且不同CUDA版本对MIG的支持不一致。GPU Sharing方案(比如阿里云的gpu-share、NVIDIA的time-slicing)配置更灵活,但隔离性弱,可能出现显存被打爆影响同卡其他Pod的情况。

我的实操经验是:生产环境优先整卡分配,用节点池来做资源划分;GPU Sharing适合测试环境或非核心服务。不要一上来就追求极致利用率,先把稳定性和隔离性保住。

3.2 vLLM推理服务的Deployment配置示例

下面这份YAML是我在实际项目里用过的,去掉了业务相关字段,保留了核心配置:

apiVersion: apps/v1 kind: Deployment metadata: name: vllm-llama-server namespace: ai-service spec: replicas: 1 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 selector: matchLabels: app: vllm-llama template: metadata: labels: app: vllm-llama spec: terminationGracePeriodSeconds: 120 containers: - name: vllm image: vllm/vllm-openai:latest command: ["python3", "-m", "vllm.entrypoints.openai.api_server"] args: - --model - /models/llama-7b-chat - --tensor-parallel-size - "1" - --max-model-len - "32768" - --gpu-memory-utilization - "0.9" - --port - "8000" - --enable-prefix-caching ports: - containerPort: 8000 name: http resources: limits: nvidia.com/gpu: 1 memory: 32Gi cpu: "8" requests: nvidia.com/gpu: 1 memory: 24Gi cpu: "4" readinessProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 30 periodSeconds: 10 livenessProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 60 periodSeconds: 30 volumeMounts: - name: model-storage mountPath: /models volumes: - name: model-storage persistentVolumeClaim: claimName: model-pvc

这里有几个参数我必须单独拿出来讲,因为它们直接决定了服务能不能稳定跑。

--max-model-len这个参数设置模型最大上下文长度。它直接影响显存的KV Cache预分配。设得太大,启动时直接把显存占满;设得太小,超过长度的用户请求被截断。我建议结合业务实际输入输出来估算,一般场景16384或32768比较常用。

--gpu-memory-utilization设置KV Cache可用的显存比例。默认是0.9,也就是90%显存会预留给KV Cache。这个值不是越高越好,留出的10%要覆盖激活参数和临时计算的开销。如果设成0.99,在部分模型上启动就会报CUDA Out of Memory。

--tensor-parallel-size是多卡张量并行参数。如果模型单卡放不下,需要设置成2、4等,但这要求模型本身支持张量并行,且多卡之间通过NVLink通讯。没有NVLink的机器,性能会明显下降。

--enable-prefix-caching是vLLM的缓存前缀复用开关,后面还会具体讲。

3.3 模型文件加载:三种方式该怎么选

大模型权重文件动不动几十GB,怎么让Pod读到模型文件,是个不能回避的问题。我试过三种方式,各有优缺点。

第一种是把模型文件打包装进容器镜像。优点是Pod启动就能用,不依赖外部存储;缺点是镜像体积巨大、构建和推送慢、更新模型要重新构建镜像。我建议除非模型很小(几GB以内)且很少更新,否则不要用这个方式。

第二种是用PVC(PersistentVolumeClaim)挂载模型文件。在K8s集群里先创建一块存储,把模型文件放进去,Pod启动时直接挂载。优点是模型更新只需替换存储里的文件,Pod不用重新拉镜像;缺点是存储要准备足够空间,多副本同时读时要注意存储的IO能力。

第三种是用Init Container从对象存储拉取模型到临时目录。Pod启动时先跑一个Init Container把模型从对象存储下载到emptyDir,再启动主容器加载。优点是不需要创建持久化存储,对象存储管模型版本很方便;缺点是每次Pod重建都要重新拉模型,冷启动时间会比较长。

我目前用的是方案二:PVC挂载。在本地测试时把模型文件传到PVC里,生产环境通过对象存储同步到PVC。这样做的好处是模型版本更新时,我只需要在PVC里切换软链接,不用重启Pod就能完成模型灰度。

3.4 模型平滑更新:一个很容易翻车的地方

K8s的滚动更新默认行为是“先起新的,再杀旧的”,但对大模型推理服务来说,这个默认行为会引发严重问题。

原因在于新Pod启动到Ready通常需要几分钟甚至十几分钟,因为要加载几十GB的模型文件、分配显存、预热缓存。如果在旧Pod还没退出时新Pod还没Ready,流量就不会切换,但如果你没配置maxUnavailable: 0,旧Pod可能会被立刻杀掉,服务就出现了空白窗口。

我的做法是三点配合:strategy.rollingUpdate.maxSurge: 1表示最多多出1个副本,maxUnavailable: 0表示旧副本不能减少,再配合readinessProbe让新Pod就绪后才接流量。这个组合保证了更新过程中始终至少有1个可用的推理副本。

另外terminationGracePeriodSeconds一定要设置足够长。vLLM接到SIGTERM后需要把正在生成的请求处理完再退出,如果这个时间设得太短(默认30秒),进程还没处理完就被强杀,线上就会看到大量客户端报连接重置。我设成了120秒,实测下来比较稳。

4. 弹性伸缩与流量治理:让GPU跟着业务节奏走

4.1 推理场景为什么不建议用CPU指标做伸缩

K8s默认的HPA通常基于CPU使用率来做伸缩,但对大模型推理服务来说,这几乎是无效的。

原因很简单:推理服务的主要瓶颈是GPU利用率和显存,CPU使用率往往很低(数据预处理、调度、tokenize),甚至可能一直低于20%。按CPU伸缩的话,只有流量已经高到把CPU打满才会扩容,但那时GPU早就打满了,请求已经在排队了。

正确的做法是基于自定义指标做伸缩。核心指标有两个:一是GPU利用率,二是推理服务的请求队列长度。GPU利用率高说明当前算力吃紧,需要扩容;推理队列长说明进来的请求超出处理能力,需要增加副本。

实现上,vLLM会暴露Prometheus格式的监控指标,包括running_requestswaiting_requestsgpu_utilization等,然后用Prometheus Adapter把它们暴露给HPA使用。

4.2 基于vLLM队列长度的KEDA自动伸缩

我用的是KEDA(Kubernetes Event-driven Autoscaling),它比原生HPA灵活,可以直接从Prometheus查询指标来做伸缩。下面是一个ScaledObject示例:

apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: vllm-llama-scaler namespace: ai-service spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: vllm-llama-server minReplicaCount: 1 maxReplicaCount: 4 triggers: - type: prometheus metadata: serverAddress: http://prometheus.monitoring.svc:9090 query: | sum(avg_over_time(vllm:waiting_requests{namespace="ai-service"}[2m])) threshold: "5"

这个配置的含义是:每2分钟采样一次vLLM的等待请求数,如果超过5个就触发扩容,最多扩到4个副本;请求数降下来后会自动缩回1个副本。

这个方案运行时一定要关注冷启动时间。大模型推理Pod的冷启动可能长达10分钟,如果一个突发流量过来,扩容的数字上去了,但新Pod还加载不完模型,集群就会陷入“扩容没用”的状态。为了缓解这个,我把minReplicaCount至少设为1,并且让核心模型始终保持一个“热副本”。

4.3 缓存命中率与vLLM Prefix Caching调优

关于“vLLM如何优化大模型的缓存命中率”这个问题,实际上指的是vLLM的Prefix Caching功能。它会把请求的公共前缀部分(比如system prompt、固定指令)的KV Cache缓存起来,后续相同前缀的请求可以直接复用这部分计算结果,不需要重新跑一遍注意力计算,显著提升吞吐。

影响命中率的关键因素有三个。一是请求必须共享相同前缀。如果每个请求的system prompt都不一样,或者prompt构建时随机性太强,缓存很难命中。二是缓存容量有限,如果max-model-len设置过大导致cache区域碎片化,命中率也会下降。三是调度策略,不同请求的prefix长度不一,vLLM需要高效匹配缓存块。

实操调优建议:

  • 所有请求统一使用固定的system prompt模板,不要逐票拼接动态前缀。
  • 启动参数加--enable-prefix-caching开启前缀缓存功能。
  • 对于模型内部prompt,把“工具定义”、“系统角色”这些固定内容放在最前面,因为前缀匹配是从开头对齐的。
  • 监控缓存命中情况,可以通过vLLM暴露的metrics来观察,命中率低的业务再反过来优化prompt结构。

4.4 多模型统一入口与限流策略

生产环境通常不止一个模型服务。LLM一个服务、Embedding一个服务、多模态一个服务,如果每个服务都暴露独立域名,调用方会非常痛苦。

我建议用统一的API网关做入口,比如APISIX或Nginx Ingress。按路径前缀把请求路由到不同后端服务:/v1/llm/chat路由到vLLM服务,/v1/embedding路由到Embedding服务。

网关层面还要做限流。原因是大模型推理资源很贵,一个业务方的突发流量随时可能打爆整个服务。限流策略要区分“并发限流”和“QPS限流”。大模型场景更建议限制并发数,因为一个请求可能持续几十秒,QPS限制反而不好把握。

我用APISIX做过一个策略:每个业务方API Key对应一个限流规则,默认单个Key最多同时3个视频对话请求,超出直接返回429。同时每个后端服务设一个最大并发数,超过后多余请求进入队列或返回“稍后重试”。这套限流规则上线后,服务再没出现过集体雪崩。

5. 常见问题与排查实录:那些我踩过的坑

5.1 显存OOM排查:启动时报错和运行时报错是两回事

显存相关的坑我踩过无数回,大致可以分成两类。

第一种是启动阶段就OOM。最常见的诱因是--max-model-len设置过大,导致KV Cache预分配超出显存。排查方法是看启动日志,如果是指KV Cache size的报错,先把--max-model-len调小一半试试。另一个诱因是--gpu-memory-utilization设得过高,和模型权重本身抢显存。正常情况保持在0.85到0.92之间比较安全。

第二种是运行过程中OOM。这类问题更隐蔽,表现为服务跑一段时间后突然无响应或Pod被杀。常见原因包括并发请求数超过模型显存上限,vLLM的--max-num-seqs参数控制的是同时处理的最大序列数,如果设得太大,每个序列的KV Cache累积起来就会爆显存。另一个原因是显存碎片化,长时间运行不重启,虽然空闲总量够,但连续分配不出大块显存。

查看报错我用三个命令:kubectl describe pod看事件、kubectl logs看推理日志、nvidia-smi看显存实时状态。一般三步就能定位。

5.2 一次滚动更新引发的服务不可用

这里分享一个真实事故。有一次我从7B模型切换到13B模型,直接kubectl set image更新Deployment。结果新Pod加载模型需要8分钟,旧Pod在滚动更新开始后就被K8s标记为Terminating,仅过了默认的30秒宽限期,旧Pod就没了。那段时间所有请求全部失败,业务方炸了锅。

事后复盘,问题出在三处:第一没设maxUnavailable: 0,旧Pod被提前销毁;第二terminationGracePeriodSeconds太短,旧Pod还没处理完流量就被强杀;第三没有为模型目录做灰度切换,新Pod起来后要重新读模型文件。

现在我的标准流程是:先在PVC里把新模型文件放好,手动调整Deployment的args指向新模型路径,用maxSurge: 1, maxUnavailable: 0策略滚动更新,等全部副本Ready后再观察10分钟,确认没问题再收缩旧副本。这个小流程帮我避免了很多次线上事故。

5.3 幻觉、上下文长度与温度参数对线上服务的影响

模型部署除了技术池,还要处理模型本身的“能力边界”。上线前就要跟业务方对齐三个参数:temperature、max_tokens、上下文长度。

temperature控制随机性,设置在0到2之间。客服、问答、代码生成这类对准确性要求高的场景,我建议temperature设为0.1到0.3,避免模型自由发挥。创意写作、头脑风暴场景,可以设到0.8以上。很多问题反馈“模型胡说八道”,往往就是temperature没调。

max_tokens是单次生成的最大token数。它决定返回长度上限,但要注意输出超长会直接截断,用户看到的回答可能是半截话。业务方如果经常要长文输出,要在prompt里要求完整回答,并在服务端检测是否触发了截断标志。

上下文长度是部署时定的max-model-len。它决定模型能“记住”多少会话内容。设得太短,长对话被截断,记忆丢失;设得太长,显存不够。我做过一个长文本总结服务,上线初期设了8192,结果用户输入几千字后模型只回复“内容太长无法处理”,后来调成32768才正常。

5.4 模型安全与合规检查别省略

从公开渠道拿到的开源模型权重,不代表可以直接放心上生产。我建议部署前至少做三件事:

第一,对模型做一轮基础安全测试。包括对抗性prompt、越狱尝试、敏感话题探测。这不是为了刁难模型,而是提前知道它有哪些偏向和漏洞,方便在网关层做补充防护。

第二,网关层增加输入输出过滤。对大模型的输入做长度限制、敏感词拦截;对输出做敏感内容检测。不要指望模型自律,工程上兜底才可靠。

第三,私有化部署要考虑权重的来源安全。“投毒测试”在业界并不是新鲜事,一个被恶意微调过的模型可能在某些特定触发词下输出异常内容。从非官方渠道下载的模型,建议先校验哈希、对比官方发布信息,再在内网隔离环境测试一轮。

5.5 监控与成本控制

最后说监控。一个合格的大模型推理服务,至少要有以下指标:GPU利用率、显存占用、请求延迟P50/P95/P99、每秒请求数、排队请求数、缓存命中率、Token吞吐量。vLLM自带Prometheus指标导出,配合Grafana面板基本够用。

成本控制方面,我的经验是GPU节点池要区分“热池”和“冷池”。热池常驻核心模型的服务副本,保证低延迟;冷池按需扩容,业务低峰时缩容到0。如果云厂商支持抢占式实例,可以用它跑非核心的批量推理任务,成本能降不少,但不要让它承担线上核心API。

6. 一点体会

把大模型部署到云原生环境,本质上不是为了追新,而是让GPU资源跟着业务节奏走。我最大的感受是:不要把问题复杂化。先用Ollama跑通模型,再用vLLM稳定服务,最后上K8s做编排和管理,每一步都是在前一步的基础上升级。如果一开始就直接上全家桶,配置项多到会让你失去耐心。

最后分享一个小技巧:给每个推理服务保留一个“逃生通道”。也就是在K8s集群之外,留一台能直连模型的备机,里面用最轻量的脚本方式把核心模型服务跑起来。正常情况它不对外服务,一旦K8s集群出现大规模故障,可以手动切换流量到这台备机顶上。这个设计在关键业务场景下救过我一次,成本不高,但很值得。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 22:51:50

数据架构性能监控与优化实战:从监控体系到根因定位

凌晨两点十七分,告警群里的消息像一颗炸弹扔进了正在值班的我的手机里。核心数仓的离线任务比预期延迟了四十分钟,这意味着早上八点前,业务方的日活报表大概率出不来。打开监控大屏,CPU水位、磁盘IO、任务队列长度全部异常&#x…

作者头像 李华
网站建设 2026/9/9 22:48:45

湖南单招职业技能测试题型

湖南高职单招采用 “文化素质 职业技能” 的考试模式,综合成绩总分 600 分,文化素质测试与职业技能测试各占 300 分。A 类应届普高生不需要参加院校组织的文化笔试,文化成绩直接使用学考语数外折算,职业适应性测试(属…

作者头像 李华
网站建设 2026/9/9 22:48:14

深入解析SmmBackdoor:UEFI系统管理模式中的后门攻防实录

简介:面向UEFI固件安全研究者、系统底层开发者和安全爱好者,围绕SmmBackdoor这一利用系统管理模式(SMM)植入后门的高级恶意技术,提供从原理理解到代码复现的关键材料,帮助解决对SMM后门实现与防御认知不足的…

作者头像 李华
网站建设 2026/9/9 22:47:12

MySQL内置函数实战指南:从字符串处理到数据分析的SQL效率提升

写这篇MySQL内置函数的分享,起因是上周帮一个学弟排查一个数据统计的问题:他写了一大段业务代码,从数据库里取出关联数据再在Java里循环做字符串拼接和日期格式化,代码又长又慢,优化之后换成数据库函数一条SQL就搞定了…

作者头像 李华
网站建设 2026/9/9 22:45:45

从零用Python和Pygame写俄罗斯方块:核心逻辑与实战

简介:这是一份基于Python语言实现的俄罗斯方块小游戏源码包,主要面向Python初学者、游戏开发爱好者以及需要课程设计的同学。压缩包内共包含4个文件,以1个核心Python脚本为主,另附2个wav格式游戏音效和1个mp3背景音乐,…

作者头像 李华