微信扫一扫
分享到朋友圈

工程师参与开源的好处与挑战以及管理开源项目的那些事儿

作者:InfoQ 来源:InfoQ 公众号
分享到:

04-06

作者 | 谭望达
编辑 | 田晓旭

2018 年末,GitHub 发布了年终总结报告,报告中指出:2018 年,Github 注册的新用户数量是前六年的总和,且目前 Github 上的代码仓库已有 1 亿个。这样的结果,相信 Linus Torvalds 在 1991 年写下第一份 Linux 开源邮件的时候怎么也不会想到,现在我们可以毫不夸张的说,“开源软件正在吞噬世界”。

1998 年,Bruce Perens 和 Eric S. Raymand 联手创建了开放源代码促进会,“开源软件”正式有了自己的定义。现在,开源软件已经二十多岁了,其内涵和外延也在不断深化和拓展之中,“开源”二字代表的不仅仅是一个项目,更是代表了整个社区,代表了隐藏在背后的开发者和工程师们。

站在开源背后的工程师们之间是如何进行协作与交流?基于开源软件的商业公司如何更好的发展?开源团队如何更好的管理和研发一个项目?......  Cloudera 计算平台研发负责人谭望达详细的为我们进行了一一解答。

写在前面


It’s actually open source software that’s eating the world——John Vrionis, Venturebeat, 博客


随着这几十年开源的热潮,开源软件逐渐的占领了整个软件的生态。1991 年 Linus Torvalds 在发出第一封宣布 Linux 开源的邮件时候可能没有想到会对软件市场造成如此大的影响。随着 1999 年 Apache 软件基金会的成立,这几年开源软件更是继续飞速发展:

从大数据领域来说,有 Hortonworks(2014 年)和 Cloudera(2017 年)的 IPO(基于 Apache Hadoop 以及各种 Apache 基金会的产品),2017 年的 Mongo IPO(基于 MongoDB),2018 年的 Elastic IPO(基于 Elastic Search, Logstash, Kibana),到近几年取得大量融资的 Databricks (基于 Apache Spark),Confluent(基于 Apache Kafka)。

从云原生领域来说,CNCF 基金会在 2015 年的建立让整个生态也飞速的发展,其中孵化了 Kubernetes、Prometheus 等等项目,后面有 Google、Redhat 等巨头参与。

别的领域的开源软件发展也不甘落后,比如说机器学习领域影响重要的软件几乎以开源为主:Tensorflow (来自 Google),Pytorch(来自 Facebook),Apache MXNet。

从国内来说,各个公司也在拥抱开源、或者以开源作为产品的基本形式,比如说 PingCAP (基于 TiDB),Kyligence (基于 Apache Kylin),还有最近炒得火热的阿里巴巴收购 Data Artisans(Apache Flink 背后的公司)。

从开源领域来说,现在是粮草兼备,也有东风的状态:好的开源项目很容易在相关的领域得到更多的反馈,也会逐渐变得更加的好用和稳定;开源项目成长到一定级别后,能够吸引独立的公司在后面支持,能够得到稳定的资金和人力的投入;参与开源软件的核心工程师们也容易得到更多的名誉、影响力。长期的反馈会让开源软件发展得越来越好,对于公司来说也会越来越重要,参与开源的工程师越来越多。

因为开源软件对于各个领域来说的影响越来越大,公司或多或少都会参与开源。所以怎么能够更好的管理基于开源技术的团队会是一个非常值得思考的话题。这方面讨论的文章相对较少,所以也希望能够分享一下我这几年在管理基于开源技术的团队中的经验。

开源团队管理

在展开之前,什么叫做是开源团队呢?从我看来,开源团队主要的特征是,团队的产出主要是基于一个或者几个开源软件,并且团队有能力投入部分的时间到开源社区之中,参与开源软件的开发与计划的制定等等。

相对来说,如果一个团队坚持“拿来主义”,直接用开源软件而很少帮助反馈开源社区。或者是在公司内部的分支上进行修改而不将改进回馈到开源社区中。那么这样的团队则不是我这里想要讨论的“开源团队”。这样做有若干的缺点,我在下面会展开讨论。

下面的文章中,(2.1 从工程师的角度出发), 首先作为团队最重要的一部分,我会谈谈开源对于团队内的工程师来说,到底有哪些好处和挑战。(2.2 从公司的角度出发)其次从资源的提供方 - 公司来说,开源到底有哪些好处和挑战,怎样选择开源与否,怎样选择不同的开源方式。(3 谈谈细节), 我会谈谈从细节出发,开源的一些具体的问题如何解决,比如说怎样制定基于开源的开发计划和发布计划等等。

从工程师的角度出发
工程师参与开源的目的和方式

首先我们来了解一下,工程师参与开源有哪些目的呢?在我看来,主要是有下面的一些目的:

  • 更好的技能,对于工程师而言,一个重要的目的是如何让自己的技能树跟随者时代的发展。由于良好的开源生态系统,现在的公司越来越少会捆绑在闭源的商业软件中,这导致优秀的开源项目一般来说生命力很长。工程师如果熟悉精通开源项目的话,一般会很容易在市场中找到一个有竞争力的位置。

  • 更好的认可度、知名度,在熟悉使用开源技术的目的之外,一部分活跃的工程师会花上不少的时间来去参与开源项目的技术讨论,反馈开源软件的缺陷,以及将改进贡献回开源项目中去。在这个过程中,这些工程师可以得到更多人的认可,并且也会让自己在市场中的竞争力得到提高。比如说一个职位需要精通 Apache Hadoop 的工程师,工程师甲只是熟悉在生产坏境的使用,乙在甲基础之上贡献了若干不错的改进并且合并回了主干,如果两者的背景类似,公司容易青睐乙。

  • 在圈子内建立更多的人脉,由于开源社区的开放性,很多开源社区的参与者也是抱着一个很开放的心态来与人沟通。多参与开源社区可以让工程师与来自不同的公司、文化背景、语言与国际的人进行沟通。在过程中可以更多的积累人脉与了解到别人的思维方式。不容易固化在自己的小圈子里面。

那么工程师参与开源主要有哪些方式呢?(从易到难排序)

  • 熟悉使用开源项目,这个比较显而易见,在工作中如果对某些开源项目用得比较多,那么自然会更好的熟悉开源项目。

  • 参与贡献开源项目,参与贡献也有很多的方式。主要有代码贡献和非代码贡献。非代码贡献主要是有,反馈缺陷;帮助社区其他用户回答相关的问题;(在技术会议、博客等等)分享自己使用某些开源项目的经验和教训;帮助开源社区推广项目 (布道师,Evangelist)

  • 参与主导开源项目的方向,当对于开源项目的贡献累积到一定程度的时候,工程师就可以更多的参与开源的开发方向,把开源项目计划往自己更希望的方向推进。

对工程师的挑战

第一个挑战:如何把个人的目标和团队的目标结合在一起。

参与开源当然可以是兴趣驱动,不过对于个人与团队来说更高效的方式是,能够让个人的目标和团队的目标结合在一起。不然对于团队而言,工程师花费的努力并不能让团队得到提升;对于工程师而言,也未必能帮助当前的工作(不过可能可以帮助下一份工作)。纯粹从个人兴趣出发的开源活动在短期内可以帮助自己思考未来的方向,但是如果长期来说,可能会难以让个人集中精力,也难以争取公司从资源、时间上的支持。

第二个挑战:广度 vs. 深度

参与开源、并且代码被接纳并且合并到某个开源项目主干会给工程师带来成就感,但是我也见过一些工程师,每天乐此不疲的在不同的开源社区中找寻各种琐碎的问题,比如说有问题的单元测试代码,一些代码的拼写或者格式上的建议,不够精准的日志信息等等。结果就是过了一年可能可以有几百个 PR (pull request) 被合并到主干中,Github 主页上的格子每个都是绿色的。

不过从个人目标和开源项目的发展来说,这个是最好的方式吗?毋庸置疑的是,对于开源项目而言,这些改进都是正面的,相对也很容易被合并进去,因为这样的改进一般很安全,不会带来什么错误。但是从另一方面来说,努力去做 5 个重要的、会改进生产环境中的性能的改进比做 100 个代码拼写错误的改进得到的提高更大,对开源社区来说也更重要。(因为代码拼写错误对于项目的用户和可维护性来说的影响一般不算很大)。

团队管理者应该做些什么

首先团队管理者应该鼓励工程师多参与开源: 参与开源可以很好的让工程师得到锻炼。从沟通能力,设计能力,代码质量方面都能够得到很多的提升。现在很多公司特别是互联网公司的工作方式比较糙快猛,要求出活快,一个人写代码就行了,代码审核只是走一下流程,代码过几年就得重写一遍。而开源项目的需求和实现往往是经过很多的讨论得到的,虽然初始的时候进展和企业内部的软件相比很难相比,但是长期来说,往往可以一步一步的超过企业内部实现的质量。从这个方面而言,多参与开源的工程师沟通能力、设计能力往往会更强一些。

其次团队管理者应该尽量的把工程师的个人方向和团队的方向给结合在一起: 以大数据领域为例子,一个公司如果对 Apache Hadoop、Apache Spark 等等项目用得比较多,那么很容易发现一些不满足需求的地方。如果能够把这些需求提回社区能够帮助让社区更好的考虑未来的方向。大部分的开源社区还是非常希望来自其他公司的贡献者能够参与进来,帮助一起把社区建设好。

那么如果有工程师对与工作内容不直接相关的开源项目感兴趣怎么办呢?比如说一个非机器学习团队的工程师对 Tensorflow 感兴趣,从我的经验来说,给这些工程师一部分的时间和自由度让他们去参与是非常有好处的,就算是日常工作内容比较忙,也不要阻止工程师去参与自己感兴趣的项目。原因是,第一你不知道什么时候这些知识储备会有作用,我经历过的好一些重要的项目都是从 20% 时间来的。第二如果打击了工程师的积极性,对长期的个人发展和团队管理都不利,也不容易建立起一个有黑客精神的团队。我通常的做法是,除非是产品发布等等非常忙的时间,我会鼓励工程师可以用 20% 的工作时间来做感兴趣的项目。坚持几年下来会发现团队积累了很多的知识来去处理更复杂的问题和需求。

从公司的角度出发

说完了个人,这里再说说公司。团队管理人作为连接公司和个人需求的桥梁,也需要认真考虑一下开源对于公司的目的和意义是什么,需要怎样做才能更好的得到公司的支持。

公司参与开源的目的是什么

首先谈一谈公司参与开源项目的目的是什么,这里分为两种开源项目:企业用来卖钱的项目;企业内部使用的项目。

企业用来卖钱的项目:

现在越来越多的企业把核心开源,然后在周边通过部署、监控、分析的软件;或者技术支持服务;或者云上的服务来实现盈利。

对于 Cloudera、 Elastic、 Confluent、Databricks 这类公司而言,理想状态下,开源核心软件的目的可以更好的接触到客户,当客户使用之后发现问题,对于大部分没有非常强大的开发团队的客户而言,他们会有很强的动力来购买云服务、收费软件或者是技术支持。这个当然是从理想状态上来说的,如果说公司提供的收费软件如果并不好用,或者是公司提供的免费开源软件没有流行开来,开源的意义就变得相对不大了。在这个话题上,我后面会稍微展开一下哪些项目适合开源、哪些项目不适合开源的讨论。

企业内部使用的项目:

每个企业或多或少地使用开源项目。那么参与这些开源项目有下面的意义:

提升工程师的水平和积极性:这里在工程师角度的一节中已经提到过,这里就不重复说了。

建立更好的公司工程品牌:对于软件、互联网公司而言,招聘到好的人才是非常难的事情。深度参与开源的团队,或者是主导了某些重要的开源软件可以建立更好的公司的工程品牌。因为参与开源往往意味着公司开放包容的文化和黑客精神,这些也是优秀的工程师所喜欢的。

同步开源社区的进展:做开源这些年接触到了很多公司在线上部署了一个开源版本之后就不再主动的升级,而是根据自己的需求在上面进行数以千计的改动。造成本地和上游的版本区别太大,几年之内因为核心工程师离职、或者是有大的改进已经在现有的版本上无法再改,不得不推翻重来。如果说公司更多的和开源社区同步,可以让长期的维护成本降低。下面的 “如何管理本地和上游版本”的章节会详细的讨论一些常见的策略。

得到开源社区的帮助:参与开源虽然说由于开源社区的代码审核、设计讨论等等问题上会花费比自己开发更多的时间,但是当建立好了与开源社区的关系之后,可以得到很多别人的帮助。最后可以达到自己投入 N 个工程师做某一个项目,然后得到 K(可以小于 N 可以大于 N)来自社区的工程师的帮助,比公司完全自己投入来讲可以节省部分的资源。

哪些东西合适开源、哪些东西不合适开源

了解到了公司参与开源的目的和好处之后,这里再谈谈哪些适合开源、哪些不适合开源。

哪些不适合开源?

  • 非通用性的项目

    首先开源的软件需要有通用性,比如说只能够跑在公司内部比较独特的环境中的软件,或者是很少有别的公司有类似的需求。对于这样的软件来说,开源不容易造成广泛的影响,公司投入开源的时间和资源(比如说为了开源而做的文档,需要做一些代码清理等等)未必能得到足够的回报。

  • 跟竞争对手拉开差距的部分

    其次对于公司用来卖钱的软件来说,对于与竞争产品拉开差距的功能部分(Differentiator),最好谨慎开源。因为开源之后竞争对手也可以免费的拿到这部分功能的实现。在这方面的开源,最好参考一下最近 MongoDB、Confluent(参考 Confluent 官宣)等等公司对软件许可证的修改以防止竞争对手(比如说云厂商)插管吸血。

  • 不必要的重复造轮子

    如果已经有一个好的的开源项目实现,背后有一个健康的开源社区的前提下,谨慎造轮子。比如说公司想要一个需求相对独特的分布式文件系统,在已经有 HDFS、Ceph 等等大的开源项目的前提下,开源的意义就变得很小,因为如果要和成熟的开源社区竞争是一个很难的过程。因为至少你要投入类似或者更多的资源来建设这个开源社区。

哪些适合开源

  • 通用的模块、项目

    跟上面提到的原因类似,如果说一个项目或者模块比较通用,比如说某种通用数据结构的 Go 实现,或者是在公有云上能够方便部署的图数据库。开源这种项目往往可以很快的吸引用户。

  • 竞争性的开源

    如果行业老二想把老大拉下马的话,开源和免费老大赖以生存的技术是常见的策略。比如说 Google 开源 Android 以对抗苹果。新的数据库公司以开源来对抗老的数据库公司等等。

  • 参与一个良好生态的开源社区

    跟重复造轮子相比,参与一个有着良好生态的开源社区可能是对公司长期来说更有好处的事情。

细节讨论
如何更好地帮助团队和开源社区沟通

开源社区的沟通和公司内部的跨团队沟通区别其实区别很大。首先公司内部的沟通常常是自上而下的:公司有一个大的目标,然后分下来到每个团队,大家扯皮划清工作界限、制定计划。然后再由技术负责人、工程师来做执行。沟通的前提往往是公司或者团队的利益所驱动的。而且除了外企有跨国界的合作以外,沟通都是在本地或者国内,鲜有语言的问题。从项目设计、代码设计来说,常常就是走两个极端:部分公司基本上口头能够解释清楚的就未必需要写下来。还有一些公司内部有非常严格的文档、沟通上的规范。

而开源社区的沟通需要更多的自下而上:参与开源社区的工程师当然会带着一些公司的目标去,但是更多的想法应该是由个人驱动。在怎样参与开源社区的过程中也会带着一些个人的印记。

在我看来,开源的沟通有下面的挑战和解决办法:

1) 分布式异步:开源团队往往遍布世界各地,跨洲、跨时区是常见的时区。对于一些社区的合作,可能同时有来自欧洲、亚洲、美洲的参与者。来自中国的工程师可能早上对某个讨论发出了评论,到晚上十一二点才收到来自美国的工程师的回复。如果某个公司重点的项目卡在了沟通上,会很让人着急的。

解决办法:

  • 主动一点:有些人喜欢早上起来第一件事就是回复别人的评论,有些人喜欢下班的时候再把前一天的评论都回复掉。由于开源社区松散,来自别的公司的参与者未必会把你的一些疑问和 PR 放在最高优先级上。在这一点上需要每个参与者更加主动一点去发起讨论,也可以礼貌地催一下社区别的参与者看一下你的回复。

  • 团队线下沟通:开源社区很喜欢知名的、大的公司来使用自己发布的软件并且做出反馈,尤其是比较新的,需要“踩坑” 的新功能、新版本。如果你的团队准备投入一定的资源来上新的版本或者功能,不妨可以问问社区相关领域的负责人可否定期不定期地进行线下沟通,来解决一些疑问,并且讨论一些功能的需求等等。从我的经验上来说,这样的沟通方式其实非常的有效。而且也能够更好的建立线下的人脉。

2) 文档、注释:由于分布式异步的沟通方式,最好能够鼓励团队把文档和注释尽量写得清楚一点。不然在沟通之中会来来回回的确认你想要表达的内容。多搞几次之后双方都容易失去耐心。

如何把对的人放在对的地方去

因为开源的参与会落实到每一个参与者,不是说每个人都适合做每一样事情。我下面会略谈一下怎样把不同的工程师放在开源社区的不同的角色之中以更好的让每个人发挥自己的长处。

我主要把工程师分为了下面四类,并且谈谈每一类的特点、适合做的事情和需要来自团队怎样的帮助。

如何管理本地和上游分支

这个是基于开源的项目开发最常见的问题,开源软件不同于传统软件,开源社区的发展方向未必是团队希望的方向。那么如何管理本地(公司内部的)分支和上游(开源社区拥有的)分支呢?这里说的开源项目是基于社区的开源项目(由多个公司共同主导的项目),如果是开源项目完全被自己的公司所主导的话,工作的方式其实和内部的项目差不多的。

其实简单说来,大概就是两种方式:

1) 第一种方式,开发的代码全部进入上游分支

一般这种方式需要对团队对开源社区有一定的控制权, 因为需要将代码合并进上游分支需要得到相应模块负责人的审核、反馈和提交。如果对社区控制权相对比较弱的话,这种方式会造成时间拖得太长。这样做的好处是,本地的代码和上游的代码是非常类似的。不太会出现同一个功能,社区版本和本地版本不一致的情况。

如果是对于比较大的功能或者是需要若干个 commit 的改进,建议在上游社区建立一个单独的分支,把新的改进都合并到上游的分支中,等到功能开发、测试完成之后,再合并入上游的主干分支和发布分支。

2)第二种方式,开发的代码先进入本地分支

相对于 1),这种方式其实是不得已而为之,不过在很多时候公司需要的功能必须在某个时间之前上线,如果社区讨论的时间太久、或者代码审核的意见太多,或者社区根本就不同意提出的方案,那么这种情况下代码会进入本地分支。

如果这种情况发生了,建议在工作任务相对不那么忙的时候,把对应的功能还是推进到上游分支中,不然时间长了之后,本地的代码实现跟上游的代码完全不一样,这样会导致内部的版本会很难升级到社区新的发布中去。

如何管理本地和上游的版本

说完了本地和上游的分支,这里说说怎么管理 本地的版本和上游的版本。

首先这里举一个最常见的一种管理方式:

上面蓝色的图标是上游(社区)版本的发布,每个版本的发布包括了若干的改进。绿色的图标是内部的版本,初始的时候内部 1.0’版本和社区的 1.0 版是一样的。

由于上游社区的开发进度太快,在 1.1 里面加入了很多激动人心的新功能,但是潜在会带来代码的不稳定性。因为内部的版本需要在公司内部里面做完测试,上线等等流程才能上线,所以内部的版本的迭代会相对保守,所以内部的下一个发布可能不是直接紧跟社区版的 1.1 作为基础,而是从社区 1.1 版本里面选择一些重要并且相对安全的改进放入内部开发分支,作为内部 1.0.1 版本的一部分。

同样等到社区 1.2 版本发布之后,内部可以把对应的一些改进放入内部 1.0.2 版本的发布中去。

那么这样长期做也不是办法,所以需要不定期的把内部的版本和社区的版本做一些同步,等到社区发布了 1.3 版本之后,因为功能被别的社区公司在不同的场景下进行了验证,所以公司内部也可以将内部的版本重置到 1.3 版本中去,并且加以验证、将改进回馈到社区。这样的过程一般来说比较痛苦,但是从长远来看对公司和社区是双赢的一个选择。

如何管理分布式的团队

说一下分布式团队管理的挑战和解决方法。

挑战主要是在时区和有效沟通上面,我们这边的做法(不同的 daily sync up time,每周的 planning),和定期的 project sync up。另外就是对工程师的要求,从招聘的时候就放在重要的位置的。

因为社区的开发者本来就分散在不同的公司、国家之中,在开源社区中发生人才流动的时候,很有可能选择去别的公司做之前的开源项目。不夸张的说,我见过的绝大部分基于开源的团队都是非常分散的,这个给团队的管理带来了很大的挑战。我们团队近 20 个同学分散在

7 个不同的时区(欧洲、印度、中国、澳大利亚、美国西部、中部、东部),我们这个超分散的团队还能够一起很好的工作、推进公司和开源社区项目的发展,我想分享一下自己的一些经验:

1)从招聘开始

第一步也是最重要的一步是选择对开源有浓厚兴趣的人,如果人对自己的工作有兴趣和激情,相应的抱怨也会少很多。从性格上来说,比较开朗(不一定是在口头交流中的)、性格比较开放的工程师比较适合开源跨时区、异步的沟通方式。

2)同步会议

对于像我们这样的分布式团队,没有办法找到一个时间是所有人都醒着的。这样对于团队的沟通和状态同步造成了很多的挑战。

我的解决办法是将项目需要合作的模块分配给时区比较接近的同学以尽量避免太晚或者太早影响生活。取消每天大家都参加的状态同步会议、取而代之的是每周每个模块 1-2 次的开发同步会议。因为一般的工程师都不太会同时工作超过 3 个模块,所以从同步会议造成的时间开销来讲应该还是在可控的范围之内的。

3)开源社区的工作方式

从工作方式来说,我也尽量的鼓励大家跟开源社区的工作方式一致。以代码审核为例,开源社区一般是需要审核者 (Reviewer/Committer) 把意见评论到对应的 JIRA 或者 PR 中,在合并代码前会至少等几个小时到几天看看有没有别人的意见。我们内部的工作方式也是类似的。如果是对组内同事的代码、设计有建议的话,线下的会议或者在线会议是可以的,但是最终的建议需要总结下来并且放到对应的 JIRA 或者 PR 中去,这样可以让团队、社区里面的其他人知道最新的状态。这样做虽然比面对面讨论、当成提交代码略慢,但是从代码质量的角度来说,这样的结果可以更好的保证代码质量,从长期来看是值得的。

当分布式的团队适应了这种开源社区的工作方式之后,我甚至发现很多时候就算完全没有面对面的交流(包括在线会议),大家也能够很好的一起合作。

总   结

本文讲了一下关于基于开源软件的团队的管理的经验。虽然说开源社区的合作方式跟大家熟知的团队内部或者跨团队的方式有诸多不同,不过当摸清楚了开源社区的沟通习惯之后,其实管理一个基于开源技术团队也没有非常多特别的东西。简单来说就是尊重个人,尊重社区还有和把团队的目标和公司的目标匹配在一起就是了。希望本文分享的经验能够对读者有帮助。

作者介绍

谭望达,Cloudera 计算平台研发负责人,高级经理,管理 Kubernetes、Hadoop YARN、深度学习平台相关的全球研发团队。在开源领域,是 Apache Hadoop committer 以及项目管理委员会委员,Hadoop 社区负责人之一。主导了 GPU 调度和隔离、资源抢占、全局调度器等等功能的设计和开发。创立了 Submarine 项目(在 Kubernetes、YARN 上运行深度学习任务),并将 Submarine 推进成为 Hadoop 的顶级项目。在加入 Cloudera 之前,曾在 Pivotal (EMC) Hadoop 团队,负责在 Hadoop 之上的高性能计算(HPC)、机器学习相关的产品研发。在此之前,曾在阿里云算法平台参与分布式机器学习平台的研发。



点个在看少个 bug

阅读38840
工程师 项目 
举报0
关注InfoQ微信号:infoqchina

用微信扫描二维码即可关注
声明

1、头条易读遵循行业规范,任何转载的稿件都会明确标注作者和来源;
2、本文内容来自“InfoQ”微信公众号,文章版权归InfoQ公众号所有。

评论
更多

文章来自于公众号:

InfoQ

微信号:infoqchina

邮箱qunxueyuan#163.com(将#换成@)
微信编辑器
免责声明
www.weixinyidu.com   免责声明
版权声明:本站收录微信公众号和微信文章内容全部来自于网络,仅供个人学习、研究或者欣赏使用。版权归原作者所有。禁止一切商业用途。其中内容并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。如果您发现头条易读网站上有侵犯您的知识产权的内容,请与我们联系,我们会及时修改或删除。
本站声明:本站与腾讯微信、微信公众平台无任何关联,非腾讯微信官方网站。