1.凤凰架构:构建可靠的大型分布式系统 --- 服务架构演进史

可靠的系统:
	冯若依曼,自复制自动机理论:
		这个理论一机器应该如何从基本的部件中构造出于自身相同的另一台机器引出,其目的不是想单纯的模拟或者理解生物体的自我复制,也不是想简单的制造自我复制的
	计算机,而是想回答一个理论问题:如何用一些"不可靠"部件构造出一个可靠的系统。


架构的演进:
	从大型机(Mainframe)、原始分布式(Distributed)、大型单体(Monolithic)、面向服务(Service-Oriented)、微服务(Microservice)、服务网格(Service Mesh)、
到无服务(Serverless)等,技术架构确实呈现"从大到小"的发展趋势。近年来,自微服务兴起之后,涌现出各类文章去总结,赞美微服务带来的种种好处,诸如 简化部署,逻辑拆分
更清晰,便于技术异构,易于伸缩扩展以提高更高的性能等,这些当然是优点和动力。可是如果不拘于特定系统或特定问题,以更宏观的角度看,前面所说的好处只能算"锦上添花",是
属于让系统"活的更好"的动因,肯定比不上系统如何"确保生存"的需求更关键,更贴近本质。在笔者看来,架构演变最重要的驱动力,或者说这种"从大到小"的变化趋势的最根本驱动力,
始终都是为了方便某个服务能够顺利的"死去"与"重生"。个体服务的生死迭代,是关系到整个系统能否可靠存续的关键因素。

不可变的基础设施:
	在云原生基金会(CNCF)所定义的"云原生"概念中,"不可变基础设施"被提升到与微服务平级的重要程度,此时它以不再局限于 方便运维、程序升级和部署手段,而是升华为向
应用代码隐藏分布式架构复杂度、让分布式架构得以成为一种可普遍推广的普适架构风格的必要前提。在云原生时代、后微服务时代,软件与硬件的界限已经彻底模糊。


第1章 服务架构演进史
1.1 原始分布式时代
	远程的服务在哪里(服务发现),有多少个(负载均衡)网络出现分区,超时或者服务出错了怎么办(熔断,隔离,降级),方法参数与返回结果如何表示(序列化协议),消息如何
传输(传输协议),服务权限如何管理(认证,授权),如何保证通信安全(网络安全层),如何令调用不同的机器的服务返回相同的结果(分布式数据一致性)等一系列问题。

1.2 单体系统时代
	单体系统的不足,必须在软件的性能需求超过了单机,软件的开发人员规模明显超过了"2 Pizza Team"范畴的前提下才有讨论价值。

	在拆分方面,单体系统的真正缺陷不在于如何拆分,而在拆分之后的自治与隔离能力上。由于所有的代码都运行在同一个进程内,所有模块、方法调用都无需考虑网络分区、对象复制
这些麻烦的事和性能损失,但在获得进程内调用的简单,高效等好处的同时,也意味着如果任何一部分代码出现缺陷,过度消耗了进程空间内的资源,所造成的影响也是全局性的,难以隔离
的。
	
	同样,由于所有代码都共享同一个进程,不能隔离,也就无法做到单独停止,更新,升级某一部分代码,所以从可维护性来说,单体系统也是不占优势的。对单体系统来说,在对程序
升级、修改时往往需要制定专门的停机更新计划,做灰度发布、A/B测试也相对复杂。
	
	由于隔离能力的缺失,单体除了难以阻断错误传播、不便于动态更新程序外,还面临技术异构的困难。

	不过以上列举的问题还不是今天微服务取代单体系统成为潮流趋势的根本原因,笔者认为重要的原因是:单体系统难以兼容 "Phoenix" 的特性。这种架构风格的潜在要求是希望
系统的每一个部件、每一处代码都尽量可靠,尽量不出或者少出缺陷。然后,战术层面再优秀,也很难弥补战略层面的不足。单体系统靠高质量来保证高可靠性的思路,在小规模软件上
运行良好,但当系统规模越大的时候,交付一个可靠的单体系统就变得越来越具有挑战性。随着软件架构的演进,构建可靠系统的观念从 "追求尽量不出错" 到正视 "出错是必然"的
转变,才是微服务架构得以挑战并逐步取代单体架构的底气所在。
	
	为了允许程序出错,获得自治与隔离能力,以及实现技术异构等目标,是继性能与算力,让程序再次选择分布式的理由。然而,开发一个分布式程序也并不意味着一定要依靠今天的
微服务架构才能实现。将一个大的单体系统拆分为若干个更小的、不运行在同一个进程的独立服务,这些服务拆分方法后带来了面向服务架构的一段兴盛期,我们称之为"SOA时代"。

1.3 SOA时代
	为了对大型的单体系统进行拆分,让每一个子系统都能独立的部署、运行、更新,开发者们尝试过很多方案,如下:
		1.烟囱式架构
			指的是一种与其他信息系统完全没有互操作或者协调工作的设计模式。

		2.微内核架构
			微内核架构也称为 插件式架构。将主数据,连同其他可能被子系统用到的公共服务、数据、资源集中在一块,组成一个被所有业务系统共同依赖的核心,具体的业务系统
		以插件的模块的形式存在。这样也可提供可扩展的、灵活的、天然隔离的功能特性,即微内核架构。

			这种模式很适合桌面程序,也经常在web应用程序中使用。如果你准备实现一个能够支持二次开发的软件系统,微内核也会是一个不错的选择。

			不过微内核架构也有局限性,它假设系统中各插件模块之间互不认识,且不可预知系统将安装哪些模块,因此这些插件可以访问内存中一些功能的资源,但不会直接交互。
		可是,无论是企业信息系统还是互联网应用,这一假设在许多场景中并不成立,所以我们必须找到办法,既能拆分出独立的系统,也能让拆分后的子系统之间顺畅的互相通信。

		3.事件驱动架构
			为了让子系统能够互相通信,一种可行的方案是在子系统之间建立一套事件管道,来自系统外部的消息将以事件的形式发送到管道中,各个子系统可以从管道里获取自己
		感兴趣、能够处理的事件消息,也可以以事件新增或者修改其中的附加消息,甚至可以自己发布一些新的事件到管道队列中去。如此,每一条消息的处理者都是独立的、高度
		解耦的,但又能与其他处理者通过事件管道进行交互。

		当架构演化到事件驱动架构时,在1.1节提到的第二条通往更大规模软件的路径,即仍在并行发展的远程服务调用也迎来了 SOAP 协议的诞生,此时面向服务的架构(SOA)已经
	有了登上软件架构舞台所需要的全部前置条件。

		软件架构来到了SOA时代,其中包括许多概念、思想都已经能在今天的微服务中找到对应的身影了,譬如 服务之间的松散耦合、注册、发现、治理、隔离、编排等。这些在微服务
	中耳熟能详的概念,大多数也是在分布式服务刚刚被提出的时就已经可以预见的困难点。SOA针对这些问题,甚至是针对"软件开发"这件事情本身,都进行了更具体、更系统的探索。
		1.更具体
			体现在尽管SOA本身还处于抽象概念,而不是特指某一种具体的技术,但它比单体架构和前面列举的3种架构模式的操作下更强,已经不能简单视为一种架构风格了,而是
		一套软件设计的基础平台。它拥有制定技术标准的组织 Open CSA;有清晰的软件设计的指导原则,譬如服务的封装性、自治、松耦合、可重用、可组合、无状态、等;明确了
		采用SOAP作为远程调用协议,依靠SOAP协议族(WSDL,UDDI和WS-*协议)来完成服务的发布、发现和治理;利用企业服务总线(ESB)的消息管道来实现各个子系统之间的交互,
		令各服务在ESB的调度下无需相互依赖就能互相通信,实现了服务的松耦合,也为以后进一步实施业务流程编排(BPM)提供了基础;使用服务数据对象(SDO)来访问和表示数据,
		使用服务组件架构(SCA)来定义服务封装的形式和服务运行的容器,等等。在这套成体系的可以互相精密协作的技术组件支持下,若仅从技术可行性这一角度评判的话,SOA可以
		算是已经成功解决了分布式环境中出现的主要技术问题。

		2.更系统
			指的是SOA的宏大理想,它的终极目标是希望总结出一套自上而下的软件研发方法论,做到企业只需要跟着SOA的思路,就能够一揽子解决掉软件开发过程中的全部问题,
		譬如如何挖掘需求、如何将需求分解为业务能力、如何编排已有服务、如何开发/测试/部署新的功能,等。这些技术问题确实是难点和重点,但也仅仅是其中的一个方面,SOA
		不仅关注技术,还关注研发过程中涉及的需求、管理、流程和组织。如果真的能达到这个目标,软件开发就有可能从此迈进工业化大生产的阶段。试想如果有一天开发符合客户
		需求的软件像写八股文一样有迹可循、有法可依,那对软件开发者来说也许是无趣的,但整个社会实施信息化的效率肯定会提升。


		SOAP协议逐渐被边缘化的本质原因:
			过于严格的规范定义带来了过度的复杂性,而构建在SOAP基础之上的ESB,BPM,SCA,SDO等诸多上层建筑,进一步加剧了这种复杂性。开发信息系统毕竟不是做八股文,
		过于精密的流程和理论需要懂得复杂概念的专业人员才能驾驭。SOA自诞生的那天,就已经注定是少数系统阳春白雪式的精密奢侈品,它可以实现多个异构大型系统之间的复杂
		集成交互,却很难作为一种具有广泛普适性的软件架构风格来推广。SOA最终没有获得成功的致命伤与当年的 EJB 如出一辙,尽管有Sun和IBM等一众巨头力挺,EJB仍然败于
		Spring,Hibernate为代表的"草根框架"。可见一旦脱离人民群众,终究会淹没在群众的海洋之中。

1.4 微服务时代
	微服务由 Peter Rodgers 提出,当时的说法是"Micro-Web-Service",指的是一种专注于单一职责的、与语言无关的细粒度的web服务。是SOA发展时催生的产物,就如同
EJB推广过程中催生了Spring和Hibernate那样,这一阶段的微服务是作为SOA的一种轻量化的补救方案而被提出的。
	
	微服务是一种软件开发技术,是SOA的一种变体。

	现代微服务的概念:
		微服务是一种通过多个小型服务组合来构建单个应用的架构风格,这些服务围绕业务能力而非特定的技术标准来构建。各个服务可以采用不同的编程语言、不同的数据存储技术,
	运行在不同的进程之中。服务采用轻量级的通信机制和自动化部署机制实现通信和运维。

		9个核心业务和技术特征:	
			1.围绕业务能力构建
				这里再次强调康威定律的重要性,有怎样结构、规模、能力的团队,就会产生对应结构、规模、能力的产品。这个结论不是某个团队、某个公司遇到的巧合,而是必然
			的演化结果。如果本应属于同一个产品内的功能被划分在不同团队中,必然会产生大量的跨团队沟通协作,而跨越团队边界无论在管理、沟通、工作安排上都会有更高昂的
			成本,因此高效的团队自然会针对其进行改进,当团队、产品磨合稳定之后,团队与产品就会拥有一致的结构。

			2.分散治理
				是指服务对应的开发团队有直接对服务运行质量负责的责任,也有不受外界干预的掌控服务各个方面的权力,譬如选择与其他服务异构的技术来实现自己的服务。
			微服务更加强调的是在确实需要技术异构时,应能有选择"不统一"的权利。

			3.通过服务来实现独立自治的组件
				之所以强调通过"服务"而不是"类库"来构建组件,是因为类库在编译期静态链接到程序中,通过本地调用提供功能,而服务是进程外组件,通过远程调用来提供功能。
			尽管远程服务有更高昂的调用成本,但这是为组件带来自治与隔离能力的必要代价。

			4.产品化思维
				避免把软件研发视作要去完成某种功能,而是视作一种持续改进、提升的过程。譬如,不应该把运维只看做运维团队的事,把开发只看做是开发团队的事,团队应该
			为软件产品的整个生命周期负责。开发者不仅应该知道软件如何开发,还应该知道它如何运作,用户如何反馈,乃至售后支持工作怎么进行的。注意,这里的用户不一定
			是终端用户,也可能是消费这个服务的另外一个服务。在微服务下,要求开发团队中的每个人都具有产品化的思维,关心整个产品的全部方面是具有可行性的。

			5.数据去中心化
				微服务明确提倡数据应该按领域分散管理、更新、维护、存储。在单体服务中,一个系统的各个功能模块通常会使用同一个数据库。诚然,中心化的存储天生就更容易
			避免一致性问题,但是,同一个数据实体在不同服务的视角里,它抽象的形态往往是不同的。譬如,Bookstore应用中的书本,在销售领域中关注的是价格,在仓储领域中
			关注的是库存数量,在商店展示领域中关注的是书的介绍,如果使用中心化存储,所有领域都必须修改和映射到同一个实体之中,这很可能使不同服务互相影响而丧失
			独立性。尽管在分布式中处理好一致性问题也相当困难,很多时候都没办法使用传统的事务处理来保证,但是两害取其轻,即使有一些必要的代价,但仍是值得使用的。

			6.强终端弱管道
				弱管道几乎是直接反对SOAP和ESB的通信机制。ESB可以处理消息的编码加工、业务规则转换等;BPM可以集中编排企业业务服务;SOAP有几十个WS-*协议在处理
			事务、一致性、认证授权等一系列工作,这些构件在通信管道上的功能也许对某个系统中的某一部分服务是有必要的,但对于另外更多的服务则是强加进来的负担。如果
			服务需要上面的额外通信能力,就应该在服务自己的Endpoint上解决,而不是在通信管道上一揽子处理。微服务提倡使用类似于unix过滤器那样简单直接的通信方式,
			所以restful风格的通信在微服务中会是更合适的选择。

			7.容错性设计
				不再虚幻的追求服务永远稳定,而是接受服务总会出错的现实,要求在微服务设计中,能够有自动的机制对其依赖的服务进行快速故障检测,在持续出错的时候进行
			隔离,在服务恢复的时候重新联通。所以"断路器"这类设施,在实际生产环境中的微服务来说并不是可选的外围组件,而是一个必须的支撑点,如果没有容错性设计,系统
			很容易被一两个服务崩溃所带来的雪崩效应淹没。可靠系统完全可能会由出错的服务组成,这是微服务最大的价值所在。

			8.演进式设计
				容错性设计承认服务会出错,演进式设计则承认服务会被报废淘汰。一个设计良好的服务,应该是能够报废的,而不是期望得到长存永生。假设系统中出现不可更改、
			无可替代的服务,这并不能说明这个服务多么优秀、多么重要,反而是一种系统设计上的脆弱的表现,微服务追求的自治、隔离,也是反对这种脆弱性的表现。

			9.基础设施自动化
				基础设施自动化,如CI/CD的长足发展,显著减少了构建、发布、运维工作的复杂性。由于微服务架构下运维对象数量是单体架构运维对象数量的数量级倍,使用
			微服务的团队更加依赖于基础设施的自动化,人工是很难支撑成百上千乃至上万级别的服务的。

		微服务不是什么:
			微服务不是SOA的变体或者衍生品,应该明确的与SOA划清界限。

			从上述微服务的定义和特征中,应该可以很明显的感觉到微服务追求的是更加自由的架构风格,摒弃了几乎所有SOA里可以抛弃的约束和规定,提出以"实践标准"代替
		"规则标准"。可是,如果没有统一的规范和约束,以前SOA解决的那些分布式服务的问题,不也就一下子都重新出现了吗?的确如此,对于服务的注册发现、跟踪治理、
		负载均衡、故障隔离、认证授权、伸缩扩展、传输通信、事务处理等问题,微服务中将不再有统一的解决方案。即使只讨论Java范围内使用到的微服务,仅一个服务远程调用
		的问题,可以列入解决方案的候选清单的就有RMI、Thrift、Dubbo、gRPC、Motan2、Finagle、bRPC、AVro、JSON-RPC、Rest,等等;仅一个服务发现问题,可以
		选择的就有Eureka、Consul、Nacos、ZooKeeper、etcd、CoreDNS等等。


1.5 后微服务时代
	分布式架构中出现的问题,如注册发现、跟踪治理、负载均衡、传输通信等,只要是分布式系统就无法完全避免,但我们不妨换个角度来思考,这些问题一定要软件系统自己解决吗?

	如果不限于采用软件的方式,这些问题几乎都有对应的硬件解决方案。譬如,某个系统需要伸缩扩容,通常会购买新机器,部署若干副本实例来分担压力;如果某个系统需要解决
负载均衡问题,通常会部署负载均衡器,选择恰当的算法来分流;如果需要解决传输安全问题,通常会部署TLS传输链路,配置好CA证书已保证通信不被窃听篡改;如果需要解决服务发现
问题,通常会设置DNS服务器,让服务访问依赖稳定的记录名而不是易变的IP地址,等等。
	
	随着计算机科学的发展,这些问题大多有了专职化的基础设施去解决,而在微服务时代,人们之所以选择在软件的代码层面而不是硬件的基础设施层面去解决分布式问题,很大程度上
是因为由硬件构成的基础设施跟不上软件构成的应用服务的灵活性的无奈之举。软件可以只用键盘命令就拆分出不同的服务,只通过拷贝、启动就能够实现伸缩服务,硬件难道就不能通过
键盘命令变出相应的应用服务器、负载均衡器、DNS服务器、网络链路这些设施吗?
	
	至此,大家大概听出下面要说的是虚拟化技术和容器技术了。尽管2014年微服务崛起的时候,Docker Swarm和Apache Mesos就已经存在,更早之前也出现过软件定义网络(SDN),
软件定义存储(SDS)等技术。但是,被业务广泛认可、普遍采用的通过虚拟化基础设施去解决分布式架构问题的开端,应该要从2017年Kubernetes取得容器战争的胜利开始算起。
	
	Kubernetes 与传统 Spring Cloud 提供的解决方案对比:
		1.弹性伸缩:Autoscaling,N/A
		2.服务发现:KubeDNS/CoreDNS,Spring Cloud Eureka
		3.配置中心:ConfigMap/Secret,Spring Cloud Config
		4.服务网关:Ingress Controller,Spring Cloud Zuul
		5.负载均衡:Load Balancer,Spring Cloud Ribbon
		6.服务安全:RBAC API,Spring Cloud Security
		7.跟踪监控:Metrics API/Dashboard,Spring Cloud Turbine
		8.降级熔断:N/A,Spring Cloud Hystrix


	当虚拟化的基础设施从单个服务的容器扩展至多个容器构成的服务集群、通信网络和存储设施时,软件与硬件的界限便已模糊。一旦虚拟化的硬件能够跟上软件的灵活性,那些于业务
无关的技术性问题便有可能从软件层面剥离,悄无声息的在硬件基础设施之内解决,让软件得以专注于业务,真正围绕业务能力构建团队与产品。如此,DCE中未能实现的"透明的分布式
应用"成为可能,Martin Flower设想的"凤凰服务器"成为可能,Chad Fowler提出的"不可变基础设施"也成为可能。从软件层面独立应对分布式架构所带来的问题,发展到应用代码与
基础设施软、硬件一体,合力对应架构问题,这个新的时代被称为"云原生",或者"后微服务时代"。
	
	k8s 成为容器战争胜利者标志着后微服务时代的开启,但k8s仍然没能完美的解决全部的分布式问题---"不完美"的意思是,仅从功能上看,单纯的k8s反而不如之前的Spring 
Cloud方案。这是因为有一些问题处于应用程序与基础设施的边缘,是的很难完全在基础设施层面中精细化的处理。举个例子,微服务A调用了微服务B的2个服务,称为B1和B2,假设B1
正常,B2不正常。那么达到一定阈值后就应该对B2进行熔断,避免雪崩。如果仅在基础设施层面来处理,就会遇到一个两难的问题,切到A到B的网络通路会影响B1的正常调用,不切断
则会受到B2的错误影响。
	
	以上问题通过Spring Cloud 这类应用代码实现的微服务中并不难处理,既然是使用程序代码来解决,只要合乎逻辑,想要实现什么功能,只受限于开发人员的想象力与技术能力,
但基础设施是针对整个容器来管理的,粒度相对粗矿,只能到容器层面,对单个远程服务则很难有效管控。类似的,在服务的监控、认证、授权、安全、负载均衡等方面都有可能面临细化
管理的需求,譬如服务调用时的负载均衡,往往需要根据流量特征,调整负载均衡的层次、算法等,而DNS虽然能够实现一定程度的负载均衡,但通常并不能满足这些额外的需求。
	
	为了解决这一问题,虚拟化的基础设施很快完成了第二次进化,引入了今天被称为"服务网格"(Service Mesh)的"边车代理模式"(Sidecar Proxy)。在虚拟化场景中的边车指的
是由系统自动在服务容器(通常指k8s的Pod)中注入一个通信代理服务器,以类似于网络安全里中间人攻击的方式进行流量劫持,在应用毫无感知的情况下,悄然接管了应用所有对外的通信。
这个代理除了实现正常的服务间通信外(称为数据平面通信),还接收来自控制器的指令(称之为控制平面通信),根据控制平面中的配置,对数据平面通信的内容进行分析处理,以实现熔断、
认证、度量、监控、负载均衡等各种附加功能。通过边车模式,便实现了既不需要在应用层面加入额外的处理代码,也提供了几乎不亚于程序代码的精细管理能力。
	
	我们很难从概念上判定清楚一个与应用系统运行在同一资源容器内的代理服务到底算软件还是基础设施,但它对应用是透明的,不需要改动任何代码就可以实现服务治理,这就够了。
相信未来k8s将会成为服务端的标准运行环境,如同linux系统一样;服务网格也将会成为微服务间通信交互的主流模式,把"选择什么通信协议","怎么调度流量","如何认证授权"之类
的技术问题隔离于代码之外,取代今天Spring Cloud全家桶中大部分组件的功能。微服务只考虑业务本身的逻辑,这才是最理想的智能终端解决方案。业务与技术完全隔离,远程与本地
完全透明。


1.6 无服务时代
	相对意义的无限性能以及成为现实。

	在工业界,2012年 Iron.io 公司率先提出 "无服务"(Serverless,应用翻译为"无服务器")。2014年,亚马逊发布了名为Lambda的商业化无服务计算平台。

	无服务到现在还没有一个特别权威的"官方"定义,但它的概念并没有钱买提到的各种架构那么复杂,本来无服务也是以"简单"为主要卖点的,它只涉及两块内容:后端设施(Backend)
和函数(Function)。
	1.后端设施,是指数据库、消息队列、日志、存储等这类用于支撑业务逻辑运行,但本身无业务含义的技术组件,这些后端设施都运行在云中,在无服务中将它们称为"后端即服务"(
	Backend as a Service, BaaS);
	2.函数,是指业务逻辑代码,这里的函数的概念与粒度都已经很接近于程序代码角度的函数了,其区别是无服务中的函数运行在云端,不必考虑算力问题,也不必考虑容量规划(从计费
	角度还是需要考虑的),在无服务中将其称为"函数即服务"(Function as a Service, FaaS)。

	无服务的愿景是让开发者只需要纯粹的关注业务:不需要考虑技术组件,不需要考虑如何部署,不需要考虑算力,可以认为算力是无限的,不需要考虑运维。类比为当年软件开发从
汇编到高级语言的发展过程,开发者不用关注 寄存器、信号、中断等与机器底层相关的细节,从而令生产力得到极大的解放。
	
	无服务的架构确实能降低一些应用开发和运维的成本,譬如不需要交互的离线大规模计算,又譬如多数web资讯类网站、小程序、公共API服务、移动应用服务端等都契合于无服务
所擅长的短连接、无状态、适合事件驱动的交互形式。但另一方面,对于那些信息管理系统、网络游戏等应用,或者说具有业务逻辑复杂、依赖服务状态、响应速度要求高、需要长连接等
特征的应用,至少目前不是很合适。这是因为无服务天生"无限算力"的假设决定了它必须要按量使用(函数运算时间和占用内存)计费以控制消耗的算力规模,因而函数不会一直以活动状态
常驻服务器,请求到了才会开始运行,这就导致了函数不便依赖服务端状态,也导致了函数会有冷启动时间,响应性能可能不太好。目前无服务的冷启动过程大概是数十到百毫秒级别,Java
这类启动性能差的应用,甚至到秒级别。
	
	如果说微服务架构是分布式系统这条路当前所能做到的极致,那么,无服务架构,也许就是"不分布式"的元旦系统这条路的起点。今天已经能初步看见一些使用无服务的云函数去实现
微服务架构的苗头了,将无服务作为技术层面的架构,将微服务视为应用层面的架构。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值