【问题标题】:cfhttp in cfloop limit? use cfthreadcfloop 中的 cfhttp 限制?使用 cfthread
【发布时间】:2013-06-24 20:05:20
【问题描述】:

我目前正在尝试开发一个 API,而我现在所处的阶段是用完整的数据集(ID、名字、姓氏、出生日期等)填充一个表。

我写这篇文章的方式是使用一个从 1 到 500,000 的 cfloop(因为我不知道 ID 的范围是什么范围),并且在每个 cfloop 中我调用一个函数来向服务器并检索内容。

然后我对返回的 JSON 进行反序列化,调用一个函数来查询我的表以查看当前项目 ID 是否已经存在,如果不存在,则调用一个函数来插入记录。

但是 cfloop 似乎在 300 请求标记附近停止,所以我想知道是否有更好的方法来做我正在做的事情?也许通过使用我从未有过使用经验的 CFTHREAD 标签。

这部分代码如下:

<cfset Variables.url = "someurl.html" />
<cfloop from=100000 to=500000 index="itemNo">
    <cfset Variables.itemID = itemNo />
    <cfset getItemData = Application.cfcs.Person.getPersonData(Variables.url,Variables.itemID) />
    <cfif StructKeyExists(Variables,"getPersonData.FileContent")>
        <cfset Variables.getPersonData = DeserializeJSON(getPersonData.FileContent)>
        <cfscript>
            // CHECK IF PERSON ALREADY IN DATABASE
            Variables.getPerson = Application.cfcs.Person.getPersonRecord(Variables.itemID);
            // INSERT ITEM IN TO TABLE
            Variables.DOB = CreateDate(Year(Variables.getPersonData.Item.DateOfBirth.Year),Month(Variables.getPersonData.Item.DateOfBirth.Month),Day(Variables.getPersonData.Item.DateOfBirth.Day));
            Variables.insPerson = Application.cfcs.Person.insPerson(Variables.getPersonData.personID,Variables.getPersonData.Item.FirstName,Variables.getPersonData.Item.LastName,Variables.getPersonData.Item.CommonName,Variables.DOB);   
        </cfscript>
    </cfif>
</cfloop>

【问题讨论】:

  • "cfloop 似乎在 300 请求标记附近停止" - 它是否给出错误消息?日志中有任何内容吗?
  • cfcs.Person.getPersonData() 从哪里得到它的数据?
  • 首先,您需要查看 API 是什么。 en.wikipedia.org/wiki/Application_programming_interface -- 您似乎所做的只是对可能存在或不存在的数据进行大量调用,并尝试将其加载到数据库中。这并不比屏幕抓取好。放下 ColdFusion 锤子,想想像批量加载这样的优雅解决方案。
  • 我同意@Claude 的观点,如果有任何方法可以避免发出 50 万个 HTTP 请求,那么就采用这种方法。如果真的没有办法解决它,这里有一些提示:你的进程可能/将会崩溃,所以你必须保持你身边的状态来跟踪你有什么和没有尝试过。如果您关心此进程的运行速度,请不要使用 CFHTTP,它在高流量时性能不佳,并且由于您已经看到的内存问题,它无法运行。而是使用支持 keep-alives 的 Java HTTP 库之一:hc.apache.org/httpcomponents-client-ga/index.html

标签: multithreading coldfusion cfhttp cfloop cfthread


【解决方案1】:

是的,这是可能的。您需要拆分通话。创建一个简单的 htlm 页面,该页面在 javascript 中生成 xmlhttprequest。我没有测试下面的例子,但它应该可以工作。

<script>
var itemNo= 1;
function download()
{
 var xhr = new XMLHttpRequest();
 xhr.open("GET", "getdata.cfm?itemNo="+itemNo, true);
 xhr.onload = function (e) {
  if (xhr.readyState === 4) {
   if (xhr.status === 200) 
   {
     itemNo++;
     if(itemNo<=500000) download();
   }
   else 
   {
     itemNo++;
    // Error handling
   }
  }
 };
 xhr.onerror = function (e) {
      itemNo++;
 // Error handling
 };
 xhr.send(null);
}
</script>

在请求的页面上调用发出 cfhttp 请求的对象。

<!--- getdata.cfm --->
<cfset Variables.url = "someurl.html" />
<cfset Variables.itemID = itemNo />
<cfset getItemData = Application.cfcs.Person.getPersonData(Variables.url,Variables.itemID) />
<cfif StructKeyExists(Variables,"getPersonData.FileContent")>
    <cfset Variables.getPersonData = DeserializeJSON(getPersonData.FileContent)>
    <cfscript>
        // CHECK IF PERSON ALREADY IN DATABASE
        Variables.getPerson = Application.cfcs.Person.getPersonRecord(Variables.itemID);
        // INSERT ITEM IN TO TABLE
        Variables.DOB = CreateDate(Year(Variables.getPersonData.Item.DateOfBirth.Year),Month(Variables.getPersonData.Item.DateOfBirth.Month),Day(Variables.getPersonData.Item.DateOfBirth.Day));
        Variables.insPerson = Application.cfcs.Person.insPerson(Variables.getPersonData.personID,Variables.getPersonData.Item.FirstName,Variables.getPersonData.Item.LastName,Variables.getPersonData.Item.CommonName,Variables.DOB);   
    </cfscript>
</cfif>

在请求的页面上,您可以使用 cfhtread 同时发出多个 http 请求。您可以在此处查看有关将 cfthread 与 cfhttp 一起使用的更多信息 http://www.bennadel.com/blog/749-Learning-ColdFusion-8-CFThread-Part-II-Parallel-Threads.htm

【讨论】:

  • 那么包含下载功能的html页面是否应该向第三方网站发出请求?
  • 调用的getdata.cfm页面不应该包含cfhttp函数。这确保了用于创建 http 请求的内存在页面完成处理后被释放。 (顺便说一句,我假设实际的 cfhttp 请求位于 Application.cfcs.Person.getPersonData 组件内。在旁注中,建议创建一个简单的容器,如 来跟踪哪个id 最后一次调用 document.getElementById("counter").innerHTML = rownr ;
  • 是的,没错。因此,在 getdata.cfm 页面中,我在包含脚本的 html 页面上执行了一个 cfinclude 模板,并且在我在一组脚本标签中调用下载函数之后,在我设置 itemID 之前直接执行?
  • 没有您在浏览器中调用的 html 页面。顺序如下。打开html页面。调用下载函数。下载函数使用名为 itemNo 的变量向 getdata.cfm 发出 http 请求。在 getdata.cfm 页面上调用该组件。在 getdata.cfm 页面上执行所有代码后,它将页面内容 (html) 返回到下载函数。然后下载函数将 itemNo 变量增加 1 并再次调用 getdata.cfm 页面。此过程一直持续到达到 rownr 500001。
  • 对原来的答案做了一些小改动,使其更容易理解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-09
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2011-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多