Почему это приложение ColdFusion 8 вызывает резкий скачок процессора?
Спасибо, что нашли время, чтобы посмотреть на этот вопрос.... терпеть меня....
На днях один из наших веб-серверов прекратил обслуживание веб-страниц. Веб-сервер - это физический сервер, работающий под управлением Windows Server 2003 R2 Standard Edition с пакетом обновления 2 (SP2) и IIS 6. Он работает под управлением ColdFusion 8.0.1 Standard с Java 1.6.0_24. Этот сервер имеет 3 общедоступных веб-сайта, которые действительно не пользуются большим спросом. Страницы на всех трех веб-сайтах истекали или возвращали 500 ошибок.
Когда я вошел на сервер, чтобы увидеть, в чем проблема, я ожидал увидеть службу JRUN, использующую тонну памяти. Память была в порядке, но я заметил, что процессор работает на уровне или около 100%. Около 50% использовалось JRUN, а остальные 50% - процессом резервного копирования, который я убил. Но затем JRUN быстро съел процессор и использовал почти 100%.
Я просмотрел журналы ColdFusion и заметил несколько ошибок пространства кучи Java.
Я просмотрел журналы IIS и заметил, что к приложению было множество запросов, которые позволяют одному из наших клиентов загружать несколько файлов изображений для своих продуктов с помощью uploadify. Приложение написано на ColdFusion и использует jQuery для вызова веб-службы, которая обрабатывает загрузку и изменяет размер загруженных изображений, используя <CFIMAGE>
,
После просмотра этой информации в журналах, я понял, что какая-то часть этого приложения должна быть виновником.
Я просто не могу найти, что именно вызвало ошибки пространства кучи Java и скачок процессора. Какие-нибудь мысли?
WebCervice CFC метод:
<cffunction
name="uploadFile"
access="remote"
returntype="Struct"
output="false"
returnformat="JSON">
<cfargument name="FileName" type="String" default="" />
<cfargument name="FileData" type="String" default="" />
<cfscript>
var _response = NewAPIResponse();
var _tempFilePath = APPLICATION.TempDir & "\" & ARGUMENTS.FileName;
var _qItem = QueryNew("");
var _product = CreateObject("component", "cfc.Product");
var _result = {};
var _sku = "";
/*
Each file must be named [Part Number].[file extension], so, \
parse the file name to get everything before the file extension
*/
_sku =
Trim(
REQUEST.UDFLib.File.getFileNameWithoutExtension(
ARGUMENTS.FileName
)
);
</cfscript>
<cfif Len(_sku) GT 20>
<cfthrow
message="#ARGUMENTS.FileName#: File Name does not correspond to an existing Part Number." />
</cfif>
<cfset _qItem = _product.readSKU(_sku) />
<cfif NOT _qItem.RECORDCOUNT>
<cfthrow
message="#ARGUMENTS.FileName#: File Name does not correspond to an existing Part Number." />
</cfif>
<cfscript>
FileCopy(ARGUMENTS.FileData, _tempFilePath);
_aMessages =
_product.setId(
_qItem.SKU
).updateThumbnailImages(uploadFilePath = _tempFilePath);
</cfscript>
<cfif ArrayLen(_aMessages)>
<cfthrow
message="#ARGUMENTS.FileName#: #_aMessages[1].getText()#" />
</cfif>
<cfscript>
_result["SKU"] = _product.getSKU();
_result["SMALLIMAGESRC"] = _product.getSmallImageSrc();
_result["LARGEIMAGESRC"] = _product.getLargeImageSrc();
ArrayAppend(_response.data, _result);
</cfscript>
<cfreturn _response />
</cffunction>
Функция изменения размера изображения:
<cffunction name="updateThumbnailImages" returntype="Array" output="false">
<cfargument name="uploadFilePath" type="String" required="true" />
<cfset var _image = {} />
<cfif FileExists(ARGUMENTS.uploadFilePath)>
<cfset _image =
REQUEST.UDFLib.Image.scale(
imagePath = ARGUMENTS.uploadFilePath,
maxHeight = 500,
maxWidth = 700
) />
<cfimage
action="write"
source="#_image#"
overwrite="true"
destination="#getLargeImagePath()#" />
<cfset _image =
REQUEST.UDFLib.Image.scale(
imagePath = ARGUMENTS.uploadFilePath,
maxHeight = 300,
maxWidth = 300
) />
<cfimage
action="write"
source="#_image#"
overwrite="true"
destination="#getMediumImagePath()#" />
<cfset _image =
REQUEST.UDFLib.Image.scale(
imagePath = ARGUMENTS.uploadFilePath,
maxHeight = 50,
maxWidth = 50
) />
<cfimage
action="write"
source="#_image#"
overwrite="true"
destination="#getSmallImagePath()#" />
</cfif>
</cffunction>
UDFs масштабирования изображения:
<cffunction name="getDimensionsToEnlarge" returntype="Struct" output="false">
<cfargument name="imageWidth" type="Numeric" required="true" />
<cfargument name="imageHeight" type="Numeric" required="true" />
<cfargument name="minWidth" type="Numeric" required="true" />
<cfargument name="minHeight" type="Numeric" required="true" />
<cfscript>
var dimensions = {
width = -1,
height = -1
};
if (
ARGUMENTS.minHeight > 0
&& ARGUMENTS.minWidth > 0
&& imageHeight < ARGUMENTS.minHeight
&& imageWidth < ARGUMENTS.minWidth
) {
dimensions.width = ARGUMENTS.minWidth;
dimensions.height = ARGUMENTS.minHeight;
}
return dimensions;
</cfscript>
</cffunction>
<cffunction name="getDimensionsToShrink" returntype="Struct" output="false">
<cfargument name="imageWidth" type="Numeric" required="true" />
<cfargument name="imageHeight" type="Numeric" required="true" />
<cfargument name="maxWidth" type="Numeric" required="true" />
<cfargument name="maxHeight" type="Numeric" required="true" />
<cfscript>
var dimensions = {
width = -1,
height = -1
};
if (
ARGUMENTS.maxHeight > 0
&& ARGUMENTS.maxWidth > 0
&& (
imageHeight > ARGUMENTS.maxHeight
|| imageWidth > ARGUMENTS.maxWidth
)
) {
dimensions.width = ARGUMENTS.maxWidth;
dimensions.height = ARGUMENTS.maxHeight;
}
return dimensions;
</cfscript>
</cffunction>
<cffunction name="getDimensionsToFit" returntype="Struct" output="false">
<cfargument name="imageWidth" type="Numeric" required="true" />
<cfargument name="imageHeight" type="Numeric" required="true" />
<cfargument name="minWidth" type="Numeric" required="true" />
<cfargument name="minHeight" type="Numeric" required="true" />
<cfargument name="maxWidth" type="Numeric" required="true" />
<cfargument name="maxHeight" type="Numeric" required="true" />
<cfscript>
var dimensions = {
width = -1,
height = -1
};
dimensions =
getDimensionsToEnlarge(
imageHeight = ARGUMENTS.imageHeight,
imageWidth = ARGUMENTS.imageWidth,
minWidth = ARGUMENTS.minWidth,
minHeight = ARGUMENTS.minHeight
);
if (dimensions.width < 0 && dimensions.height < 0)
dimensions =
getDimensionsToShrink(
imageHeight = ARGUMENTS.imageHeight,
imageWidth = ARGUMENTS.imageWidth,
maxWidth = ARGUMENTS.maxWidth,
maxHeight = ARGUMENTS.maxHeight
);
return dimensions;
</cfscript>
</cffunction>
<cffunction name="scale" returntype="Any" output="false">
<cfargument name="imagePath" type="String" required="true" />
<cfargument name="action" type="String" default="fit" hint="shrink, enlarge, or fit"/>
<cfargument name="minWidth" type="Numeric" default="-1" />
<cfargument name="minHeight" type="Numeric" default="-1" />
<cfargument name="maxWidth" type="Numeric" default="-1" />
<cfargument name="maxHeight" type="Numeric" default="-1" />
<cfscript>
var scaledDimensions = {
width = -1,
height = -1
};
var scaledImage = ImageNew();
scaledImage = ImageNew(ARGUMENTS.imagePath);
switch (ARGUMENTS.action) {
case "shrink":
scaledDimensions =
getDimensionsToShrink(
imageHeight = scaledImage.getHeight(),
imageWidth = scaledImage.getWidth(),
maxWidth = ARGUMENTS.maxWidth,
maxHeight = ARGUMENTS.maxHeight
);
break;
case "enlarge":
scaledDimensions =
getDimensionsToEnlarge(
imageHeight = scaledImage.getHeight(),
imageWidth = scaledImage.getWidth(),
minWidth = ARGUMENTS.minWidth,
minHeight = ARGUMENTS.minHeight
);
break;
default:
scaledDimensions =
getDimensionsToFit(
imageHeight = scaledImage.getHeight(),
imageWidth = scaledImage.getWidth(),
minWidth = ARGUMENTS.minWidth,
minHeight = ARGUMENTS.minHeight,
maxWidth = ARGUMENTS.maxWidth,
maxHeight = ARGUMENTS.maxHeight
);
break;
}
if (scaledDimensions.width > 0 && scaledDimensions.height > 0) {
// This helps the image quality
ImageSetAntialiasing(scaledImage, "on");
ImageScaleToFit(
scaledImage,
scaledDimensions.width,
scaledDimensions.height
);
}
return scaledImage;
</cfscript>
</cffunction>
1 ответ
Ниже приведен пример кода, о котором я говорил в разделе комментариев. Это повысило надежность для нас, но при экстремальной нагрузке мы обнаружили, что проблема все еще возникает, поэтому мы перешли на Java 1.7. Однако у 1.7 были свои проблемы, поскольку производительность резко упала, как показано здесь. Надеюсь, поможет.
<cffunction name="init" access="private" output="false" returntype="void">
<cfset variables.instance = StructNew() />
<!--- create object and set to variables.instance --->
<cfset setProductObject()>
</cffunction>
<cffunction name="setProductObject" access="private" returntype="void" output="false">
<!--- create object once and set it to the variables.instance scope --->
<cfset var product = createObject("component","cfc.Product")>
<cfset variables.instance.product = product/>
<cfset product = javacast('null', '')>
</cffunction>
<cffunction name="getProductObject" access="private" returntype="cfc.Product" output="false">
<!--- instead of creating object each time use the one already in memory and duplicate it --->
<cfset var productObj = duplicate(variables.instance.product)>
<cfreturn productObj />
</cffunction>
<cffunction name="uploadFile" access="remote" returntype="struct" returnformat="JSON" output="false">
<cfargument name="FileName" type="String" default="" />
<cfargument name="FileData" type="String" default="" />
<cfscript>
var _response = NewAPIResponse();
var _tempFilePath = APPLICATION.TempDir & "\" & ARGUMENTS.FileName;
var _qItem = QueryNew("");
var _product = "";
var _result = {};
var _sku = "";
//check init() function has been run if not run it
if NOT structKeyExists(variables,'instance') {
init();
}
_product = getProductObject();
/*
Each file must be named [Part Number].[file extension], so, \
parse the file name to get everything before the file extension
*/
_sku =
Trim(
REQUEST.UDFLib.File.getFileNameWithoutExtension(
ARGUMENTS.FileName
)
);
</cfscript>
<cfif Len(_sku) GT 20>
<cfthrow
message="#ARGUMENTS.FileName#: File Name does not correspond to an existing Part Number." />
</cfif>
<cfset _qItem = _product.readSKU(_sku) />
<cfif NOT _qItem.RECORDCOUNT>
<cfthrow
message="#ARGUMENTS.FileName#: File Name does not correspond to an existing Part Number." />
</cfif>
<cfscript>
FileCopy(ARGUMENTS.FileData, _tempFilePath);
_aMessages =
_product.setId(
_qItem.SKU
).updateThumbnailImages(uploadFilePath = _tempFilePath);
</cfscript>
<cfif ArrayLen(_aMessages)>
<cfthrow
message="#ARGUMENTS.FileName#: #_aMessages[1].getText()#" />
</cfif>
<cfscript>
_result["SKU"] = _product.getSKU();
_result["SMALLIMAGESRC"] = _product.getSmallImageSrc();
_result["LARGEIMAGESRC"] = _product.getLargeImageSrc();
ArrayAppend(_response.data, _result);
</cfscript>
<cfreturn _response />
</cffunction>