[转帖]庐山真面目之十五微服务架构的动态分离的设计实现

庐山真面目,十五,服务,架构,动态,分离,设计,实现 · 浏览次数 : 0

小编点评

**Services Configuration** ```csharp // Configure email options from memory builder.Services.Configure(options => { options.Title = "FromMemory"; options.From = "services.Configure--Name-null--Same with ConfigureAll"; }); // Configure email options from configuration builder.Services.Configure(builder.Configuration.GetSection("Email")); // Configure email new options from configuration builder.Services.Configure(builder.Configuration.GetSection("EmailNew")); // Configure email options from a configuration file builder.Services.AddOptions().Configure(options => { options.Title = "AddOtpion Title-- DefaultName"; }); // Configure email options from a configuration file with a null value builder.Services.Configure(null, options => { options.From = "services.Configure--Name-null--Same with ConfigureAll"; }); // Configure email options from a configuration file with a name-based value builder.Services.Configure("AddOption").Configure(options => { options.Title = "AddOtpion Title-- DefaultName"; }); // Configure email options from a configuration file with a path-based value builder.Services.Configure("services.Configure<EmailOption>--Name-null--Same with ConfigureAll").Configure(options => { options.Title = "AddOtpion Title-- DefaultName"; }); // Configure email options from a configuration file with a path-based value with a null value builder.Services.Configure("services.Configure<EmailOption>--Name-null--Same with ConfigureAll").Configure(options => { options.From = "services.Configure<EmailOption>--Name-null--Same with ConfigureAll"; }); // Configure email options from a configuration file with a path-based value with a null value builder.Services.Configure("services.Configure<EmailOption>--Name-null--Same with ConfigureAll").Configure(options => { options.From = "services.Configure<EmailOption>--Name-null--Same with ConfigureAll"; }); // Configure email options from a configuration file with a path-based value with a null value builder.Services.Configure("services.Configure<EmailOption>--Name-null--Same with ConfigureAll").Configure(options => { options.Title = "AddOtpion Title-- DefaultName"; }); // Configure email options from a configuration file with a path-based value with a null value builder.Services.Configure("services.Configure<EmailOption>--Name-null--Same with ConfigureAll").Configure(options => { options.From = "services.Configure<EmailOption>--Name-null--Same with ConfigureAll"; }); // Configure email options from a configuration file with a path-based value with a null value builder.Services.Configure("services.Configure<EmailOption>--Name-null--Same with ConfigureAll").Configure(options => { options.Title = "AddOtpion Title-- DefaultName"; }); // Configure email options from a configuration file with a path-based value with a null value builder.Services.Configure("services.Configure<EmailOption>--Name-null--Same with ConfigureAll").Configure(options => { options.From = "services.Configure<EmailOption>--Name-null--Same with ConfigureAll"; }); ```

正文

https://www.cnblogs.com/PatrickLiu/p/16688731.html

 

一、开场白
      我是一名程序员,是基于 NET 框架的跨平台开发的程序员。现在的业务系统,不论大小都开始实现了微服务,不管合不合适,最起码说起来挺牛气的。我做一位程序员,当然也不能落后了。微服务是为了满足高并发、高可用和高扩展特性进化出来的一个架构模式。一个微服务架构中,为了解决其中一个性能问题,可能就会有很多技术方案。我今天就和大家天天为了应付高并发可以使用的缓存和动态分离的设计,听起来挺高大上的,其实实现起来也没有那么复杂。
      开发环境我简单的介绍一下。
          开发语言:C#
          开发工具:Visual Studio 2022
          开发框架:ASP.NET WEB MVC
          负载均衡:Nginx(Windows版本)。
          操作系统:Windows10 专业版

二、代码实现
            代码实现分为两个部分,第一个部分是有关Nginx的配置,第二个部分是C#代码扩展的中间件的实现。
      1、Nginx配置的实现。
                               说明一下,Nginx的配置文件里包含了很多其他部分,我都放在一起了,便于以后自己查用,如果使用,需要过滤一下。里面都有备注,说的很清楚。
                               

复制代码
#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #缓存设置
    proxy_cache_path /MicroService\MicroServiceCode\NginxCache\Data levels=1:2 keys_zone=web_cache:50m inactive=1m max_size=1g;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    #集群地址
    #dotnet run PatrickLiu.MicroServices.Webs.exe --urls="http://*:5678" --ip="127.0.0.1" --port="5678"
    #dotnet run PatrickLiu.MicroServices.Webs.exe --urls="http://*:5679" --ip="127.0.0.1" --port="5679"
    #dotnet run PatrickLiu.MicroServices.Webs.exe --urls="http://*:5680" --ip="127.0.0.1" --port="5680"
    #负载均衡策略
    #1)、轮训
    #2)、权重 server 127.0.0.1:5678 weight=1;
    #3)、url_hash:hash $request_uri
    #4)、ip_hash:ip_hash
    #5)、least_conn:最少连接数
    #6)、fair:

    upstream MicroServices{
        #ip_hash;
        server 127.0.0.1:5678 weight=1;
        server 127.0.0.1:5679 weight=15;
        server 127.0.0.1:5680 weight=10;
    }

    server {
        listen       8086;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        #单对单请求转发
        #location / {
        #    proxy_pass http://127.0.0.1:7152;
        #}

        #单对多集群配置
        location / {
            proxy_pass http://MicroServices;
        }


        #缓存配置
        location /third/{
            proxy_store off;
            proxy_redirect off;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $http_host;
            proxy_pass http://127.0.0.1:7152/third/;

            proxy_cache web_cache;
            proxy_cache_valid 200 304 2m;
            proxy_cache_key $scheme$proxy_host$request_uri;
        }

        #动静分离
        location /item/{
            alias E:\MicroService\MicroServiceCode\NginxHtmls/;#root的话需要拼接地址
            if (!-f $request_filename){#如果文件不存在直接转发到服务器生成
                proxy_pass http://MicroServices;
                break;
            }
        }
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}
}
复制代码


      2、中间件扩展实现。
                               代码也很简单,我是直接扩展的MVC的中间件实现的静态化。废话不多说,直接上代码。
                                

复制代码
 1 namespace PatrickLiu.MicroServices.Webs.Extensions
 2 {
 3     /// <summary>
 4     /// 自定义扩展静态中间件实现。
 5     /// </summary>
 6     public static class StaticPageMiddlewareExtensions
 7     {
 8         /// <summary>
 9         /// 
10         /// </summary>
11         /// <param name="app"></param>
12         /// <param name="path"></param>
13         /// <param name="isDelete"></param>
14         /// <param name="isWarnup"></param>
15         /// <returns></returns>
16         public static IApplicationBuilder UseStaticPage(this IApplicationBuilder app,string path,bool isDelete,bool isWarnup)
17         {
18             return app.UseMiddleware<StaticPageMiddleware>(path,isDelete,isWarnup);
19         }
20     }
21 }
复制代码
复制代码
  1 namespace PatrickLiu.MicroServices.Webs.Extensions
  2 {
  3     /// <summary>
  4     /// 支持在返回HTML时,将返回的Stream保存到指定目录。
  5     /// </summary>
  6     public sealed class StaticPageMiddleware
  7     {
  8         private readonly RequestDelegate _next;
  9         private string _directoryPath;
 10         private bool _supportDelete;
 11         private bool _supportWarmup;
 12 
 13         /// <summary>
 14         /// 构造实例。
 15         /// </summary>
 16         /// <param name="next"></param>
 17         /// <param name="directoryPath"></param>
 18         /// <param name="supportDelete"></param>
 19         /// <param name="supportWarmup"></param>
 20         public StaticPageMiddleware(RequestDelegate next, string directoryPath = "", bool supportDelete = false, bool supportWarmup = false)
 21         {
 22             _next = next;
 23             _directoryPath = directoryPath;
 24             _supportDelete = supportDelete;
 25             _supportWarmup = supportWarmup;
 26         }
 27 
 28         /// <summary>
 29         /// 
 30         /// </summary>
 31         /// <param name="context"></param>
 32         /// <returns></returns>
 33         public async Task InvokeAsync(HttpContext context)
 34         {
 35             if (context.Request.Headers.ContainsKey("XmlHttpRequest"))
 36             {
 37                 await _next(context);
 38             }
 39             else if (_supportDelete && "Delete".Equals(context.Request.Query["ActionHeader"]))
 40             {
 41                 DeleteHtml(context.Request.Path.Value);
 42                 context.Response.StatusCode = 200;
 43             }
 44             else if (_supportWarmup && "ClearAll".Equals(context.Request.Query["ActionHeader"]))
 45             {
 46                 ClearDirectory(10);//考虑数量级
 47                 context.Response.StatusCode = 200;
 48             }
 49             else if (context.Request.Path.Value.Contains("/item/", StringComparison.OrdinalIgnoreCase))
 50             {
 51                 var originalStream = context.Response.Body;
 52                 using (var copyStream = new MemoryStream())
 53                 {
 54                     context.Response.Body = copyStream;
 55                     await _next(context);
 56 
 57                     copyStream.Position = 0;
 58                     var reader = new StreamReader(copyStream);
 59                     var content = await reader.ReadToEndAsync();
 60                     string url = context.Request.Path.Value;
 61                     await SaveHtml(url, content);
 62 
 63                     copyStream.Position = 0;
 64                     await copyStream.CopyToAsync(originalStream);
 65                     context.Response.Body = originalStream;
 66                 }
 67             }
 68             else
 69             {
 70                 await _next(context);
 71             }
 72         }
 73 
 74 
 75         /// <summary>
 76         /// 
 77         /// </summary>
 78         /// <param name="v"></param>
 79         private void ClearDirectory(int index)
 80         {
 81             if (index > 0)
 82             {
 83                 try
 84                 {
 85                     var files = Directory.GetFiles(_directoryPath);
 86                     foreach (var file in files)
 87                     {
 88                         File.Delete(file);
 89                     }
 90                 }
 91                 catch (Exception ex)
 92                 {
 93                     Console.WriteLine($"Clear Directory failed {ex.Message}");
 94                     ClearDirectory(index--);
 95                 }
 96             }
 97         }
 98 
 99         /// <summary>
100         /// 可以指定策略删除Html文件。
101         /// </summary>
102         /// <param name="url"></param>
103         private void DeleteHtml(string url)
104         {
105             if (string.IsNullOrEmpty(url))
106             {
107                 return;
108             }
109             try
110             {
111                 if (!url.EndsWith(".html", StringComparison.OrdinalIgnoreCase))
112                 {
113                     return;
114                 }
115                 var fullPath = Path.Combine(_directoryPath,url.Split("/").Last());
116                 File.Delete(fullPath);
117             }
118             catch (Exception ex)
119             {
120                 Console.WriteLine($"Delete {url} 异常,{ex.Message}");
121             }
122         }
123 
124         /// <summary>
125         /// 将 HTML 内容写到服务器上。
126         /// </summary>
127         /// <param name="url"></param>
128         /// <param name="content"></param>
129         /// <exception cref="NotImplementedException"></exception>
130         private async Task SaveHtml(string url, string content)
131         {
132             if (string.IsNullOrEmpty(content) || string.IsNullOrEmpty(url))
133             {
134                 return;
135             }
136 
137             if (!url.EndsWith(".html", StringComparison.OrdinalIgnoreCase))
138             {
139                 return;
140             }
141 
142             try
143             {
144 
145                 if (!Directory.Exists(_directoryPath))
146                 {
147                     Directory.CreateDirectory(_directoryPath);
148                 }
149 
150                 var fullPath = Path.Combine(_directoryPath, url.Split("/").Last());
151                 await File.WriteAllTextAsync(fullPath, content);
152             }
153             catch (Exception ex)
154             {
155                 Console.WriteLine(ex.Message);
156             }
157         }
158     }
159 }
复制代码
复制代码
 1 using PatrickLiu.MicroServices.Interfaces;
 2 using PatrickLiu.MicroServices.Models;
 3 using PatrickLiu.MicroServices.Services;
 4 using PatrickLiu.MicroServices.Webs.Extensions;
 5 
 6 var builder = WebApplication.CreateBuilder(args);
 7 
 8 // Add services to the container.
 9 builder.Services.AddControllersWithViews();
10 
11 #region Options
12 
13 string configurationDateTime = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss fff");
14 
15 builder.Services.Configure<EmailOption>(op => op.Title = $"services.Configure<EmailOption>--DefaultName {configurationDateTime}--{DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss fff")}");
16 
17 builder.Services.Configure<EmailOption>("FromMemory", op => op.Title = "services.Configure<EmailOption>----FromMemory");
18 
19 builder.Services.Configure<EmailOption>("FromConfiguration", builder.Configuration.GetSection("Email"));
20 
21 builder.Services.Configure<EmailNewOption>("FromConfigurationNew", builder.Configuration.GetSection("EmailNew"));
22 
23 builder.Services.AddOptions<EmailOption>("AddOption").Configure(op => op.Title = "AddOtpion Title-- DefaultName");
24 
25 builder.Services.Configure<EmailOption>(null, op => op.From = "services.Configure<EmailOption>--Name-null--Same with ConfigureAll");
26 
27 builder.Services.PostConfigure<EmailOption>(null, op => op.Body = "services.PostConfigure<EmailOption>--Name null---Same with PostConfigureAll");
28 
29 #endregion
30 
31 //builder.Services.AddSingleton<OrderServiceOption>();
32 //builder.Services.AddScoped<IOrderServiceForOptions, MyOrderServiceForOptions>();//Scoped<==>IOptionSnapshot
33 builder.Services.AddSingleton<IOrderServiceForOptions, MyOrderServiceForOptions>();//AddSingleton<==>IOptionMonitor
34 builder.Services.Configure<OrderServiceOption>(builder.Configuration.GetSection("MyCount"));
35 builder.Services.PostConfigure<OrderServiceOption>(p => {
36     p.MaxOrderCount += 1212121;
37 });
38 
39 
40 var app = builder.Build();
41 
42 // Configure the HTTP request pipeline.
43 if (!app.Environment.IsDevelopment())
44 {
45     app.UseExceptionHandler("/Home/Error");
46 }
47 app.UseStaticFiles();
48 
49 app.UseStaticPage(@"E:\MicroService\MicroServiceCode\NginxHtmls", false, false);静态中间件使用方法。
50 
51 app.UseRouting();
52 
53 app.UseAuthorization();
54 
55 app.MapControllerRoute(
56     name: "default",
57     pattern: "{controller=Home}/{action=Index}/{id?}");
58 
59 app.Run();
复制代码


                     3、实现效果。
                             1】、缓存的目录生成。
                                         


                            2】、静态文件的生成
                                  

 

三、结束
                   好了,今天就到这里了,有了新的积累在保存起来。程序员这个行业需要持续学习,其实,不光是程序员这个行业,很多行业都是需要持续学习的,只不过我们持续学习的内容不同而已。老天不会辜负努力的人,我们坚持自己,努力在学习中改变自己,在提升自己的同时可以让自己更融合,发现我们的目标。技术好是一个追求,也是一个承诺,对人对己都是一样。努力前进,不负韶华。

天下国家,可均也;爵禄,可辞也;白刃,可蹈也;中庸不可能也

与[转帖]庐山真面目之十五微服务架构的动态分离的设计实现相似的内容:

[转帖]庐山真面目之十五微服务架构的动态分离的设计实现

https://www.cnblogs.com/PatrickLiu/p/16688731.html 一、开场白 我是一名程序员,是基于 NET 框架的跨平台开发的程序员。现在的业务系统,不论大小都开始实现了微服务,不管合不合适,最起码说起来挺牛气的。我做一位程序员,当然也不能落后了。微服务是为了满

[转帖]庐山真面目之十三微服务架构中如何在Docker上使用Redis缓存

https://www.cnblogs.com/PatrickLiu/p/14518160.html 一、介绍 1、开始说明 在微服务器架构中,有一个组件是不能少的,那就是缓存组件。其实来说,缓存组件,这个叫法不是完全正确,因为除了缓存功能,它还能完成其他很多功能。我就不隐瞒了,今天我们要探讨的就是

[转帖]

Linux ubuntu20.04 网络配置(图文教程) 因为我是刚装好的最小系统,所以很多东西都没有,在开始配置之前需要做下准备 环境准备 系统:ubuntu20.04网卡:双网卡 网卡一:供连接互联网使用网卡二:供连接内网使用(看情况,如果一张网卡足够,没必要做第二张网卡) 工具: net-to

[转帖]

https://cloud.tencent.com/developer/article/2168105?areaSource=104001.13&traceId=zcVNsKTUApF9rNJSkcCbB 前言 Redis作为高性能的内存数据库,在大数据量的情况下也会遇到性能瓶颈,日常开发中只有时刻

[转帖]ISV 、OSV、 SIG 概念

ISV 、OSV、 SIG 概念 2022-10-14 12:29530原创大杂烩 本文链接:https://www.cndba.cn/dave/article/108699 1. ISV: Independent Software Vendors “独立软件开发商”,特指专门从事软件的开发、生产、

[转帖]Redis 7 参数 修改 说明

2022-06-16 14:491800原创Redis 本文链接:https://www.cndba.cn/dave/article/108066 在之前的博客我们介绍了Redis 7 的安装和配置,如下: Linux 7.8 平台 Redis 7 安装并配置开机自启动 操作手册https://ww

[转帖]HTTPS中间人攻击原理

https://www.zhihu.com/people/bei-ji-85/posts 背景 前一段时间,公司北京地区上线了一个HTTPS防火墙,用来监听HTTPS流量。防火墙上线之前,邮件通知给管理层,我从我老大那里听说这个事情的时候,说这个有风险,然后意外地发现,很多人原来都不知道HTTPS防

[转帖]关于字节序(大小端)的一点想法

https://www.zhihu.com/people/bei-ji-85/posts 今天在一个技术群里有人问起来了,当时有一些讨论(不完全都是我个人的观点),整理一下: 为什么网络字节序(多数情况下)是大端? 早年设备的缓存很小,先接收高字节能快速的判断报文信息:包长度(需要准备多大缓存)、地

[转帖]awk提取某一行某一列的数据

https://www.jianshu.com/p/dbcb7fe2da56 1、提取文件中第1列数据 awk '{print $1}' filename > out.txt 2、提取前2列的文件 awk `{print $1,$2}' filename > out.txt 3、打印完第一列,然后打

[转帖]awk 中 FS的用法

https://www.cnblogs.com/rohens-hbg/p/5510890.html 在openwrt文件 ar71xx.sh中 查询设备类型时,有这么一句, machine=$(awk 'BEGIN{FS="[ \t]+:[ \t]"} /machine/ {print $2}' /