首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java开发者的PaaS指南

Java开发者的PaaS指南

作者头像
yuanyi928
发布2018-07-26 10:23:22
2.1K0
发布2018-07-26 10:23:22
举报
文章被收录于专栏:EAWorldEAWorld

本文获得codingthearchitecture.com授权翻译发表,转载需要注明来自公众号EAWorld。

作者:Simon Brown

译者:月满西楼

原题:Paas for Java developers

全文7600字,阅读约需要20分钟

简介

我从事软件开发工作已有20多年,在此期间,我参与了各种不同的环境下,各类软件系统的搭建工作,其中大部分系统都以Java和web技术为核心,当然其他技术也有所接触。同时,我也有幸参与了从开始到交付的整个软件开发过程。不过在基础设施这一块,我没有参与太多。另外,我也创建过一些服务器,但大多数生产基础设施的构建都是由基础设施团队完成的。我认为这很常见。提供生产级基础设施是一项专门的任务;需要了解安装、配置和强化操作系统、数据库、负载平衡器、防火墙等方面的知识。坦率来讲,这都不是我特别感兴趣的,尤其身在软件行业,我们都需要不断地去学习新知识、新技能,新技术的更新换代实在太快。

记得三年前,我在匈牙利布达佩斯的Craft Conference上,曾就我的一个名为Structurizr的创新应用程序和与会者进行了多次探讨。这个程序的初期演示是在Rackspace的Ubuntu上运行的,但牵扯到了一系列基础设施和操作上的问题,这些问题的解决不在我的能力范围内。会中我收到的一个建议是, 我可以去关注一下Pivotal Web Services这个 PaaS云服务。我确实也在泽西运营一些当地学校的编程俱乐部时接触过这个服务,但没有考虑过它是否能承载我自己的应用程序。

1、Pivotal Web Services

与Cloud Foundry

Pivotal Web Services是一个基于Cloud Foundry的商业服务,提供“平台即服务”(PaaS)。从本质上讲,Cloud Foundry通过API提供了一个应用程序部署平台,可以将部署在公有云、私有云或是数据中心服务器上的底层基础结构抽象出来。

假设你正要在Apache Tomcat Web服务器上构建一个Java web应用程序。那么,在其能在网络上运行之前,你需要在某处提供服务器,安装Java和Apache Tomcat Web服务器。你还需要强化服务器、配置SSL、定期应用补丁等,如果你还想通过使用两个实例来提高恢复能力,那还需要启动第二个服务器,重复前面的步骤,并配置这两个服务器,来支持例如负载平衡器。

当然,你还可以,也可能会,使用Vagrant, Chef, Puppet, Docker等这些自动化配置和部署工具来自动化大部分的操作步骤。

当Cloud Foundry命令行界面安装完成之后,如果我们想部署一个Java .WAR 或.JAR文件,只需要简单地运行一个“cf push”命令,就可以将它部署到Pivotal Web Services 这个PaaS云服务上。仅此而已! 我还可以使用“cf scale”命令来请求Pivotal Web Services来纵向扩展应用程序,例如添加更多的RAM,或把应用程序横向扩展,例如添加更多实例。

如果需要更新应用程序,则要用到另一个“cf push”命令。但这么做会中止当前实例的运行,并将其替换为新版本,因此会有一些服务停止时间。然而,Cloud Foundry PaaS云平台使得通过命令行接口来进行蓝绿部署变得非常容易。如此一来,Java开发人员就可以不具备底层基础设施专业知识的前提下,也在几分钟内建立一个“零停机时间(zero-downtime)”(即服务不会停止)的连续交付通道。

2、基础设施上层的应用程序

正如Joshua McKenty在最近的一个关于思科云的播客中所讲的,Pivotal Web Services和Cloud Foundry为开发者提供了一个更高的抽象层。软件开发人员的职责是处理应用程序,而不是基础设施或容器。

目前,业内关于Docker容器的讨论很火热。我认为Docker是一项了不起的技术。但是,软件开发人员更多的还是要专注于处理应用程序,而不是去关注容器技术或基础设施。我认为关注Docker技术是对大多数软件开发人员本职工作的干扰,对此,我会在另一篇博客里进行阐述。

3、供应商锁定(Vendor Lock-in)

在上文中,我介绍了平台即服务(PaaS),并讨论了如何使用Pivotal Web Services PaaS云服务和Cloud Foundry PaaS云平台来实现应用程序的快捷部署,且无需担心任何底层基础设施的问题。 一个比较常见的误区是,大家总觉得使用Cloud Foundry PaaS云平台(以及Pivotal Web Services PaaS云服务或其他项目)会导致供应商锁定(Vendor Lock-in),从而不能轻易转换云服务提供商。

回过头来再看Structurizr,它是用于可视化和文件记录软件架构的一组工具,系统图示如下:

总而言之,经过身份验证的用户使用Structurizr Client函数库(Java 和.NET)可创建和上传软件架构模型,并通过web查看这些模型的内容。Structurizr使用SendGrid这个电子邮件服务平台发送电子邮件,所有支付处理都是由Taxamo和 Braintree支付工具服务一起完成的。这里也用到了其他一些云服务(例如CloudFlare、Pingdom和Papertrail),但在图表中没有显示。

从一个(C4模型)容器角度来看,Structurizr如下图所示(图表中忽略了外部服务,因为它们与此次讨论无关):

从本质上讲, Structurizr由一个运行在web浏览器(服务于HTML、CSS和JavaScript)的客户端应用程序组成,而服务器端包含一个Java web应用程序服务https://structurizr.com,和另一个Java应用程序服务https://api.structurizr.com,再加上一些数据存储(MySQL数据库管理系统, Redis缓存和Amazon S3云存储服务)。这两个Java web应用程序都运行在Pivotal Web Services这个PaaS云服务上。

这两个Java web应用程序都基于Spring MVC框架,并按照“twelve-factor methodology”中所说明的一系列原则实现的。实际上,从技术角度来看,这两个程序都只是设计在云平台上运行的典型Java web应用程序。两个程序都是无状态的,不会向本地文件系统写入重要信息。

4、供应商锁定(Vendor Lock-in)

和迁移成本

接下来让我们来谈谈供应商锁定(Vendor Lock-in),正如Sam Newman说的那样,“不要一提到供应商锁定(Vendor Lock-in),就自然想到迁移成本”。 Structurizr的所有开发都是在Mac上使用IntelliJ IDEA完成的,而Vagrant虚拟机运行环境管理工具则被用来运行本地的MySQL数据库系统和Redis缓存拷贝。在代码库中,没有任何东西与Cloud Foundry PaaS云平台有关,我也没有在本地运行Cloud Foundry相关的内容。Java应用程序是部署到本地运行的Apache Tomcat实例的标准Java EE.WAR文件。

推送(Push) Structurizr“Web应用程序”(使用“cf push”命令)会导致Web应用程序被部署到Pivotal Web Services 上,并且可以在https://struct-web.cfapps.io的URL中使用。想要把这个web应用程序迁移到另一个云服务提供商的话,以下是我需要进行的一些操作。

1.首先我需要找到另一个支持Java 8,Apache Tomcat 8.x服务器的PaaS云服务,或者构建自己的服务器。另外,Java虚拟机(JVM)还要求安装"Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files",这是因为web应用程序在存储数据时使用了一些强度更高的加密算法。

2. 考虑到web应用程序多个实例在运行(显然,Pivotal Web Services PaaS云服务在单一的URL后进行处理),我需要对这个设置进行镜像。

3. Structurizr.com域的域名服务器(DNS)正由CloudFlare管理,为映射新的部署位置,一些别名(即CNAME)记录需要更改。

就是这么简单。虽说部署脚本需要更改,但不需要对代码进行任何变动。Pivotal Web Services 这个PaaS云服务确实提供了一些基于Cloud Foundry PaaS云平台的附加功能,比如它们的数据仪表板,这对监控和管理很很方便,但这些并不是应用程序的关键组成部分。总之,我并遇到没有任何供应商锁定的问题(Vendor Lock-in),而且迁移成本很低。毕竟,我的Java web应用程序很普通,并不依赖于Cloud Foundry PaaS云平台。

至此,你可能会想,“等等,那数据存储呢?”,这是另一个话题。接下来,我将分享在Pivotal Web Services PaaS云服务中可用的市场服务(Marketplace Service),以及为什么我不做推荐。

5、应用市场服务

(Marketplace Service)

从这部分开始,我想说,我个人确实喜欢且推荐Pivotal Web Services PaaS云服务和Cloud Foundry PaaS云平台来作为部署Java应用程序的方法, 它们能显著简化部署流程,并带来出色的性能表现。我在Pivotal Web Services PaaS云服务上运行Structurizr已经三年多了,几乎没在核心平台上发现有什么问题。但应用市场服务(Marketplace Service)则另当别论。

除了提供一个用于运行代码的部署平台之外,大多数像Pivotal Web Services、Heroku、AzurePaaS云服务这类的平台还会提供“应用市场服务(Marketplace Service)”集合。本质上,这些是附加服务,可以让用户方便地访问数据库、信息传递提供程序、监视工具等,在我写这篇文章时,Pivotal Web Services PaaS云服务应用市场(Marketplace)包含很多当下比较流行的技术; 比如MySQL、 PostgreSQL、 Redis、 Memcached、MongoDB、RabbitMQ等。

6、MySQL 即服务

假设你正构建一个Java web应用程序,并希望将数据存储在MySQL数据管理系统中。你可以有几种处理方法:一种是在Amazon AWS之类的平台上构建你自己的数据库服务器。当然,这要求你有能力来实现,前文中我曾用很大篇幅来阐述利用PaaS平台构建个性化基础设施的优点,但这种DIY方法不一定适用于每个人。

另一种选择是找到一个“数据库即服务(DaaS)”的提供商,由它来为你创建和运行MySQL服务器。ClearDB就是一个例子,你可以在Pivotal Web Services PaaS云服务应用市场(Marketplace)上找到它。你只需通过应用市场(Marketplace)订阅一个免费的ClearDB,并将其连接到数据库,从而来构建你的解决方案。就是这么简单,MySQL数据库在操作方面大都都需要维护;包括备份和复制。

当Java应用程序连接到ClearDB时,同样也有几种选择。一是常规做法,将数据库端点URL、用户名和密码放在配置中。也以用Cloud Foundry命令行接口来发出一个“cf bind”命令,将ClearDB数据库实例绑定应用程序实例,并使用云平台的自动重新配置功能来进行操作。

如果您构建的是一个基于spring框架的应用程序,且已经配置了MySQL数据源(一些注意事项),那么Cloud Foundry PaaS云平台将自动地重新配置数据源,指向已绑定到应用程序的MySQL数据库。这项功能一经使用,你一定会觉得体验非常不错,因为又少了一件需要你担心的事。这还意味着,即使后续更改了URL、用户名和密码,你也不需要自己去更新。

几年来我都是这么操作的,在Structurizr changelog上你会发现版本号都快过1000了。每个版本号都代表一个在Pivotal Web Services上的独立(自动)部署。在我运行的这些大量部署中,大多数都部署成功了,偶尔,我也会收到一些因为服务(比如ClearDB)不能绑定到应用程序实例的失败提示。

不过这都是些暂时性的错误,只需要重新启动部署就能修复它们。但遇到其他错误提示时,我不得不承认我实在没有办法解决它。PaaS的一个大问题就在于,一旦出错,管理者就会陷入困境,因为无法访问到底层的基础设施。好在这类错误出现频度很低,现实中没有让我真正担心过,但还是挺烦人的。

更闹心的是我发现了一个Structurizr和UTF-8字符编码的小bug。当用户注册帐户时,记录会被保存在MySQL里,用户会收到一封“请验证您的电子邮件地址”的电子邮件。一旦注册者的名字中包含了UTF-8字符,尽管第一封电子邮件不会有什么问题,但后续就会出错。这个问题出在MySQL无法正确地存储UTF-8字符上。

我在dev环境中重演了这个问题,可以通过向JDBC URL添加一个字符编码参数来修复。不过,推送这个补丁到实时环境也存在问题,因为Cloud Foundry又会自动重新配置我的数据源URL。简单处理是不启用自动重新配置,这很容易通过Java构建包来实现禁用,也不需要将MySQL数据库实例绑定到Java应用程序。基于以上操作,现在我仍然会通过应用市场来使用ClearDB,但在配置中我会指定连接细节。

我所遇到的有关ClearDB的最后一个问题是在今年早些时候,当时我经常在日志中看到错误消息,提示已经超过了能连接的最大数量。不同的ClearDB计划会提供不同级别的性能和连接数量。我认为应用市场提供的ClearDB数据库是面向多租户(Multi-tenant)的,它会设置一个连接限制来确保所有客户的服务质量。这可以理解,但我不明白为什么我会超过可使用数量,因为我清楚地知道我运行的应用实例数量,而且也清楚每个应用实例所限定的连接数量范围。

于是,我在Apache基准测试中运行了一些负载测试,结果我无法得知打开连接的数量,从而无法判断它们是否超过了连接池中所配置的最大限额。我再三查看ClearDB的数据指示仪表板,按说它可以显示打开连接的数量,但我的应用程序却无法连接,仪表板上只显示了几个实时连接。

回到供应商锁定和迁移成本这个话题,将应用程序从ClearDB迁移到另一个MySQL供应商的成本很低,特别是不使用Cloud Foundry的自动重新配置机制之后。因此,我可以导出数据,并在Amazon RDS上创建一个MySQL数据库。每个月在不需要支付很多费用的前提下,我就可以有个运行在多个可用性区域的MySQL数据库,在rest中使用加密的数据,并且我确信JDBC连接是通过SSL进行的(因为这就是我配置它的方式)。

7、电子邮件传送即服务

我早期使用的另一个应用市场服务是SendGrid,它提供“电子邮件传送即服务(E-mail delivery as a service)”。同样的,运行一个“cf bind”命令就可以将SendGrid服务绑定到应用程序。

但在这种情况下,不会有自动重新配置,因为SendGrid公开了一个web API。这就提出了一个问题,即在哪里找到API凭据。应用市场服务一个很好的特性是,只需要一个单点登录的操作,就能通过关键Web服务 UI来访问服务数据仪表板(例如ClearDB仪表板、SendGrid仪表板等),在服务仪表板上的某个位置找到服务凭证。

在获取SendGrid的密码后,我将它硬编码到一个配置文件中,并将其推送到应用程序中。出乎我意料的是,程序尝试连接SendGrid后提示了身份验证失败,因为密码错误。于是我再次访问了仪表板,发现密码已经不一样了,我不知道造成这样的结果是否是因为运行了一个“cf bind”命令而导致SendGrid凭证被更改。

我没有意识到服务凭证是在运行中的JVM的 VCAP_SERVICES 环境变量中设置的,凭证应该从那里提取。这只是一个带有JSON content 的常规环境变量。获取它并解析所需的凭证,或是使用GitHub上众多代码示例或函数库(library)就可以完成此操作。从开发的角度来看,我现在对这个VCAP的数据有小小的依赖,我需要确保我的本地Apache Tomcat实例以相同的方式进行配置,并在启动时使用VCAP_SERVICES环境变量。

一段时间之后,SendGrid已经将其Web API升级到了v3版 ,其中也包括了Java函数库的新版本。 所以我也进行了升级,但却导致了API调用的失败。在登录到SendGrid数据仪表板之后,我注意到现在可以通过API密钥进行连接。简而言之,我放弃了VCAP的可调用数据,配置了SendGrid客户端,用使用API密钥的方法来调用API,这些也被我添加到了部署配置中。

8、其他服务

我还使用过一段时间的Pivotal SSL Service,用来上传SSL证书。当它与Cloud Foundry路由器同时工作,就可以通过一个有效的SSL证书为指定域名提供流量服务。在使用过程中我也遇到一些问题,比如会导致运行停止。Java程序在cfapps.io域里还能正常工作,但structurizr.com域则不行。

此后,我又换成了CloudFlare专用的SSL证书服务,每月花费5美元。我确实尝试过免费的SSL证书服务,但一部分用户还是反馈了通过Structurizr's web API上传软件架构模型时,发现了一些“SSL握手”方面的问题。

曾经我也结合 Spring Session一起,用了免费的Redis缓存服务,将其作为存储HTTP session信息的一种方式。不过,我很快就消耗完了免费的额度,同时发现通过Redis Labs直接切换到Redis Cloud计划性价比会更高些。

9、无市场服务的PaaS

使用与PaaS产品相配套的应用市场服务(Marketplace Service)肯定有一些好处。你只需要选择订阅一项附加服务,就可以开始使用了,既快又便捷。而且所有的服务都可以在同一个市场里进行购买和管理,这点也很棒。在使用Cloud Foundry PaaS云平台时,我就通过VCAP_SERVICES进行配置;这样所有的服务都在一起。

如果你刚开始使用PaaS,我想你肯定会考虑与其配套的那些应用市场服务。虽然大家具体情况会有所不同,但我还是不推荐用这些应用市场服务来从事生产活动。正如我在本文开头所说,我使用Pivotal Web Services PaaS的核心功能差不多有三年,这期间系统一直都比较稳定。我所遇到的那些不稳定的情况,都和应用市场服务有关。这些市场服务很可能导致你无法获知一些具体情况,比如在特定情况下,服务实际能带来什么样的运行结果,以及服务具体在哪里运行。

ClearDB数据库计划其实也有暗示,免费计划(Spark DB)是“完美适用于概念验证和初级开发”,而每月100美元的"Shock DB"计划则“专为高性能应用而设计”。这些计划没有在ClearDB网站上列出,因此很难判断它们是多租户服务 还是单一租户服务。考虑到需要进行网络登录,应用市场服务创建的一些访问密码看起来也相当简短(比如8个字符)。

考虑到以上种种情况,我更倾向于直接注册一个服务,并以常用的方式来进行集成,我不认为采用应用市场服务利大于弊。如果哪一天我需要从PaaS项目中移走。我还将进一步降低迁移成本。总的来说,Structurizr目前的现场部署方案图如下所示:

Java应用程序托管在Pivotal Web Services PaaS云服务上,其他所有组件都在外部运行,但它仍然在亚马逊(Amazon)的us-east-1 AWS区域。这应该有助于解决另一个常见的,大家都认为需要在PaaS环境中运行所有内容的误区,但其实没什么能阻止你在PaaS上运行Java应用程序,并让它们连接到你自己构建的数据库服务器。如此一来,你可以自由使用你选择的技术,不管它是否在应用市场(Marketplace)上可用。当然,你还需要考虑适配性、性能和安全性。

以上是我对应用市场服务(Marketplace Service)经验的总结。接下来,我将更多地讨论构建/部署脚本,以及通过Cloud Foundry PaaS云平台实现零停机时间(zero-downtime)、蓝绿部署方面的内容。

本文的前几部分已经从多个不同的角度对Cloud Foundry PaaS云平台作了介绍; 包括high-level概念、供应商锁定(vendor lock-in) 和Pivotal Web Services PaaS云服务应用市场服务(Marketplace Service)。接下来,我们将讨论Cloud Foundry PaaS云平台如何实现“零停机时间(zero-downtime)”部署,并让这个操作变得更为简易。

10、蓝绿部署

先简要介绍下这个主题,假设有个Java web应用程序在某处运行。将该应用程序升级到新版本的一个简单方法是先暂停程序,然后更新相关的部署构件(例如.JAR 或 .WAR文件),再重启。一些web应用程序服务器也会为应用程序的热部署(hot swapping) 提供支持,但原理都一样。

尽管这个方法是可行的,但在这个过程中,用户就会有一段时间无法使用服务。多年来,技术人员也构想了许多技术方案来处理这个问题,业界最流行的就是蓝绿部署,在这种部署方案里,会有一个物理或是虚拟的路由器,将流量从应用程序的一个运行实例切换到另一个。这听起来很先进,但如果你使用Cloud Foundry,任何规模的开发团队都可以轻松地进行蓝绿部署。

在本文的前面部分我也提到过,Structurizr是由两个java/spring web应用程序组成;一个服务于HTML、CSS和JavaScript的“Web应用程序”和一个允许客户获取或放置软件架构的工作区的“API应用程序”。构建和部署过程由Amazon EC2服务器上运行的TeamCity触发,等待提交到git存储库,这整个过程都是完全自动化的。总而言之,蓝绿部署的构建和部署过程遵循以下几个步骤:

  1. 处理好依赖关系(dependencies)
  2. 初始化构建目录、新增版本号等
  3. 编译生产和测试代码
  4. 运行单元/类(unit/class)测试
  5. 运行集成/组件测试
  6. 创建部署构件(例如.WAR文件)
  7. 将API应用程序推送至Pivotal Web Services
  8. 在API应用程序上运行e2e/系统测试
  9. 将Web应用程序推送至Pivotal Web Services
  10. 在Web应用程序上运行e2e/系统测试
  11. 激活API应用程序
  12. 激活Web应用程序
  13. 生成并发布新的软件架构图和文档

11、推送应用程序至

Pivotal Web Services

假设构建和测试的过程都顺利, 那么这个过程中,每个API和Web应用程序都会被推送至Pivotal Web Services PaaS云服务。构建服务器上安装了Cloud Foundry命令行接口,构建脚本只需使用“cf push”命令来推送(Push).WAR文件。为便于应用程序的推送(Push),我们使用“--no-start”标记(flag),但不启动它,这样就可以通过“cf env”命令来设置像配置这样的应用程序环境变量。设置完配置后,在实际启动应用程序之前,使用“cf scale”命令还可以设置所需的实例和RAM数量。此时,应用程序还在运行,但是只能通过包含版本号的临时URL进行访问(例如“https://structurizrweb - 123. cfapps.io”)。

在应用程序运行的同时,构建脚本可以运行一系列端到端测试,比如“冒烟测试(smoke test)” 和系统测试并行的混合测试,以验证新版本的应用程序是否按预期运行。这些测试包括一些像登录、获取/安装软件架构模型等场景。

12、激活新版本

如果成功通过了端到端测试,接下来就是激活这些程序的新版本。这需要使用Cloud Foundry命令行接口,将实时URL映射到应用程序的新版本("cf map-route"),然后将其从旧版本中删除(“cf-unmap-路由”)。这个过程使用了Cloud Foundry路由器,它可以实现对访问当前运行程序的URL的配置。 如果这一切都成功了,那么应用程序的前一个版本就会被删除。整个构建过程只需要不到10分钟。如果你感兴趣,这里还有一些关于如何进行蓝绿部署的内容。

将实时URL切换到应用程序新版本的这个过程,是允许“零停机时间(zero-downtime)”部署的。这里要提醒大家的是,切换到新版本后,任何只驻留在旧版程序内存空间中的信息都会丢失。例如,如果HTTP 会话(session)状态只存储在内存中,那么一旦用户在请求被导入到新的Apache Tomcat实例时,就会被迫退出。 处理这个问题有包括会话(session)复制在内的多种方法, 但Structurizr使用Spring session+Redis技术,将HTTP会话信息存储在Apache Tomcat服务器实例之外,以便在部署过程中保留会话信息,从而解决了会话共享问题。

如此一来……仅仅是使用Cloud Foundry命令行接口,我们就简单高效地完成了一个“零停机时间(zero-downtime)”部署过程。

原文地址:

http://www.codingthearchitecture.com/2017/09/27/paas_for_java_developers_part_1.html

http://www.codingthearchitecture.com/2017/09/28/paas_for_java_developers_part_2.html

http://www.codingthearchitecture.com/2017/09/29/paas_for_java_developers_part_3.html

http://www.codingthearchitecture.com/2017/10/10/paas_for_java_developers_part_4.html

(编者注:原文分为四部分,此文为全部内容的整合。)

作者简介: Simon Brown,全球知名软件架构独立咨询师、讲师,专注于软件架构研究,他是C4软件架构模型的创建者,也是Structurizr的创始人。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-06-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 EAWorld 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • (Marketplace Service)
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档