嘉峪关市网站建设_网站建设公司_一站式建站_seo优化
2026/1/17 18:58:54 网站建设 项目流程

Setup rabbitmq using Docker 

[root@szsit148 ~]# docker run --name rabbitmq -d -p 5672:5672 -p 15672:15672 --h ostname rabbitmq rabbitmq:3-management

[root@szsit148 ~]# docker ps

CONTAINER ID IMAGE                           COMMAND                  CREATED     STATUS       PORTS                                                                                                                                       NAMES
8b27776fa3eb rabbitmq:3-management "docker-entrypoint.s…" 11 hours ago Up 11 hours 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp rabbitmq

[root@szsit148 ~]# docker rm rabbitmq -f

Setup rabbitmq, redis, using Docker Compose

[root@szsit148 ~]# docker-compose -f mongo-rabbit-redis.yml up -d

version: "3.5"services:mongo:image: mongo:4container_name: mongoports:- 27017:27017networks:- dshop# network_mode: hostvolumes:- mongo:/data/dbrabbitmq:image: rabbitmq:3-managementcontainer_name: rabbitmqports:- 5672:5672- 15672:15672networks:- dshop# network_mode: hostvolumes: - rabbitmq:/var/lib/rabbitmqredis:image: rediscontainer_name: redisports:- 6379:6379networks:- dshop# network_mode: hostvolumes: - redis:/datanetworks:dshop:name: dshop-networkvolumes:mongo:driver: localrabbitmq:driver: localredis:driver: local
mango-rabbit-redis

 [root@szsit148 compose]# docker inspect dshop-network

[
{
"Name": "dshop-network",
"Id": "1545e967cc479ed40e859c1b82a8477b6ff90ccd7ff868b91c2788f9e15e2ae2",
"Created": "2019-01-29T08:38:48.739641213+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"7cdfdf302de6c7fea656670e3076f1b36309791409ff2f9db510013630897068": {
"Name": "mongo",
"EndpointID": "5cc3bb708e274be58d2fb2450aa1a6054848d89738e653d62f90cc1bdeffca58",
"MacAddress": "02:42:ac:12:00:04",
"IPv4Address": "172.18.0.4/16",
"IPv6Address": ""
},
"9a66c04a4171791121bfb319d5f3dbaef8c326e89a1384239d485bc72b93364b": {
"Name": "redis",
"EndpointID": "4ab30409c9a3b786dd566cc424b4257edc5664a2383e4ed768ba51afeed14e84",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"c2f328b8896ac1c53701dfc15b1f563e63bd3818dedfb87ad03bc95eb14e238e": {
"Name": "rabbitmq",
"EndpointID": "103ce313867ac5069f7416ba713879329fead30233ebed39005c355402acb769",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "dshop-network",
"com.docker.compose.project": "compose",
"com.docker.compose.version": "1.22.0-rc1"
}
}
View Result

Start all applicaiton up using start-all.sh

#!/bin/bash
export ASPNETCORE_ENVIRONMENT=local
DOTNET_RUN=./scripts/dotnet-run.sh
PREFIX=DNC-DShop
SERVICE=$PREFIX.Services
REPOSITORIES=($PREFIX.Api $SERVICE.Customers $SERVICE.Identity $SERVICE.Operations $SERVICE.Orders $SERVICE.Products $SERVICE.Signalr)for REPOSITORY in ${REPOSITORIES[*]}
doecho ========================================================echo Starting a service: $REPOSITORYecho ========================================================cd $REPOSITORY$DOTNET_RUN &cd ..
done
Use git bash to run

 

 MangoDB tool

 

 

Conditional Resolving multiple implementation from generic interface base on types

articles

Dependency injection is applied where there is only one implementation to the interface, DI via constructor is mostly seen.

but if a interface has multiple implementation, resolving the right one can be done in runtime and determined by the paramterized type variables

 

   public IServiceProvider ConfigureServices(IServiceCollection services){services.Configure<CookiePolicyOptions>(options =>{// This lambda determines whether user consent for non-essential cookies is needed for a given request.options.CheckConsentNeeded = context => true;options.MinimumSameSitePolicy = SameSiteMode.None;});services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);var builder = new ContainerBuilder();builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly()).AsImplementedInterfaces();builder.Populate(services);Container = builder.Build();return new AutofacServiceProvider(Container);}
Use Autofac as DI framework at startup.cs
[HttpPost]public IActionResult GetAll([FromBody] GetAllQuery query){var handleType = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(List<DemoModel>));dynamic QueryHandler = _context.Resolve(handleType);return new JsonResult(QueryHandler.execute((dynamic)query));}namespace DynamicDI.Query
{public interface IQuery<TResult>{}
}namespace DynamicDI.Query
{public class GetAllQuery : IQuery<List<DemoModel>> {public int Id { get; set; }}
}namespace DynamicDI.QueryHandler
{interface IQueryHandler<IQuery, TResult>{TResult execute(IQuery query);}
}namespace DynamicDI.QueryHandler
{public class GetAllQueryHandler : IQueryHandler<GetAllQuery, List<DemoModel>>{public GetAllQueryHandler(){//Here you can put repository implmentation at the constructor
        }public List<DemoModel> execute(GetAllQuery query){//repo.getallreturn new List<DemoModel>{new DemoModel{Id=0, Name="Matt"},new DemoModel{Id=1, Name="Yang"}};}}
}
View Code

 Spin up docker compose for Consul, 

[root@szsit148 ~]# docker-compose -f consul-fabio-vault.yml up -d

version: "3.5"services:consul:image: consulcontainer_name: consulports:- 6500:6500networks:- dshop# network_mode: hostvolumes:- consul:/consul/datafabio:image: fabiolb/fabiocontainer_name: fabioenvironment:- FABIO_REGISTRY_CONSUL_ADDR=consul:6500networks:- dshop# network_mode: hostports:- 9998:9998- 9999:9999vault:image: vaultcontainer_name: vaultports:- 8200:8200networks:- dshop# network_mode: hostenvironment:- VAULT_ADDR=http://127.0.0.1:8200
      - VAULT_DEV_ROOT_TOKEN_ID=secretcap_add:- IPC_LOCKnetworks:dshop:name: dshop-networkexternal: truevolumes:consul:driver: local
View Code

Access  http://10.89.24.148:8500

Add a common library and create a extension method to take servicecollection and register the consul configuration

Add microsoft.extensions.dependencyinjection and configuration

microsoft.extensions.dependencyinjection is the namespace for IServiceCollection 

Add 3 import type to transcient service

  • ConsulClient - component of Consul Library provided by Nuget, responsible for sending request to consul and getting the service info in return
  • ConsulServiceRegistry - which takes the ConsulClient at constructor and leverage it to get the AgentService(Consul type) which has the service name and its host name and port
  • ConsultHttpClient - a wrapper class of HttpClient that aggregate ConsulServiceRegistry via ConsulServiceDiscoveryMessageHandler

Service A register to Consul

client.Agent.ServiceRegister(new AgentServiceRegistration{servicename="ServiceA"});

using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;namespace Common.Consul
{public static class ConsulExtensions{public static IServiceCollection AddConsul(this IServiceCollection services){IConfiguration configuration;using (var servicebuilder = services.BuildServiceProvider()){configuration = servicebuilder.GetService<IConfiguration>();}var options = new ConsulOptions();configuration.GetSection("Consul").Bind(options);services.Configure<ConsulOptions>(configuration.GetSection("consul"));services.AddTransient<IConsulServicesRegistry, ConsulServiceRegistry>();services.AddTransient<ConsulServiceDiscoveryMessageHandler>();services.AddHttpClient<IConsulHttpClient, ConsulHttpClient>().AddHttpMessageHandler<ConsulServiceDiscoveryMessageHandler>();return services.AddSingleton<IConsulClient>(c =>new ConsulClient(cfg => cfg.Address = new System.Uri(options.url)));}public static string UseConsul(this IApplicationBuilder app){using (var scope = app.ApplicationServices.CreateScope()){var consulOptions = scope.ServiceProvider.GetService<IOptions<ConsulOptions>>();// var fabioOptions = scope.ServiceProvider.GetService<IOptions<FabioOptions>>();var enabled = consulOptions.Value.enabled;var consulEnabled = Environment.GetEnvironmentVariable("CONSUL_ENABLED")?.ToLowerInvariant();if (!string.IsNullOrWhiteSpace(consulEnabled)){enabled = consulEnabled == "true" || consulEnabled == "1";}if (!enabled){return string.Empty;}var address = consulOptions.Value.address;if (string.IsNullOrWhiteSpace(address)){throw new ArgumentException("Consul address can not be empty.",nameof(consulOptions.Value.pingEndpoint));}var uniqueId = Guid.NewGuid();var client = scope.ServiceProvider.GetService<IConsulClient>();var serviceName = consulOptions.Value.service;var serviceId = $"{serviceName}:{uniqueId}";var port = consulOptions.Value.port;var pingEndpoint = consulOptions.Value.pingEndpoint;var pingInterval = consulOptions.Value.pingInterval <= 0 ? 5 : consulOptions.Value.pingInterval;var removeAfterInterval =consulOptions.Value.removeAfterInterval <= 0 ? 10 : consulOptions.Value.removeAfterInterval;var registration = new AgentServiceRegistration{Name = serviceName,ID = serviceId,Address = address,Port = port,Tags = null//Tags = fabioOptions.Value.Enabled ? GetFabioTags(serviceName, fabioOptions.Value.Service) : null
                };if (consulOptions.Value.pingEnabled )//|| fabioOptions.Value.Enabled)
                {var scheme = address.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)? string.Empty: "http://";var check = new AgentServiceCheck{Interval = TimeSpan.FromSeconds(pingInterval),DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(removeAfterInterval),HTTP = $"{scheme}{address}{(port > 0 ? $":{port}" : string.Empty)}/{pingEndpoint}"};registration.Checks = new[] { check };}client.Agent.ServiceRegister(registration);return serviceId;}}}
}
ConsulExtension

 

Service B user service discovery

only aware the SERVICE NAME for Service A and reach out to Consul to resolve the name into host name and forward the rquest to the Service A 

 Unregister consul when applicaiton exit

applicationLifetime.ApplicationStopped.Register(() =>
{
client.Agent.ServiceDeregister(consulServiceId);
// Container.Dispose();
});

Add config section consul

{"consul": {"enabled": true,"url": "http://localhost:8500","service": "conditionalinjection-service","address": "localhost","port": "5000","pingEnabled": true,"pingEndpoint": "ping","pingInterval": 5,"removeAfterInterval": 10,"requestRetries": 3},"Logging": {"LogLevel": {"Default": "Warning"}},"AllowedHosts": "*"
}

 Fabio LoadBalancing 

Fabio's unqiueness is unlike Nginx which needs to manually set up the reseverse proxied ip address.

Fabio pair with Consul to provide service. Consul does not provide LB features

Fabio collect the ipaddress from Consul where IP are binded during runtime. and re-route the traffice to registered instance address

 

 

 

 

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询