任务调度方法、装置和系统与流程

文档序号:11432133阅读:204来源:国知局
任务调度方法、装置和系统与流程

本公开涉及计算机技术领域,尤其涉及一种任务调度方法、装置和系统。



背景技术:

在web(网页)开发中,我们经常会遇到需要处理长耗时任务的情况,这些任务可能是用户提交的,比如群发邮件的任务;也可能是系统被某个事件触发的。如果是用户提交的任务,用户需要实时等待服务器处理完毕,而在此期间用户不能关闭浏览器窗口,如果任务处理速度非常慢,那用户体验将会受到很大影响。

对此,通常的解决方法是使用队列软件实现异步任务处理机制。例如,服务器接收到用户提交的请求之后,把消息写入队列,并立刻返回处理结果给用户,告知用户任务正在进行中(如邮件正在发送中)。同时,多个队列消费进程会从队列中读取消息,并对消息进行处理。

然而,本发明的发明人发现,上述方案在实际应用中往往会存在队列任务中高优先级任务无法及时处理问题。



技术实现要素:

鉴于现有技术中的上述缺陷或不足,期望提供一种保障高优先级任务能够得到及时处理的方案。

第一方面,本申请实施例提供了一种任务调度方法,所述方法包括:

从预设的数据表中筛选出任务状态为已创建未运行的所有任务,作为待运行的任务;所述数据表中记录了任务状态和任务创建时配置的调度影响参数;

根据所述调度影响参数,计算各待运行的任务的调度优先级;以及

按照所述调度优先级从高到低的顺序,依序执行待运行的任务。

第二方面,本申请实施例还提供了一种任务调度装置,所述装置包括:

任务筛选单元,配置用于从预设的数据表中筛选出任务状态为已创建未运行的所有任务,作为待运行的任务;所述数据表中记录了任务状态和任务创建时配置的调度影响参数;

优先级计算单元,配置用于根据所述调度影响参数,计算各待运行的任务的调度优先级;以及

任务调度运行单元,配置用于按照所述调度优先级从高到低的顺序,依序执行待运行的任务。

第三方面,本申请实施例还提供了一种任务调度系统,所述系统包括:任务创建模块和任务调度模块;其中,

所述任务创建模块配置用于任务创建时配置对应的任务状态和调度影响参数,并存储于预设的数据表中;

所述任务调度模块配置用于创建工作进程,所述工作进程用于从所述数据表中筛选出任务状态为已创建未运行的所有任务,作为待运行的任务;根据所述调度影响参数,计算各待运行的任务的调度优先级;按照所述调度优先级从高到低的顺序,依序执行待运行的任务。

第四方面,本申请实施例还提供了一种计算设备,包括一个或多个处理器以及存储器,所述存储器包含可由所述处理器执行的指令以使得所述处理器执行本申请实施例提供的任务调度方法。

第五方面,本申请实施例还提供了一种存储有计算机程序的计算机可读存储介质,所述计算机程序使计算机执行本申请实施例提供的任务调度方法。

本申请实施例提供的方案,可以基于实际考虑设置不同的调度影响参数;基于任务状态和任务创建时配置的调度影响参数,计算各待运行的任务的调度优先级,从而能够按照优先级高低顺序进行执行,保障高优先级任务能够得到及时处理,提高用户体验。

进一步地,本申请实施例提供的方案,可以基于任务的预期开始时刻、超时时长等内容,对任务的运行时间进行控制,使得等待时间较长的任务能够及时被处理,以及超时任务能够及时被清除,以此避免出现任务积压。

附图说明

通过阅读参照以下附图所作的对非限制性实施例所作的详细描述,本申请的其它特征、目的和优点将会变得更明显:

图1示出了其中可以应用本申请实施例的示例性系统架构;

图2示出了根据本申请实施例的任务调度方法的示例性流程图;

图3示出了根据本申请一个实施例的任务调度装置的示例性结构图;

图4示出了根据本申请一个实施例的任务调度系统的示例性结构图;

图5示出了根据本申请另一实施例的运行在linux系统的示例性结构框图;以及

图6示出了根据本申请一个实施例的计算设备的示例性结构框图。

具体实施方式

下面结合附图和实施例对本申请作进一步的详细说明。可以理解的是,此处所描述的具体实施例仅仅用于解释相关发明,而非对该发明的限定。另外还需要说明的是,为了便于描述,附图中仅示出了与发明相关的部分。

需要说明的是,在不冲突的情况下,本申请中的实施例及实施例中的特征可以相互组合。下面将参考附图并结合实施例来详细说明本申请。

请参考图1,其示出了可以应用本申请实施例的示例性系统架构100。

如图1所示,系统架构100可以包括终端设备101、102、网络103和服务器104、105、106和107。网络103用以在终端设备101、102和服务器104、105、106、107之间提供通信链路的介质。网络103可以包括各种连接类型,例如有线、无线通信链路或者光纤电缆等等。

用户110可以使用终端设备101、102通过网络103与服务器104、105、106、107交互,以访问各种服务,例如浏览网页、下载数据等。终端设备101、102上可以安装有各种客户端应用,例如可以接入统一资源定位符url云服务的应用,包括但不限于浏览器、安全应用等。

终端设备101、102可以是各种电子设备,包括但不限于个人电脑、智能手机、智能电视、平板电脑、个人数字助理、电子书阅读器等等。

服务器104、105、106、107可以是提供各种服务的服务器。服务器可以响应于用户的服务请求而提供服务。可以理解,一个服务器可以提供一种或多种服务,同一种服务也可以由多个服务器来提供。

应该理解,图1中的终端设备、网络和服务器的数目仅仅是示意性的。根据实现需要,可以具有任意数目的终端设备、网络和服务器。

如背景技术中所提到的,现有技术使用队列软件实现异步任务处理机制的方案中,任务没有优先级的概念,同一队列中的多个任务只能按照写入队列的顺序先进先出地依次处理,导致高优先级的任务无法得到及时处理;而且,任务处理过程中,无法控制任务的运行时间上限,如果大量任务被悬挂住而长时间无法结束,则极有可能会造成队列消费进程耗尽,从而造成队列任务积压。

鉴于现有技术的上述缺陷,本申请实施例提供了一种任务调度方法,可预先基于实际需求设置调度影响参数;继而,在任务创建时配置对应的任务状态和调度影响参数;这样,后续可根据调度影响参数,计算出任务的调度优先级,根据调度优先级的高低顺序进行依次执行。这样,可保障高优先级的任务得到及时处理,提高用户体验。

下面将结合流程图来描述本申请实施例的方法。

参考图2,其示出了根据本申请一个实施例的任务调度方法的示例性流程图。图2所示的方法可以在图1中的服务器端或客户端执行。

如图2所示,在步骤210中,从预设的数据表中筛选出任务状态为已创建未运行的所有任务,作为待运行的任务。

其中,数据表中记录了任务状态和任务创建时配置的调度影响参数。

任务状态为如下任意一种:已创建为运行、运行中、运行结束、被结束。当然,实际应用中可以根据需求减少或增设任务状态。

本申请实施例中,调度影响参数可以包括但不限于:任务原始优先级、预期开始时刻。

其中,任务原始优先级的可选值包括:非常低、低、中、高、非常高。

预期开始时刻的配置可便于实现任务运行的时间控制,比如定时运行。

实际应用中,任务创建时在数据表中还可存储:任务id(身份标识)、任务消费进程所在主机名称、任务消费进程的进程id等。

接着,在步骤220中,根据调度影响参数,计算各待运行的任务的调度优先级。

具体地,当调度影响参数包括任务原始优先级时,针对待运行的每个任务,可执行如下操作:

根据该任务的任务类型,确定对应的类型调度权重;以及

根据该任务的任务原始优先级、所述类型调度权重,计算该任务的调度优先级。

当调度影响参数包括预期开始时刻时,针对待运行的每个任务,可执行如下操作:

根据当前时刻和所述调度影响参数中的预期开始时刻,确定该任务当前的任务等待时长;

根据所述任务等待时长,确定对应的时长调度权重;以及

根据该任务的任务等待时长、所述时长调度权重,计算该任务的调度优先级。

而当调度影响参数包括预期开始时刻和任务原始优先级的情况下,可针对待运行的每个任务,执行如下操作:

根据当前时刻和调度影响参数中的预期开始时刻,确定该任务当前的任务等待时长;根据确定出的任务等待时长,确定对应的时长调度权重;根据该任务的任务类型,确定对应的类型调度权重;以及根据该任务的任务原始优先级、任务等待时长、类型调度权重和时长调度权重,计算该任务的调度优先级。

其中,任务当前的任务等待时长可以当前时刻与调度影响参数中的预期开始时刻的差值;或者,将调度影响参数中的预期开始时刻累加上预设的预期等待时长之后,将当前时刻与累加后时刻的差值作为任务当前的任务等待时长。

实际应用中,针对不同任务类型,可预先设置不同的类型调度权重;比如,相较于应用级,系统级的类型调度权重更高。

预先划分不同级别的任务等待范围,不同级别的任务等待范围对应不同的时长调度权重;任务等待范围的端点取值越大,时长调度权重越高。这样,当任务当前的任务等待时长处于某一任务等待范围,则可以将该范围对应的时长调度权重作为该任务等待时长所对应的时长调度权重。

任务的调度优先级可根据该任务的任务原始优先级与对应的类型调度权重的乘积,以及任务等待时长与对应的时长调度权重的乘积来计算,具体计算方法可更加实际需求进行设置。

这样,对于任务原始优先级较高的任务、和/或任务等待时长较长的任务,其所对应的调度优先级也会相应较高,便于后续可保证高优先级的任务和等待时长较长的任务能够及时得到处理,避免出现任务积压,提高用户体验。

之后,在步骤230中,按照调度优先级从高到低的顺序,依序执行待运行的任务。

本申请实施例中,通过步骤220计算出各待运行的任务的调度优先级后,可按照从高到低的顺序,从数据表中依序执行待运行的任务。

相对于现有技术基于任务的创建时间或者加入队伍的先后来决定任务的执行顺序,本申请实施例的方案中,基于任务创建时配置的调度影响参数来决定任务的执行顺序,可保证高优先级的任务能够及时得到处理,提高用户体验。

实际应用中,数据表中还记录了任务创建时配置的指定下游处理模块和任务输入参数。因此,在执行待运行的任务时,可以更新数据表中对应任务状态为运行中;以及根据对应的任务输入参数,调用对应的指定下游处理模块执行该待运行的任务。

相应地,在执行待运行的任务之后,可以将任务执行结束后返回的任务返回值写入数据表中,并更新数据表中任务状态为运行结束。为了避免任务积压,后续可以按照第二设定周期对数据表中任务状态为运行结束的任务进行删除。

进一步地,本发明的发明人考虑,实际运行中,如果存在大量任务被悬挂住而长时间无法结束,则极有可能会造成队列消费进程耗尽,从而造成队列任务积压,因此,本申请实施例的方案中,在任务创建时数据表中还记录了任务创建时配置的超时时长,用于周期性地检测数据表中有没有超时的任务,以便及时清理,避免任务积压。

具体地,可以按照第一设定周期,根据超时时长,从数据表中任务状态为运行中的任务中,检测出超时任务;结束检测出的超时任务,并更新数据表中任务状态为被结束。

例如,当前周期到达后,可以筛选出数据表中任务状态为运行中的任务;继而,针对筛选出的任务,根据当前时刻和开始运行时时刻,计算任务的运行时长;若运行时长大于该任务对应的超时时长,则确定该任务为超时任务。或者,可以将当前时刻与预期运行时刻的差值,与超时时长进行比较,若该差值大于超时时长,则确定该任务为超时任务。

相应地,后续可以按照第三设定周期对数据表中任务状态为被结束的任务进行删除,完成对超时任务的及时清理,避免出现任务积压。

进一步参考图3,其示出了根据本申请一个实施例的任务调度装置300的示例性结构框图。

如图3所示,本申请实施例的任务调度装置可以包括:任务筛选单元301、优先级计算单元302和任务调度运行单元303。

其中,任务筛选单元301配置用于从预设的数据表中筛选出任务状态为已创建未运行的所有任务,作为待运行的任务。

其中,数据表中记录了任务状态和任务创建时配置的调度影响参数。

本申请实施例中,调度影响参数可以包括但不限于:任务原始优先级、预期开始时刻。任务原始优先级的可选值包括:非常低、低、中、高、非常高。预期开始时刻的配置可便于实现任务运行的时间控制,比如定时运行。

实际应用中,任务创建时在数据表中还可存储:任务id、任务消费进程所在主机名称、任务消费进程的进程id等。

优先级计算单元302配置用于根据调度影响参数,计算各待运行的任务的调度优先级。

本申请实施例中,调度影响参数包括任务原始优先级时,优先级计算单元302配置用于针对待运行的每个任务,执行如下操作:根据该任务的任务类型,确定对应的类型调度权重;以及根据该任务的任务原始优先级、类型调度权重,计算该任务的调度优先级。

当调度影响参数包括预期开始时刻时,优先级计算单元302配置用于针对待运行的每个任务,执行如下操作:根据当前时刻和调度影响参数中的预期开始时刻,确定该任务当前的任务等待时长;根据任务等待时长,确定对应的时长调度权重;以及根据该任务的任务等待时长、时长调度权重,计算该任务的调度优先级。

进一步地,当调度影响参数包括预期开始时刻和任务原始优先级时,优先级计算单元302配置用于针对待运行的每个任务,执行如下操作:根据当前时刻和调度影响参数中的预期开始时刻,确定该任务当前的任务等待时长;根据任务等待时长,确定对应的时长调度权重;根据该任务的任务类型,确定对应的类型调度权重;以及根据该任务的任务原始优先级、任务等待时长、类型调度权重和时长调度权重,计算该任务的调度优先级。

其中,任务当前的任务等待时长可以是当前时刻与调度影响参数中的预期开始时刻的差值;或者,将调度影响参数中的预期开始时刻累加上预设的预期等待时长之后,将当前时刻与累加后时刻的差值作为任务当前的任务等待时长。

实际应用中,可预先划分不同级别的任务等待范围,不同级别的任务等待范围对应不同的时长调度权重;任务等待范围的端点取值越大,时长调度权重越高。这样,当任务当前的任务等待时长处于某一任务等待范围,则可以将该范围对应的时长调度权重作为该任务等待时长所对应的时长调度权重。而针对不同任务类型,可预先设置不同的类型调度权重;比如,相较于应用级,系统级的类型调度权重更高。

任务的调度优先级可根据该任务的任务原始优先级与对应的类型调度权重的乘积,以及任务等待时长与对应的时长调度权重的乘积来计算,具体计算方法可更加实际需求进行设置。

任务调度运行单元303配置用于按照调度优先级从高到低的顺序,依序执行待运行的任务。

更优地,数据表中还记录了任务创建时配置的指定下游处理模块和任务输入参数。

任务调度运行单元303还配置用于更新数据表中对应任务状态为运行中;以及根据任务输入参数,调用指定下游处理模块执行待运行的任务。

进一步地,任务调度运行单元303还配置用于将任务执行结束后返回的任务返回值写入数据表中,并更新数据表中任务状态为运行结束。

更优地,数据表中还记录了任务创建时配置的超时时长。

任务调度运行单元303还配置用于按照第一设定周期,根据超时时长,从数据表中任务状态为运行中的任务中,检测出超时任务;结束检测出的超时任务,并更新数据表中任务状态为被结束。

进一步地,任务调度运行单元303还配置用于按照第二设定周期对数据表中任务状态为运行结束的任务进行删除;和/或按照第三设定周期对数据表中任务状态为被结束的任务进行删除。

应当理解,装置300中记载的诸单元与参考图2描述的方法中的各个步骤相对应。由此,上文针对方法描述的操作和特征同样适用于装置300及其中包含的单元,在此不再赘述。

从上面描述可以看出,在本申请的一些实施例中,针对任务执行的问题,提出了根据预先配置的调度影响参数计算任务优先级的方案。这样,基于实际考虑设置不同的调度影响参数,并根据任务状态和任务创建时配置的调度影响参数,计算出各待运行的任务的调度优先级之后,可按照优先级高低顺序进行执行,保障高优先级任务能够得到及时处理,提高用户体验。

进一步地,本申请实施例提供的方案,可以基于任务的预期开始时刻、超时时长等内容,对任务的运行时间进行控制,使得等待时间较长的任务能够及时被处理,以及超时任务能够及时被清除,以此避免出现任务积压。

进一步参考图4,其示出了根据本申请一个实施例的任务调度系统400的示例性结构框图。

如图4所示,本申请实施例的任务调度系统400可以包括:任务创建模块401和任务调度模块402。

其中,任务创建模块401配置用于任务创建时配置对应的任务状态和调度影响参数,并存储于预设的数据表中。

任务调度模块402配置用于创建工作进程,工作进程用于从数据表中筛选出任务状态为已创建未运行的所有任务,作为待运行的任务;根据调度影响参数,计算各待运行的任务的调度优先级;按照调度优先级从高到低的顺序,依序执行待运行的任务。

更优地,任务创建模块401还配置用于在数据表中记录任务创建时配置的超时时长。相应地,任务调度模块402还配置用于创建监视进程,监视进程用于按照第一设定周期,根据超时时长,从数据表中任务状态为运行中的任务中,检测出超时任务;以及工作进程结束检测出的超时任务,并更新数据表中任务状态为被结束。

更优地,任务调度模块还配置用于创建清除进程,清除进程用于按照第二设定周期对数据表中任务状态为运行结束的任务进行删除;和/或按照第三设定周期对数据表中任务状态为被结束的任务进行删除。

更优地,任务调度模块还配置用于监测工作进程、监视进程和清除进程,在出现指定的异常情况时重新创建。

参考图5,其示出了根据本申请一个实施例的运行在linux系统的示例性结构框图。

本申请实施例运行在linux系统,具体实现方案如下:

1、任务存储:

需要在数据库中创建一张数据表,用来保存任务。数据表中的字段主要有:任务id、任务原始优先级、任务输入参数、任务返回值、任务状态、下游处理模块、任务消费进程所在主机名称、任务消费进程的进程id、超时运行时长、预期运行时间、任务开始运行的时间等。

其中,任务状态可选值有4种:1已创建未运行、2运行中、3运行结束、4被结束。

2、任务创建:

a)生产者向数据表中写入一条任务状态字段值为1的记录,即为创建一个任务。

b)在创建任务的时候,需要明确指定下游处理模块及任务输入参数字段。

c)任务原始优先级、超时运行时长,预期开始时刻字段,在未进行特殊配置时,可采取默认值,比如分别为中级,600秒,当前时间戳(表示此任务可以立刻开始执行)。

3、任务调度:

a)daemon(守护)程序多机布署。

b)daemon程序启动之后,如图5所示,会创建三类子进程,分别是:1个monitor(监视)进程,1个purge(清除)进程,还有多个worker(工作)进程。

c)worker进程根据以下条件对数据表中的任务进行筛选:

1)任务状态值为1(已创建未运行)。

2)当前时间戳大于等于预期开始时刻字段的值。

如果筛选出来的任务列表为空,则隔一段时间之后再次尝试获取任务。

如果筛选出来的任务列表非空,记为集合a,则可对集合a按照以下规则进行排序操作:

1)定义调度优先级公式为:p=任务原始优先级*a+任务等待时长*b,其中,系数a为预先设置的类型调度权重,系数b为预先设置的时长调度权重。

2)对于集合a中的全部任务,依次计算其p值。

3)按照p值,对集合a中的任务进行降序排列。

排序之后,worker进程从集合a中取出第一个任务(调度优先级最高的任务),并把自己的进程id与主机名更新到数据表中,同时设置任务状态为2(运行中)。

之后,以数据表的任务输入参数字段做为参数,调用指定下游处理模块字段所代表下游模块的执行接口,来实际执行任务。

最终把接口输出的结果写回到数据表的任务返回值字段,同时更新数据表的任务状态字段值为3(运行结束)。

d)purge进程周期性地删除已经完成的历史任务,避免数据表中历史数据过多。

e)monitor进程周期性地检测数据表中有没有超时的任务。

检测条件为:当前时间戳减去预期运行时刻字段的值之后,是否大于超时时长字段的值。

如果有超时任务,则结束该工作进程的运行,同时把数据表中的任务状态字段设置为4(被结束)。这样就可以防止任务运行时间超长,导致worker进程耗尽,进而造成任务积压。

f)daemon进程周期性地监测worker,purge,monitor进程的数量,如果小于阈值,则重新派生足够数量的子进程。

下面参考图6,其示出了适于用来实现本申请实施例的计算设备600的结构示意图。

如图6所示,计算机设备600包括中央处理单元(cpu)601,其可以根据存储在只读存储器(rom)602中的程序或者从存储部分608加载到随机访问存储器(ram)603中的程序而执行各种适当的动作和处理。在ram603中,还存储有系统600操作所需的各种程序和数据。cpu601、rom602以及ram603通过总线604彼此相连。输入/输出(i/o)接口605也连接至总线604。

以下部件连接至i/o接口605:包括键盘、鼠标等的输入部分606;包括诸如阴极射线管(crt)、液晶显示器(lcd)等以及扬声器等的输出部分607;包括硬盘等的存储部分608;以及包括诸如lan卡、调制解调器等的网络接口卡的通信部分609。通信部分609经由诸如因特网的网络执行通信处理。驱动器610也根据需要连接至i/o接口605。可拆卸介质611,诸如磁盘、光盘、磁光盘、半导体存储器等等,根据需要安装在驱动器610上,以便于从其上读出的计算机程序根据需要被安装入存储部分608。

特别地,根据本公开的实施例,上文参考图2描述的过程可以被实现为计算机软件程序。例如,本公开的实施例包括一种计算机程序产品,其包括有形地包含在机器可读介质上的计算机程序,计算机程序包含用于执行图2的方法的程序代码。在这样的实施例中,该计算机程序可以通过通信部分609从网络上被下载和安装,和/或从可拆卸介质611被安装。

附图中的流程图和框图,图示了按照本发明各种实施例的系统、方法和计算机程序产品的可能实现的体系架构、功能和操作。在这点上,流程图或框图中的每个方框可以代表一个模块或单元、程序段、或代码的一部分,模块或单元、程序段、或代码的一部分包含一个或多个用于实现规定的逻辑功能的可执行指令。也应当注意,在有些作为替换的实现中,方框中所标注的功能也可以以不同于附图中所标注的顺序发生。例如,两个接连地表示的方框实际上可以基本并行地执行,它们有时也可以按相反的顺序执行,这依所涉及的功能而定。也要注意的是,框图和/或流程图中的每个方框、以及框图和/或流程图中的方框的组合,可以用执行规定的功能或操作的专用的基于硬件的系统来实现,或者可以用专用硬件与计算机指令的组合来实现。

描述于本申请实施例中所涉及到的单元或模块可以通过软件的方式实现,也可以通过硬件的方式来实现。所描述的单元或模块也可以设置在处理器中。这些单元或模块的名称在某种情况下并不构成对该单元或模块本身的限定。

附图中的流程图和框图,图示了按照本发明各种实施例的系统、方法和计算机程序产品的可能实现的体系架构、功能和操作。在这点上,流程图或框图中的每个方框可以代表一个模块、程序段、或代码的一部分,模块、程序段、或代码的一部分包含一个或多个用于实现规定的逻辑功能的可执行指令。也应当注意,在有些作为替换的实现中,方框中所标注的功能也可以以不同于附图中所标注的顺序发生。例如,两个接连地表示的方框实际上可以基本并行地执行,它们有时也可以按相反的顺序执行,这依所涉及的功能而定。也要注意的是,框图和/或流程图中的每个方框、以及框图和/或流程图中的方框的组合,可以用执行规定的功能或操作的专用的基于硬件的系统来实现,或者可以用专用硬件与计算机指令的组合来实现。

描述于本申请实施例中所涉及到的单元或模块可以通过软件的方式实现,也可以通过硬件的方式来实现。所描述的单元或模块也可以设置在处理器中。这些单元或模块的名称在某种情况下并不构成对该单元或模块本身的限定。

作为另一方面,本申请还提供了一种存储有计算机程序的计算机可读存储介质,该计算机可读存储介质可以是上述实施例中所述计算设备中所包含的计算机可读存储介质;也可以是单独存在,未装配入设备中的计算机可读存储介质。计算机可读存储介质存储有一个或者一个以上程序,所述程序被一个或者一个以上的处理器用来执行描述于本申请的公式输入方法。

以上描述仅为本申请的较佳实施例以及对所运用技术原理的说明。本领域技术人员应当理解,本申请中所涉及的发明范围,并不限于上述技术特征的特定组合而成的技术方案,同时也应涵盖在不脱离所述发明构思的情况下,由上述技术特征或其等同特征进行任意组合而形成的其它技术方案。例如上述特征与本申请中公开的(但不限于)具有类似功能的技术特征进行互相替换而形成的技术方案。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1