Zainspirował mnie film "Scaling the Real-time Web with ASP.NET SignalR" w dziale 56 min i 11 sek.Azure, SignalR i Web Api nie wysyłają wiadomości do klienta
Wyobraź sobie internetowego klienta czatowego używającego SignalR do komunikacji z serwerem. Gdy klient łączy się, jego informacje o punkcie końcowym są przechowywane w tabeli Azure.
Klient czatu może wysłać wiadomość do innego klienta czatu przez SignalR, który wyszukuje punkt końcowy interesującego klienta docelowego (może w innej instancji), a następnie za pomocą interfejsu Web API wysyła wiadomość do drugiej instancji do klienta za pośrednictwem SignalR.
Aby wykazać, że mam uploaded a sample application to github.
Wszystko to działa, gdy istnieje jedna instancja platformy Azure. Jeśli jednak istnieje wiele WIELKICH lazurowych instancji, to ostatnie wywołanie SignalR z serwera do klienta po cichu się nie udaje. Jest tak, jak kod dynamiczny po prostu nie istnieje lub znika z "złego" wątku lub wiadomość została w jakiś sposób wysłana do niewłaściwej instancji lub właśnie popełniłem błąd dopingu.
Wszelkie pomysły będą mile widziane.
strona internetowa jest z tego
<input type="radio" name='ClientId' value='A' style='width:30px'/>Chat client A</br>
<input type="radio" name='ClientId' value='B' style='width:30px'/>Chat client B</br>
<input type='button' id='register' value='Register' />
<input type='text' id='txtMessage' size='50' /><input type='button' id='send' value='Send' />
<div id='history'>
</div>
i JS jest
<script type="text/javascript">
$(function() {
// Declare a proxy to reference the hub.
var chat = $.connection.chatHub;
chat.client.sendMessageToClient = function (message) {
$('#history').append("<br/>" + message);
};
// Start the connection.
$.connection.hub.start().done(function() {
$('#register').click(function() {
// Call the Send method on the hub.
chat.server.register($('input[name=ClientId]:checked', '#myForm').val());
});
$('#send').click(function() {
// Call the Send method on the hub.
chat.server.sendMessageToServer($('input[name=ClientId]:checked', '#myForm').val(), $('#txtMessage').val());
});
});
});
</script>
Piasta jest następujący. (Mam małą klasę pamięci do przechowywania informacji o punkcie końcowym w tabeli Azure). Zwróć uwagę na metodę statyczną SendMessageToClient. To ostatecznie kończy się niepowodzeniem. Nazywa z klasy Web API (poniżej)
public class ChatHub : Hub
{
public void Register(string chatClientId)
{
Storage.RegisterChatEndPoint(chatClientId, this.Context.ConnectionId);
}
/// <summary>
/// Receives the message and sends it to the SignalR client.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="connectionId">The connection id.</param>
public static void SendMessageToClient(string message, string connectionId)
{
GlobalHost.ConnectionManager.GetHubContext<ChatHub>().Clients.Client(connectionId).SendMessageToClient(message);
Debug.WriteLine("Sending a message to the client on SignalR connection id: " + connectionId);
Debug.WriteLine("Via the Web Api end point: " + RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["WebApi"].IPEndpoint.ToString());
}
/// <summary>
/// Sends the message to other instance.
/// </summary>
/// <param name="chatClientId">The chat client id.</param>
/// <param name="message">The message.</param>
public void SendMessageToServer(string chatClientId, string message)
{
// Get the chatClientId of the destination.
string otherChatClient = (chatClientId == "A" ? "B" : "A");
// Find out this other chatClientId's end point
ChatClientEntity chatClientEntity = Storage.GetChatClientEndpoint(otherChatClient);
if (chatClientEntity != null)
ChatWebApiController.SendMessage(chatClientEntity.WebRoleEndPoint, chatClientEntity.SignalRConnectionId, message);
}
}
Wreszcie ChateWebApiController jest to
public class ChatWebApiController : ApiController
{
[HttpGet]
public void SendMessage(string message, string connectionId)
{
//return message;
ChatHub.SendMessageToClient(message, connectionId);
}
/// <summary>
/// This calls the method above but on a different instance via Web API
/// </summary>
/// <param name="endPoint">The end point.</param>
/// <param name="connectionId">The connection id.</param>
/// <param name="message">The message.</param>
public static void SendMessage(string endPoint, string connectionId, string message)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://" + endPoint);
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string url = "http://" + endPoint + "/api/ChatWebApi/SendMessage/?Message=" + HttpUtility.UrlEncode(message) + "&ConnectionId=" + connectionId;
client.GetAsync(url);
}
}
Czy obejrzałeś wbudowaną obsługę skalowania? http://www.asp.net/signalr/overview/performance-and-scaling/scaleout-in-signalr –
Tak. Moje potrzeby w zakresie skalowania będą łatwo przekraczać ograniczenia prędkości w technologiach kasetowych. Patrz 47 min 45 s. Będę miał WIELU wiadomości na sekundę. Interesują mnie niestandardowe wzorce od 54 min 30 s, a szczególnie 56 min i 11 sec. – DJA