论坛首页 综合技术论坛

求求你们,千万别再说自己是REST了

浏览 45487 次
该帖已经被评为精华帖
作者 正文
   发表时间:2008-12-18   最后修改:2008-12-18
冉翔 写道
REST已经过去了,现在流行滴是:社会化

俺们做滴是社会化滴XXX网站……

REST过去了,HTTP也过去了,HTML也过去了,Web也过去了。

Really?
兄弟,说话要慎重些,免得被人笑。
0 请登录后投票
   发表时间:2008-12-18   最后修改:2008-12-18
个人的一个看法.
REST目前的这个情况实际上就是RMDB的翻版.现在几乎所有基于SQL的database都不符合Codd的关系数据的理念,注意不是兼容性的上或者子集的问题,而是玩玩全全两个不同的概念在Codd哪里根本是没有Table这种概念的,他的核心思想就是底层的数据结构对用户是根本不可见的,哪怕下面是网状结构都没关系只要你能够在上面作出他给出的关系操作.所以你要是说Oracle是关系数据库,Codd肯定会从棺材里爬起来跟你理论(如果他可以的话呵呵).但是大家现在都管SQL数据库叫关系数据库,主要的原因还是Codd的想法太超前,目前的技术条件没法实现只能退而求其次了.研究者的想法和实际应用工程师的情况是两个层次的.要完完全全的RESTful,得让Berners-Lee把语义网搞出来(如果他在有生之年可以搞出来的话)。现在只能hybird,没办法的事情.
0 请登录后投票
   发表时间:2008-12-18  
~~ 呃 哪天还有人给我介绍rest呢
0 请登录后投票
   发表时间:2008-12-19  
以前看REST觉得应该是面向资源的操作,现在觉得 rest应该是面向“资源的控制”的操作。那么什么是资源呢?莫非就是传说中的领域对象?
难道rest最终的思想是和领域模型保持一致的?
如果这么说的话,rest的架构应该就是http中领域驱动的架构了。
所以,rest中的 controller(假设叫controller)应该就是ddd中的 service,而逻辑应该包含在领域模型中。

越想越乱,dlee 也说说想法?:-)
0 请登录后投票
   发表时间:2008-12-19   最后修改:2008-12-19
yananay 写道
以前看REST觉得应该是面向资源的操作,现在觉得 rest应该是面向“资源的控制”的操作。那么什么是资源呢?莫非就是传说中的领域对象?
难道rest最终的思想是和领域模型保持一致的?
如果这么说的话,rest的架构应该就是http中领域驱动的架构了。
所以,rest中的 controller(假设叫controller)应该就是ddd中的 service,而逻辑应该包含在领域模型中。

越想越乱,dlee 也说说想法?:-)

事实上REST的重点在RE,而不是ST.呵呵,这是两拨人理解的最大差异之处.请注意RE用的是形容词Representational,想想为什么要用形容词?所以现在把REST翻译成表现状态转移的人,几乎就是没有理解REST
0 请登录后投票
   发表时间:2008-12-19  
顶dlee.

我认为,只有读过这篇论文,才能进行REST相关的讨论和交流。否则,连术语都无法统一,更别说交流了。

所以,在现实工作中碰到REST-ish的兄弟,我通常会先问一下:读过Fielding的论文没有?


为了避免误解,我必须坦白,我自己也只蜻蜓点水的通读而已,这篇论文要精读,还是需要一些毅力和功底的。

不过我至少不敢把REST常挂在嘴巴上。










0 请登录后投票
   发表时间:2008-12-19   最后修改:2008-12-19
yananay 写道
以前看REST觉得应该是面向资源的操作,现在觉得 rest应该是面向“资源的控制”的操作。那么什么是资源呢?莫非就是传说中的领域对象?
难道rest最终的思想是和领域模型保持一致的?
如果这么说的话,rest的架构应该就是http中领域驱动的架构了。
所以,rest中的 controller(假设叫controller)应该就是ddd中的 service,而逻辑应该包含在领域模型中。

越想越乱,dlee 也说说想法?:-)

过几天吧,反正大家也都没指望靠REST吃饭,除非是那些挂羊头卖狗肉的家伙。

这两天与Trustno1、o6z等朋友对Fielding的这篇blog和comments进行了深入的讨论,我对REST的认识也加深了很多。
我还需要几天做一下沉淀,过几天我把我们的相关讨论以及我个人的点评一起发上来。

既然“非主流”、“非著名”成为了时髦,那么“非REST”也没什么可丢人的。
REST被过度宣传和滥用才是可悲的。人家Fielding不是说了吗:就算你不采用REST架构风格也没什么关系,但是你别搞些个假冒伪劣的东西来恶心我!
Fielding 写道
That’s fine with me as long as you don’t call the result a REST API. I have no problem with systems that are true to their own architectural style.

别把REST搞的将来有一天像中国男足一样,让下面这句成了一句骂人话:
“你才需要REST,你全家都需要REST!”
0 请登录后投票
   发表时间:2008-12-21   最后修改:2008-12-21
Trustno1说:
说什么了?
dlee说:
Fielding的主要意思是说,客户端不应该事先了解服务器端URI的结构和针对每个URI的操作,而是应该通过某种发现机制来确定。
dlee说:
例如我使用浏览器访问一个网站,我先访问其首页,然后首页返回给我带有URI和link和form,指导我去访问其他页面。
dlee说:
这些link和form的URI、针对URI所执行的操作都是有可能变化的。
dlee说:
我如果不通过这种机制,事先在客户端代码中写死了,未来这些东西变了,客户端代码就会完全失效。
dlee说:
客户端不应该对服务器端的URI和针对URI所执行的操作做过多假设,那样客户端和服务器端的耦合就太紧了。
dlee说:
客户端应该通过服务器端返回给它带有超链接的表现来进行状态的迁移。
dlee说:
hypertext不一定是html,也可以是带有超链接的其他格式。
Trustno1说:
en,那么其他人在争论什么呢?
dlee说:
他们争论这个理想国在实际的Web应用开发中是否有价值。
dlee说:
对于普通Web开发者来说,这样间接的方式是违反直观的。
Trustno1说:
违反直观?怎么说?
dlee说:
比如你设计了一个Web服务的API,在文档里面告诉我可以使用/books/123/comments/55这种方式找到一本书的评论。
dlee说:
我在客户端代码中直接访问这个URI,
dlee说:
GET /books/123/comments/55
dlee说:
但是Fielding告诉你,你这样做是错误的,你不应该暴露出/books/123/comments/55。
dlee说:
你应该返回给客户端一个hypertext,里面含有这个URI。
dlee说:
然后客户端在服务器返回的这个hypertext的指导下访问这个URI。
dlee说:
但是客户端不应该事先假设服务器端一定会有这样一个URI。
dlee说:
采用这样间接的方式来实现你的API,将来你就可以改变URI的结构,而不影响客户端的功能。
dlee说:
按照Fielding的说法,目前Google/Amazon/Yahoo!等大公司的API其实都不是REST。
Trustno1说:
hem...
这个很简单咯,我觉得没有必要讨论的那么复杂。
dlee说:
普通Web开发人员不喜欢这种间接方式,他们更习惯RPC那种方式,所以其实很多API都是RPC。
Trustno1说:
理解一下,电话的使用方式。
Trustno1说:
最早的电话是没有来电显示的,因此都必须人手一本黄页和通信录。
Trustno1说:
但是现在电话和手机都有来电显示。
Trustno1说:
于是别人打过来电话以后你就能立刻打回去。
Trustno1说:
但是,现在仍然有黄页和个人通信录。
Trustno1说:
即便是有手机,我们也无法避免对方变更号码。
Trustno1说:
从某一方面来说,他说的不无道理,来电显示的确避免了很多麻烦,但是每人保持一个个人通信录也是必要的。
Trustno1说:
只要他变更的成本不是那么高。
dlee说:
是的,Web应用没有必要保持单一的架构风格。
dlee说:
不过REST方式在可伸缩性上确实比RPC方式更好。
Trustno1说:
其实这个主要是离线和在线的问题。
Trustno1说:
在线的情况下,RESTful怎么做都没问题。
Trustno1说:
但是我们总是有离线的情况。
dlee说:
移动应用这方面尤其重要,离线可以通过自动同步机制来实现,不过这跟REST关系不大。
dlee说:
以前我看到Google的一个Ajax应用的方案,它使用了Google Gears,能够自动检测浏览器离线还是在线。无论离线还是在线,这个Ajax应用都能正常运行。
Trustno1说:
至于说可伸缩性,就不知道了和RESTful有什么关系了。
dlee说:
REST的一个架构约束是统一接口,你还记得吗?
dlee说:
有了统一接口,缓存就很容易实现。
dlee说:
当然RPC也能实现缓存,但是很难像REST那样实现通用的大规模的缓存机制。
dlee说:
HTTP 1.1协议差不多有1/5内容都是与缓存相关的。
Trustno1说:
我个人认为,这些反对声最大的原因是,RESTful把结构和表现捆绑的太紧。
dlee说:
还是Fielding以前没说清楚,导致了大家的误解。
Trustno1说:
客户端需要从表现里扣出结构,这个是一个麻烦工作
dlee说:
To some extent, people get REST wrong because I failed to include enough detail on media type design within my dissertation. That’s because I ran out of time, not because I thought it was any less important than the other aspects of REST. Likewise, I suspect a lot of people get it wrong because they read only the Wikipedia entry on the subject, which is not based on authoritative sources.
dlee说:
他说对于hypertext这个约束,他以前没有在论文中强调。
dlee说:
如果他有时间,本来还想在论文中讨论media type的设计。
Trustno1说:
我觉得是这个样子的,RESTful是否实用与如何设计media type没有关系
dlee说:
Fielding的意思说,media type包含了如何操作媒体的知识,这些知识是带外的,是客户端和服务器端事先都了解的。
dlee说:
例如,html有一个img标签,客户端浏览器和服务器端都知道这个是一个图片,应该使用GET方法获得。
Trustno1说:
从比较抽象的层次上讲,将URI结构变为媒体表现是一个熵增的过程。而在客户端去从媒体中识别和挖掘出这些URI是一个熵减的过程。一个熵减的过程注定是要耗费计算的。
dlee说:
如何操作媒体的知识,不需要通过带内数据来传输。
Trustno1说:
关键是做到这个熵减,要做多少工作。
Trustno1说:
比如讲,我这里有一个项目是给电信的做的短信网关。
dlee说:
我觉得通俗来说,就是当URI改变时,服务器端开发者需要付出多少代价。
Trustno1说:
他们的做法是电信给所有的短信网关使用者公布一个URL。比如http://xxx.xxx./mobile/xxx./msg/xxxx
Trustno1说:
这样的做法当然不RESTful。
Trustno1说:
但是如果真要RESTful。那么你就得公布出去一个hypertxt比如说xml。
Trustno1说:
然后短信网关的使用者每个人都得写一个xml解析程序,找到这个URL。
Trustno1说:
你看出这里的问题了吗?
Trustno1说:
这里不是说那种技术的问题,而是社会结构关系的问题。RESTful在大多数网站上有比较好,是因为浏览器的标准是约定的。
Trustno1说:
但是在短信网关这里,客户端是不约定的。
Trustno1说:
有可能是一个Web服务器,或者一个VB写的小软件。
Trustno1说:
所以我觉得他是彻底搞反了,不是先约定协议,再约定媒体,而是先约定媒体再约定协议。
dlee说:
如果按照Fielding的说法,目前符合标准的REST客户端只有浏览器。
dlee说:
目前我不是完全支持Fielding的说法。我们也做了很长时间的REST开发了,感觉按照他说的那样做确实有很多困难。
dlee说:
很多年以来,Web基础架构(URI、HTTP、HTML等等)的设计者(Tim Berners-Lee、Roy T. Fielding等等)对于Web架构的理解和Web架构的使用者(普通的Web应用开发者)对于Web架构的理解之间存在着非常大的断层,希望这些深入的讨论有助于弥补这个断层。
dlee说:
面向人类用户的Web应用(通过一个浏览器)和面向机器用户的Web服务,这两者是否一定要采用相同的架构风格,目前我也有很大的疑问。
Trustno1说:
我觉得这个问题其实是Berners-Lee一直想解决的语义网的问题。
Trustno1说:
现在的媒体其实只负责表现,并不负责理解。
Trustno1说:
理解的工作实际上是靠客户人工干预的。
Trustno1说:
因此他们理想中的RESTful,其实需要语义网。
Trustno1说:
没有这个东西,实际应用中很多情况下只能是unrestful了。
dlee说:
我也感觉RESTful确实与语义网有些关系。
dlee说:
看了Fielding的发言,我现在理解microformat与REST的关系了。
dlee说:
microformat在hypertext中表达操作的语义,指导客户端执行操作,在各种状态间迁移。
dlee说:
不过Fielding提出REST还要在Berners-Lee提出语义网之前,语义网我记得是2001年提出的。
Trustno1说:
我觉得先后到不是重点。
dlee说:
我还是觉得对于人类用户高效率的实现方式,对于机器用户来说未必高效率。
dlee说:
所以Web应用和Web服务应该区别对待。
Trustno1说:
这些人的脑袋瓜和想法,是我们不能理解的,呵呵。
Trustno1说:
实际上我觉得挺难分开的,特别是Web服务的肥客户端化。
Trustno1说:
我觉得现在趋势是Web接口会跳出浏览器。因此针对机器和针对人,可能是相同的东西。
dlee说:
按照Fielding设想的理想做法,客户端需要具备更高的智能,这意味着更多的开发。
dlee说:
以前我理解URI就是服务器端的接口,URI应该仔细设计,URI后面才是实现。
dlee说:
现在Fielding告诉我们,URI的结构本身也是实现,不应该暴露给客户端。
dlee说:
客户端使用hypertext,遵循服务器的指导,以一种启发性的方式与服务器交互,而不是事先就了解服务器端所有的URI组成。
0 请登录后投票
   发表时间:2008-12-21   最后修改:2008-12-21
Trustno1说:
http://www.iteye.com/topic/295195?page=3
dlee说:
我觉得你说的是对的。
dlee说:
几乎所有的Ajax应用都不是REST,因为交换的数据不是hypertext。
dlee说:
有些Ajax应用交换的还是JS脚本。
dlee说:
参与这个讨论的很多人是专家级的开发者,有的人还写过书,但是仍然没有完全理解REST。
Trustno1说:
http://www.iteye.com/post/800391
dlee说:
我觉得RE和ST都是重要的
dlee说:
RE——表现,即media type的设计。
dlee说:
ST——通过跟踪超链接实现状态迁移。
Trustno1说:
不是,REST翻译过来不是表现状态转移.应该是基于表现的状态转移。
Trustno1说:
看到这个区别了么?
dlee说:
是具有表述性的状态迁移,representational是个形容词。
Trustno1说:
是的
Trustno1说:
SOAP,AJax都是状态转移,但是不是基于表述性的。
dlee说:
通过hypertext将可选的状态迁移展现给客户端,客户端来选择执行那个迁移。
dlee说:
这种交互模式与我们熟悉的基于接口的交互模式有很大差别。
dlee说:
但是具体的差别有哪些,这样做有哪些具体好处,我现在还没有完全想清楚。
dlee说:
Fielding所设想的解除客户端和服务器端的耦合是一个明显好处,这样服务器和客户端都可以更加自由地进化。
Trustno1说:
在他看来hypertext是协议的一部分,而不是表现。
dlee说:
Fielding说REST是为10年都不变的系统而设计的,但是这样的系统是否存在呢?
Trustno1说:
Browser
dlee说:
REST还有一个用途是用来指导Web基础协议的设计和开发,他希望各种Web协议都能够相互独立地进化。
dlee说:
例如,将来有一天甚至HTTP都没人用了,还可以继续用URI。
dlee说:
Fielding使用REST的架构约束来检测一种新的Web标准中是否存在与Web架构不兼容的成分。
dlee说:
但是很显然,并非所有的W3C工作组都理解了REST。例如SOAP最终还是被W3C接受了。如果Fielding参与这个工作做,SOAP本来可以做的更好。
dlee说:
SOAP以一种非常低效的方式来使用HTTP。
dlee说:
按照Fielding的描述,REST可以用来检测各种Web基础架构标准的相容性。如果将来出现大量互相冲突的Web标准,那么会给Web的健康发展带来灾难性后果。
Trustno1说:
我觉得这个想法有问题。标准不是定出来的。
dlee说:
Fielding希望总结出Web架构为何会在技术上取得巨大成功的原因。他探索后的结论就是REST。
dlee说:
如果Web基础架构不采用REST这样一种架构风格,而是采用类似CORBA之类的分布式对象架构风格,Web架构在技术上就不可能这么成功了。
dlee说:
HTML doesn't need type specifications. No RESTful architecture needs type specifications. Don't expect REST to act like some other architectural style. You don't get to decide what POST means — that is decided by the resource. Its purpose is supposed to be described in the same context in which you found the URI that you are posting to. Presumably, that context (a hypertext representation in some media type understood by your client) tells you or your agent what to expect from the POST using some combination of standard elements/relations and human-readable text. The HTTP response will tell you what happened as a result. In HTTP, a single resource-creating POST action will result in a 201 response with another hypertext representation (telling you what happened and what can be done next) or 204 response with the Location header field indicating the URI of the new resource.
dlee说:Fielding的这段话讲的也非常清楚,REST暴露给客户端的不是接口,而是通过hypertext描述的迁移选项,客户端软件选择这些迁移选项,然后迁移到服务器端的下一个状态。
dlee说:
我们绝大多数开发者都习惯于接口/类/实例这些东西,所以将URI理解为服务器暴露给客户端的接口。
dlee说:
但是这不是Fielding的真实想法。
Trustno1说:
客户端决定做什么,服务端决定怎么做。
dlee说:
没错
Trustno1说:
a hypertext representation in some media type understood by your client
我觉得他这个assumption太大了。现在几乎不可能完成的东西。
dlee说:
比如html就是一种media type,浏览器可以理解。
Trustno1说:
我觉得他搞错了,browser只能理解html的一小部分。
Trustno1说:
剩下的工作都是人在理解。
dlee说:
为某种特殊领域实现一种客户端,就需要设计一种新的media type。
dlee说:
感觉是有这样一个问题,我前面说,按照他的想法,客户端必须非常智能。
dlee说:
有一个叫做TheOtherMarcus也这样说
dlee说:
I agree that we won't get any further with this discussion. I just want to know if there are any known media types besides HTML that is suitable for REST interfaces. As I see it, HTML is not ideal for an API intended to be used by a machine. I would have to use an AI if I want it to be able to figure out that a submit button that yesterday was called "Send order" is the same as the button now called "Submit order". More formalization is needed.
Trustno1说:
我现在唯一能想到的是xml。
Trustno1说:
但是这个东西感觉就是脱了裤子放屁。
dlee说:
XML要带上超链接才行。
dlee说:
不管什么media type,都需要带上超链接。
Trustno1说:
除非URI很多,结构比较复杂。
Trustno1说:
否则实现一个client的成本就太高了。
dlee说:
是的,我觉得实现起来比较麻烦,可能我还没有完全想通。
0 请登录后投票
   发表时间:2008-12-21   最后修改:2008-12-21
ozzzzzz说:
我觉得目前应该把REST风格 跟REST技术框架加以区分。
ozzzzzz说:
我同意现在很多人都是在用REST风格 而不是在使用REST技术构架
dlee说:
Fielding说的那种理想做法,在实际实现上确实有很多困难。
ozzzzzz说:
大概他就是为这个发脾气。
他是觉得应该从风格到实现完全是REST的,讲纯洁。
dlee说:
他想收回使用REST的权利,呵呵。:)
ozzzzzz说:
嘿嘿,大概是这样。
dlee说:
不过我也很讨厌某人自称实现了REST API。
ozzzzzz说:
是的,其实说实现了REST风格的API就行了
dlee说:
When representations are provided in hypertext form with typed relations (using microformats of HTML, RDF in N3 or XML, or even SVG), then automated agents can traverse these applications almost as well as any human. There are plenty of examples in the linked data communities. More important to me is that the same design reflects good human-Web design, and thus we can design the protocols to support both machine and human-driven applications by following the same architectural style.
我觉得Fielding这段话说的最清楚了。
ozzzzzz说:
我觉得他有点太原教旨了。
dlee说:
设计标准的人可能都这样。
ozzzzzz说:
是啊 是啊。
dlee说:
《RESTful Web Services》里面有两章的例子就是这样做的,展示了这样做的可行性。
那个例子用html做数据格式,而不是我们常用的xml/json。
ozzzzzz说:
我觉得RESTful这个词跟REST还是应该有区别的。
现在的分歧大概就是在这个地方。
dlee说:
不过一年前我读这两章时没有充分理解这样做的好处。
dlee说:
其实世界上没有什么绝对,采用什么架构设计主要是权衡好处和代价的比例。
ozzzzzz说:
是啊 是啊。
dlee说:
However, I think most people just make the mistake that it should be simple to design simple things. In reality, the effort required to design something is inversely proportional to the simplicity of the result. As architectural styles go, REST is very simple.
REST is software design on the scale of decades: every detail is intended to promote software longevity and independent evolution. Many of the constraints are directly opposed to short-term efficiency. Unfortunately, people are fairly good at short-term design, and usually awful at long-term design. Most don’t think they need to design past the current release. There are more than a few software methodologies that portray any long-term thinking as wrong-headed, ivory tower design (which it can be if it isn’t motivated by real requirements).
ozzzzzz说:
其实这也是学者和技术人的差别。
dlee说:
Fielding说REST是为那种10年保持不变的软件设计的,可以保持服务器端对外的接口不变。
ozzzzzz说:
不可能存在这样的系统,除非是星际探测系统。
dlee说:
他还抨击某些方法论完全忽视长期设计,认为长期设计是脑子坏掉了,是象牙塔。
我怀疑他抨击的就是XP的“不为明天而设计”。
ozzzzzz说:
这个我不管,我主要是觉得不可能存在长期不变的设计,除非你放弃一定的环境适应性。
这个事情其实有点类似驳壳枪。
设计者认为应该有一种使用方式,但是使用者发明了另外一种使用方式。
如果设计者要是发脾气,不允许使用者按照他们的想法来,那么这个东西就没事情。
dlee说:
是的,Web架构的设计者在将自己的设计意图完全传达给使用者方面,显示出了很大的无奈。
ozzzzzz说:
如果他允许像中国人这样不瞄准而直接歪着甩着的射击,那么就能卖出去。
dlee说:
中国人总是喜欢另辟蹊径,喜欢循规蹈矩的可能是日本人。
ozzzzzz说:
其实最后驳壳枪的主要客户就是中国人。
国人没开创的天才,但是有使用中发现新用法的天才。
这个是中国人创新的特点。
而他不喜欢这个做法,我觉得至少中国人不会喜欢他这个说法。
dlee说:
在如何更有效地使用HTTP方面,还会出现很多创新。
Rails的用法只是第一种,还会有很多其他的用法。
ozzzzzz说:是的
而且未必就跟HTTP挂钩。
就那种REST风格的接口就该去好好研究研究。
dlee说:
http://www.infoq.com/cn/news/2008/09/jsr311-approved
问及JSR 311上的工作是否改变了他对Web和Web服务的观点时,Mark表示这印证了他的一个观点,即一个人“无需依赖更复杂的东西就可以用HTTP完成一件非常伟大的事”。Paul指出,REST发明者Roy Fielding的将稀疏位数组(sparse bit array)用于通知便是REST可在将来带来惊喜的一个例子。
ozzzzzz说:
这个东西我现在还看不出会有啥结果,毕竟jcp这块情况太不一般了。
dlee说:
我对这段话很感兴趣,你知道Mark就是SOAP规范的核心设计者。
从SOAP的思维方式转到REST是很困难的
ozzzzzz说:
你记得ajoo曾经写过一个东西,演示用简单的元素组合而成一个复杂的结果吗?
历来就有两种思维:一种是认为复杂是由于由于有太多的元素,另外一种是认为复杂是几种基本元素多种组合后的结果。
REST的思想大概就是后者。
dlee说:
老子的思想应该是后者。
ozzzzzz说:
是的,现代物理的主流思想也是这个。
dlee说:
中国人在简化方面很有天赋,善于透过现象看到本质。
ozzzzzz说:
是的,所以中国人在理论物理方面研究的不错。
dlee说:
Fielding说结果越简单的系统,设计起来越复杂。
ozzzzzz说:
这个个未必,而且还存在通过复杂的推导和思考得出简单设计的可能。
dlee说:
我很理解他的这种说法,例如memcache从外界来看是极其简单的,而其内部实现其实相当复杂。
普通的开发者只希望得到鱼,对于打渔的工具没有任何兴趣。
这应该是普遍规律了,呵呵。
ozzzzzz说:
但是这个事情也可以这么说,memcache这个简单设计造成了十分复杂的后果。
我觉得对钓鱼竿没兴趣是普遍中国目前开发者的通病。
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics