• 一个情怀引发的生产事故


      在一个项目中,需要轻量级用到脚本语言,来提高应用服务的灵活性。因为知道Roslyn可以动态编辑C#,本着情怀,就自然用Roslyn来处理这块业务了。开在windows上执行,一次调用风平浪静,因为这个功能使用频次不高,性能也没有太在意,上线后一切安好。事情发生在n天后,随着数据的增多,批量的数据上来了,批量使用这个功能时,把pod(我们的环境是kubernetes)使用爆炸了,只要用这个功能的批量,pod就会重启,从而造成了生产事故。

      完后,我对这个功能作了一次测试,附上内存使用情况。

    下图是windows上的测试结果,内存还有机会释放

     

     下图是docker上的结果,内存只增不减

      看图,觉得在windows上效果还好一些,但对于生产,其实都是要命的,如图,即使在windows上,内存的起伏也是巨大的。

      Roslyn的代码如下:

    using Microsoft.CodeAnalysis;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Reflection;
    using System.Runtime;
    using System.Text;
    using System.Globalization;
    using Microsoft.CodeAnalysis.CSharp;
    using Newtonsoft.Json;
    using Smart.Text.Japanese;
    
    namespace NLuaAndRoslynCompare5
    {
        public class RoslynClass
        {
            public static object Transform(string csharp,params object[] pares)
            {           
                var sourceCodeText = $@"
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Linq;
    using Smart.Text.Japanese;
    using System.Globalization;
    
    namespace RoslynDynamicGenerate
    {{
        public class DynamicGenerateClass
        {{
            public object Generate(object par)
            {{                
              {csharp}
            }}      
        }}
    }}
    ";
                var syntaxTree = CSharpSyntaxTree.ParseText(sourceCodeText, new CSharpParseOptions(LanguageVersion.Latest)); // 获取代码分析得到的语法树
                var assemblyName = $"RoslynDynamicGenerate";
                // 创建编译任务
                var metadata = GetMetadataReference(typeof(System.Text.RegularExpressions.Regex),typeof(StringExpand), typeof(KanaConverter), typeof(List<>), typeof(IDictionary), typeof(JapaneseCalendar),typeof(CultureInfo),typeof(DateTime),
                     typeof(JsonConvert), typeof(object), typeof(AssemblyTargetedPatchBandAttribute));
                var compilation = CSharpCompilation.Create(assemblyName) //指定程序集名称
                    .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))//输出为 dll 程序集               
                     .AddReferences(metadata) //添加程序集引用   
                    .AddSyntaxTrees(syntaxTree) // 添加上面代码分析得到的语法树     
                    ;
                using (var memory = new MemoryStream())
                {
                    var compilationResult = compilation.Emit(memory);
                    if (compilationResult.Success)
                    {
                        try
                        {
                            var assembly = Assembly.Load(memory.ToArray());
                            var type = assembly.GetType("RoslynDynamicGenerate.DynamicGenerateClass");
                            var obj = Activator.CreateInstance(type);
                            var methodInfo = type.GetMethod("Generate");
                            return methodInfo.Invoke(obj, pares)?.ToString();
                        }
                        finally
                        {
                            memory.Close();
                        }
                    }
                    else
                    {
                        foreach (var diagnositic in compilationResult.Diagnostics)
                        {
                            Console.WriteLine(diagnositic);
                        }
                        throw new ApplicationException($"下面C#语句有语法错误{sourceCodeText}");
                    }
                }
            }
            /// <summary>
            /// 从类型获取原数据引用
            /// </summary>
            /// <param name="types">类型集合</param>
            /// <returns></returns>
            static List<MetadataReference> GetMetadataReference(params Type[] types)
            {
                var list = new List<MetadataReference>();
                foreach (var type in types)
                {
                    var metadateRef = MetadataReference.CreateFromFile(type.Assembly.Location);
                    list.Add(metadateRef);
                    foreach (var assembly in type.Assembly.GetReferencedAssemblies())
                    {                  
                        list.Add(MetadataReference.CreateFromFile(Assembly.Load(assembly).Location));                  
                    }
                }
                return list;
            }
        }
    }

      调用方法如下:

      List<string> Roslyn()
            {
                var list = new List<string>();
                var csharp = @"return DateTime.Now.ToString(""yyyy-MM-dd HH:mm:ss.ffffff""); ";
                for (int i = 0; i < 1000; i++)
                {
                    list.Add(RoslynClass.Transform(csharp, 1).ToString());
                }      
                return list;
            }

      现在是换方式的时候了!!!

     

      想要更快更方便的了解相关知识,可以关注微信公众号 
     

     

     

  • 相关阅读:
    redux的理解
    跨域的三种解决方案
    HTTP缓存字段总结
    src属性与浏览器渲染
    ES6之promise原理
    http header Content-Type之常用三种
    用css实现正方形div
    js判断数据类型
    react中PureComponent浅对比策略
    React中自己实现选项卡动画
  • 原文地址:https://www.cnblogs.com/axzxs2001/p/15859084.html
Copyright © 2020-2023  润新知