【发布时间】:2016-03-09 13:38:05
【问题描述】:
我刚刚开始使用 POC 来实现 SignalR 2 + SQL Dependency 以创建实时仪表板(尽管我正在使用的 POC 与项目要求略有不同)。
此 POC 测量每个逻辑核心的服务器 CPU 使用率。
POC 测试页面预览
我已经成功实现了依赖关系预览,并且我可以在测试 html 页面上看到实时预览,即在我的本地 SQL DB 中进行任何更改的那一刻。
这些更改由一个独立的命令行应用程序通过一个简单的更新查询进行更新。而且我的数据库也有一个 4 列的简单单行结构(至少现在是这样)。
问题是 CPU 使用率在通过“dependency_OnChange”事件触发 20-30 次更改后达到 95-100%(即使仅打开 Visual Studio 和单个浏览器并且命令行应用程序运行以进行更新) em>。
余震预览
我在 Windows 8.1 和 IIS 8.5 中使用 Visual Studio(2015 社区版)。 POC 页面以“http://localhost:55725/index.html”运行,尚未托管在 IIS 中。
我尝试了这里描述的解决方案:https://github.com/SignalR/SignalR/wiki/Performance
并且还查看了此线程以寻求解决方案: SignalR & SqlDependency Query performance
我还不知道,还没有花哨的东西(如果性能很好,将在 Asp.Net MVC 下实现),但即使是最简单的愚蠢的东西也没有运气。
Global.asax 的代码
protected void Application_Start(object sender, EventArgs e)
{
SqlDependency.Start(connString);
}
protected void Application_End(object sender, EventArgs e)
{
SqlDependency.Stop(connString);
}
Startup.cs 代码
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
app.MapSignalR();
}
}
Hub 类代码
public class AppHub : Hub
{
private static string conString = ConfigurationManager.ConnectionStrings["DBConn"].ToString();
[HubMethodName("sendMessages")]
public static void SendMessages()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<AppHub>();
context.Clients.All.updateMessages();
}
}
测试html页面的代码(index.html):
<head>
<script src="http://bernii.github.io/gauge.js/dist/gauge.min.js"></script>
<script src="/Scripts/jquery-1.10.2.min.js"></script>
<script src="/Scripts/jquery.signalR-2.1.2.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// Declare a proxy to reference the hub.
var notifications = $.connection.appHub;
//debugger;
// Create a function that the hub can call to broadcast messages.
notifications.client.updateMessages = function () {
//alert("connection updated.")
getAllMessages()
};
// Start the connection.
$.connection.hub.start().done(function () {
//alert("connection started")
getAllMessages();
}).fail(function (e) {
alert(e);
});
});
function getAllMessages() {
var tbl = $('#messagesTable');
$.ajax({
url: '/appdata.ashx',
contentType: 'application/html ; charset:utf-8',
type: 'GET',
dataType: 'json'
}).success(function (result) {
// tbl.empty().append(result);
DrawGauges(result);
}).error(function () {
});
}
function DrawGauges(jsondata) {
var opts = {
lines: 12, // The number of lines to draw
angle: 0.15, // The length of each line
lineWidth: 0.44, // The line thickness
pointer: {
length: 0.9, // The radius of the inner circle
strokeWidth: 0.035, // The rotation offset
color: '#000000' // Fill color
},
limitMax: 'false', // If true, the pointer will not go past the end of the gauge
colorStart: '#9BF0E9', // Colors
colorStop: '#61D2D6', // just experiment with them
strokeColor: '#E0E0E0', // to see which ones work best for you
generateGradient: true
};
for (var i = 1; i < 5; i++) {
var target = document.getElementById('canvas' + i); // your canvas element
var textlabel = document.getElementById('text' + i); // your canvas element
var gauge = new Gauge(target).setOptions(opts); // create sexy gauge!
gauge.maxValue = 100; // set max gauge value
gauge.animationSpeed = 32; // set animation speed (32 is default value)
gauge.set(jsondata[0]["Core" + i + "Usage"]); // set actual value
textlabel.innerText = jsondata[0]["Core" + i + "Usage"];
}
}
</script>
<style>
h4 {
text-align: center;
width: 100%;
font-family:'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
font-size:27pt;
}
span{
position:relative;
left:-12%;
top:-75px;
font-family:'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
font-size:14pt;
font-weight:bold;
color:#000000;
}
</style>
</head>
<body>
<div class="row">
<div class="col-md-12">
<h4>CPU Usage Per Core</h4>
<div id="realtimepreview">
<canvas width="300" height="120" id="canvas1"></canvas><span id="text1"></span>
<canvas width="300" height="120" id="canvas2"></canvas><span id="text2"></span>
<canvas width="300" height="120" id="canvas3"></canvas><span id="text3"></span>
<canvas width="300" height="120" id="canvas4"></canvas><span id="text4"></span>
</div>
ASPX 通用处理程序的代码 - 由客户端根据请求调用
public class AppData : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/json";
CPUUsageHistory _messageRepository = new CPUUsageHistory();
context.Response.Write(
JsonConvert.SerializeObject(_messageRepository.GetAllMessages()));
}
public bool IsReusable
{
get
{
return true;
}
}
}
SQL 依赖代码
public class CPUUsage
{
public string Core1Usage { get; set; }
public string Core2Usage { get; set; }
public string Core3Usage { get; set; }
public string Core4Usage { get; set; }
}
public class CPUUsageHistory
{
readonly string _connString = ConfigurationManager.ConnectionStrings["DBConn"].ConnectionString;
public IEnumerable<CPUUsage> GetAllMessages()
{
var cpuusage = new List<CPUUsage>();
using (var connection = new SqlConnection(_connString))
{
connection.Open();
using (var command = new SqlCommand(@"SELECT [Core1Usage],[Core2Usage],[Core3Usage],[Core4Usage] FROM [dbo].[CpuUsageDetails]", connection))
{
command.Notification = null;
var dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
var reader = command.ExecuteReader();
while (reader.Read())
{
cpuusage.Add(item: new CPUUsage
{
Core1Usage = reader["Core1Usage"].ToString(),
Core2Usage = reader["Core2Usage"].ToString(),
Core3Usage = reader["Core3Usage"].ToString(),
Core4Usage = reader["Core4Usage"].ToString()
});
}
}
}
return cpuusage;
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
AppHub.SendMessages();
}
}
}
}
我错过了什么/做错了什么?
【问题讨论】:
-
使用 2 -3 浏览器实例(主要是 Chrome 48)...如果一起使用,系统 chocks 和 FireFox 45b 会崩溃。
标签: asp.net signalr real-time signalr-hub sqldependency