mongodump 失败且导致mongo服务挂掉【本质原因,wt文件损坏】
======================================================
标题遇到的问题是我要解决的问题的中间环节。
原本问题是:需要在之前standlone的MongoDB数据库中搭建replicaSet集群,发现该集合同步一半就导致本MongoDB实例挂掉
怎么搭建MongoDB relicaSet集群,参考另一篇博客:http://www.cnblogs.com/zhzhang/p/6783425.html
======================================================
服务器虚拟机:6核8G。
问题阐述:
mongodb版本3.2.7(yum安装)
需要mongodump出一个collection 如下
mongodump --collection abc --db db
abc 为接近2亿条,单条大概200B
每次执行mongodum命令,进度到52.5%就会报错如下,并且mongo服务挂掉,必须重启
--02T17::51.663+ [############............] db.abc / (51.4%)
--02T17::54.663+ [############............] db.abc / (51.7%)
--02T17::57.663+ [############............] db.abc / (52.0%)
--02T17::00.663+ [############............] db.abc / (52.2%)
--02T17::03.663+ [############............] db.abc / (52.4%)
--02T17::05.619+ [############............] db.abc / (52.5%)
--02T17::09.823+ Failed: error reading collection: EOF
You have mail in /var/spool/mail/admin [admin@syslog-.dev.abc-inc.com /abc_log_nas]
$ps aux | grep mongo
admin 0.0 0.0 pts/ S+ : : grep mongo
You have mail in /var/spool/mail/admin [root@syslog-.dev.abc-inc.com /home/admin/bin]
#/etc/init.d/mongod status
mongod dead but subsys locked [root@syslog-.dev.abc-inc.com /home/admin/bin]
#/etc/init.d/mongod restart
Stopping mongod: [ OK ]
Starting mongod: [ OK ] [root@syslog-.dev.abc-inc.com /home/admin/bin]
#tail -n /var/spool/mail/admin
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=admin>
X-Cron-Env: <USER=admin>
Message-Id: <.741D2601FD@syslog-.dev.abc-inc.com>
Date: Mon, Apr :: + (CST) ssh: Could not resolve hostname syslog-: Temporary failure in name resolution
rsync: connection unexpectedly closed ( bytes received so far) [receiver]
rsync error: unexplained error (code ) at io.c() [receiver=3.0.] rsync error: unexplained error (code ) at io.c() [receiver=3.0.] rsync: connection unexpectedly closed ( bytes received so far) [receiver]
rsync error: unexplained error (code ) at io.c() [receiver=3.0.]
目前已经找到解决的方法。。。。。。同时多谢网络中的各位匿名大神。。。。。。总结文稿,希望对其他人有帮助
=====================================================================
尝试方法一(无效):增大连接数,传送门:http://www.cnblogs.com/zhzhang/p/6762239.html参考文件数打开限制的配置
尝试方法二(无效):将oplogSize增大,之前为1G,修改完之后10G,传送门MongoDB官网:
https://docs.mongodb.com/manual/tutorial/change-oplog-size/
尝试方法三(无效):因为这个collection上只有_id一个索引,尝试建索引,结果也是建在50%左右的时候挂掉。
而且MongoDB重启默认还是执行建索引的操作,必须在配置文件中显示指定
storage:
indexBuildRetry: false
这样重启,才不至于导致重蹈建索引。。。死机。。。重启。。。建索引。。。的死循环
尝试方法四(无效):想着怎么把该集合分开,该集合恰好没有人为建索引。哎哎哎,索引?忽的发现了貌似的救命稻草:mongo自带的ObjectId索引
在该服务器或者其他服务器启动mongod实例,利用mongo自带的索引(ObjectId使用12字节的存储空间,每个字节两位十六进制数字,是一个24位的字符串)clone出按照时间区分的几个集合。
clone方法:在新建的mongo实例中
db.runCommand({cloneCollection: "db.abc", from: "syslog-1:27017", query: {"_id": {$gt: ObjectId("583aa21d382653813be7c18d"),$lte: ObjectId("587aa21d382653813be7c18d")}}})
db.getCollection("abc").renameCollection("abc_587")
在原来的实例中:
db.runCommand({cloneCollection: "db.abc_587", from: "syslog-3:37017", query: {}})
检查下没问题就可以删除那个巨大的集合中对应的数据了:
db.abc.remove({"_id": {$gt: ObjectId("583aa21d382653813be7c18d"),$lte: ObjectId("587aa21d382653813be7c18d")}})
不得不吐槽下,mongo的集合的文档批量删除实在是太慢了。。。。几千万的数据估计得删几十个小时。。。平均每分钟5w左右的样子。
貌似机器负载不重的时候,3-4w/秒
等等等。。。。。。
尝试方法五(实测有效,也是问题根本原因):
再看一下详细的报错信息
--04T19::06.533+ I NETWORK [initandlisten] connection accepted from 127.0.0.1: # ( connections now open)
--04T19::06.545+ I NETWORK [conn35] end connection 127.0.0.1: ( connections now open)
--04T19::06.550+ I NETWORK [initandlisten] connection accepted from 127.0.0.1: # ( connections now open)
--04T19::06.563+ I NETWORK [conn36] end connection 127.0.0.1: ( connections now open)
--04T19::06.818+ I NETWORK [initandlisten] connection accepted from 127.0.0.1: # ( connections now open)
--04T19::06.831+ I NETWORK [conn37] end connection 127.0.0.1: ( connections now open)
--04T19::06.837+ I NETWORK [initandlisten] connection accepted from 127.0.0.1: # ( connections now open)
--04T19::06.870+ I NETWORK [conn38] end connection 127.0.0.1: ( connections now open)
--04T19::24.465+ I COMMAND [conn24] query service.client_agent query: { $query: {}, $orderby: { _id: } } planSummary: IXSCAN { _id: } cursorid: ntoreturn: ntoskip: keysExamined: docsExamined: keyUpdates: writeConflicts: numYields: nreturned: reslen: locks:{ Global: { acquireCount: { r: } }, Database: { acquireCount: { r: } }, Collection: { acquireCount: { r: } } } 10756ms
--04T19::24.531+ E STORAGE [conn24] WiredTiger () [:][:0x7f40712c3700], file:collection-4--1812812328855925336.wt, WT_CURSOR.search: read checksum error for 8192B block at offset : block header checksum of doesn't match expected checksum of 3037857471
--04T19::24.531+ E STORAGE [conn24] WiredTiger () [:][:0x7f40712c3700], file:collection-4--1812812328855925336.wt, WT_CURSOR.search: collection---.wt: encountered an illegal file format or internal value
--04T19::24.531+ E STORAGE [conn24] WiredTiger (-) [:][:0x7f40712c3700], file:collection-4--1812812328855925336.wt, WT_CURSOR.search: the process must exit and restart: WT_PANIC: WiredTiger library panic
--04T19::24.531+ I - [conn24] Fatal Assertion
--04T19::24.531+ I - [conn24] ***aborting after fassert() failure --04T19::24.599+ I - [WTJournalFlusher] Fatal Assertion
--04T19::24.599+ I - [WTJournalFlusher] ***aborting after fassert() failure --04T19::24.609+ F - [conn24] Got signal: (Aborted). 0x1304482 0x13033a9 0x1303bb2 0x7f40828dd7e0 0x7f408256c625 0x7f408256de05 0x128a472 0x1072bb3 0x1a7945c 0x1a7991d 0x1a79d04 0x19acfb7 0x19c9c85 0x19cf380 0x19f0207 0x19ba7a8 0x1a0c71c 0x1067a83 0xbdc2c9 0xb9916e 0xbbf2b5 0xdee255 0xdee919 0xdaaf72 0xdab66d 0xc82da9 0xc89075 0x94ed5c 0x12aea65 0x7f40828d5aa1 0x7f408262293d
----- BEGIN BACKTRACE -----
{"backtrace":[{"b":"","o":"F04482","s":"_ZN5mongo15printStackTraceERSo"},{"b":"","o":"F033A9"},{"b":"","o":"F03BB2"},{"b":"7F40828CE000","o":"F7E0"},{"b":"7F408253A000","o":"","s":"gsignal"},{"b":"7F408253A000","o":"33E05","s":"abort"},{"b":"","o":"E8A472","s":"_ZN5mongo13fassertFailedEi"},{"b":"","o":"C72BB3"},{"b":"","o":"167945C","s":"__wt_eventv"},{"b":"","o":"167991D","s":"__wt_err"},{"b":"","o":"1679D04","s":"__wt_panic"},{"b":"","o":"15ACFB7","s":"__wt_bm_read"},{"b":"","o":"15C9C85","s":"__wt_bt_read"},{"b":"","o":"15CF380","s":"__wt_page_in_func"},{"b":"","o":"15F0207","s":"__wt_row_search"},{"b":"","o":"15BA7A8","s":"__wt_btcur_search"},{"b":"","o":"160C71C"},{"b":"","o":"C67A83","s":"_ZN5mongo21WiredTigerRecordStore6Cursor9seekExactERKNS_8RecordIdE"},{"b":"","o":"7DC2C9","s":"_ZN5mongo16WorkingSetCommon5fetchEPNS_16OperationContextEPNS_10WorkingSetEmNS_11unowned_ptrINS_20SeekableRecordCursorEEE"},{"b":"","o":"79916E","s":"_ZN5mongo10FetchStage4workEPm"},{"b":"","o":"7BF2B5","s":"_ZN5mongo9SkipStage4workEPm"},{"b":"","o":"9EE255","s":"_ZN5mongo12PlanExecutor11getNextImplEPNS_11SnapshottedINS_7BSONObjEEEPNS_8RecordIdE"},{"b":"","o":"9EE919","s":"_ZN5mongo12PlanExecutor7getNextEPNS_7BSONObjEPNS_8RecordIdE"},{"b":"","o":"9AAF72"},{"b":"","o":"9AB66D","s":"_ZN5mongo7getMoreEPNS_16OperationContextEPKcixPbS4_"},{"b":"","o":"882DA9","s":"_ZN5mongo15receivedGetMoreEPNS_16OperationContextERNS_10DbResponseERNS_7MessageERNS_5CurOpE"},{"b":"","o":"","s":"_ZN5mongo16assembleResponseEPNS_16OperationContextERNS_7MessageERNS_10DbResponseERKNS_11HostAndPortE"},{"b":"","o":"54ED5C","s":"_ZN5mongo16MyMessageHandler7processERNS_7MessageEPNS_21AbstractMessagingPortE"},{"b":"","o":"EAEA65","s":"_ZN5mongo17PortMessageServer17handleIncomingMsgEPv"},{"b":"7F40828CE000","o":"7AA1"},{"b":"7F408253A000","o":"E893D","s":"clone"}],"processInfo":{ "mongodbVersion" : "3.2.7", "gitVersion" : "4249c1d2b5999ebbf1fdf3bc0e0e3b3ff5c0aaf2", "compiledModules" : [], "uname" : { "sysname" : "Linux", "release" : "2.6.32-504.el6.x86_64", "version" : "#1 SMP Wed Oct 15 04:27:16 UTC 2014", "machine" : "x86_64" }, "somap" : [ { "elfType" : , "b" : "", "buildId" : "384A822B93AE1E4CFE393F0CECA08575DF6EB381" }, { "b" : "7FFF67CB8000", "elfType" : , "buildId" : "08E42C6C3D2CD1E5D68A43B717C9EB3D310F2DF0" }, { "b" : "7F4083775000", "path" : "/usr/lib64/libssl.so.10", "elfType" : , "buildId" : "B84C31B86733DE212F6886FE6F55630FE56180A9" }, { "b" : "7F4083391000", "path" : "/usr/lib64/libcrypto.so.10", "elfType" : , "buildId" : "A30A68D2F579614CBEA988BDAAC20CD56D8C48FC" }, { "b" : "7F4083189000", "path" : "/lib64/librt.so.1", "elfType" : , "buildId" : "95159178F1A4A3DBDC7819FBEA2C80E5FCDD6BAC" }, { "b" : "7F4082F85000", "path" : "/lib64/libdl.so.2", "elfType" : , "buildId" : "29B61382141595ECBA6576232E44F2310C3AAB72" }, { "b" : "7F4082D01000", "path" : "/lib64/libm.so.6", "elfType" : , "buildId" : "989FE3A42CA8CEBDCC185A743896F23A0CF537ED" }, { "b" : "7F4082AEB000", "path" : "/lib64/libgcc_s.so.1", "elfType" : , "buildId" : "9350579A4970FA47F3144AD8F40B183B0954497D" }, { "b" : "7F40828CE000", "path" : "/lib64/libpthread.so.0", "elfType" : , "buildId" : "C56DD1B811FC0D9263248EBB308C73FCBCD80FC1" }, { "b" : "7F408253A000", "path" : "/lib64/libc.so.6", "elfType" : , "buildId" : "8E6FA4C4B0594C355C1B90C1D49990368C81A040" }, { "b" : "7F40839E1000", "path" : "/lib64/ld-linux-x86-64.so.2", "elfType" : , "buildId" : "959C5E10A47EE8A633E7681B64B4B9F74E242ED5" }, { "b" : "7F40822F6000", "path" : "/lib64/libgssapi_krb5.so.2", "elfType" : , "buildId" : "441FA45097A11508E50D55A3D1FF169BF2BE7C62" }, { "b" : "7F408200F000", "path" : "/lib64/libkrb5.so.3", "elfType" : , "buildId" : "F62622218875795666E08B92D176A50791183EEC" }, { "b" : "7F4081E0B000", "path" : "/lib64/libcom_err.so.2", "elfType" : , "buildId" : "152E2C18A7A2145021A8A879A01A82EE134E3946" }, { "b" : "7F4081BDF000", "path" : "/lib64/libk5crypto.so.3", "elfType" : , "buildId" : "B8DEDADC140347276164C729418C7A37B7224135" }, { "b" : "7F40819C9000", "path" : "/lib64/libz.so.1", "elfType" : , "buildId" : "5FA8E5038EC04A774AF72A9BB62DC86E1049C4D6" }, { "b" : "7F40817BE000", "path" : "/lib64/libkrb5support.so.0", "elfType" : , "buildId" : "4BDFC7A19C1F328EB4FCFBCE7A1E27606928610D" }, { "b" : "7F40815BB000", "path" : "/lib64/libkeyutils.so.1", "elfType" : , "buildId" : "AF374BAFB7F5B139A0B431D3F06D82014AFF3251" }, { "b" : "7F40813A1000", "path" : "/lib64/libresolv.so.2", "elfType" : , "buildId" : "C39D7FFB49DFB1B55AD09D1D711AD802123F6623" }, { "b" : "7F4081182000", "path" : "/lib64/libselinux.so.1", "elfType" : , "buildId" : "E6798A06BEE17CF102BBA44FD512FF8B805CEAF1" } ] }}
mongod(_ZN5mongo15printStackTraceERSo+0x32) [0x1304482]
mongod(+0xF033A9) [0x13033a9]
mongod(+0xF03BB2) [0x1303bb2]
libpthread.so.(+0xF7E0) [0x7f40828dd7e0]
libc.so.(gsignal+0x35) [0x7f408256c625]
libc.so.(abort+0x175) [0x7f408256de05]
mongod(_ZN5mongo13fassertFailedEi+0x82) [0x128a472]
mongod(+0xC72BB3) [0x1072bb3]
mongod(__wt_eventv+0x42C) [0x1a7945c]
mongod(__wt_err+0x8D) [0x1a7991d]
mongod(__wt_panic+0x24) [0x1a79d04]
mongod(__wt_bm_read+0x77) [0x19acfb7]
mongod(__wt_bt_read+0x85) [0x19c9c85]
mongod(__wt_page_in_func+0x180) [0x19cf380]
mongod(__wt_row_search+0x677) [0x19f0207]
mongod(__wt_btcur_search+0xB08) [0x19ba7a8]
mongod(+0x160C71C) [0x1a0c71c]
mongod(_ZN5mongo21WiredTigerRecordStore6Cursor9seekExactERKNS_8RecordIdE+0x53) [0x1067a83]
mongod(_ZN5mongo16WorkingSetCommon5fetchEPNS_16OperationContextEPNS_10WorkingSetEmNS_11unowned_ptrINS_20SeekableRecordCursorEEE+0x99) [0xbdc2c9]
mongod(_ZN5mongo10FetchStage4workEPm+0x2FE) [0xb9916e]
mongod(_ZN5mongo9SkipStage4workEPm+0x45) [0xbbf2b5]
mongod(_ZN5mongo12PlanExecutor11getNextImplEPNS_11SnapshottedINS_7BSONObjEEEPNS_8RecordIdE+0x275) [0xdee255]
mongod(_ZN5mongo12PlanExecutor7getNextEPNS_7BSONObjEPNS_8RecordIdE+0x39) [0xdee919]
mongod(+0x9AAF72) [0xdaaf72]
mongod(_ZN5mongo7getMoreEPNS_16OperationContextEPKcixPbS4_+0x52D) [0xdab66d]
mongod(_ZN5mongo15receivedGetMoreEPNS_16OperationContextERNS_10DbResponseERNS_7MessageERNS_5CurOpE+0x1A9) [0xc82da9]
mongod(_ZN5mongo16assembleResponseEPNS_16OperationContextERNS_7MessageERNS_10DbResponseERKNS_11HostAndPortE+0xE35) [0xc89075]
mongod(_ZN5mongo16MyMessageHandler7processERNS_7MessageEPNS_21AbstractMessagingPortE+0xEC) [0x94ed5c]
mongod(_ZN5mongo17PortMessageServer17handleIncomingMsgEPv+0x325) [0x12aea65]
libpthread.so.(+0x7AA1) [0x7f40828d5aa1]
libc.so.(clone+0x6D) [0x7f408262293d]
----- END BACKTRACE -----
纳尼,竟然文件坏了,我特么什么时候动过这个文件了。。。。。。
没办法,继续修问题。。。
下面解决问题的最核心的步骤即将到来。。。
1. 下载安装必要的软件
wget http://source.wiredtiger.com/releases/wiredtiger-2.7.0.tar.bz2
tar xvf wiredtiger-2.7..tar.bz2
cd wiredtiger-2.7.
sudo apt-get install libsnappy-dev build-essential
./configure --enable-snappy
make
2. 将出问题的wt文件拷贝一份出来(至于怎么查看可以查看通过对应的集合查看,如下)
db.abc.stats().wiredTiger.uri
3. 拯救坏掉的集合
./wt -v -h ../mongo-bak -C "extensions=[./ext/compressors/snappy/.libs/libwiredtiger_snappy.so]" -R salvage collection---.wt
4. 通过dump/load导入wt文件到MongoDB集合
./wt -v -h ../data -C "extensions=[./ext/compressors/snappy/.libs/libwiredtiger_snappy.so]" -R dump -f ../collection.dump collection---
5. 创建一个新的mongo实例,目的是获取一个空的集合实例,以方便将load出的文件导入该集合
mongod --dbpath tmp-mongo --storageEngine wiredTiger --nojournal
use Recovery
db.borkedCollection.insert({test: })
db.borkedCollection.remove({})
db.borkedCollection.stats()
6. 将第4步生成的collection.dump文件导入刚启动的mongo实例的数据目录下(对应的mongo实例需要停掉)
对应的collection-******,参考第五步创建的集合的db.abc.stats().wiredTiger.uri状态
./wt -v -h ../data -C "extensions=[./ext/compressors/snappy/.libs/libwiredtiger_snappy.so]" -R load -f ../collection.dump -r collection--
7. 启动mongo实例,并且登录进去,发现文档为空
db.borkedCollection.count()
8.但是通过利用如下语句查询,确实是有内容的:
db.borkedCollection.find({}, {_id: })
9.利用mongodump将集合数据dum出来
mongodump
10.利用mongorestore将集合数据导入进mongo中
mongorestore --drop
11.登录MongoDB,发现数据恢复
由于是数据文件损坏,可能会少一些数据,像我这个例子,1.7亿条少了10w左右,可以接受
本次问题解决,参考网址:http://www.alexbevi.com/blog/2016/02/10/recovering-a-wiredtiger-collection-from-a-corrupt-mongodb-installation/
希望对各位能有所帮助。
PS:发现通过排查问题确实是学习的好方法。
通过本次问题排查,MongoDB摸索的东西不少。。。
mongodump 失败且导致mongo服务挂掉【本质原因,wt文件损坏】的更多相关文章
- 最牛MongoDB灾难恢复(WiredTiger.wt文件损坏,Mongo无法启动)
WiredTiger.wt文件是mongoDB的元数据文件,存储了其他数据库表的元数据信息.笔者最近遇到了WiredTiger.wt文件损坏的情况,MongoDB无法启动,数据库中的重要数据危在旦夕. ...
- ipv6禁用导致rpcbind服务启动失败实例
ipv6禁用导致rpcbind服务启动失败实例 昨天在做服务器磁盘分区扩容的时候出现过一个服务启动的问题,在此记录.情景再现:前天晚上申请做磁盘扩容,得到批准后,昨天早上5点开始做停机调整维护 ...
- MSSQLSERVER 服务运行内存设置较小导致启动服务失败
问题产生原因: 手动设置MSSQLSERVER 运行内存,设置值未达到MSSQLSERVER 服务运行内存最低值(max server memory 所允许的最小内存量是 128 MB.),导致MSS ...
- [网站日志]当Memcached缓存服务挂掉时性能监视器中的表现
我们用的Memcached缓存服务是阿里云OCS,今天晚上遇到了一次OCS挂掉的情况(计划中的升级),看一下性能监视器中的表现,也许对分析黑色1秒问题有帮助. 应用日志中错误: 2014-06-05 ...
- Windows Mysql启动出现1069错误 “由于登录失败而无法启动服务” 的处理方法
问题现象 windows下mysql服务无法启动,报1069错误. 问题原因 如果Mysql启动用户的密码或者权限错误,会导致Windows服务器Mysql启动时出现"由于登录失败而无法启动 ...
- php-fpm服务挂掉
今天发了个链接,可能同时在线的人瞬间比较多,结果网站报503错误,回去打开php-fpm错误日志一看,php-fpm服务挂掉了,报如下错误: [04-Apr-2016 15:38:04] NOTICE ...
- 软件安装失败,导致ubuntu软件中心软件消失
感谢百度上各位IT界朋友的帮助,由于某个软件安装失败,导致ubuntu软件中心软件消失的解决办法: 找百度,有人说, 使用命令:sudo apt-get install software-center ...
- 【SAP BO】【DI】DataService 服务无法启动。错误1069:由于登录失败而无法启动服务
重启BI服务器后,突然发现DataServices服务无法启动,提示: 错误 1069:由于登录失败而无法启动服务. 解决方法: (1)打开控制面板--> 服务 --> 右键点击Data ...
- paip.花生壳 服务启动失败 以及不能安装服务,权限失败的解决
paip.花生壳 服务启动失败 以及不能安装服务,权限失败的解决 系统win7 NewPhDDNS_1.0.0.30166.exe 作者Attilax 艾龙, EMAIL:1466519819@ ...
随机推荐
- nginx高性能webserver具体解释(1)--安装nginx
1. 下载 本次使用nginx-0.1.2.3 版本号,下载地址 http://nginx.org/en/download.html 新公布版本号 http://nginx.org/download ...
- java手动加载jar
@RequestMapping("/testJar") public @ResponseBody String exteriorJar(int ys, int csd,int jg ...
- Sqlite 复制表结构和数据
复制表结构 ; 复制表结构和数据 create table newTb as select * from oldTb:
- android上进行c/C++开发测试(转)
Android C编程技巧 运行模拟器 emulator -console * 将文件写入到模拟器的userdata.img文件中 adb push *将一个目录拷贝到模拟器中,包括子目录 adb p ...
- Cocos2dx 学习记录 [2] 关于混合和高亮一些知识点的体会
网上有一篇博客讲的是高亮的http://www.cnblogs.com/mrblue/p/3455775.html 就是这篇,尽管代码简单,但对于刚開始学习的人的我,看的还是有些吃力的,毕竟有些内容不 ...
- 【自创+转发】jQuery给input 密码框绑定回车事件
<script type="text/javascript" src="Scripts/jquery-1.6.2.js"></script&g ...
- MySQL主从同步的一个小问题解决
由于历史遗留问题,我们的MySQL主从库的表结构不一致,主库的某个表tableA比从库表tableA少了一个字段. 当尝试在主库上更改表结构时,这行alter语句会随着binlog同步到从库,如果从库 ...
- HDUOJ-Counting Triangles
Counting Triangles Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
- SVN解决创建文件时不带锁
解决创建文件时不带锁 C:\Documents and Settings\你的用户名\Application Data\Subversion 找到上面的用户路径 打开config添加 ### ...
- 【ASP.NET Web API教程】2.4 创建Web API的帮助页面[转]
注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. 2.4 Creating a Help Page for a Web API2.4 创建W ...