"Long-term updates" to modernize the. Net configuration refers to the north

Source: Internet
Author: User
Tags docker run
1. Celebrating the era of. NET Standard

I don't quite mention that . NET core, for me, future development will be based on. NET Standard, not just for the future , but also for the past ; not only. NET core can be facilitated . NET Framework can enjoy the benefits of. NET standard without upgrading. (currently. NET Standard supports. NET Framework 4.6.1+)

2. Lack of traditional configuration

When I first stepped into the world of. Net, there was a confusion , is it not all configurations must be written in Web.Config ? And until you start learning about the configuration mode of. Net Core, you realize the lack of traditional configuration:

    • In addition to XML, we may need more configuration source support, such as Json
    • Whether the configuration can be serialized directly into an object or multiple types (directly out of int the way), not juststring
    • After modifying the configuration, IIS restarts, and there is no way to modify the configuration without restarting
    • The difficulty of managing configuration under MicroServices (or distributed) applications

It is clear that Microsoft is aware of these issues and has devised a powerful and customized configuration, but this also means that the era of removal from the configuration is gone AppSettings .

3. Initial knowledge of IConfiguration

Before we start exploring modern configuration designs, let's get started with the. Net Core. Microsoft.Extensions.Configuration

As mentioned earlier, this is not exclusive to. Net Core. We first create a console application (code address) based on the. NET Framework 4.6.1, and then install the dependencies we need.

Nuget Install Microsoft.Extensions.Configuration.JsonNuget Install Microsoft.Extensions.Configuration.Binder

Then introduce our configuration file my.conf :

{  "TestConfig": {    "starship": {      "name": "USS Enterprise",      "registry": "NCC-1701",      "class": "Constitution",      "length": 304.8,      "commissioned": false    },    "trademark": "Paramount Pictures Corp. http://www.paramount.com"  }}

Finally, enter the following code and start:

  var configurationBuilder = new ConfigurationBuilder().AddJsonFile("my.conf", optional: true, reloadOnChange: true)                                .AddInMemoryCollection(new List<KeyValuePair<String, String>>                {                    new KeyValuePair<String,String>("myString","myString"),                    new KeyValuePair<String,String>("otherString","otherString")                });            IConfiguration config = configurationBuilder.Build();            String myString = config["myString"]; //myString            TestConfig testConfig = config.GetSection("TestConfig").Get<TestConfig>();            var length = testConfig.Starship.Length;//304.8            Console.WriteLine($"myString:{myString}");            Console.WriteLine($"myString:{JsonConvert.SerializeObject(testConfig)}");            Console.ReadKey();

Microsoft supports a variety of sources, including memory sources, system variables ,Json files,XML files, and other sources of configuration , while Community Open source brings More possibilities , and also supports distributed configuration centers such as Consul,Etcd , and Apollo .

In addition to supporting more configuration sources, we have also observed that the source can be configured by default , whether it can be overloaded , or not. Especially automatic overloading, which in. NETFramework era is unimaginable, every time we modify Web.config the configuration file, the enthusiastic IIS will automatically help us restart the application, and users see 500 of the hint or a blank, can not help to send this site really rotten praise. (also pay attention to configuring IIS security to avoid direct access to the configured JSON file, the best way is to change the JSON suffix to such as conf, etc.)

4. Configuration of anti-corrosion layer

Although Microsoft comes with IConfiguration enough, let's enjoy the future, or go back to the question I'm confused about. are all configurations based on iconfiguration? The answer is naturally negative, programming technology is constantly developing, even if the old and oppositely is AppSetting also difficult to escape the day of elimination. So in order to make our architecture a bit longer, we need to design the anticorrosive layer . And, if you are still maintaining your old project, you need to use the magic of the anti-corrosion layer to counteract the concerns of your colleagues or superiors.

Let's revisit the usage of the configuration to get the corresponding value from a key (possibly a string or an object), so we can define a iconfigurationgeter in the lowest class library or global class library to meet our requirements.

namespace ZHS.Configuration.Corepublic interface IConfigurationGeter {    TConfig Get<TConfig>(string key);    String this[string key] { get;}}

And about IConfigurationGeter the implementation, let's call it Configurationgetter, based on the anti-corrosion layer design, we can't install any dependencies on the underlying class library. So we need to create a new infrastructure layer or implement it at the application entrance layer. (You can see in the code example that it is in a different project)

  namespace ZHS. Configuration.dotnetcore public class Configurationgetter:iconfigurationgeter {private ReadOnly Iconfigurat        Ion _configuration;        Public Configurationgetter (IConfiguration configuration) {_configuration = Configuration; Public Tconfig get<tconfig> (string key) {if (string.            Isnullorwhitespace (key)) throw new ArgumentException ("Value cannot be null or whitespace.", nameof (key)); var section = _configuration.            GetSection (key); Return section.        Get<tconfig> ();    } public string this[string key] = _configuration[key]; }

All of our configurations are acquired in the future IConfigurationGeter , thus avoiding the dependencies that are introduced in your application layer (or the BAL layer in the three-tier architecture) Microsoft.Extensions.Configuration . Of course, some people may feel overqualified, but in fact, when you get to the real development, you will feel the benefits. Not just me,. Net Core designers have long been aware of the importance of anti-corrosion layer, so there will be a Microsoft.Extensions.Configuration.Abstractions series of only the interface of the abstract base library.

5. Static Get Configuration

Although we already have an anti-corrosion layer, it is clear that we have not considered the actual usage, especially if your application has not yet introduced dependency injection support, the anti-corrosion layer We implemented earlier is not for you to feel. At the same time, I still like the former kind AppSetting of direct removal from the configuration of convenience. So, here we need to introduce the service locator mode to satisfy the convenient operation of static get configuration .

  namespace ZHS. Configuration.corepublic class configurationgeterlocator{Private ReadOnly Iconfigurationgeter _   Currentserviceprovider;    private static Iconfigurationgeter _serviceprovider; Public Configurationgeterlocator (Iconfigurationgeter currentserviceprovider) {_currentserviceprovider = CurrentSe    Rviceprovider;    } public static Configurationgeterlocator current = new Configurationgeterlocator (_serviceprovider);    public static void Setlocatorprovider (Iconfigurationgeter serviceprovider) {_serviceprovider = serviceprovider;     } public tconfig get<tconfig> (String key) {return _currentserviceprovider.get<tconfig> (key); } public String this[string key] = _currentserviceprovider[key];}  
       public static IConfiguration AddConfigurationGeterLocator(this IConfiguration configuration)        {            ConfigurationGeterLocator.SetLocatorProvider(new ConfigurationGetter(configuration));            return configuration;        }

After doing this basic work, we also need to read a mantra in the application entry function to get him into effect.

config.AddConfigurationGeterLocator();var myString = ConfigurationGeterLocator.Current["myString"];// "myString"

Now, as before, we can call directly ConfigurationGeterLocator.Current to get the configuration we want.

6. The dawn of Dependency injection

Now suppose we get rid of the savage era, with a dependency on injected weapons, using the most convenient configuration to directly inject a configuration object, in. Net Core practices are as follows:

public void ConfigureServices(IServiceCollection services){    services.AddScoped<TestConfig>(provider =>Configuration.GetSection("TestConfig").Get<TestConfig>());}

And its use is very convenient:

public class ValuesController : ControllerBase    {        private readonly TestConfig _testConfig;        public ValuesController(TestConfig testConfig)        {            _testConfig = testConfig;        }        // GET api/values        [HttpGet]        public JsonResult Get()        {            var data = new            {               TestConfig = _testConfig            };            return new JsonResult(data);        }    }

See here you may be confused, how and the official recommended ioptions usage is not the same? Although it is highly respected in official documents, I would hardly use it in actual development, in my opinion:

    • It's got a corresponding effect without using ioptions.
    • Use Ioptionssnapshot to constrain whether the configuration requires thermal overloading, but this is not a good control (so chicken ribs)
    • We've got the embalming layer, and the introduction is destroying the design.
7. Convention better than the Gospel of configuration

In the popularity of microservices applications today, we need more and more configuration classes. We are constantly injected, and finally exhausted. Editor, is there an automated injection method to liberate our keyboard? The answer is naturally, but before we do it, we need to make a pact better than the configuration of our vows.

First, for all configuration classes, they can be seen as a class or an interface implementation.

public interface IConfigModel{ }public class TestConfig : IConfigModel {     public String DefauleVaule { get; set; } = "Hello World";     public Starship Starship { get; set; }     public string Trademark { get; set; }}public class Starship{    public string Name { get; set; }    public string Registry { get; set; }    public string Class { get; set; }    public float Length { get; set; }    public bool Commissioned { get; set; }}

Lenovo we just injected TestConfig the time, is not specified the configuration node "Testconfig", then if we want to automatically inject, is not possible to consider directly using the class's unique flag, such as the full name of the class, then the injection method can be modified as follows:

public static IServiceCollection AddConfigModel(this IServiceCollection services){          var types = AppDomain.CurrentDomain.GetAssemblies()                .SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IConfigModel))))                .ToArray();          foreach (var type in types)            {                services.AddScoped(type, provider =>                {                    var config = provider.GetService<IConfiguration>().GetSection(type.FullName).Get(type);                    return config;                });            }            return services;}

Just using the full name of the class is not enough to show that the contract is better than the power of the configuration, contact the reality, is not the configuration of some options are default values, such as TestConfig DefauleVaule . In the absence of configuration DefauleVaule , DefauleVaule the value will be the default value , that is, "Hello world" in our code, the other is set to DefauleVaule overwrite the original default value.

8. Distributed Configuration Center

In the popularity of microservices today, if it is still the same as the previous manual modification of the configuration file, it is very cumbersome and error-prone thing, which requires the introduction of the configuration center, and the configuration center must be distributed, in order to avoid a single point of failure.

8.1 Consul

Consul is now my preferred solution, first of all it is simple enough, easy to deploy, and already sufficient. If you have also used Consul, you can use the Docker one-click Deployment:

docker run -d -p 8500:8500  --name consul  consul

The dependency of Winton.Extensions.Configuration.Consul is then introduced into the Application portal project. Because it is a personal open source, there will inevitably be some problems, such as my version is 2.1.0-master0003 , it solves 2.0.1 some of the problems, but has not released the official version.

8.1.1. Net Core using Consul Configuration Center

If you are a. Net Core application, you need to Program.cs configure ConfigureAppConfiguration :

    public class Program {public static readonly CancellationTokenSource Configcancellationtokensource = new Ca        Ncellationtokensource (); public static void Main (string[] args) {createwebhostbuilder (args). Build ().        Run (); } public static Iwebhostbuilder Createwebhostbuilder (string[] args) = Webhost.createdefaultbuilder (A RGS). Configureappconfiguration (buildercontext, config) = {Ihostingenvironment env = Bui                    Ldercontext.hostingenvironment;                    var tempconfigbuilder = config; var key = $ "{env. ApplicationName}. {env. Environmentname} ";//zhs. Configuration.DotNetCore.Consul.Development CONFIG. Addconsul (Key, configcancellationtokensource.token, options = options. Consulconfigurationoptions = Co. {Co. Address = new Uri ("http://127.0.0.1:8500");    };                    Options.                        Reloadonchange = true; Options.                        Optional = true; Options. Onloadexception = Exceptioncontext = {Exceptioncontext.ignore = Tru                        E                    };                }); })                .    Usestartup<startup> (); }

Also, since the interaction between. Net clients and Consul uses long polling, we need to remember to recycle the connection while shutting down the application, which needs to be Startup.cs handled in the Configure following:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime) {     appLifetime.ApplicationStopping.Register(Program.ConfigCancellationTokenSource.Cancel); }
8.1.2. NET Framework using Consul Configuration Center

Similarly, for. NET Framework applications, it is also necessary to do the corresponding processing in Global.asax :

public class WebApiApplication:System.Web.HttpApplication {public static readonly CancellationTokenSource Con        Figcancellationtokensource = new CancellationTokenSource ();            protected void Application_Start () {Addconsul ();        Globalconfiguration.configure (Webapiconfig.register);            } private static void Addconsul () {var config = new Configurationbuilder (); Config. Addconsul ("ZHS.                Configuration.DotNetCore.Consul.Development ", configcancellationtokensource.token, options = Options. Consulconfigurationoptions = Co. {Co. Address = new Uri ("http://127.0.0.1:8500");                }; Options.                Reloadonchange = true; Options.                Optional = true; Options.                Onloadexception = Exceptioncontext = {Exceptioncontext.ignore = true;            };            }); var test = config.    Build ();        Config. Build ().        Addconfigurationgeterlocator (); } protected void Application_End (object sender, EventArgs e) {Configcancellationtokensource.canc        El (); }    }
8.1.3 Configuration Consul

What we call the configuration, for Consul, is key/value . We have two configurations, one of which is to write the previous JSON configuration file into a key.

The other is to create a directory of keys, and then configure each section separately.

9. Conclusion

Writing this article is a big motivation to see a lot of. Net Core Beginners Complaining about the use of the various pits in the configuration, complaining about the Microsoft documentation is not clear enough, but also as my two years of some development experience summary.

Finally, we need to talk about feelings. Most of the experience is the impact of. NET core open source, a lot of developers are excited to put the traditional project into a. NET core project, but the idea has not been upgraded, but the more I think of the. NET core discomfort. But as long as ideas escalate, even developing. NET Framework applications can enjoy the convenience of. NET Standard.

In the writing process, there may be omissions, but I will try to make some additions and deletions in time, so if it is seen on the content may be outdated, please also visit my blog , and the sample code of this article will also make corresponding changes.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.