.Net大户的选择:Windows Container在携程的应用

数人云上海与深圳两地的“容器之mesos/k8s/swarm三国演义”活动第四弹嘉宾分享记录,小数被接连不断的干货搞得头晕目眩,沉浸在技术的海洋中幸福感爆棚!在国内,windows container的应用案例相对较少,携程作为.net应用的大户,率先进行了调研和实际应用,并将成果与大家分享。

.Net大户的选择:Windows Container在携程的应用罗勇,携程云平台开发经理

负责携程云平台的建设和维护,精通OpenStack、Docker以及Linux/Windows Container等技术领域。

今天的主题是Windows容器。今年下半年,携程开始了对Windows container的调研工作,目前已经取得了一些成果和实际应用案例,现与大家分享,主要内容包括:

携程为何选择使用Windows container?国内对Windows container的了解相对较少,特别是在具体实践方面,本次分享将重点关注Windows container的细节。传统.Net应用的容器化实践、容器的存储、网络和编排。

携程为什么要使用Windows container?

现状:

携程是.Net应用的大户,由技术栈决定,早期的携程应用架构全部基于该平台,线上运行了3000多个核心应用,覆盖了20多个业务部门,这让我们不得不关注这个庞大的系统。平台希望转向Java来分享其红利,但.Net的线上应用无法全部重写;目前90%左右的.Net应用运行在虚拟机上,从虚拟机本身来看,资源使用率并不理想。持续发布和应用上线,从获取机器环境到准备环境再到上线生产,虚拟机模式下的周期较长,扩容速度慢。新一代发布平台的需求是缩短环境准备时间,实现秒级部署,Linux平台的应用很容易实现,但Windows .Net应用在这方面支持较为困难。此外,为了确保生产和测试环境的高度一致性,希望应用发布是单一应用、单一镜像的,最好是一个容器包含尽可能少的系统进程,这样可以将资源隔离的粒度控制在较小范围内,尽量榨取宿主机的资源,同时希望Linux容器和Windows容器的方案尽可能接近,比如网络、存储,不需要两套不同的方案或有大的变化。

一些Windows container的技术细节

最初,携程使用物理机部署应用,为了避免冲突,用户在一个物理机上只部署一个应用。后来认为这种做法太浪费,就部署了多个应用,但这给管理带来了麻烦,应用之间可能产生冲突或相互影响。随后有了虚拟机,虚拟机上可以部署更多应用,且隔离性较好,但虚拟机资源隔离的粒度太粗,于是容器应运而生,能够将一个应用打包,这个包包含了环境配置等,运行起来只是一个进程,又具备一定的隔离性,同时将资源使用的粒度控制得足够细。

.Net大户的选择:Windows Container在携程的应用Windows container目前支持的系统是Windows Server 2016,该版本于去年10月份正式发布(携程是国内较早一批获得其RTM版本的用户),支持两种Server,一种是Server Core,另一种是Nano Server。Nano Server是微软比较推荐的服务器系统,启动速度非常快,可以大幅缩短计划内维护的宕机时间,通常几秒钟就能启动,不包括硬件检测的时间,几十秒就能启动。目前携程还没有在生产环境中使用Nano Server,目前仅测试了使用Server Core作为容器宿主机系统的情况。需要特别提一下的是,如果宿主机打了补丁或进行了升级,容器也需要进行相应的补丁或升级。当然,不一定立即进行补丁升级,但必须精确找到对应的版本进行升级。

.Net大户的选择:Windows Container在携程的应用Windows container有两种容器类型,这两种容器都运行在Windows Server 2016上,但还有一种容器方案是在Linux平台上运行.Net Core,这种方案我们也研究过,大家很容易想到它的局限性,只能运行使用.Net技术开发的Windows应用,一些非.Net的应用不支持,因此这个方案被否决了。直接在Windows Server上运行容器的方案更为可靠,该方案有两种类型,Windows Server Container和Hyper-V Container。

.Net大户的选择:Windows Container在携程的应用有人会问,Hyper-V不就是一个虚拟机技术吗?是的,实际上它有点像虚拟机,但Hyper-V的技术略有不同,速度明显比虚拟机快很多,只是在申请资源或获取资源时,比Windows Server Container稍慢一点,Windows Server Container可能需要3秒,而Hyper-V Container可能需要4到5秒。但资源隔离度较好,类似于虚拟机,微软公有云Azure的容器服务也采用这种容器类型,他们的考虑是公有云上部署的应用不是受信任的,可能会发生“打架”的情况,因此希望隔离得更好一些。

.Net大户的选择:Windows Container在携程的应用另一个区别是,Windows Server Container的内核是共享的,可以在宿主机上看到每个容器内的进程,这与Linux容器相似,可以直接终止进程。Hyper-V Container宿主机看不见容器内的进程,像一个虚拟机一样。此外,内存资源隔离不同,Windows Server Container的内存可以共享,Hyper-V Container不能共享,Hyper-V Container一旦分配就不能重新修改。对系统应用是信任的,这种比较适合做私有云的一些产品,因为在应用上运行什么东西,这个应用能做什么坏事或相互之间有没有影响,都可以控制,但公有云不能这样做,应用使用率很高,会影响到其他容器。启动速度上也会有差别,一个启动快,一个启动稍慢,当然并不是特别慢。

.Net大户的选择:Windows Container在携程的应用容器镜像,与Linux容器的镜像类似,可以分层。最下面一层是基础镜像,但基础镜像与Linux有区别。Linux镜像可以自己制作,弄一个系统把它做成镜像,但微软无法自己制作一个Windows container基础镜像。或者说,现在只有Windows Server 2016的镜像,想运行一个2012的系统是不行的。当前系统内核只能支持Win10,可以继续安装想要的东西,比如接着安装Framework,然后在最上面安装应用。

.Net大户的选择:Windows Container在携程的应用镜像构建也是一样,Windows container与Docker集成较好,可以使用Docker工具的一些命令进行构建,使用Dockerfile来构建一个镜像。registry是镜像可以直接push到一个平台或私有的registry上面,通过Docker pull方式拉下来,Docker run运行起来。

.Net大户的选择:Windows Container在携程的应用Windows container的镜像,可以在Docker网站上找到关于Windows container的一些基础镜像,拉下来大约有8G左右,在外网上下载可能需要两天。大家可以尝试一下。也可以建立私有的registry,携程采用了VMware开源的Harbor方案,本身没有做太多的修改,直接可以使用。和携程的AD整合后基本上能用了,registry可以将Linux和Windows的镜像都放在一起,两边都能用,都能管理,这部分省掉了很多的内容,不需要做额外的开发,这样Windows和Linux的平台的镜像管理方案是一致的。

传统.Net应用迁移

迁移背景:

之前提到携程有3000多个.Net应用,这些应用每天要不停地发布、测试、编译打包,是一项很大的繁琐工程,有个叫“build”的项目负责这个事情。最初这些运行在虚拟机里,资源使用率很低,白天很忙,晚上使用率很低,有一定的资源浪费,且构建环境也经常不一致。为了积累容器应用使用的经验,我们考虑先把build项目容器化,这意味着.Net应用自己的编译在容器内进行,看能产生什么样的火花。

原来写几千个应用的编译脚本,如果改了一些东西,变更维护的代价是非常大的,尽量这个方案不要使用原来以往用的工具和使用方式,不去动它,最好能够拿过来不怎么修改,就能运行起来。另外,重点看一下像VS2010和VS201这样的工具能不能在容器里运行,实践证明是可以的。然后看MSBuild在容器内是否兼容,支持不同的.Net Framework版本,这些都是比较通用的软件,结果是这些功能都能够支持,另外也包括Python、MVC、GIT等。

迁移收益

首先是环境,编译的环境高度一致,每个环境没有太多的区别,容器拉起来直接运行,提高了编译成功率。其次资源利用率提高了,我们把虚拟机资源砍掉了一半,只需要两台宿主机就能搞定整个携程3000多个.Net应用的编译。编译时长也缩短了,原来用一次构建平均要几分钟,现在90秒左右就能构建完成。.Net大户的选择:Windows Container在携程的应用待解决的问题:

图形不支持,这是某些企业想使用Windows container的一个大问题,它本身不支持图形。后台程序没有太大问题,不过有一些依赖图像工具比较难支持。旧应用兼容不是很好。比如遇到MGwin编译出来的包,一旦代码中有调用标准输出的语句程序直接就挂了,遇到这类问题,需要把源码拉下来重新编译,比较有难度。不支持RDP,远程桌面是不能用的,那怎么做到远程访问呢?还好Windows现在支持SSHD安装了,只需要在容器内安装一个SSHD,然后远程SSH去,当然可以使用PowerShell远程的登录方式,两种方案都可以用,SSH方案更统一一些,如果用户当前正在Linux平台上工作,突然想登一个Windows的容器怎么办?当然也可以使用Linux平台的PowerShell工具实现远程登录容器。不支持D盘。携程迁移过来很多老的应用是要安装在D盘的,容器拉起来没有D盘,只有一个C盘。本身Docker有一个volume功能,可以挂一个数据盘,问题是这样会在宿主机上留下一些东西,和宿主机产生耦合,如果容器删除或迁移,宿主机上就留下了脏数据。后来我们为D盘做一个link,相当于D盘可以快捷的方式连到C盘,映射到C盘的某个目录,这样数据都是落地到在容器的磁盘上,如果想在别的地方拉起来这个容器,可以直接push register,就可以在别的地方部署且环境一样。存储&网络&编排

接下来分享Windows container容器的存储、网络、编排方面的技术。

Windows container资源的隔离方式和配置管理API是借用Docker规范,设计理念和Linux Container类似,也支持CPU share的方式去控制资源的分配。内存可以通过quota的方式去分配内存,Disk也能够充分应用到IO的带宽,这一块还没有做非常多严格的测试。关于网络的支持,携程做了很多测试,整体来讲比较不错,问题较少。性能也满足需求,多个容器在一个同一个宿主机上也能尽量用到整个宿主机的带宽。

容器的存储

.Net大户的选择:Windows Container在携程的应用存储有三种:一种是镜像,镜像本身是一个存储,设计之初定义就不是一个永久的存储,当前容器存储拉掉那个存储就没有了,也不是设计安全的。另外一种存储是volume(卷),可以挂一个数据盘到某一个容器上,在容器里扩展存储空间。同时多个容器也可以挂载宿主机上的一个同一个volume(卷目录),这样大家可以实现NFS一样的效果。最后一类存储是网络存储,比如可以用SMB的方式挂网络盘在容器里面使用,里面如果有万兆的带宽支持还可以玩一下,如果没有万兆带宽的话就不要玩了,它只能放一些冷数据。

容器的网络

.Net大户的选择:Windows Container在携程的应用相对来讲复杂一些,Windows支持四种网络模型,第一种NAT模式大家比较熟悉,起一个本地或者是数据本地的IP地址,如果你想外网访问的话,把Docker映射出来,这种方式比较适合做一个JOB类型的应用在上面,不需要外边可以访问它,但容器里面可以去下载东西。之前讲的build项目就是用这个网络模型,非常简单,不需要考虑太多网络的模型就可以直接用。

第二种是transparent网络模型,这种模型是现在主要用于生产的模型,首先它是通过mac地址伪装实现数据透传,对网络的性能本身折损也比较少,它也支持把多个工作网卡绑到一个交换机上,然后把这个交换机给容器用。网络模型在容器宿主机以外的机器上看到Windows容器和一台物理机没有什么区别。

还有一种是L2 bridge这种采用OpenStack网络的Flat模式,所用的网络跟宿主机的网络是一样的,和宿主机在同一个网段,这样有很大的局限性,网络和宿主机混在一起没有办法做到多租户隔离,然后网段用光了就完了,适用于比较小的集群。

最后一种是Tunnel mode,没有太多研究这一种,但微软Azure用的这一种网络模型。本身携程为了和虚拟机的很多的品牌网络模型一致,所以这一种没有那么快的推进。

Hyper-V的网络模型

.Net大户的选择:Windows Container在携程的应用Hyper-V宿主机是2012上面Hyper-V的网络模型,之前要求一台宿主机尽量要4块网卡,为什么要用4块网卡?两块给虚拟机用,另外两块做一些管理,比如对存储用,虚拟机迁移等,可以做宿主机的管理。另一种方式,2016建议的一种网络方式,这里面有一个叫做embed team,内嵌交换机,它的好处是把下面无论是两块还是N块网卡都可以绑在一个bound,然后把这个bound放在一个交换机里面,每个容器port全部放在交换机里面,然后容器给port打相应的vlan tag,这样容器的网就通了。

.Net大户的选择:Windows Container在携程的应用embed team的好处是不需要要求宿主机一定要有这么多的网卡才可以用,另一个好处是对这些不同的vlan之间做一些流量的控制,携程的container的网络模型也是基于嵌入式交换机上实现的。把宿主机至少两块网卡做了bound,放在一个embed team里面去,另外加一个port给宿主机做管理网卡。容器宿主机相比虚拟机宿主机简单,没有存储和迁移的需求,就不要以额外的划分网络了,如果需要为容器的存储单独挂一个网络的话可以加一个Port做这个事情。不同的网段的这种容器在上面可以再创建不同的Docker,加不同的port,然后容器在里面可以互通,这样的好处就是既实现了多租户、实现了网络隔离,同时和虚拟机包括Linux上面的网络模型是一致的。

容器编排

.Net大户的选择:Windows Container在携程的应用编排这块通常一个容器部署到多个宿主机上,同时一套应用下来有数据层、业务层、也有web层,这些应用要分开放,它们中间放在哪里需要有一个地方,把整个管起来,也希望这个东西能自动化,本身做编排这些,无论是Swarm、K8S、Mesos都是需要解决的问题。一种方案是用Docker Compose这种方式,适合于单宿主机管理。想编排一下容器,看如何运行,这种方式用Docker Compose就能解决。当然,微软现在对Docker Swarm支持好一些,实现成本比较低,基本上能管,但是性能方面没有做太多的测试,目前一些基本的调度、主机分类等都能用。

为什么携程选择使用Mesos?

.Net大户的选择:Windows Container在携程的应用因为携程的Linux平台用的也是这套方案做的编排相关的管理,希望有一套方案能够尽量两种容器一致,于是我们的方案采用Mesos加上Marathon对它进行管理,本身它也有一些现成的工具,比如UI等现成的工具都可以用,这部分还在进行测试和研究中。官方下来的包不能直接跑到Windows Server上面,要拿下来重新编译才能用。最终携程是想做到这么简单的一个容器的管理的架构,就是说希望Mesos在里面能够同时管Linux容器和Windows容器,对它进行统一的调度,最大限度的优化这种调度策略,提升使用率,这是最终整体的设计理念。

待解决问题

有一些急迫解决的问题,与大家交流一下。首先Windows container的镜像比较大,在生产环境,如果批量pull base image,网络的带宽会很快被打满,会对业务带宽造成影响。我们需要有一套方案来解决这个问题,如何能够比较“经济”的方式把Based image或者变更的Layer文件下发下去,是后续要解决的问题。

Windows container的监控日志,没有现成的方案,我也有与微软团队交流过,这部分文档非常少,携程之后也会重点解决监控问题。

推行单容器、单应用的发布方式,希望后面能够把各种FAT/UAT/Prod环境之间打通,都可以通过Windows容器方式,秒级发布。

携程有3000多个应用,一旦容器跑起来了,宿主机的规模还是比较可观的,这种情况下,大规模容器如何管理好?这也是后面需要解决的问题。

这是我今天给大家分享的主要内容,谢谢大家!

以上就是.Net大户的选择:Windows Container在携程的应用的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/440833.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月7日 18:32:40
下一篇 2025年11月7日 18:35:50

相关推荐

  • CSS mask属性无法获取图片:为什么我的图片不见了?

    CSS mask属性无法获取图片 在使用CSS mask属性时,可能会遇到无法获取指定照片的情况。这个问题通常表现为: 网络面板中没有请求图片:尽管CSS代码中指定了图片地址,但网络面板中却找不到图片的请求记录。 问题原因: 此问题的可能原因是浏览器的兼容性问题。某些较旧版本的浏览器可能不支持CSS…

    2025年12月24日
    900
  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 为什么设置 `overflow: hidden` 会导致 `inline-block` 元素错位?

    overflow 导致 inline-block 元素错位解析 当多个 inline-block 元素并列排列时,可能会出现错位显示的问题。这通常是由于其中一个元素设置了 overflow 属性引起的。 问题现象 在不设置 overflow 属性时,元素按预期显示在同一水平线上: 不设置 overf…

    2025年12月24日 好文分享
    400
  • 网页使用本地字体:为什么 CSS 代码中明明指定了“荆南麦圆体”,页面却仍然显示“微软雅黑”?

    网页中使用本地字体 本文将解答如何将本地安装字体应用到网页中,避免使用 src 属性直接引入字体文件。 问题: 想要在网页上使用已安装的“荆南麦圆体”字体,但 css 代码中将其置于第一位的“font-family”属性,页面仍显示“微软雅黑”字体。 立即学习“前端免费学习笔记(深入)”; 答案: …

    2025年12月24日
    000
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何解决本地图片在使用 mask JS 库时出现的跨域错误?

    如何跨越localhost使用本地图片? 问题: 在本地使用mask js库时,引入本地图片会报跨域错误。 解决方案: 要解决此问题,需要使用本地服务器启动文件,以http或https协议访问图片,而不是使用file://协议。例如: python -m http.server 8000 然后,可以…

    2025年12月24日
    200
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • 为什么我的特定 DIV 在 Edge 浏览器中无法显示?

    特定 DIV 无法显示:用户代理样式表的困扰 当你在 Edge 浏览器中打开项目中的某个 div 时,却发现它无法正常显示,仔细检查样式后,发现是由用户代理样式表中的 display none 引起的。但你疑问的是,为什么会出现这样的样式表,而且只针对特定的 div? 背后的原因 用户代理样式表是由…

    2025年12月24日
    200
  • CSS元素设置em和transition后,为何载入页面无放大效果?

    css元素设置em和transition后,为何载入无放大效果 很多开发者在设置了em和transition后,却发现元素载入页面时无放大效果。本文将解答这一问题。 原问题:在视频演示中,将元素设置如下,载入页面会有放大效果。然而,在个人尝试中,并未出现该效果。这是由于macos和windows系统…

    2025年12月24日
    200
  • inline-block元素错位了,是为什么?

    inline-block元素错位背后的原因 inline-block元素是一种特殊类型的块级元素,它可以与其他元素行内排列。但是,在某些情况下,inline-block元素可能会出现错位显示的问题。 错位的原因 当inline-block元素设置了overflow:hidden属性时,它会影响元素的…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 为什么使用 inline-block 元素时会错位?

    inline-block 元素错位成因剖析 在使用 inline-block 元素时,可能会遇到它们错位显示的问题。如代码 demo 所示,当设置了 overflow 属性时,a 标签就会错位下沉,而未设置时却不会。 问题根源: overflow:hidden 属性影响了 inline-block …

    2025年12月24日
    000
  • 如何利用 CSS 选中激活标签并影响相邻元素的样式?

    如何利用 css 选中激活标签并影响相邻元素? 为了实现激活标签影响相邻元素的样式需求,可以通过 :has 选择器来实现。以下是如何具体操作: 对于激活标签相邻后的元素,可以在 css 中使用以下代码进行设置: li:has(+li.active) { border-radius: 0 0 10px…

    2025年12月24日
    100
  • 为什么我的 CSS 元素放大效果无法正常生效?

    css 设置元素放大效果的疑问解答 原提问者在尝试给元素添加 10em 字体大小和过渡效果后,未能在进入页面时看到放大效果。探究发现,原提问者将 CSS 代码直接写在页面中,导致放大效果无法触发。 解决办法如下: 将 CSS 样式写在一个单独的文件中,并使用 标签引入该样式文件。这个操作与原提问者观…

    2025年12月24日
    000
  • 如何模拟Windows 10 设置界面中的鼠标悬浮放大效果?

    win10设置界面的鼠标移动显示周边的样式(探照灯效果)的实现方式 在windows设置界面的鼠标悬浮效果中,光标周围会显示一个放大区域。在前端开发中,可以通过多种方式实现类似的效果。 使用css 使用css的transform和box-shadow属性。通过将transform: scale(1.…

    2025年12月24日
    200

发表回复

登录后才能评论
关注微信