docker-compose.yml
version: '3.4'
services:
consul:
image: hashicorp/consul:latest
command: consul agent -dev -log-level=warn -ui -client=0.0.0.0
hostname: consul
container_name: consul
networks:
- common_network
ports:
- "8500:8500"
identityservice.httpapi.host:
image: ${DOCKER_REGISTRY-}identityservicehttpapihost
build:
context: .
dockerfile: Services/IdentityService/IdentityService.HttpApi.Host/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ConnectionStrings__IdentityService=server=DESKTOP;database=IdentityDatabase;Integrated Security=True;TrustServerCertificate=true;
- ConsulConfig__Id=IdentityService-9100
- ConsulConfig__Name=IdentityService
- ConsulConfig__DiscoveryAddress=http://consul:8500
- ConsulConfig__Address=localhost
- ConsulConfig__Port=8000
- ConsulConfig__HealthCheckEndPoint=healthcheck
ports:
- "8000:8080"
networks:
- common_network
depends_on:
- consul
usersettings.httpapi.host:
image: ${DOCKER_REGISTRY-}usersettingshttpapihost
build:
context: .
dockerfile: services/UserSettings/UserSettings.HttpApi.Host/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ConsulConfig__Id=UserSettingsService-9100
- ConsulConfig__Name=UserSettingsService
- ConsulConfig__DiscoveryAddress=http://consul:8500
- ConsulConfig__Address=localhost
- ConsulConfig__Port=8001
- ConsulConfig__HealthCheckEndPoint=healthcheck
- IdentityService__Address=http://UserSettingsService.openapi:8000
ports:
- "8001:8080"
volumes:
- ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro
- ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro
networks:
- common_network
depends_on:
- consul
networks:
common_network:
driver: bridge
consulhosted.cs
,两项服务相同
using Consul;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UserSettings.Domain.Models;
namespace UserSettings.Application.Helpers
{
public class ConsulHostedService : IHostedService
{
private readonly IConsulClient _consulClient;
private readonly ConsulConfig _consulConfig;
private readonly IHostApplicationLifetime _lifetime;
private string _registrationId;
private ILogger<ConsulHostedService> _logger;
public ConsulHostedService(IConsulClient consulClient, IOptions<ConsulConfig> consulConfig, ILogger<ConsulHostedService> logger, IHostApplicationLifetime lifetime)
{
_consulClient = consulClient;
_consulConfig = consulConfig.Value;
_lifetime = lifetime;
_logger = logger;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
_registrationId = _consulConfig.Id;
var serviceHost = Environment.GetEnvironmentVariable("HOST_IP") ?? "localhost";
var registration = new AgentServiceRegistration
{
ID = _consulConfig.Id,
Name = _consulConfig.Name,
Address = _consulConfig.Address,
Port = _consulConfig.Port,
};
_logger.LogInformation("Registering service with Consul. ID: {ID}, Name: {Name}, Address: {Address}, Port: {Port}",
registration.ID, registration.Name, registration.Address, registration.Port);
await _consulClient.Agent.ServiceRegister(registration, cancellationToken).ConfigureAwait(false);
_lifetime.ApplicationStopping.Register(async () =>
{
await _consulClient.Agent.ServiceDeregister(_registrationId, cancellationToken);
});
}
public async Task StopAsync(CancellationToken cancellationToken)
{
await _consulClient.Agent.ServiceDeregister(_registrationId, cancellationToken).ConfigureAwait(false);
}
}
}
我尝试从用户设置服务调用身份服务的家庭控制器
using System.Net.Http;
using System.Text;
using System.Text.Json;
using Consul;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
using System.Linq;
[Route("api/[controller]")]
[ApiController]
public class HomeController : ControllerBase
{
private readonly IConsulClient _consulClient;
private readonly ILogger<HomeController> _logger;
private readonly IHttpContextAccessor _httpContextAccessor;
public HomeController(IConsulClient consulClient, ILogger<HomeController> logger, IHttpContextAccessor httpContextAccessor)
{
_consulClient = consulClient;
_logger = logger;
_httpContextAccessor = httpContextAccessor;
}
[HttpGet("healthcheck")]
public IActionResult Healthcheck()
{
var context = _httpContextAccessor.HttpContext; // Get the current HttpContext
var msg = $"{context.Request.Host} is healthy";
_logger.LogInformation(msg);
return Ok(msg);
}
[HttpGet("CallIdentityService")]
public async Task<IActionResult> CallIdentityService()
{
var services = await _consulClient.Agent.Services();
var identityService = services.Response.Values.FirstOrDefault(s => s.Service.Equals("IdentityService", StringComparison.OrdinalIgnoreCase));
if (identityService == null)
{
return NotFound("IdentityService not found");
}
var loginUserRequest = new LoginUserRequest
{
email = "[email protected]",
password = "123ex"
};
var client = new HttpClient();
var content = new StringContent(JsonSerializer.Serialize(loginUserRequest), Encoding.UTF8, "application/json");
try
{
_logger.LogInformation("Attempting to call IdentityService at {Url}", $"http://{identityService.Address}:{identityService.Port}/api/Account/Authorize");
var response = await client.PostAsync($"http://{identityService.Address}:{identityService.Port}/api/Account/Authorize", content);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
return Ok(responseContent);
}
return StatusCode((int)response.StatusCode, response.ReasonPhrase);
}
catch (HttpRequestException ex)
{
_logger.LogError(ex, "HTTP request to IdentityService failed: {Message}", ex);
return StatusCode(StatusCodes.Status500InternalServerError, "Error calling IdentityService");
}
catch (Exception ex)
{
_logger.LogError(ex, "An unexpected error occurred: {Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError, "An unexpected error occurred");
}
}
}
public class LoginUserRequest
{
public string email { get; set; }
public string password { get; set; }
}
我正在尝试通过在领事上动态注册并从领事发现来在两个微服务之间进行通信。
当我使用 docker 时,就会出现这个问题。当我在本地运行 consul 而不是 docker image,然后注册它们的服务时,我没有收到连接被拒绝的错误。
完整错误:
2024-09-04 18:26:32 fail: HomeController[0]
2024-09-04 18:26:32 HTTP request to IdentityService failed: System.Net.Http.HttpRequestException: Connection refused (localhost:8000)
2024-09-04 18:26:32 ---> System.Net.Sockets.SocketException (111): Connection refused
2024-09-04 18:26:32 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
2024-09-04 18:26:32 at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|285_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 --- End of inner exception stack trace ---
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(QueueItem queueItem)
2024-09-04 18:26:32 at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
2024-09-04 18:26:32 at HomeController.CallIdentityService() in D:\github\proj\services\UserSettings\UserSettings.HttpApi.Host\Controllers\HomeController.cs:line 57
2024-09-04 18:26:32 System.Net.Http.HttpRequestException: Connection refused (localhost:8000)
2024-09-04 18:26:32 ---> System.Net.Sockets.SocketException (111): Connection refused
2024-09-04 18:26:32 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
2024-09-04 18:26:32 at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|285_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 --- End of inner exception stack trace ---
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(QueueItem queueItem)
2024-09-04 18:26:32 at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:32 at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
2024-09-04 18:26:32 at HomeController.CallIdentityService() in D:\github\proj\services\UserSettings\UserSettings.HttpApi.Host\Controllers\HomeController.cs:line 57
2024-09-04 18:26:32 info: HomeController[0]
2024-09-04 18:26:32 Attempting to call IdentityService at http://localhost:8000/api/Account/Authorize
2024-09-04 18:26:36 fail: HomeController[0]
2024-09-04 18:26:36 HTTP request to IdentityService failed: System.Net.Http.HttpRequestException: Connection refused (localhost:8000)
2024-09-04 18:26:36 ---> System.Net.Sockets.SocketException (111): Connection refused
2024-09-04 18:26:36 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
2024-09-04 18:26:36 at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|285_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 --- End of inner exception stack trace ---
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(QueueItem queueItem)
2024-09-04 18:26:36 at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
2024-09-04 18:26:36 at HomeController.CallIdentityService() in D:\github\proj\services\UserSettings\UserSettings.HttpApi.Host\Controllers\HomeController.cs:line 57
2024-09-04 18:26:36 System.Net.Http.HttpRequestException: Connection refused (localhost:8000)
2024-09-04 18:26:36 ---> System.Net.Sockets.SocketException (111): Connection refused
2024-09-04 18:26:36 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
2024-09-04 18:26:36 at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|285_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 --- End of inner exception stack trace ---
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(QueueItem queueItem)
2024-09-04 18:26:36 at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
2024-09-04 18:26:36 at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
2024-09-04 18:26:36 at HomeController.CallIdentityService() in D:\github\proj\services\UserSettings\UserSettings.HttpApi.Host\Controllers\HomeController.cs:line 57
当您在主机上运行服务时,它们在同一 IP 地址上运行。因此,从一项服务连接到另一项服务时,您可以使用
localhost
。
当您在容器上运行它们时,每个服务都有自己的 IP 地址。 Docker 创建一个桥接网络并将每个容器连接到它。连接时可以使用服务名称作为主机名。
因此,当从 Consul 连接到身份服务器时,您将使用主机名
identityservice.httpapi.host
和端口 8080。
当您需要从创建的 Docker 桥接网络外部访问容器时,请使用端口映射。当桥接网络上的容器相互通信时,它们使用未映射的端口号。这就是为什么 Consul 容器需要使用端口 8080 而不是端口 8000。