我正在编写一些 Azure Functions 脚本,用于从内部数据库读取和写入内部数据库,并将相关信息显示到网页中。
我注意到在加载调用 Azure Function 脚本的网页时,Web UI 速度极慢甚至超时。经过进一步调查,我意识到以下几点:
这是我的 Azure 函数脚本:
module.exports = function(context, req) {
context.log("Function Started: " + new Date());
// Import package
const sql = require('mssql');
var _ = require('underscore-node');
var moment = require('moment');
var Promise = require('promise');
// Create a configuration object for our Azure SQL connection parameters
var config = {
server: "***", // Use your SQL server name
database: "***", // Database to connect to
user: "***", // Use your username
password: "***", // Use your password
port: ***,
// Since we're on Windows Azure, we need to set the following options
options: {
encrypt: true
},
multipleStatements: true,
parseJSON: true
};
var flagDefinitionId = null;
if (req.query.Id == null || req.query.Id == "" || req.query.Id.length == 0) {
context.res = {
// status: 200, /* Defaults to 200 */
body: "No have flagDefinitionId "
};
context.done();
// return;
}
var listTicketsFlag = [];
flagDefinitionId = req.query.Id;
sql.close();
var DBSchema = "b8akjsms2_st.";
sql.connect(config).then(function() {
context.log("SQL Connected: " + new Date());
var getAllEventTicketGoToMarket = new Promise(function(resolve, reject) {
var queryGetEvent = ";WITH EventLog1 AS(" +
" SELECT MD1, max([DateTime]) as LTime from " + DBSchema + "EventLog" +
" where ([Event] = 'Ticket_Go_To_Market' OR [Event] = 'Acknowledge_Timeout')" +
" group by MD1 )" +
" SELECT * from ( SELECT EV.MD1 , EV.MD2," +
" (SELECT COUNT(*) from " + DBSchema + "EventLog where MD1 = EV.MD1 and [Event] = 'Market_Ticket_Clear') as TotalClear" +
" FROM " + DBSchema + "[Ticket] T" +
" JOIN (SELECT E.* from " + DBSchema + "EventLog E join EventLog1 E1 on E.MD1 = E1.MD1 and E.[DateTime] = E1.LTime) EV ON T.Id = EV.MD1" +
" WHERE T.IsInMarket = 1 and EV.MD2 <> ''" +
" AND T.Id NOT IN (Select TicketId from " + DBSchema + "TicketFlag where FlagDefinitionId = " + flagDefinitionId + ")" +
" ) R where R.TotalClear > 0";
context.log("get event log - Ticket_Go_To_Market" + queryGetEvent);
new sql.Request().query(queryGetEvent, (err, result) => {
context.log("this is --------> EventLog " + result.recordset.length);
resolve(result.recordset);
});
});
Promise.all([getAllEventTicketGoToMarket]).then(function(values) {
var ticketGoToMarket = values[0];
context.log("this is --------> values: " + values[0].length + " ==+++++==== " + JSON.stringify(values[0], null, 2));
if (ticketGoToMarket.length != 0) {
listTicketsFlag = _.filter(ticketGoToMarket, function(num) {
var countSP = num.MD2.split(',');
// context.log("countSP =====> " + countSP.length + "num.TotalClear ==>" + num.TotalClear)
if (num.TotalClear > countSP.length) {
return num.MD1;
}
});
// context.log("listTicketsFlag =====> " + JSON.stringify(listTicketsFlag, null, 2));
}
insertTicketFlag();
});
function insertTicketFlag() {
context.log("this is ----- ===> Insert: " + listTicketsFlag);
// insert
var insertTicketFlagPromise = new Promise(function(resolve, reject) {
context.log("listTicketFlag ----- ===> " + listTicketsFlag.length);
if (listTicketsFlag.length == 0) {
context.log(" -------------------- No have ticket need FLAG");
resolve();
} else {
// insert new data to TicketFlag FlagTickets
var listTicketInsert = ""; //convertArrayToSQLString(listTicketsFlag, true, flagDefinitionId);
var len = listTicketsFlag.length - 1;
for (var j = 0; j <= len; j++) {
listTicketInsert += '(\'' + listTicketsFlag[j] + '\', \'' + flagDefinitionId + '\')';
if (j != len) {
listTicketInsert += ",";
}
}
context.log("HERE : " + listTicketInsert);
var insertQuery = 'Insert into ' + DBSchema + '[TicketFlag] (TicketId, FlagDefinitionId) values ' + listTicketInsert + '';
context.log("this is --------> InsertQuery" + insertQuery);
// return;
context.log("read data of FlagRule");
new sql.Request().query(insertQuery, (err, result) => {
context.log("this is --------> insertQuery");
resolve(result);
});
}
});
Promise.all([insertTicketFlagPromise]).then(function(values) {
context.log("DONE ALL");
sql.close();
context.done();
})
}
}).catch(function(err) {
console.log(err);
context.done();
});
};
如何解决这个缓慢的问题?
最佳答案
我们在 node.js 函数中也注意到了这一点。经过大量研究和测试后,我们发现:
功能应用在闲置五分钟后进入“冷”状态。当它们从冷状态中出来时,您可以预计最多 10 秒的时间似乎是将节点 JavaScript 编译/转换为 .Net 代码,以便它们可以在更大的函数引擎中本地运行。请注意,我在上面说的是“Function App”,而不仅仅是“Function”
即使它处于“热”状态(即 < 5="">
造成这种性能下降的最大罪魁祸首是包含许多小文件的较大外部库。
那么你能做些什么来缓解这种情况呢?以下是我们按复杂程度排序所做的工作:
设置一个在不到 5 分钟的时间范围内执行的计时器函数。我们每四分钟运行一个简单的计时器,持续时间在 0 毫秒到 10 毫秒之间,您可以计算一下,看看这是让您的 Function App 保持热状态的一种非常便宜的方法。
使用 Functions-Pack包以将所有外部库合并到一个文件中。当函数被重新编译或转译或发生任何魔法时,它会变得更快,因为它不必查找数十或数百个文件。
使用 REST API 而不是 SDK 意味着需要零个外部库。最大的问题是生成授权 header ,Azure 中没有关于如何形成 Auth header 的标准,而且在大多数情况下,他们的文档的这一部分几乎没有涉及,尤其是 node.js。我考虑过为生成各种 Azure Auth token 的 node.js 代码创建一个 github 存储库。
将您的函数移植到 C#(是的,我对这个选项也不满意 - 我想为我们的产品提供一个全 JavaScript/TypeScript 平台)。尽管如此,删除交叉编译/转译/任何东西,它应该会大大加快速度。我现在正在将我们最复杂的函数之一移植到 C# 以进一步测试这一理论。
转向应用服务计划似乎有悖于 Azure Functions 的值(value)。我想要 Microsoft 处理的无限规模和每次执行成本。应用服务计划迫使我重新考虑 CPU 和内存以及应用容量。
这是一个 MSDN forums thread我发布的请求对我们的问题的反馈。
关于javascript - Azure Functions 执行速度极慢且不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44878247/
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul
我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试
如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否
//1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json
我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions
两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio
我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption
我写了一个非常简单的rake任务来尝试找到这个问题的根源。namespace:foodotaskbar::environmentdoputs'RUNNING'endend当在控制台中执行rakefoo:bar时,输出为:RUNNINGRUNNING当我执行任何rake任务时会发生这种情况。有没有人遇到过这样的事情?编辑上面的rake任务就是写在那个.rake文件中的所有内容。这是当前正在使用的Rakefile。requireFile.expand_path('../config/application',__FILE__)OurApp::Application.load_tasks这里
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的