中小研发团队架构实践之生产环境诊断工具WinDbg 三分钟学会.NET微服务之Polly 使用.Net Core+IView+Vue集成上传图片功能 Fiddler原理~知多少? ABP框架(asp.

中小研发团队架构实践之生产环境诊断工具WinDbg

生产环境偶尔会出现一些异常问题,WinDbg或GDB是解决此类问题的利器。调试工具WinDbg如同医生的听诊器,是系统生病时作问题诊断的逆向分析工具,Dump文件相似于飞机的黑匣子,记录着生产环境程序运行的状态。本文主要介绍了调试工具WinDbg和抓包工具ProcDump的使用,并分享一个真实的案例。N年前不知谁写的代码,致使每一两个月偶尔出现CPU飙高的现象。咱们先使用ProcDump在生产环境中抓取异常进程的Dump文件,而后在不了解代码的状况下经过WinDbg命令进行分析,最终定位到有问题的那行代码。css

1、诊断工具简介
1.1 WinDbg

WinDbg是在Windows平台下的、强大的用户态和内核态调试工具。相比较于Visual Studio,它是一个轻量级的调试工具,所谓轻量级指的是它的安装文件大小较小,可是其调试功能,却比VS更为强大。它的另一个用途是能够用来分析Dump数据。WinDbg是Microsoft公司免费调试器调试集合中的GUI的调试器,支持Source和Assembly两种模式的调试。WinDbg不只能够调试应用程序,还能够进行Kernel Debug。结合Microsoft的Symbol Server,能够获取系统符号文件,便于应用程序和内核的调试。WinDbg支持的平台包括x8六、IA6四、AMD64。虽然WinDbg也提供图形界面操做,但它最强大的地方仍是有着强大的调试命令,通常状况会结合GUI和命令行进行操做,经常使用的视图有:局部变量、全局变量、调用栈、线程、命令、寄存器、白板等。其中“命令”视图是默认打开的。html

1.2 DebugDiag

DebugDiag最初是为了帮助分析IIS的性能问题而开发的,它一样能够用于任何其余的进程。DebugDiag工具主要用于帮助解决如挂起、 速度慢、 内存泄漏或内存碎片,和任何用户模式进程崩溃等问题。该工具包括附加调试脚本,侧重于互联网信息服务(IIS)应用程序、 Web数据访问组件、 COM+和相关Microsoft技术、SharePoint和.NET。它提供可扩展对象模型中的COM对象的形式,并具备一个内置的报告框架提供的脚本主机。它由3 部分组成,包括调试服务、 调试器主机和用户界面。前端

1.3 ProcDump

ProcDump是System Internal提供的一个专门用来监测程序CPU高使用率从而生成进程Dump文件的工具。ProcDump能够根据系统的CPU使用率或者指定的性能计数器来针对特定进程生成一系列的Dump文件,以便调试者对事故缘由进行分析。vue

2、诊断工具下载
3、获取异常进程的Dump文件

有如下四种方式获取Dump文件,具体以下:node

3.1 经过【任务管理器】获取Dump文件,这样获取的是MinDump

3.2 利用WinDbg的adplus获取Dump文件,这样获取的是FullDump

3.3 经过DebugDiag建立.NET异常转储Dump文件

3.4 经过ProcDump抓取异常线程Dump文件

如今重点介绍经过ProcDump抓取异常线程Dump文件,使用方法以下:ios

a. 命令行:
procdump [-a] [[-c|-cl CPU usage] [-u] [-s seconds]] [-n exceeds] [-e [1 [-b]] [-f <filter,...>] [-g] [-h] [-l] [-m|-ml commit usage] [-ma | -mp] [-o] [-p|-pl counter threshold] [-r] [-t] [-d <callback DLL>] [-64] <[-w] <process name or service name or PID> [dump file] | -i <dump file> | -u | -x <dump file> <image file> [arguments] >] [-? [ -e]
b. 实例:

procdump -c 70 -s 5 -ma -n 3 w3wpgit

当系统CPU使用率持续5秒超过70%时,连续抓3个Full Dump。github

procdump outlook -p "\Processor(_Total)\% Processor Time" 80web

当系统CPU使用率超过80%,抓取Outlook进程的Mini Dump。redis

procdump -ma outlook -p "\Process(Outlook)\Handle Count" 10000

当Outlook进程Handle数超过10000时抓取Full Dump

procdump -ma 4572

直接生成进程号为4572的Full Dump。

 

下图是在WindgbHighCpu进程中形成High CPU时运行ProcDump命令的运行效果,能够看到在CPU每次持续5秒达到5%后就会生成相应的Dump文件,共生成了3份Full Dump文件:

c. 注意:
  • ProcDump须要进程已经启动,而且中途不能中止。好比须要抓取IIS Worker Process的High CPU Dump,因为IIS Worker Process默认会配置Idle Timeout = 20 min,即该进程在20分钟内没有任何请求的话就会自动结束,这种状况下ProcDump也会自动结束。须要从新运行命令。所以若是目标程序存在这样的配置,须要暂时将该配置取消。
  • 有些系统管理员但愿可以运行该工具后退出用户session,ProcDump是作不到的,若是有这种需求能够考虑使用DebugDiag。
  • 在调试High CPU问题的时候常常用到的一个命令是!runaway,可是有些时候!runway在ProcDump抓取Dump文件的过程当中运行不出来,报错信息以下:
0:000> !runaway ERROR: !runaway: extension exception 0x80004002. "Unable to get thread times - dumps may not have time information"

解决的方法是将Debugging Tools for Windows (WinDbg)安装目录下的dbghelp.dll拷贝到procdump.exe所在目录下,而后再运行命令抓取Dump。 

4、WinDbg使用方法

操做步骤以下:

4.1 抓取异常程序的Dump文件
4.2 设置符号表

符号表是WinDbg关键的“数据库”,若是没有它,WinDbg基本上就是个废物,没法分析更多问题。因此使用WinDbg设置符号表,是必需要走的一步。

a、运行WinDbg软件,而后按【Ctrl+S】弹出符号表设置窗。

b、将符号表地址:SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols 粘贴在输入框中,点击肯定便可。点击肯定以前,请先确认红色字的文件夹是否已被新建。

注:红色字表示符号表本地存储路径,建议固定路径,可避免符号表重复下载。

4.3 学会打开第一个Dump文件

       

 

当你拿到一个Dump文件后,可以使用【Ctrl+D】快捷键来打开一个Dump文件,或者点击WinDbg界面上的【File=>Open Crash Dump...】按钮,来打开一个Dump文件。第一次打开Dump文件时,可能会收到以下提示,出现这个提示时,勾选“Don't ask again in this WinDbg session”,而后点否便可。

当你想打开第二个Dump文件时,可能由于上一个分析记录未清除,致使没法直接分析下一个Dump文件,此时你可使用快捷键【Shift+F5】来关闭上一个对Dump文件的分析记录。

4.4 经过简单的几个命令学会分析Dump文件

分享一个数据库链接超时的Dump案例的分析过程:

当你打开一个Dump文件后,可能由于太多信息,让你无所适从,不过不要紧,咱们只须要关注几个关键信息就能够了。

a. 加载SOS扩展命令

加载SOS以前,先肯定SOS的位置和版本,肯定方法以下:

若是安装了Visual Studio,那么先按照以下步骤打开VS的命令行:

而后,在打开的VS命令行中输入【where sos.dll】,使得到SOS的位置和版本:

 

肯定完SOS位置和版本号后,开始加载SOS扩展命令:

.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.dll

以下图所示:

b. 使用!clrstack命令来查看当前的调用堆栈信息

以下图所示:

c. 使用!dso命令来查看堆栈上的全部对象详细信息

以下图所示:

综合以上分析能够大胆地猜想Common.cs 中第16行“Data Source=***;Initial Catalog=***;Persist Security Info=True;User ID=sa;Password=***”的这个数据库链接字符串应该有问题,而后到代码中相应的地方进一步确认和修改就能够了。        

5、一个真实案例

分享笔者工做过的一家公司某业务系统CPU飙高90%以上的Dump分析过程案例,步骤以下:

5.1 使用ProcDump抓包
5.2 加载SOS扩展命令
.load C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll

5.3 分析

执行!runaway命令,查看线程使用CPU时间状况,以下图所示。着重分析前面几个线程。 

执行~22s命令,进入到线程22,以下图所示:

执行!clrstack命令查看当前线程堆栈变量值的信息,从图中能够猜出大概是ExecuteNonQuery()这方法有点问题,以下图所示:

再执行!dso命令能够查看堆栈上的全部对象详细信息,以下图所示:

从图中看,形成CPU飙高的罪魁祸首多半由SQL Server执行

INSERT INTO [dbo].[tbl_Interface_ProcessLog] (IKey,Username,ClientIP,Module,OrderNo,LogType,Content) VALUES (@IKey,@Username,@ClientIP,@Module,@OrderNo,@LogType,@Content)

这条语句时产生异常引发,而后到源代码中找出相应的语句,通过进一步的确认、修改和从新发布后就解决了CPU飙高的问题。

 

至此,掌握几个简单的WinDbg命令以后,基本上绝大多数Dump你们均可以独立分析了。固然WinDbg是个强大的工具,同时产生CPU飙高和内存泄漏的缘由也有不少。若是想分析得足够准确,那么就只有多学多练,多去分析。由于掌握WinDbg分析除了须要懂得几个命令以外,经验更加剧要,最后再补充两点:

  1. WinDbg不是专门用于调试.NET程序的工具,它更偏向于底层,可用于内核和驱动调试,特别是对于某些至关疑难的问题调试有所帮助,例如内存泄漏等问题。进行普通的.NET程序调试仍是使用微软专为.NET开发所提供的调试工具更方便一些。
  1. SOS扩展命令中最有用的命令是!help,使用该命令能够列出全部可用的SOS扩展命令列表,使用!help [SOSCommandName]能够查看每个具体扩展命令的详细使用说明。例如!help dumpheap就能够查看!dumpheap这个扩展命令的具体使用方法。多多利用!help命令能够很快上手SOS。
6、Demo下载及更多资料

 

 

熔断降级是一个很是重要的概念,咱们先说一下什么是熔断降级,我们都知道服务发现,一个有问题的服务器没来得急注销过一会就崩溃掉了,那么咱们的请求就有可能访问一个已经崩溃的服务器,那么就会请求失败,由于已经game over了。那么这个问题怎么解决呢,你必定要认可,这个问题是没法避免的。没有什么方法说,我拿到的服务器都没有问题,这事是不可能的,因此你要认可你会有机会拿到有问题的服务器。那么熔断降级就是来解决这种问题的。

 

 一.什么是熔断

熔断就像是“保险丝”,当出现梦中情况时,切断服务,从而防止应用程序不断地尝试形成雪崩,这和咱们农村的保险丝很像,天气热了防止火灾,那保险丝会自动断开,防止更大的损失。

降级的目的是当某个服务提供者发生故障的时候,向调用方返回一个错误响应替代响应。

好比咱们要作一个双11活动的系统,那么好比一个抽奖的模块崩溃,这个时候呢广大客户端疯狂F5,就会致使整个集群雪崩,这个时候咱们就应该中断。

还有一栗子,好比说电信和联通,它们在稳定,有也不稳定的时候,那么若是咱们用它们的接口,若是电信崩了,咱们就是用联通,这种操做的行为就叫作熔断降级。

其使用场景呢,例如,咱们要展现商品信息,咱们先从数据库读取,读取失败了,咱们就经过cache/redis,若是再失败,咱们经过固定的Javascript object 来绑定,若是再失败那就返回一个错误的信息。这就是完美的下降了错误。

这种错误的几率就犹如0.01*way³  就是1000次才会出现的几率。那若是是不熔断降级 就是100.以上一些栗子,好好读读便可。

 

二.Polly介绍

.Net Core 中有一个被.Net基金会承认的k库,能够用来进行熔断降级,主要功能:1.重试(retry);2.断路器(circuit-breaker);3.超时检测(timeout);4.缓存(cache);5.降级(fallback)

 官方:https://github.com/app-vnext/polly  nuget: install-package Polly-Version 6.0.1

 

三.使用

建立项目与安装库,为了稳定仍是选择6.0.1吧。

使用Policy的静态方法建立ISyncPolicy实现类对象,建立方法j既有同步方法也有异步方法,根据本身的需求来选择,下面先演示同步方法,异步的方法也相似。

复制代码
复制代码
static void Main(string[] args)
        {
            //handle 当发生argumentException的异常
            Policy policy = Policy.Handle<ArgumentException>()
                .Fallback(() =>
                {
                    //就干什么事情
                    Console.WriteLine("出错了");
                });
       //有可能异常的时候 policy.Execute(() => { Console.WriteLine("开始执行"); throw new ArgumentException(); Console.WriteLine("执行结束"); }); }
 
复制代码

咱们运行一下,是以下结果。

但若是书咱们故意写一个抛出异常,咱们稍微修改一下代码。

复制代码
复制代码
policy.Execute(() =>
            {
                Console.WriteLine("开始执行");
                throw new ArgumentException();
                Console.WriteLine("执行结束");
            });
 
复制代码

上面呢,我么捕捉的是ArgumentException异常,那么咱们若是是报的其余的错误应该会怎样呢?

复制代码
复制代码
policy.Execute(() =>
            {
                Console.WriteLine("开始执行");
                throw new Exception();
                Console.WriteLine("执行结束");
            });
 
复制代码

 FallBack中有不少不一样的重载,咱们能够根据重载获取不一样的报错信息,如下是全部的方法。

咱们能够简单的去获取一个对象,代码以下:

复制代码
复制代码
 Policy policy = Policy.Handle<ArgumentException>()
                .Fallback(() =>
                {
                    //就干什么事情
                    Console.WriteLine("出错了");
                },ex=> {
                    Console.WriteLine(ex.Message);
                });
            policy.Execute(() =>
            {
                Console.WriteLine("开始执行");
                throw new ArgumentException();
                Console.WriteLine("执行结束");
            });
 
复制代码

由于我们的业务逻辑啊有多是带返回值的,也有多是不带返回值的。那若是你的业务逻辑是带返回值的,你就得用一个Policy带参的泛型来建立,那么这个Policy也是泛型的,在FallBack中也要 提一个替代值,由于毕竟是降级嘛,确定要有一个值来进行替代。

复制代码
复制代码
Policy<string> policy = Policy<string>.Handle<Exception>()
                .Fallback(() =>
                {
                    return "降级后的值";
                });
           string value = policy.Execute(() => {
                return "正常值";
            });
 
复制代码
 

四.重试处理

polly提供了重试处理机制,那么这个RetryForever()的场景不可能会出现,我也不知道它是处于什么个操做。我以为这违背了熔断降级,这不可能让它重试的,那么如下就是用法,可是这根本用不着~

仍是推荐使用Retry吧。Retry中能够写个int值进去,就是重试的次数,这个仍是不错的!

复制代码
复制代码
Policy policy = Policy.Handle<Exception>().RetryForever();
            policy.Execute(() => {
                Console.WriteLine("play task!!");
                if (DateTime.Now.Second % 10 != 0)
                {
                    throw new Exception();
                }
                Console.WriteLine("完成任务!");
            });
 
复制代码

不过仍是有比较正常点的方法,例如WaitAndRetry这个方法,等等再重试。这个很不错!这个方法里的重载很是之多。

复制代码
复制代码
Policy policy = Policy.Handle<Exception>().WaitAndRetry(100, i => TimeSpan.FromMinutes(100));
            policy.Execute(() => {
                Console.WriteLine("play task!!");
                if (DateTime.Now.Second % 10 != 0)
                {
                    throw new Exception();
                }
                Console.WriteLine("完成任务!");
            });
 
复制代码
 

 五.短路保护Circuit Breaker

短路保护是什么意思呢,这个单词翻译过来就叫作线路切断器,出现N次连续错误,则把“熔断器”(保险丝)熔断,等待一段时间,等待这段时间内若是再Execute则直接抛出BrokenCircuitException异常,根本不会再去尝试调用业务代码。等待时间过去以后,再执行Execute的时候若是又错了(一次就够了),那么继续熔断一段时间,不然就恢复正常。这样就避免一个服务已经不可用了,仍是使劲的请求给系统形成更大压力。

这样就避免了一个服务不可用了还在使劲的请求。

复制代码
复制代码
 Policy policy = Policy
            .Handle<Exception>()
            .CircuitBreaker(3, TimeSpan.FromSeconds(5));//连续出错3次以后熔断5秒(不会再
            while (true)
            {
                Console.WriteLine("开始Execute");
                try
                {
                    policy.Execute(() =>
                    {
                        Console.WriteLine("开始任务");
                        throw new Exception("出错");
                        Console.WriteLine("完成任务");
                    });
                }
                catch (Exception ex)
                {
                    Console.WriteLine("execute出错" + ex);
                }
                Thread.Sleep(500);
            }
 
复制代码

 这就像刚才咱们说的,我设置了连续3次熔断,那么若是连续3次报错,那么直接再也不执行之后的内容,这无疑是很是不错的机制。保证了服务器的性能丢失和不起眼的问题。

 

 六.策略封装与超时处理

策略封装使用的方法是Policy提供的Wrap方法,英译叫作包裹,那么从单词的意思就知道,能够经过策略包裹策略来进行封装,即里面的不行,就走外面的。

复制代码
复制代码
Policy policyRetry = Policy.Handle<Exception>()
                .Retry(3);
            Policy policyFallback = Policy.Handle<Exception>()
                .Fallback(() =>
                {
                    Console.WriteLine("降级");
                });
            Policy policy = policyFallback.Wrap(policyRetry);
            policy.Execute(() =>
            {
                Console.WriteLine("play task!!");
                if (DateTime.Now.Second % 10 != 0)
                {
                    throw new Exception();
                }
                Console.WriteLine("完成任务!");
            });
 
复制代码

注意这个wrap的包裹顺序的,外在后,内在前。再经过一个超时处理就能够对消耗时间够长的请求进行GG了。

那么你就能够经过超时处理来对咱们文章开头的诉说进行一个很是生动形象的经过代码来宣誓。下面说明超时异常的说明

复制代码
复制代码
Policy policytimeout = Policy.Timeout(3, TimeoutStrategy.Pessimistic);
            Policy policyFallBack = Policy.Handle<TimeoutRejectedException>()
                .Fallback(() =>
                {
                    Console.WriteLine("熔断降级");
                });
            Policy policy = policyFallBack.Wrap(policytimeout);
            policy.Execute(() =>
            {
                Console.WriteLine("完成任务");
                Thread.Sleep(5000);
                Console.WriteLine("完成任务");
            });
            Console.ReadKey();
 
复制代码

这玩腻的用途不过就是:请求网络接口,避免接口长期没有响应形成系统卡死。

 

 七.Polly的异步

复制代码
复制代码
     Test1().Wait(); //调用

        static async Task Test1()
        {

            Policy<byte[]> policy = Policy<byte[]>
           .Handle<Exception>()
           .FallbackAsync(async c => {
               Console.WriteLine("执行出错");
               return new byte[0];
           }, async r => {
               Console.WriteLine(r.Exception);
           });
            policy = policy.WrapAsync(Policy.TimeoutAsync(20, TimeoutStrategy.Pessimistic,
            async (context, timespan, task) =>
            {
                Console.WriteLine("timeout");
            }));
            var bytes = await policy.ExecuteAsync(async () =>
            {
                Console.WriteLine("开始任务");
                HttpClient httpClient = new HttpClient();
                var result = await httpClient.GetByteArrayAsync("https://www.cnblogs.com/images/logo_small.gif");
                Console.WriteLine("完成任务");
                return result;
            });
            Console.WriteLine("bytes长度" + bytes.Length);
        }
 
复制代码

使用Polly的异步,那么全部的方法都必须是异步,除了Handle方法,由于handle就不须要异步,也没有返回值。经过异步呢,全部的重载方法都构造了一遍,仍是能够继续用的。那么这段代码的意思是,经过异步的方式若是我经过httpclient获取某站点的图片的base值,若是在此期间我定义了一个policy,抓住一个异常,若是说两秒以内尚未反应我就超时。直接终止。测试的时候 你能够把值 改变下。

 

 

 

最近的项目里有上传图片的功能,固然这个功能在项目里是必需要有的,那么目前这个项目是使用彻底的先后端分离,在选择文件上传的组件中仍是选择了全面支持Vue的IView,任何上传图片都是经过HTTP请求,服务端从request中读,那么思路有了,直接建立webapi项目吧。

通常来讲,在.net core中静态文件应该放到wwwroot,在其中建立一个文件夹。

再作好跨域的东西,通常都是经过cors包。建立控制器,代码以下:

复制代码
复制代码
    public class IndexController : ControllerBase
    {
        [HttpPost]
        public async Task<bool> InsertPicture([FromServices]IHostingEnvironment environment)
        {
            var data = new PicData();
            string path = string.Empty;
            var files = Request.Form.Files;
            if (files == null || files.Count() <= 0) { data.Msg = "请选择上传的文件。"; return false; }
            //格式限制
            var allowType = new string[] { "image/jpg", "image/png","image/jpeg"};
            if (files.Any(c => allowType.Contains(c.ContentType)))
            {
                if (files.Sum(c => c.Length) <= 1024 * 1024 * 4)
                {
                    foreach (var file in files)
                    {
                        string strpath = Path.Combine("Upload", DateTime.Now.ToString("MMddHHmmss") + file.FileName);
                        path = Path.Combine(environment.WebRootPath, strpath);

                        using (var stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                        {
                            await file.CopyToAsync(stream);
                        }
                    }
                    data.Msg = "上传成功";
                    return true;
                }
                else
                {
                    data.Msg = "图片过大";
                    return false;
                }
            }
            else

            {
                data.Msg = "图片格式错误";
                return false;
            }
        }

    }
    public class PicData
    {
        public string Msg { get; set; }
    }
 
复制代码

代码解读:

读取wwwroot是在IHostingEnvironment对象中的,若是不经过依赖注入,就须要直接写成参数,那么file上传的参数开头都应该[FromServices]来修饰,在代码中判断了响应的文件格式、文件大小,经过file.copy就把文件保存在了服务器。

须要跨域:

复制代码
复制代码
public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services.AddCors(options =>
            {
                options.AddPolicy("hehe", p => p.AllowAnyMethod()// 容许任何方法 GET,POST,PUT,DELETE, OPTIONS
                            .AllowAnyHeader()       // 容许任何请求头
                            .AllowAnyOrigin()       // 容许任何地址
                   );
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseStaticFiles(); app.UseCors("hehe");
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseMvc();
        }
 
复制代码

前台:

复制代码
复制代码
<template>
    <div>
        <Upload
        multiple
        type="drag"
        action="http://localhost:54331/api/Index">
        <div style="padding: 20px 0">
            <Icon type="ios-cloud-upload" size="52" style="color: #3399ff"></Icon>
            <p>点击或将文件拖拽到这里上传</p>
        </div>
    </Upload>
    </div>
</template>
<script>
export default {

}
</script>
 
复制代码

代码解读::

复制代码
前台是很是简单的,在main.js中引用Iview,固然这一切的前提都须要Npm一下它.iview的这个组件,action就是你请求的方法,默认呢就是post请求。那么Iview还有别的属性,详见下方。
 
属性 说明 类型 默认值
action 上传的地址,必填 String -
headers 设置上传的请求头部 Object {}
multiple 是否支持多选文件 Boolean false
data 上传时附带的额外参数 Object -
name 上传的文件字段名 String file
with-credentials 支持发送 cookie 凭证信息 Boolean false
show-upload-list 是否显示已上传文件列表 Boolean true
type 上传控件的类型,可选值为 select(点击选择),drag(支持拖拽) String select
accept 接受上传的文件类型 String -
format 支持的文件类型,与 accept 不一样的是,format 是识别文件的后缀名,accept 为 input 标签原生的 accept 属性,会在选择文件时过滤,能够二者结合使用 Array []
max-size 文件大小限制,单位 kb Number -

效果图:

文末:

后来咱们团队考虑到使用七牛这个在线储存图片站点,准备好实名的帐号和sdk,获取AccessKey,SecretKey。登陆七牛管理后台->我的信息->秘钥管理

那么官方给咱们提供了.net core 的版本直接nuget就能够了。

 

代码:

复制代码
复制代码
/// <summary>
         /// 实现将文件上传到七牛云
         /// </summary>
         /// <param name="stream">文件流</param>
         /// <param name="fileName">文件名称</param>
         /// <returns></returns>
         public UploadQiNiuResult UploadImgToQiNiu(byte[] stream, string fileName)
         {
             Mac mac = new Mac(BlogStatic.QiNiuInfo_AccessKey, BlogStatic.QiNiuInfo_SecretKey);
             // 上传策略,参见
             // https://developer.qiniu.com/kodo/manual/put-policy
             PutPolicy putPolicy = new PutPolicy();
             // 若是须要设置为"覆盖"上传(若是云端已有同名文件则覆盖),请使用 SCOPE = "BUCKET:KEY"
             // putPolicy.Scope = bucket + ":" + saveKey;
             var saveKey = string.Format("BlogImg/{0}/", DateTime.Now.ToString("yyyy/MM/dd")) + fileName;
             putPolicy.Scope = "blog:" + saveKey;
             // 上传策略有效期(对应于生成的凭证的有效期)
             putPolicy.SetExpires();
             // 上传到云端多少天后自动删除该文件,若是不设置(即保持默认默认)则不删除
             // putPolicy.DeleteAfterDays = 1;
             string jstr = putPolicy.ToJsonString();
             //获取上传凭证
             var uploadToken = Auth.CreateUploadToken(mac, jstr);
             UploadManager um = new UploadManager();
 
             HttpResult result = um.UploadData(stream, saveKey, uploadToken);
 
             )
             {
                 return JsonConvert.DeserializeObject<UploadQiNiuResult>(result.Text);
             }
             return null;
         }
 
复制代码

UploadQiNiuResult类

复制代码
public class UploadQiNiuResult
     {
         public string Hash { get; set; }
         public string Key { get; set; }
     }
 
 
 
 

Fiddler原理~知多少?

 

首先咱们学习Fidder这个工具,咱们就应该去了解它的基本东西,好比这个单词的意思。Fiddler叫:小提琴、骗子的意思。

 

那么它是干什么的呢?

Fiddler是一个http协议调试代理工具,它可以记录并检查全部你的电脑和互联网之间的http通信,设置断点,查看全部的“进出”Fiddler的数据(指cookie,html,js,css等文件)。 Fiddler 要比其余的网络调试器要更加简单,由于它不只仅暴露http通信还提供了一个用户友好的格式,Fiddler 是用C#写出来的,它包含一个简单却功能强大的基于JScript .NET 事件脚本子系统,它的灵活性很是棒,能够支持众多的http调试任务,而且可以使用.net框架语言进行扩展。

那么从简介中能够看到,他是一个http协议的调试工具,那HTTP协议是干什么呢?

HTTP(HyperText Transport Protocol)是超文本传输协议的缩写,它用于传送WWW方式的数据,关于HTTP协议的详细内容请参考RFC2616。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求,请求头包含请求的方法、URL、协议版本、以及包含请求修饰符、客户信息和内容的相似于MIME的消息结构。服务器以一个状态行做为响应,响应的内容包括消息协议的版本,成功或者错误编码加上包含服务器信息、实体元信息以及可能的实体内容。

刚才我说fiddler是个骗子,那它怎么骗的啊,咱们来打开一下。

刚刚打开没多久,这些列表就会慢慢的加进来,这是什么呢?这是来自于你电脑上的http请求的信息。实际上fiddler打开以后就已经进行代理了。

 

Fiddler的原理

 

左侧是咱们的客户端,就是一些终端,那它访问各类网站的时候,会经过http请求经过进行fiddler进行代理,而后再经过fiddler的转发请求服务器,服务器再经过response进行响应,反正就是经过fiddler是个中间层。就是这么个意思。固然,在打开fiddler的时候就已经打开代理了。它是如何进行代理的呢?

为何咱们打开应用或者说软件就会被fiddler进行代理呢?咱们随便打开个页面,例如百度新闻。

咱们发现,咱们只要干什么事,都被会被他们截取,他们到底是干了什么邪门的事情?咱们打开浏览器的设置-搞基-系统-代理。

以下图,咱们逐一打开,发现其中的端口号和咱们的Fiddler工具中的设置端口一毛同样,这就是代理工具关键。固然这也是fiddler修改的。意思就是中间通过了我的,就是这个代理工具,fiddler,因此它能抓到这个包。

其中须要注意的是,当fiddler一关闭,那么这个代理就会被关闭,也就变成灰色的了。

若是是其余浏览器,有可能打开fiddler那个代理可能不会自动开启,须要你本身找,本身开,本身关。。。。

 

 

 

ABP框架(asp.net core 2.X+Vue)模板项目学习之路(一)

 

 

 

 

前言:

  第一次接触ABP的项目是在2018年6月份,可是当时没有深刻具体的研究,而今天由于工做的须要,须要学习、了解这个框架,在时隔半年以后,今天从新下载了这个项目,虽然在园子里有不少前辈们写的这类的文章,可是我仍是会在博客园中记录一下学习的过程,一是但愿可以帮助到有须要的人,二是也算是本身学习的一个历程,虽然原先的时候,偶尔也会写一些随笔,因为文采的缘由,写的可能不是特别的详细,主要也是以代码为主,可是在这个学习的过程当中,会发布一些代码,发布一些截图,同时也会写一些本身的心得!

 

正文:

本篇内容主要说的是从ABP官网下载项目到项目可以在浏览器中正式运行起来的一个过程!

  1. 前期准备工做,具体详细的安装步骤,在园子里有不少大佬和前辈都有介绍,再次就不一一写出来了
    • 根据本身系统的须要去选择安装Node.js(官网地址:https://nodejs.org/en/download/)验证是否安装成功,在windos命令窗口输入:node -v
    • 经过npm安装VUE脚手架(vue-cli):npm install -g vue-cli //-g是全局安装,验证是否安装成功,在windos命令窗口输入:vue -V
    • 安装npm安装yarn:npm install -g yarn,验证是否安装成功,在windos命令窗口输入:yarn -v
  2. 从官网下载ABP项目(官网地址:https://aspnetboilerplate.com/Templates)

  3. 下载项目压缩包后的文件列表展现
  4. 首先咱们先运行aspnet-core项目,经过vs2017打开后,会自动去下载相关的dll字符串,在项目从新生成所有成功后更改MyABPProject.Web.Host这个项目中appsettings.json中的数据库链接字符串,改为本身的字符串,而后进行数据库还原。
  5. 数据库还原方式:
    • 将MyABPProject.EntityFrameworkCore这个项目设置成启动项目(不然会报错:

      The specified framework version '2.1' could not be parsed
      The specified framework 'Microsoft.NETCore.App', version '2.1' was not found.

    • 打开程序包管理器控制台(工具->NuGet包管理器->程序包管理器控制台)
    • 通“Update-Database”这个命令进行数据库还原,等待还原完成后,直接F5启动,在端口号后面加上“/swagger”会在浏览器中看到如下界面运行到此,说明asp.net core服务器端项目已正式启动完成
  6. 接下来咱们来运行vue的客户端程序
    • vue项目的列表信息详细如同所示:
    • 在终端中打开vue项目的目录地址(D:\项目管理\MyABPProject\4.3.1\vue>),经过命令“yarn install”进行安装项目依赖,恢复安装完成后以下图显示:
    • 经过命令“yarn serve --open”直接运行客户端项目,“--open”的做用是,项目启动后,直接在浏览器中打开,不须要手动输入地址,命令“yarn serve”也能够启动项目,可是须要手动在浏览器中输入地址
    • 浏览器中打开客户端项目地址(http://localhost:8080/#/)显示如下界面:
    • 用户名:admin  密码:123qwe 点击登陆后成功进入系统:

  直至到此,项目运行完成,在上面能够根据本身的需求进行更改,在之后的日子里,我会详细的记录这个项目的前端和后端,但愿你们可以监督,若是在文章中发现错误信息,请您及时联系我,我收到后会第一时间进行改正,谢谢

 

 

 

C#程序中设置全局代理(Global Proxy)

1. HttpWebRequest类的Proxy属性,只要设置了该属性就可以使用代理了,以下:

复制代码
1             //设置代理
2         WebProxy WP = new WebProxy("41.76.44.76", 3128);
3             ICredentials jxCredt = new NetworkCredential("proxy_username", "proxy_password");
4             WP.Credentials = jxCredt;
5             
6             HttpWebRequest webreq = HttpWebRequest.Create(uri);
7             webreq.Proxy = WP;//将代理赋值给HttpWebRequest的Proxy属性    

复制代码

2.可是程序中的每个HttpWebRequest都须要如此设置,是否存在更简便的方法,例如在某个地方设置了代理,则整个程序的全部请求都使用代理呢。

   答案是:有这样的方法。

   ===================================

   不过在此以前先来理解一下 C#的WebRequest类(即HtteWebRequest的父类)在发送前的一些处理:

          新建立一个WebRequest实例时(经过Create方法),会自动初始化其Proxy属性,

    而它还有一个DefaultWebProxy属性,当用户没有手动设置Proxy属性时,

    则WebRequest会使用DefaultWebProxy做为其Proxy;

    而DefaultWebProxy是读取项目的app.config文件来进行初始化;

    当没有app.config文件,或者没有在app.config中配置Proxy时,

    DefaultWebProxy就会去读取Internet Explorer (IE)的代理设置

   ============================================

    提示:

          怎么查看当前的请求Rquest是否使用了代理?

3.因此设置全局代理的方式有如下几种:

   第一种:程序不作任何处理,仅设置IE的代理;

   第二种:在程序的app.config文件进行相关的配置,官方文档,如:

复制代码
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <configuration>
 3   <system.net>
 4     <defaultProxy>
 5       <proxy
 6         proxyaddress="http://192.168.1.10:3128"
 7       />
 8     </defaultProxy>
 9   </system.net>
10 </configuration>
复制代码

            使用app.config设置代理时,若是想在运行时修改代理,则须要编辑app.config文件,

            能够参考:C#读写config配置文件

 第三种:在代码中为DefaultWebProxy从新赋值,以下:         

1 WebProxy WP = new WebProxy("41.76.44.76", 3128);
2 ICredentials jxCredt = new NetworkCredential("proxy_username", "proxy_password");//若是有用户名和密码须要设置
3 WP.Credentials = jxCredt;
4 
5 WebRequest.DefaultWebProxy = WP;

4.总结:

    第一种直接在IE上设置的,更多适合平时测试,由于让用户去做这种设置很不理智;

    第二种和第三种都相对简单,只要设置好,整个程序的全部WebRequest都会使用代理,但第二种还须要对app.config文件进行编辑,因此非硬性要求,建议使用第三种,设置DefaultWebProxy的方式;

    假如不想使用代理,则将DefaultWebProxy设为null,这样即便IE或者app.config设置了代理也不会影响。

    代理的优先顺序:手动设置WebRequest.Proxy属性 > DefaultWebProxy > app.config > IE的代理设置;

 

转原文地址:https://www.cnblogs.com/tommy-huang/p/5832998.html

 

 

 

 

WCF 4.0 使用说明

WCF 4.0开发说明,工具VS2013 ,IIS,使用http协议

 


  1. 打开VS2013,新建项目Visual C#>Web>Asp.NET Web应用程序,添加相关引用:

   System.ServiceModel、System.ServiceModel.Activation、System.ServiceModel.Web

  • 新增全局应用程序类Global.asax,文件内部代码以下:

 

       

 

     

 

  • 配置web.config文件,具体代码以下, 不详细解释

 

 

  • 配置完成后,在此项目中增长Routes.xml文件,内容以下

<?xml version="1.0" encoding="utf-8" ?> <routes>   <!--添加route定义,MyPublicWCF将自动加载下面定义的服务,并添加服务路由。       perfix为服务的跟路径,如http://localhost/MyWCF/GetData;       serviceType为服务类名,如命名空间MyWCF下的服务MyFirst,为MyWCF.MyFirst;       AssemblyFile为服务生成的DLL文件名,全部服务的DLL文件均需放到MyPublicWCF的bin目录中,如MyWCF.dll       -->   <route perfix="MyFirst" serviceType="MyWCF.MyFirst" AssemblyFile ="MyWCF.dll" />   </routes>

  1. 不一样的WCF接口能够建立不一样的类库:
  • 新建类库MyWCF,添加类MyFirst.cs,添加dll引用

System.ServiceModel、System.ServiceModel.Web

添加完成后,分别添加Get和POST方法,代码以下

 

 

 经过以上编写,一个简单的WCF小例子就这样完成啦。 初学者,你们多多指教啦O(∩_∩)O~

 

 

 

IIS 部署WCF 4.0

上一章节讲解如何新建WCF服务,此文讲解如何在IIS上发布,并能正常访问 


  1. 本地部署IIS
    • 首先在本机安装IIS,IIS如何勾选,哪些是必须的?不太清楚,有清楚的大牛请指正!目前个人基本配置以下:

     

     

  •  

配置完成后,重启电脑,将会在C盘下自动生成IIS目录,C:\inetpub\wwwroot

  • IIS安装完成后,配置WCF网站   ,首先建立应用程序池,FramWork4.0

 

建立完应用程序池后,添加网站,指定物理路径,应用程序池选择刚刚建立的Net4,如图:


 

  • C盘文件夹下内容包括WCF项目生成的DLL,Global.asax文件,Routes.xml文件,Web.config文件。如图所示:

 

     

 

部署完成后,重启IIS,选中应用程序MyWCF,在功能师徒中选择目录浏览,启用。而后选中MyWCF,右键管理应用程序,浏览,能够看到以下界面:


出现以下界面,证实WCF服务部署成功!

具体借口路径,以下:

http://localhost/MyWCF/MyFirst/Help

MyWCF为应用程序名称,MyFirst为Routes.xml文件中的perfix,经过访问Help能够查看当前服务下有多少接口,以下:

 

 

 

那么前端就能够经过AJAX的POST或GET方法访问接口,和数据库通信啦!注意:此处接口均使用JSON格式。

相关文章
相关标签/搜索