c# - ASP.NET MVC 和 ASP.NET WebAPI 的负载平衡
问题描述
我正在从事两个项目。一种是使用 ASP.NET MVC,另一种是使用 ASP.NET WebAPI。我们的客户端想要实现负载均衡,但他们担心一旦完成,它可能会影响登录功能,因为用户的身份验证令牌可能不会在服务器之间共享。我被分配研究这个问题。谁能告诉我是否可以在服务器之间同步和共享用户的登录状态和身份验证令牌以达到负载平衡的目的?如果是这样,怎么做?这是 ASP.NET WebAPI 项目中登录功能的代码。
public async Task<IHttpActionResult> Login(LoginModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Invoke the "token" OWIN service to perform the login (POST /api/token)
var requestParams = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("client_id", APP_CLIENT_ID),
new KeyValuePair<string, string>("username", model.Username),
new KeyValuePair<string, string>("password", model.Password)
};
var requestParamsFormUrlEncoded = new FormUrlEncodedContent(requestParams);
var baseUrl = apiConfiguration.Host;
var getTokenUrl = $"{baseUrl}/token";
var tokenServiceResponse = await httpClient.PostAsync(getTokenUrl, requestParamsFormUrlEncoded);
if (!tokenServiceResponse.IsSuccessStatusCode)
{
// Log response
if (tokenServiceResponse.StatusCode == HttpStatusCode.NotFound)
{
log.ErrorFormat("Can not get token from url: {0}", getTokenUrl);
return BadRequest(SERVER_ERROR_MESSAGE);
}
else
{
string content = await tokenServiceResponse.Content.ReadAsStringAsync();
if (tokenServiceResponse.StatusCode == HttpStatusCode.InternalServerError)
{
log.Error(content);
return BadRequest(SERVER_ERROR_MESSAGE);
}
else
{
log.InfoFormat("Get token fail request fail | RESPONE - StatusCode: {0} - Reason: {1} - Content: {2}", tokenServiceResponse.StatusCode, tokenServiceResponse.ReasonPhrase, content);
return BadRequest(INVALID_USER_DATA_MESSAGE);
}
}
}
var result = ResponseMessage(tokenServiceResponse);
var user = await userManager.FindByNameAsync(model.Username);
if (user == null || user.IsDeleted)
{
log.InfoFormat("Invalid user data. Username: {0}", model.Username);
return BadRequest(INVALID_USER_DATA_MESSAGE);
}
else if (user.AccountBlocked == true)
{
log.InfoFormat("The account {0} is blocked", model.Username);
return BadRequest(ACCOUNT_IS_BLOCKED_MESSAGE);
}
var userId = user.Id;
accountNotificationService.LogIn(userId, result.Response.IsSuccessStatusCode, APP_CLIENT_ID);
return result;
}
这是 ASP.NET MVC 项目中登录功能的代码。
public async Task<IHttpActionResult> Login(LoginModel model)
{
if (model == null)
{
return this.BadRequest("Invalid user data");
}
// Invoke the "token" OWIN service to perform the login (POST /api/token)
var requestParams = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("client_id", APP_CLIENT_ID),
new KeyValuePair<string, string>("username", model.Username),
new KeyValuePair<string, string>("password", model.Password)
};
try
{
var requestParamsFormUrlEncoded = new FormUrlEncodedContent(requestParams);
var tokenServiceResponse = await new HttpClient().PostAsync(
string.Format("{0}/Token", Config.Application.Host), requestParamsFormUrlEncoded);
var result = this.ResponseMessage(tokenServiceResponse);
if (!result.Response.IsSuccessStatusCode)
{
return this.BadRequest("Credentials are incorrect");
}
var user = result.Response.IsSuccessStatusCode ? await accountService.FindUser(model.Username, model.Password) : null;
if (user == null)
{
return this.BadRequest("Credentials are invalid");
}
else if (user.IsDeleted)
{
return this.BadRequest("This user does not exists");
}
if (user.AccountBlocked == true)
{
return this.BadRequest("This account is blocked");
}
notificationService.LogIn(user?.Id, result.Response.IsSuccessStatusCode, APP_CLIENT_ID);
return result;
}
catch (Exception ex)
{
ErrorLogging.LogError(ex, "Error in Login");
return BasicResponse(new ResultModel
{
Success = false,
ResponseCode = System.Net.HttpStatusCode.InternalServerError,
Message = Constants.ErrorMessageCategory.General
});
}
}
解决方案
当在负载均衡器后面运行机器时,负载均衡器上通常有一个 Affinity 设置,它将指示会话的“粘性”程度,负载均衡器应根据这些会话保持与同一服务器的连接。因此,根据道路平衡器的配置方式,这可能不是问题吗?特别是如果客户端(用户)在每次调用时发送会话信息或 API 令牌。
这是 Azure 负载均衡器分发模式的说明https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-distribution-mode
推荐阅读
- mongodb - 按计数排序并获取父节点属性
- c - OpenACC 循环未矢量化/并行化:包含调用
- java - 创建一个等待所有 Schedulers.io() 完成的 Mockito 测试用例
- java - 以编程方式正确打开“设置”中的“关于设备”页面?
- sql - 如何计算内连接函数的结果
- python - 在 Django 中编辑验证错误
- angular - Angular 9:在构造函数运行之前检查组件模板
- c++ - std::sort() C++ 的自定义比较函数
- ruby-on-rails - ruby-on-rails 中的 Mongoid
- python - 熊猫“替换”方法无法替换点(。)字符