2017-10-30 9 views
2

외부 서버가 ColdFusion 서버에 JSON 데이터를 게시 할 수있는 API를 구축했습니다. 그런 다음 ColdFusion 서버는이 데이터를 처리하고 (배열을 반복하고 데이터베이스에 데이터를 삽입하는 등) 모든 것이 잘 수행되었는지 외부 서버에 응답합니다.CFTHREAD를 사용하여 외부 HTTP 요청을 처리하고 비동기 응답을 반환합니다.

하지만 CFTHREAD에서 프로세스를 실행하려면 부하가 더 많아 져야합니다. 이런 종류의 비동기 작업을 수행하고 요청을 한 서버에 계속 응답하려면 어떻게해야합니까?

이벤트 게이트웨이를 살펴 보았지만 갈 길이 멀지 않았습니다. 외부 서버가 "아직 끝났습니까?", "아직 끝났습니까?"등의 반복 호출을 허용하는 것에 대해서도 생각했지만 궁극적 인 해결책은 아닙니다.

ColdFusion 서버를 우리가 원하는 방식으로 호출 할 수 있도록 외부 서버를 관리하는 사람을 확보 할 수 있으므로 최소한 나는 그것에 구속되지 않습니다.

: (다시의 단순화 된 버전) 호출을 처리하는 내 udf.cfm을

<cftry> 
    <cfinclude template="udf.cfm" /> 
    <cfset _run()> 
    <cfcatch type="any"> 
    <cfcontent type="application/json; charset=utf-8" reset="yes"> 
    <cfoutput>{"success":0,"message":"#cfcatch.Message# - #cfcatch.Detail#"}</cfoutput> 
    </cfcatch> 
</cftry> 

그리고 여기에 있습니다 : 여기

전화를 받아 내 index.cfm의 단순화 된 버전입니다
<cffunction name="_run" output="yes" returntype="void"> 
    <cfset local.success=true> 
    <cfset local.msg=""> 
    <cftry> 
     <!---get request data---> 
     <cfset local.requestData=GetHttpRequestData()> 
     <!---validate post---> 
     <cfif NOT StructKeyExists(local.requestData,"headers")> 
      <!---headers is missing---> 
      <cfset _returnJson(msg="Headers is missing")> 
     </cfif> 
     <!---and a bunch of other validations...---> 
     <!---get body---> 
     <cfset local.isBinaryBody=IsBinary(local.requestData.content)> 
     <cfset local.bodyAsString=local.isBinaryBody ? ToString(local.requestData.content) : local.requestData.content> 
     <cfset local.body=DeserializeJson(local.bodyAsString)> 
     <cftransaction action="begin"> 
      <cftry> 
       <!---prepare for database inserts by cleansing tables etc---> 
       <!---loop data array, can be tens of thousands of rows---> 
       <cfloop array="#local.body.items#" index="local.item"> 
        <!---do some inserts/updates into MySQL Database---> 
       </cfloop> 
       <cfcatch type="any"> 
        <!---error---> 
        <cfset local.msg=_parseCatchError(catch=cfcatch)> 
        <cfset local.success=false> 
       </cfcatch> 
      </cftry> 
      <!---rollback or commit transaction depending on success flag---> 
      <cftransaction action="#local.success ? 'commit' : 'rollback'#" /> 
     </cftransaction> 
     <cfcatch type="any"> 
      <!---error---> 
      <cfset local.msg=_parseCatchError(catch=cfcatch)> 
      <cfset local.success=false> 
     </cfcatch> 
    </cftry> 
    <!---return JSON---> 
    <cfset _returnJson(msg=local.msg,success=local.success)> 
</cffunction> 
<cffunction name="_returnJson" output="yes" returntype="void"> 
    <cfargument name="msg" type="string" required="yes"> 
    <cfargument name="success" type="boolean" default="false"> 
    <cfscript>getPageContext().getOut().clearBuffer();</cfscript> 
    <cfcontent type="application/json; charset=utf-8" reset="yes"> 
    <cfoutput>#SerializeJson(arguments)#</cfoutput> 
    <cfabort> 
</cffunction> 
<cffunction name="_parseCatchError" output="no" returntype="string"> 
    <cfargument name="catch" type="any" required="yes"> 
    <cfset local.error="#Trim(arguments.catch.message)# - #Trim(arguments.catch.detail)#"> 
    <cfif StructKeyExists(arguments.catch,"tagContext")> 
     <!---grab line info---> 
     <cfset local.tagContext=arguments.catch.tagContext[1]> 
     <cfset local.error=local.error&" - #Trim(local.tagContext.template)# line #Trim(local.tagContext.line)#"> 
    </cfif> 
    <cfreturn local.error> 
</cffunction> 
+0

많은 활동이 예상되는 경우 ''은 해결책보다 문제가 더 많습니다. 동시 스레드 수가 너무 많으면 문제가 발생하여 CF Monitor에서 해당 상황을 처리 할 수 ​​없습니다. –

+0

좋아, 아마 내가 요청할 수있는 가장 효과적인 방법으로 내 프로세스를 실행하는 데 집중한다. 또한 너무 많은 양의 데이터를 수신하는 것을 허용하지 않고 하나의 요청에서 객체 배열이 아닌 단일 요청으로 단일 객체를 처리하도록 분할합니다. –

+0

나는 그 길을 가기 전에 약간의 코드를 볼 필요가있다. 번들링이 올바른 접근 방식이었던 일을했습니다. DB 서버는 CF보다 확장 성이 좋습니다. 그러나 다시,이 모든 것은 너무 많은 추측입니다. –

답변

1

발신자가 제공 한 콜백 만 있으면됩니다.

  1. 하는 것은 기본 요청하기
  2. 스레드를 종료 처리되고 그 요청을 호출자에게
  3. 반환 정보를 가입하지 않는 코드가 완료되면
  4. 시작 스레드를 칠하는 외부 URL을 포함하여, 요청을 수락 계속 실행 중이고 끝에서 성공 또는 실패에 대한 추가 정보를 제공하는 콜백 URL을 누르십시오.

여기에는 몇 가지 다른 옵션도 있습니다. 우선 큐의 요청에 필요한 데이터를 수락하고 기록한 다음 나중에 조회 할 수 있습니다. 또한 명시된대로 호출자가 진행 상태를 확인하기위한 상태 끝점을 제공 할 수 있습니다.

+0

당신이 옳다고 생각합니다. 두 URL이 모두 웹 서버 인 경우 제공된 URL에 콜백을 사용하면 내 원래 질문에 가장 적합한 솔루션이 될 것입니다. 제 경우에는 호출자가 웹 서버가 아닙니다. 그것은 여전히 ​​그 서버에 콜백을 만들 수 있지만 내 지식을 넘어. –

1

coldfusion의 스레드는 서버 버전에 의해 제한됩니다. 표준 버전이 최대 10 개의 스레드를 지원하고 다른 스레드는 대기열에 들어 있다고 생각합니다. 스레드에 "콜백"을 제공하면 작업이 수행됩니다. 또한 SQL 덤프가 완료된 후 예약 된 작업을 활용할 수 있습니다.