一站式动态多环境建设案例

简介: 作为创业团队来讲,能够快速具备一站式解决服务治理问题,是一件非常酷的事。这整个方案的讨论实施过程中,研发团队对于 K8s、Nginx Ingress、MSE 都有较深入的理解。“像我们部门研发团队,没有专门的运维团队,每个开发人员都可以深入了解每个产品的来龙去脉,想想就很有意义。”

作者:李思源、武良军

问题背景


致景科技成立于 2013 年 12 月,是领先的纺织产业互联网企业,国家高新技术企业。旗下拥有“百布”、“全布”、“天工”、“致景金条”、“致景纺织智造园”、“致景智慧仓物流园”等业务板块,致力于通过大数据、云计算、物联网等新一代信息技术,全面打通纺织服装行业的信息流、物流和资金流,帮助行业实现协同化、柔性化、智能化的升级,构建纺织服装纵向一体化的数智化综合服务平台。


我们作为集团公司已经成立 2 年多的一个业务团队,项目并行开发上线的情况越来越多。值得一提的是,我们目前处于微服务化拆分刚开始的阶段,目前 35 个微服务,拆完之后大概会去到 60 个左右。在这样的背景下,原先大家都使用一套开发/测试/生产环境串行跑研发流程,随着项目数量、开发测试需求的变多,微服务拆分的进行,原先的方式已经不太适合我们。下面简单罗列一下,我们在这过程中所遇到的三个问题。


项目测试环境被抢占


最典型的问题就是一个项目测试环境经常性被缺陷修复的测试流程抢占,导致项目测试时断时续,对测试而言缺乏沉浸式体验,同时测试环节成为项目并行度的主要瓶颈,验证影响项目迭代的进度。


开发联调环境不稳定


为了保证开发的体验,开发环境是允许开发同学自由发布。由于使用一套环境,不同的同学进行开发环境发布,经常性地导致联调中断。不少开发同学转而寻求端到端的线下联调,在个人机器上部署上下游应用,这种模式在微服务化推广之后,特别是面对众多的微服务应用基本上寸步难行。如何解决开发阶段代码调试的便携性,成为了我们遇到的第二个问题。


线上灰度环境的缺乏


第三个问题也是最重要的,之前我们缺少专门提供给产品经理进行功能验证的预发环境。新功能完成测试之后直接上线到线上环境,研发团队为了避免避免对客户产生不良影响,经常性地将发布计划安排在晚上。抛开研发团队的发布幸福度不谈,线上环境缺乏灰度发布能力意味着新功能上线以后就会对全量用户放开,一旦发生了产品设计缺陷或者代码漏洞的情况,那么影响面将会是全网的,风险巨大且不可控。


综上所述,我们需要解决线下缺乏隔离的多套环境来支持多项目的开发和测试,同时在线上需要具备灵活的流量路由策略支持灰度发布需求。


方案调研与探索


结合我们公司实际情况,我们的目标是开发团队不依赖运维团队,即 DEV = OPS 。我们可以一键拉起逻辑隔离的开发/项目环境,同时可以支持预发环境隔离,对于生产环境可以通过配置灰度规则流量、自然流量来进行全链路灰度的验证。


根据我们对当前问题的分析,参考目前互联网上的解决方案,都指向了项目环境治理和服务流量治理的方案,我们稍微罗列下常用的几种方案,我们最终选择的是阿里云微服务引擎 MSE 全链路灰度 + 云效应用交付平台 APPSTACK 的集成方案。


自研 Ribbon 实现


1.png


我们使用的是 Spring Cloud 框架,在平时的业务开发过程中,后端服务与服务之间的调用往往通过 Fegin 或者 RestTemplate 两种调用方式。这其中是通过 Ribbon 这个组件帮我们做了负载均衡的功能。灰度的核心就是路由,我们可以通过重写 Ribbon 默认的负载均衡算法,在负载均衡调用之前,增加流量路由的逻辑,那么就意味着我们能够控制服务流量的转发。


这个方案要实施下去,对于大厂来说确实可以从 0 到 1 再到 100 进化出来,对我们来说,如果仅仅是实现一个路由的功能,做一个只支持核心场景的简陋版确实不是非常困难的事情。但如果要达到成熟可应用的阶段,需要投入专门的技术资源对其进行管理与维护,同时由于 Spring Cloud 微服务框架本身的复杂性,随着微服务数量逐步增多,链路越来越长,相关的微服务治理问题的定位与解决,也会耗费不菲的时间成本。


物理隔离(蓝绿发布)


2.png


这种方案需要为要灰度的服务搭建一套网络隔离、资源独立的环境,在其中部署服务的灰度版本。由于与基础环境隔离,基础环境中的其他服务无法访问到需要灰度的服务,所以需要在灰度环境中冗余部署这些服务,以便整个调用链路正常进行流量转发。此外,注册中心等一些其他依赖的中间件组件也需要冗余部署在灰度环境中,保证微服务之间的可⻅性问题,确保获取的节点 IP 地址只属于当前的网络环境。这个方案需要为这些业务场景采用堆机器的方式来维护多套灰度环境,会造成运维、机器成本过大,成本和代价远超收益;当然如果应用数目很小,就两三个应用,这个方式还是很方便的,可以接受的。


MSE 标签路由+APPSTACK 应用编排(我们的选择)


这两款产品的说明文档见链接:
云效应用交付平台 AppStack :
https://help.aliyun.com/document_detail/321856.html
阿里云微服务引擎 MSE 全链路灰度 :
https://help.aliyun.com/document_detail/170454.html


我们假定通过上面的两篇文章,读者已经对这两个产品已经有了简单的了解,一句话介绍就是:APPSTACK 负责应用的环境管理和流水线发布,MSE 负责流量的全链路灰度。


  • MSE 全链路灰度的重要概念
     

对照下面的 MSE 标签路由的图,我们重点介绍下 MSE 标签路由的几个重要概念如应用的打标、流量染色/自动染色、标识链路传递等,同时下图也是我们采用方案的核心原理,使用域名来标识不同的逻辑隔离环境。


3.png

核心示意图


1.  应用(服务)打标


对照核心示意图,我们发现每个应用都有个(base/gray)的 tag,有了这个 tag,我们才可以根据 tag 定义流量规则。


我们创建 MSE 应用的时候是通过特定 annotation 和环境变量给 MSE 应用打标的。


特定 annotation
alicloud.service.tag=dev1
环境变量:
spring.cloud.nacos.discovery.metadata.version


4.png

增加特定的 annotation 跟环境变量


比如通过 annotation 打标之后我们就可以在 MSE 的标签路由中进行流量规则定义,同时我们也可以看到 Nacos 里面的服务有了一个标签相关的元数据(_micro.service.env_);


5.png

MSE 流量规则配置


6.png

Nacos 里面元数据信息


也有额外增加一个容器环境变量的做法:
spring.cloud.nacos.discovery.metadata.version


这种做法会在 Nacos 的服务元数据中增加一个 version 属性,像 MSE 云原生网关就会借助这个 version 属性进行流量管理,而 MSE 全链路灰度是借助 alicloud.service.tag 定义的标签进行流量管理。


7.png

容器中增加 gray 相关的环境变量


8.png

MSE 流量规则配置出现 gray 节点


9.png

Nacos 里面有gray环境的元数据信息


10.png

MSE 云原生网关可以选择 gray 版本


2. 流量染色/自动染色


简单讲,流量染色就是流量带上了特别的标识,对于 HTTP 请求来说,是请求头里带了一些标识信息,对于 Message 来说,是消息头里带了标识信息;我们这里主要讲下 HTTP 流量染色问题;一种是人工的往 HTTP 请求里面增加标识信息,比如前端请求后端 API 的时候,增加一个 xx:111 的标识信息,那我们就说这个流量被染色了。而自动染色,则说的是一个没有标识的 HTTP 请求,经由某个打了标的 nacos 服务之后,往后调用下一个服务的时候,自动会带上这个 nacos 服务的标签信息在请求头里;最简单的举例就是 a 应用调用 b(gray)应用,那b应用调用后面的 c 应用的时候,会自动带上 x-mse-tag:gray 的请求头,这就是自动染色。


这里特别提到 x-mse-tag:xxx 这个标识,他是 MSE 系统保留的标识,不仅仅代表了染色,同时也代表了链路传递(这个请求链路上的各个节点都会依次传递这个标签下去)和默认的路由规则(优先选择 xxx 标识的服务,没有找到的情况下,再选择 base 服务-没有打标的),这个默认路由规则是不需要显式定义的。


我们的解决方案也是特别地利用了这一点,对照核心示意图,我们在域名名字中添加了流量标识,然后在 Ingress-Nginx 中将流量标识解析出来然后通过 x-mse-tag:xxx 的方式一路传递下去,这样就实现了在整个链路上优先选择 xxx 标识的服务,使用没有标识的 base 服务进行兜底。


3. 标识链路传递


流量被染色,也就是请求头中有特定标识之后,这个标识在调用链路中如何可以传递下去,比如一个 HTTP 请求,带了 user-id:100 的头,陆续需要经过 A->B->C。即调用 A 的时候带了 user-id:100,A 调用 B 的时候也希望可以带上 user-id:100 的请求头,同样 B 调用 C 的时候也要带上 user-id:100。这个就是标识的链路传递,有了这个标识链路传递,我们才可以在为 A/B/C 应用定义按 user-id 的值进行路由的策略。MSE 的标识链路传递的方法是定义环境变量 alicloud.service.header=x-user-id,在入口应用 A(所有版本,gray+base)增加该环境变量以后,往后的调用 B 和 C 的过程中,都会自动添加请求头 x-user-id 进行传递,这样就方便我们在 A,B,C 节点按照特有规则进行路由定义。当然 x-mse-tag 这个特殊的请求头默认就是链路传递的,MSE 会把这个标识层层传递下去并进行默认的路由规则(tag 优先,base 兜底);MSE 标识链路传递的原理如下,借助分布式链路追踪的框架的实现方式,每个应用的探针拦截请求并解析标识,然后暂存到线程空间,在往后调用的时候再通过探针把标识塞到下个请求。通过分布式链路追踪的框架完成标识传递。


11.png


  • 阿里云效应用交付 APPSTACK 简述
     

我们把云效 APPSTACK 引入进来,主要目的是方便开发同学通过白屏的管理方式自助完成 MSE 所需要的配置工作,同时在微服务架构下,我们希望应用进行拆分之后,每个应用都有自己的 owner。


12.png


通过 APPSTACK 我们可以屏蔽 K8s 的 deployment,service,ingress 等细节,研发同学面向的就是应用+环境+流水线。这样最终开发人员在 APPSTACK 通过流水线完成应用的环境部署,每个环境都会按照 MSE 标签路由的要求打上不同的标识。


13.png

应用的多套环境部署


14.png

每个环境都会按照 MSE 标签路由的要求打上不同的标识


在这里我们不展开讲述 APPSTACK 的核心功能,我们这里主要的就是借助应用编排,让每个应用的每个环境部署的时候,可以设置好 MSE 标签路由所需要的各种环境变量和 annotation。


我们的解决方案


我们在调研了以上能力之后,根据自己公司的实际场景与业务需求,根据不同环境的特性,定义了多种环境的抽象,基于此构建了一站式动态多环境的能力,并针对主要场景设计了不同的实施方案。


环境定义


通过对阿里云微服务引擎 MSE 标签路由和云效应用编排 APPSTACK 的调研,结合我们前面提到所面临的问题,我们最终定义了我们整个研发体系所需要的环境体系即:多套的开发环境(含基础环境)+多套项目环境(含基础环境)+(集成)测试环境+预发环境+(支持灰度)生产环境,如下图


15.png


多套开发环境:目标是支持多个项目的在开发阶段的开发联调,核心要求是各项目动态隔离并且支持端云互联,项目动态隔离是每个项目都有自己的开发联调环境且只需部署有变动应用,端云互联是开发可以将自己本地跑的应用注册到这个 MSE 这个体系里面来,实现可以本地调试的目的,两个研发可以点对点地进行本地 debug 来跟踪问题。开发基础环境是负责兜底服务调用的,每个应用生产部署之后都需要同步更新开发基础环境,保障基础环境是最新的生产版本。


多套项目环境:目标是支持耗时较长的大型项目,比如重大技改,重大业务项目,需要长时间占用测试环境跟内外部关联方进行稳定测试的。核心要求是各个项目动态隔离。关于项目动态隔离的定义同上。


测试环境:目标是支持短平快的项目测试和集成测试,比如日常的缺陷修复,或者多个小项目需要集成到一起发布,同时也是我们日常自动化测试的环境。项目环境中的特性分支也需要经过测试环境的自动化测试才可以上线。


预发环境:目标是支持产品经理在真实环境中验证产品功能,进行验收,预发环境使用的基础建设如数据库等同生产环境是一致的,当然这里对系统设计也会提出更高的要求,比如需要保持向前兼容,就像数据库,只能增列不能减列,不能在 sql 中使用 select * 等等,这些我们通过 DMS 进行数据库结构变更的约束和通过代码检查保障,此处不赘述。


生产环境:目标是支持规则流量+自然流量的全链路灰度,这里的规则流量指的是带有明显特征的流量,通过 MSE 的流量规则能够清晰定义的请求,比如请求头,参数,cookie,body 中数据符合规则的。自然流量则相反,我们不指定任何特征,比如全部流量的 1%导入到灰度环境,这个我们就理解成自然流量。


综合来看,目前的环境体系里,开发环境和项目环境涉及到动态隔离,所以需要部署基础环境来完成服务兜底的能力,这个基础环境也就是 MSE 标签路由中无标签(base)应用的提供者。


这一套环境体系的流转流程主要有:


1. 拉取特性分支进入开发环境进行本地开发和前后端联调,然后提测到项目环境


2. 项目环境由测试团队完成功能测试之后,将应用部署到(集成)测试环境


3.在(集成)测试环境同其他特性分支一起完成集成,并通过自动化测试和简单验证,就可以部署至预发环境


4. 产品经理在预发环境进行功能验收测试,通过之后可以发布到生产环境进行灰度验证


5. 在生产环境可以按照规则流量+自然流量进行灰度验证,通过之后就可以导入全部流量


6. 最后将特性分支合并至主干后用最新的生产版本更新开发/项目基础环境。


主要场景实施


  • 场景一:项目隔离的动态多环境
     

按照我们的解决方案,项目环境要实现的是逻辑隔离的动态多环境,相当于每个应用我们要通过 APPSTACK 部署基础环境(负责兜底的无标签 base 应用)和动态项目环境(有变更的)同时我们需要保障前端调用后端的域名可以转换成 x-mse-tag 的请求头。


16.png


1. 通过 APPSTACK 部署好有标签的应用(项目环境)和没标签的应用(基础环境),下列截图仅做示范


17.png

18.png


2. 在 ingress-nginx 中解析域名中的 tag 属性转换成 x-mse-tag 请求头链路传递,通过 ingress 配置携带 header 方式到 api 网关。


19.png


通过注解

nginx.ingress.kubernetes.io/configuration-snippet 实现,具体如下:
metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet:
proxy_set_header x-mse-tag dev1


通过这样简单配置之后,前端调用后端服务的时候,只要通过特定的域名请求,那 ingres-nginx 就可以把这个域名对应的请求自动添加一个 x-mse-tag 的请求传递到 api 网关应用,然后借助这个 x-mse-tag 的特殊请求头,在调用下游服务的时候,就会一路优先选择 dev1 标签的服务,没有 dev1 标签的服务就会去找兜底的 base 服务。


  • 场景二:规则流量全链路灰度的生产环境
     

1. 通过 APPSTACK 在生产环境部署好有灰度标识的应用。


2. 定义流量路由规则,在 MSE 控制台为本次灰度链路中的入口应用设置流量路由规则,比如本次发布更新了 A-B-C 三个应用,A 就是入口应用。


20.png

21.png


通过这种方式定义之后,我们可以设置符合某些特征的流量进入到 A 应用的 gray 版本,并且向后层层传递过去,不用每个应用重复设置路由规则。这就会满足了规则流量的全链路灰度的要求。


  • 场景三:自然流量全链路灰度的生产环境
     

1. 通过APPSTACK在生产环境部署好有灰度标识的应用,略图。这里至少需要为本次项目的入口应用 A(也可以是全部应用)增加一个自动染色的变量 profiler.micro.service.tag.trace.enable=true,这个变量会把经过这个入口应用 A 的流量自动染色,往后传递的时候自动增加 x-mse-tag 的请求头,从而实现全链路灰度


2. 定义流量规则,即自然流量的多少比例进入 gray 环境


22.png

23.png


这样通过入口应用的自动染色,以及入口应用的自然流量分批,我们就可以让进入到入口应用 gray 节点的自然流量进入到全链路的灰度环境(灰度优先,基础应用兜底)。


目前为止,我们实现了默认按照域名进行项目/开发多环境逻辑动态隔离的效果;同时提供给研发团队便捷的白屏管理的工具,可以由项目组独立拉起整个环境,通过三个场景化的实施方案,完美解决了开篇提到的三个问题。


相关技术原理概要介绍


MSE + APPSTACK 的解决方案,核心的地方在于流量规则的定义以及流量标识的传递,其核心的解决方案在于流量中标识的解析和传递,我们再看一次这个标识传递的图:


24.png


怎么样才能实现这里面最核心的解析 Extract 和注入 Inject 的功能呢?


答案是探针,为每个 MSE 管理的应用运行时候增加一个 java agent 的探针,完成一个类似 JVM AOP 的能力,在 ACK(K8s)的容器中,MSE 通过如下的方式自动为应用安装 java agent;


1. 配置 Webhook,然后根据 Pod 或者 Namespac中的 Labels,来判断是否要挂载 Java Agent。如果需要挂载,则就对 Pod 的声明⽂件做出后续修改


2. 获取并添加环境变量 JAVA_TOOL_OPTIONS,⽤于加载 Java Agent。


3. 给业务容器添加 Volume,⽤于存储 Java Agent 的⽂件内容。


4. 给 Pod 添加 Init container,⽤于在业务容器启动前下载 Java Agent


最终我们每个被 MSE 管理的应用在 POD 层面可以看到如下信息:


25.png

26.png


有了这个探针,我们可以拦截所有 HTTP REQUEST 的处理类,将我们关心的标识信息暂存起来,然后在应用内部消费 Nacos 服务的时候增加 MSE 支持的路由逻辑,选择合适的服务 provider(比如是打了 gray 标的),同时在调用这个 provider 的服务的时候,可以将暂存的流量标识带在请求头里继续传递下去,大体上跟我们最开始提到的自研 Ribbon 的方式相似。不过 MSE 在这块做得比较成熟,同时不单单支持了 HTTP REST 这种服务调用方式,还包括了 Dubbo、RocketMQ 的消息灰度、数据库灰度等。当然全链路灰度仅仅是微服务引擎 MSE 一个很小的功能,微服务引擎 MSE(Microservices Engine)是一个面向业界主流开源微服务生态的一站式微服务平台,提供注册配置中心(原生支持 Nacos/ZooKeeper/Eureka)、云原生网关(原生支持 Ingress/Envoy)、微服务治理(原生 支持Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)的能力,有兴趣的同学可以看看官方文档。


借事修人


作为创业团队来讲,能够快速具备一站式解决服务治理问题,是一件非常酷的事。这整个方案的讨论实施过程中,研发团队对于 K8s、Nginx Ingress、MSE 都有较深入的理解。“像我们部门研发团队,没有专门的运维团队,每个开发人员都可以深入了解每个产品的来龙去脉,想想就很有意义。”

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
机器人
小红书自动发布笔记,真好用!
小红书自动发布笔记,真好用!
2229 0
|
25天前
|
人工智能 API 数据库
OpenClaw 告别失忆与费 Token 吞金教程:阿里云/本地部署+配置免费API+lossless-claw插件优化管理上下文指南
2026年,OpenClaw(曾用名Clawdbot)凭借“本地优先+长时记忆”的特性成为开源圈热门工具,但用户普遍面临两大痛点:一是“失忆”——长对话中关键信息被随机丢弃,任务执行到一半偏离目标;二是“吞金”——默认滑动窗口压缩机制导致上下文冗余,Token消耗剧增,长期使用成本高昂。这两个问题形成恶性循环:脏上下文让模型表现拉胯,用户被迫降低模型规格,而低规格模型在冗余信息中更难发挥作用,最终让OpenClaw陷入“不好用”的口碑困境。
1429 2
|
2月前
|
人工智能 安全 搜索推荐
2026年年阿里云部署OpenClaw Skills实战:搞定Clawra AI女友+小红书AI运营自动生成发布图文流程
2026年,OpenClaw(前身为Clawdbot、Moltbot)凭借“能动手干活”的核心优势持续爆火,GitHub星标早已突破10万+,成为AI工具领域的现象级项目。它不再是单纯的对话AI,而是能直接操控应用、自动化执行任务的智能代理——既能接入小红书实现全流程社媒运营,又能通过Clawra技能变身“有生活感”的AI女友,真正实现“一个工具,多重身份”。
1246 3
|
SQL 关系型数据库 MySQL
你学会如何将项目部署到Linux系统上了吗?
Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布,它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。
你学会如何将项目部署到Linux系统上了吗?
|
2月前
|
人工智能 弹性计算 搜索推荐
2026年OpenClaw(Clawdbot)+必装Skills阿里云部署保姆级教程
2026年,OpenClaw(原Clawdbot,曾用名Moltbot)凭借轻量化架构、高适配性及强大的自动化能力,成为阿里云生态下最热门的AI自动化代理工具,其秒级部署方案彻底打破开源工具的技术门槛,无需复杂环境配置,零基础新手也能轻松上手。OpenClaw本身仅提供核心编排框架,不具备独立的实操能力,而Skills作为其“能力扩展插件”,如同为AI助手安装不同的“专业大脑”,能赋予它网页浏览、邮件管理、数据统计、多平台联动等各类实用功能,二者结合可快速搭建专属智能助手,适配个人办公、企业运维、AI创意生产等多场景,堪称“AI效率神器”[3]。
1713 5
|
3月前
|
存储 人工智能 搜索推荐
不懂向量数据库?别怕!一文讲清8大主流工具,手把手教你做选择
向量数据库是AI应用的“超级记忆中枢”,能将文本、图像等转化为数学指纹并快速检索相似内容。本文通俗解析8大主流向量数据库,涵盖托管型、开源型与嵌入式三类,助你根据场景选型,轻松构建智能搜索、推荐系统与RAG应用。
2198 6
|
7月前
|
Web App开发 数据挖掘 网络安全
Playwright MCP 实现小红书全自动发布的全流程指南
本文为小红书运营者带来一份实用指南:通过Playwright MCP技术,只需一次手动登录即可实现图文自动发布。教程从环境配置到完整脚本编写,手把手教你搭建稳定高效的无人值守发布系统,彻底解决登录验证难题。
|
编译器 Go
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。
|
SQL PHP 数据库
21 PHP如何进行事务处理的?
路老师在知乎上分享PHP语言知识,帮助大家入门并深入了解PHP。本文介绍了PDO中的事务处理,通过实例讲解了如何使用beginTransaction()、commit()和rollback()方法实现事务操作。