首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 63)——Cocoa Touch设计模式及应用之单例模式

什么是设计模式。设计模式是在特定场景下对特定问题的解决方案,这些解决方案是经过反复论证和测试总结出来的。实际上,除了软件设计,设计模式也被广泛应用于其他领域,比如UI设计和建筑设计等。 下面来介绍Cocoa Touch框架中的设计模式中的单例模式。 单例模式 单例模式的作用是解决“应用中只有一个实例”的一类问题。在Cocoa Touch框架中,有UIApplication、NSUserDefaults和NSNotificationCenter等单例类。另外,NSFileManager和NSBundle类虽然属于Cocoa框架的内容,但也可以在Cocoa Touch框架中使用(Cocoa框架中的单例类有NSFileManager、NSWorkspace和NSApplication等)。 问题提出 在一个应用程序的生命周期中,有时候只需要某个类的一个实例。例如:当iOS应用程序启动时,应用的状态由UIApplication类的一个实例维护,这个实例代表了整个“应用程序对象”,它只能是一个实例,其作用是共享应用程序中的一些资源、控制应用程序的访问,以及保持应用程序的状态等。 解决方案 单例模式的实现有很多方案,苹果公司在《UsingSwift with Cocoa and Objective-C》官方文档中给出了一种单例模式的实现。最简单形式代码如下: 1 2 3 class Singleton{ static letsharedInstance=Singleton() } 上述代码采用static的类属性实现单例模式,这种类属性只被延迟加载执行一次,即便是在多线程情况下也只是执行一次,并且保证是线程安全的。 如果需要进行一些初始化,可以使用如下带有闭包形式代码: 1 2 3 4 5 6 7 class Singleton{ static letsharedInstance:Singleton={ letinstance=Singleton() //初始化处理 returninstance }() } 单例模式除了上述苹果官方给出的实现外,还有很多种实现方式。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1748670,如需转载请自行联系原作者

优秀的个人博客,低调大师

Hadoop HBase概念学习系列之HBase里的宽表设计概念(表设计)(二十七)

HBASE宽表应用很多 比如BBS,可以用帖子的URL地址作为ROWKEY保存,而后面的每一个回复,作为单独的COLUMNS,回复越多,COLUMNS就越多,表就变宽了。 COLUMNS的qualifier名称设计很简单 假设你的表FC="_0" qualifier={"_0:_00000001","_0:_00000002","_0:_00000003",.....,"_0:_0XXXXXXX"} 对于每个ROW的数据,qualifier也是按字典排序的,所以qualifier的左边需要补"0"。 还有一种设计方法,假设BBS每一页显示100行 qualifier={"_0:_0000100","_0:_0000101","_0:_0000102"...."_0:_0000200","_0:_0000201"....,"_0:_0XXXXXXX"} 用页数编号加每一页的行数来定义qualifier 。 VALUE中放每一行的具体内容。 网站性能指标采集 id表示服务器的编号,type表示监控的指标,时间表示监控的时间点。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6160078.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Hadoop概念学习系列之搭建(windows)Eclipse/MyEclipse远程操作(Linux上)hadoop2.2.0/hadoo...

问题1:在DFS Lcation 上不能多文件进行操作: 在Hadoop上的每个节点上修改该文件 conf/mapred-site.xml 增加: <property> <name>dfs.permissions</name> <value>false</value> </property> 关闭权限验证 问题2 log4j:WARN No appenders could be foundfor logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory). log4j:WARN Please initialize the log4jsystem properly. log4j:WARN Seehttp://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. 在src文件夹下创建以log4j.properties命名的文件 文件内容如下 log4j.rootLogger=WARN, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d%p [%c] - %m%n 问题3 Java.io.IOException: Could not locateexecutable null/bin/winutils.exe in the Hadoop binaries. 缺少winutils.exe下载一个添加进去就行 下载地址 http://download.csdn.net/detail/u010106732/9630094 问题4 Exceptionin thread "main" java.lang.UnsatisfiedLinkError:org.apache.hadoop.util.NativeCrc32.nativeComputeChunkedSumsByteArray(II[BI[BIILjava/lang/String;JZ)V 这是由于hadoop.dll 版本问题,2.2之前的和之后的需要的不一样 需要选择正确的版本并且在 Hadoop/bin和 C:\windows\system32 上将其替换 问题5 Exception in thread "main"java.lang.UnsatisfiedLinkError:org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z atorg.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Native Method) at org.apache.hadoop.io.nativeio.NativeIO$Windows.access(NativeIO.java:557) 目前未找到解决方法,只能修改源代码 源代码下载 http://pan.baidu.com/s/1jGJzVSy 将源代码放入 工程的src目录下并创建同样的包名,然后修改源代码 源代码 未修改前 publicstaticbooleanaccess(String path, AccessRight desiredAccess) throwsIOException { returnaccess0(path,desiredAccess.accessRight()); } 源代码 修改后 publicstaticbooleanaccess(String path, AccessRight desiredAccess) throwsIOException { return ture; //returnaccess0(path,desiredAccess.accessRight()); } 修改后编译成功,但是看不到软件运行时候的信息反馈。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6053970.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 69)——Swift与Objective-C混合编程之语言

在Swift语言出现之前,开发iOS或OS X应用主要使用Objective-C语言,此外还可以使用C和C++语言,但是UI部分只能使用Objective-C语言。 选择语言 Swift语言出现后,苹果公司给程序员提供了更多的选择,让这两种语言并存。既然是并存,我们就有4种方式可以选择: 采用纯Swift的改革派方式; 采用纯Objective-C的保守派方式; 采用Swift调用Objective-C的左倾改良派方式; 采用Objective-C调用Swift的右倾改良派方式。 文件扩展名 在Xcode等工具开发iOS或OS X应用可以编写多种形式的源文件,原本就可以使用Objective-C、C和C++语言,Swift语言出现后源文件的形式更加多样。可能的文件扩展名说明: 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1749105,如需转载请自行联系原作者

优秀的个人博客,低调大师

Hadoop HBase概念学习系列之HBase里的高表设计概念(表设计)(二十八)

在不同场景,结合使用到底是高表还是宽表。 高表有高表的好处,宽表有宽表的优势。 起始行键是1001,结束行键是10010,则可查出如下图框出部分结果。 当然,也可以根据其他的查询条件,来查询。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6160077.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Hadoop MapReduce概念学习系列之MyEclipse和Hadoop上都出现中文乱码问题(二十四)

出现中文乱码问题情况,详细如下! 在MyEclipse里 在Hadoop里 那么,如果是这样情况,说明是要改编码。 解决的办法? 1 、windows -> preferences 2、将Text file encoding的other部分,改为UTF-8。 3、hadoop项目,右键,prpperties,然后出现以下界面。就是配置好了,即hadoop项目的消除中文乱码问题解决。 将Inherited from container(UTF-8)的Other改为UTF-8。 4、刷新,重新即可。将之前的salary.txt重新上传。 即,本地的MyEclipse中已经解决了乱码问题。 5、现在,需要到hadoop集群上去成功运行,这该怎么做呢? Hadoop -> Export -> Export, Java -> JAR file -> next 6、 因为,在hadoop里,这些依赖的架包是存在的,所以我们就不需要再多此一举再打包了。 为架包取一个名称,为SalaryCount.jar,先在D盘新建文件夹JAR,存放在D:\JAR\SalaryCount.jar 在D盘的JAR目录下,查看sc.jar 7、接下来,用xshell来连接CentOS6.5。 8、rz,打开D:\JAR\sc.jar ,上传至CentOS6.5 9、通过rz命令上传sc.jar包 10、 执行命令 hadoop jar sc.jarcom.dajiangtai.hadoop.test.SalaryCount /salary/ /salary/out/ 11 查看结果 hadoop fs -text /salary/out/part-r-00000 即,与在本地的MyEclipse的结果是一样的。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5077864.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

学习ASP.NET Core, 怎能不了解请求处理管道[4]: 应用的入口——Startup

一个ASP.NET Core应用被启动之后就具有了针对请求的处理能力,而这个能力是由管道赋予的,所以应用的启动同时意味着管道的成功构建。由于管道是由注册的服务器和若干中间件构成的,所以应用启动过程中一个核心的工作就是完成中间节的注册。由于依赖注入在ASP.NET Core应用这得到非常广泛的应用,框架绝大部分的工作都会分配给我们预先注册的服务,所以服务注册也是启动WebHost过程的另一项核心工作。这两项在启动过程中必须完成的核心工作通过一个名为Startup的对象来承载。 [本文已经同步到《ASP.NET Core框架揭秘》之中] 目录 一、 DelegateStartup 二、ConventionBasedStartup StartupMethods StartupLoader 如何选择启动类型 如何选择服务注册方法和中间件注册方法 StartupMethods对象的创建 UseStartup方法究竟做了些什么? 三、选择哪一个Startup 这里所谓的Startup实际上是对所有实现了IStartup接口的所有类型以及对应对象的统称。如下面的代码片段所示,服务注册由ConfigureServices方法来实现,它返回一个ServiceProvider对象,至于另一个方法Configure则负责完成中间件的注册,方法输入参数是一个ApplicationBuilder对象。 1: public interface IStartup 2: { 3: IServiceProvider ConfigureServices(IServiceCollection services); 4: void Configure(IApplicationBuilder app); 5: } IStartup接口所在的NuGet包中还定义了另一个实现了这个接口的抽象类StartupBase。如下面的代码片段所示,StartupBase实现了抽象方法ConfigureServices,该方法直接利用提供的ServiceCollection对象创建返回的ServiceProvider。换句话说,派生于StartupBase的Startup类型如果没用重写ConfigureServices方法,它们实际上只关心中间件的注册,而不需要注册额外的服务。 1: public abstract class StartupBase : IStartup 2: { 3: public abstract void Configure(IApplicationBuilder app); 4: public virtual IServiceProvider ConfigureServices(IServiceCollection services) 5: { 6: return services.BuildServiceProvider(); 7: } 8: } 一、 DelegateStartup 我们来想想具体的应用中是如何注册中间件和服务的。中间件的注册可以采用两种方式,最简单的方式就是直接调用IWebHostBuilder的Configure方法。如下面的代码片段所示,这个方法直接上是借助于一个类型为Action<IApplicationBuilder>的委托对象将中间件注册到提供的ApplicationBuilder对象上。 1: public static class WebHostBuilderExtensions 2: { 3: public static IWebHostBuilder Configure(this IWebHostBuilder hostBuilder, Action<IApplicationBuilder> configureApp); 4: } 5: 6: new WebHostBuilder() 7: .Configure(app => app 8: .UseExceptionHandler("/Home/Error") 9: .UseStaticFiles() 10: .UseIdentity() 11: .UseMvc()) 12: … 如果我们在应用中通过调用上面这个Configure方法来注册所需的中间件,WebHost在启动的时候会创建一个类型为DelegateStartup的Startup对象来完成真正的中间件注册工作。如下面的代码片段所示,DelegateStartup派生于StartupBase这个抽象类,它利用一个在构造时提供的Action<IApplicationBuilder>对象实现了Configure方法。很明显,我们调用IWebHostBuilder的Configure方法指定的Action<IApplicationBuilder>对象将用来创建这个DelegateStartup对象。 1: public class DelegateStartup : StartupBase 2: { 3: private Action<IApplicationBuilder> _configureApp; 4: 5: public DelegateStartup(Action<IApplicationBuilder> configureApp) 6: { 7: _configureApp = configureApp; 8: } 9: 10: public override void Configure(IApplicationBuilder app) 11: { 12: _configureApp(app); 13: } 14: } 如下的代码片段体现了 IWebHostBuilder的扩展方法Configure的实现逻辑。如下面的代码片段所示,这个方法根据提供的Action<IApplicationBuilder>对象创建了一个DelegateStartup对象,并调用ConfigureServices方法以淡例模式注册到WebHostBuilder的服务集合中。这段代码还体现了另一个细节,除了进行Startup的服务注册之外,该方法还对“ApplicationName”选项(对应WebHostOptions的ApplicationName)进行了设置。 1: public static class WebHostBuilderExtensions 2: { 3: public static IWebHostBuilder Configure(this IWebHostBuilder hostBuilder, Action<IApplicationBuilder> configureApp) 4: { 5: var startupAssemblyName = configureApp.GetMethodInfo().DeclaringType.GetTypeInfo().Assembly.GetName().Name; 6: return hostBuilder 7: .UseSetting("applicationName", startupAssemblyName) 8: .ConfigureServices(svcs => svcs.AddSingleton<IStartup>(new DelegateStartup(configureApp)); 9: } 10: } 二、ConventionBasedStartup 我们知道应用中最常见的服务和中间件注册代码都定义在一个单独的类中,通常直接将其命名为Startup。为了与IStartup接口代表的Startup相区别,我们使用 “启动类(型)” 来称呼这个类。按照约定,启动类中会分别定义一个ConfigureServices和Configure方法来注册服务和中间件。一般情况下,这样的类型一般需要通过调用UseStartup<T>这个扩展方法注册到WebHostBuilder上。 1: public class Startup 2: { 3: public void ConfigureServies(IServiceCollection services); 4: public void Configure(IApplicationBuilder app); 5: } 6: 7: new WebHostBuilder() 8: .UseStartup<Startup>() 9: … 如果我们在应用中将服务和中间件注册的实现定义在启动类型中,当WebHost被启动的时候,ASP.NET Core会创建一个类型为ConventionBasedStartup的Startup对象。这个Startup类型之所以采用这样的命名方式,是因为ASP.NET Core并没有采用接口实现的方式为启动类型做强制性的约束,而仅仅是为作为启动类型的定义提供了一个约定而已,至于具体采用怎样的约定,我们将在后续部分进行详细介绍。 StartupMethods 在了解了启动类型的约定以及常见的定义形式之外,我们现在来讨论这对这个类型创建的ConventionBasedStartup就是怎样的对象。从下面的代码片段可以看出,一个ConventionBasedStartup对象是根据一个类型为StartupMethods对象创建的。顾名思义,StartupMethods只在提供两个用户注册服务和中间件的方法,这两个方法体现在由它的两个属性(ConfigureServicesDelegate和ConfigureDelegate)提供的两个委托对象,这两个委托对象分别实现了定义在ConventionBasedStartup的ConfigureServices和Configure方法。 1: public class ConventionBasedStartup : IStartup 2: { 3: public ConventionBasedStartup(StartupMethods methods); 4: public IServiceProvider ConfigureServices(IServiceCollection services); 5: public void Configure(IApplicationBuilder app); 6: } 7: 8: public class StartupMethods 9: { 10: public Func<IServiceCollection, IServiceProvider> ConfigureServicesDelegate { get; } 11: public Action<IApplicationBuilder> ConfigureDelegate { get; } 12: 13: public StartupMethods(Action<IApplicationBuilder> configure); 14: public StartupMethods(Action<IApplicationBuilder> configure, Func<IServiceCollection, IServiceProvider> configureServices); 15: } StartupLoader 既然ConventionBasedStartup对象是根据提供的一个StartupMethods对象创建的,那么现在的核心问题则变成了这个StartupMethods对象如何根据启动类型创建的。StartupMethods的创建者是一个类型为StartupLoader的对象,如下面的代码片段所示,StartupLoader定了两个名为FindStartupType和LoadMethods静态方法,前者用于启动类型的解析,后者则实现了StartupMethods对象的创建。 1: public class StartupLoader 2: { 3: public static Type FindStartupType(string startupAssemblyName, string environmentName); 4: public static StartupMethods LoadMethods(IServiceProvider services, Type startupType, string environmentName); 5: } 如何选择启动类型 如果启动类型没有通过调用WebHostBuilder的如下两个扩展方法UseStartup/UseStartup<TStartup>的显式注册,那么StartupLoader的FindStartupType方法会被调用来解析出正确的启动类型。这个方法具有两个参数,分别代表启动类型所在的程序集名称和当前环境名称,它们实际上对应着WebHostOptions的两个同名属性。当FindStartupType方法被执行并成功加载了提供的程序集之后,它会按照约定的启动类型全名从该程序集中加载启动类型,候选的启动类型全名按照选择优先级排列如下: Startup{EnvironmentName} (无命名空间) {StartupAssemblyName}.Startup{EnvironmentName} Startup(无命名空间) {StartupAssemblyName}.Startup{EnvironmentName} **. Startup{EnvironmentName}(任意命名空间) **. Startup(任意命名空间) 这个列表体现了启动类型解析过程中选择有效类型名称的一个基本策略,即“环境名称优先”和“无命名空间优先”。我们可以通过一个简单的实例来证明这个策略的存在。我们在一个ASP.NET Core控制台应用中添加一个名为“StartupLib”(程序集也采用这个名称)的类库项目,然后在这个项目中定义如下两组启动类,其中一组具有命名空间,另一组则采用程序集名称作为命名空间。这些启动类都派生于我们自定义的基类StartupBase,后者的Configure方法中注册了一个中间件将自身的类型作为响应内容。对于每组中的三个启动类,一个命名为Startup,另外两个则分别以环境名称( “Development” 和 “Production” )作为后缀。 1: public class StartupBase 2: { 3: public void ConfigureServices(IServiceCollection services){} 4: public void Configure(IApplicationBuilder app) 5: { 6: app.Run(async context => await context.Response.WriteAsync(this.GetType().FullName)); 7: } 8: } 9: 10: public class Startup : StartupBase{} 11: public class StartupDevelopment : StartupBase{} 12: public class StartProduction : StartupBase{} 13: 14: namespace StartupLib 15: { 16: public class Startup : StartupBase{} 17: public class StartupDevelopment : StartupBase{} 18: public class StartProduction : StartupBase{} 19: } 我们采用如下的程序来启动一个ASP.NET Core应用。如下面的代码代码片段所示,我们在利用WebHostBuilder创建并启动WebHost之前,调用UseSettings方法以配置的形式指定了启动程序集(“StartupLib”)和当前运行环境(“Development”)的名称。 1: public class Program 2: { 3: public static void Main() 4: { 5: new WebHostBuilder() 6: .UseKestrel() 7: .UseSetting("startupAssembly", "StartupLib") 8: .UseSetting("environment", "Development") 9: .Build() 10: .Run(); 11: } 12: } 根据上述的启动类型解析规则,对于六个候选的启动类型,最终被选择的是不具有命名空间的StartupDevelopment类型。当应用启动之后,我们利用浏览器请求应用监听地址(“http://localhost:5000”),这个被选择的启动程序的名称将会以如下的形式直接显示出来。 如何选择服务注册方法和中间件注册方法 在了解了ASP.NET Core针对启动类型命名的约定之后,我们来讨论一下定义在启动类中用于注册服务和中间件的两个方法的约定。这两个方法可以是静态方法,也可以是实例方法。从方法命名来看,这两个方法除了命名为“ConfigureServices”和“Configure”之外,方法名还可以携带运行环境名称,具体采用的格式分别为“Configure{EnvironmentName}Services”和“Configure{EnvironmentName}”,后者具有更高的选择优先级。 ConfigureServices/Configure{EnvironmentName}Services方法具有一个类型为IServiceCollection接口的参数,表示存放注册服务的ServiceCollection对象。如过这个方法没有定义任何参数,它依然是合法的。一般来说,这个方法不具有返回值(返回类型为void),但是它也可以定义成一个返回类型为IServiceProvider的方法。如果这个方法返回一个ServiceProvider对象,后续过程中获取的所有服务将从这个ServiceProvider中提取。对于没有返回值的情况,系统会根据当前注册的服务创建一个ServiceProvider。 Configure/Configure{EnvironmentName}方法只要求只要求第一个参数类型采用IApplicationBuilder接口,至于这个方法可以包含多少个参数,各个参数应该具有怎样的类型,并未做任何规定。实际上我们为这个方法定义任意后续参数都是合法的。当ConventionBasedStartup在调用这个方法的时候,同样是采用依赖注入的方式来提供这些参数。如下面的代码片段所示,我们为启动类的Configure方法定义相应的参数来直接使用在ConfigureServices方法上注册的三个服务。 1: new WebHostBuilder() 2: .ConfigureServices(services => services.AddSingleton<IFoobar, Foobar>()) 3: … 4: 5: public class Startup 6: { 7: public Startup(IFoobar foobar) 8: { 9: Debug.Assert(foobar.GetType() == typeof(Foobar)); 10: } 11: public void ConfigureServies(IServiceCollection services) ; 12: public void Configure(IApplicationBuilder app) ; 13: } StartupMethods对象的创建 除此之外,对于定义成实例类型的启动类,我们并不要求它具有一个默认无参的构造函数。如果构造函数具有参数,ConventionBasedStartup在实例化的时候会采用构造函数注入的方式来提供构造函数的参数。至于提供参数所用的ServiceProvider,就是WebHostBuilder在创建WebHost对象时作为构造函数参数提供的那个ServiceProvider。如下面的代码片段所示,我们利用WebHostBuilder创建并启动WebHost之前,调用他的ConfigureServices方法针对接口IFoobar注册了一个服务,那么注册为启动类的Startup类可以在构造函数中以注入的形式使用这个服务对象。 1: public class StartupLoader 2: { 3: public static StartupMethods LoadMethods(IServiceProvider serviceProvider, Type startupType, string environmentName) 4: { 5: return new StartupMethods(BuildConfigureDelegate(serviceProvider, startupType, environmentName), 6: BuildConfigureServicesDelegate(serviceProvider, startupType, environmentName)); 7: } 8: 9: private static Func<IServiceCollection, IServiceProvider> BuildConfigureServicesDelegate(IServiceProvider serviceProvider, Type startupType, string environmentName) 10: { 11: MethodInfo method = FindMethod(startupType, $"Configure{environmentName}Services", "ConfigureServices"); 12: object instance = method.IsStatic ? null : ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, startupType); 13: return services => 14: { 15: object[] arguments = method.GetParameters().Length > 0 ? new object[] { services } : new object[0]; 16: return (method.Invoke(instance, arguments) as IServiceProvider) ?? services.BuildServiceProvider(); 17: }; 18: } 19: 20: private static Action<IApplicationBuilder> BuildConfigureDelegate(IServiceProvider serviceProvider, Type startupType, string environmentName) 21: { 22: MethodInfo method = FindMethod(startupType, $"Configure{environmentName}", "Configure"); 23: object instance = method.IsStatic ? null : ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, startupType); 24: object[] arguments = method.GetParameters().Select(p => serviceProvider.GetService(p.ParameterType)).ToArray(); 25: return app => 26: { 27: arguments[0] = app; 28: method.Invoke(instance, arguments); 29: }; 30: } 31: 32: private static MethodInfo FindMethod(Type startupType, string method1, string method2) 33: { 34: BindingFlags bindAttribute = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; 35: return startupType.GetMethod(method1, bindAttribute)?? startupType.GetMethod(method2, bindAttribute); 36: } 37: } UseStartup方法究竟做了些什么? 当我们调用IWebHostBuilder接口的扩展方法UseStartup/UseStartup<TStartup>注册某个启动类的时候,该方法会按照如下的形式创建一个ConventionBasedStartup对象并注册到WebHostBuilder的服务集合上。和上面介绍的Configure方法一样,UseStartup方法同样会设置 “ApplicationName” 选项。除此之外,这段还体现了另一个细节,那就是如果我们直接定义一个实现了IStartup接口的启动类,UseStartup方法会直接注册这个类型,而不会再多此一举地创建一个ConventionBasedStartup对象。 1: public static class WebHostBuilderExtensions 2: { 3: public static IWebHostBuilder UseStartup<TStartup>(this IWebHostBuilder hostBuilder) where TStartup : class 4: { 5: return UseStartup(hostBuilder, typeof(TStartup)); 6: } 7: 8: public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType) 9: { 10: var startupAssemblyName = startupType.GetTypeInfo().Assembly.GetName().Name; 11: return hostBuilder 12: .UseSetting("ApplicationName", startupAssemblyName) 13: .ConfigureServices(svcs => 14: { 15: if (typeof(IStartup).IsAssignableFrom(startupType)) 16: { 17: svcs.AddSingleton(typeof(IStartup), startupType); 18: } 19: else 20: { 21: svcs.AddSingleton<IStartup>(sp => new ConventionBasedStartup(StartupLoader.LoadMethods(sp, startupType, sp.GetService<IHostingEnvironment>().EnvironmentName))); 22: } 23: }); 24: } 25: } 三、选择哪一个Startup 应用启动的时候,Startup帮助我们完成所需服务和中间件的注册,而Startup对象自身也是服务的形式被注册到WebHostBuilder或者WebHost的服务集合中。总的来说,Startup的注册具有如下三种途径: 调用IWebHostBuilder的扩展方法Configure方法创建并注册一个DelegateStartup对象。 调用IWebHostBuilder的扩展方法UseStartup或者UseStartup<TStartup>创建并注册一个ConventionBasedStartup对象。 如果设置了启动程序集名称(对应WebHostOptions的StartupAssembly属性)并且对应的程序集中存在一个满足约定的启动类型,也会创建并注册一个ConventionBasedStartup对象。 那么现在的问题来说,如果我们采用上述这三种途径创建并注册了多个Startup,那么系统是只选择其中一个,还是所有的Startup均有效呢?就如下这段程序来说,如果当前程序集同时定义了三个有效的Startup类型(Startup、Startup1和Startup2),最终将会有五个Startup对象被注册,其中两个是通过Configure方法注册的DelegateStartup对象,对于额外三个ConventionBasedStartup对象来说, 其中两个针对显式指定的启动类型(Startup1和Startup2),另外一个则是针对默认的约定解析出来的启动类型(Startup)。对于这个五个Startup对象,究竟哪些是有效的呢? 1: new WebHostBuilder() 2: .Configure(app => {}) 3: .Configure(app => {}) 4: .UseStartup<Startup1>() 5: .UseStartup<Startup2>() 6: .UseSetting("startupAssembly", Assembly.GetEntryAssembly().FullName) 7: … 不论我们注册多少个Startup,系统最终都只会其中一个来注册服务和中间件。由于WebHost会直接利用ServiceProvider来获取Startup对象,根据 “后来居上” 的原则,最终选择的总是最后注册的那个Startup。由于Configure方法和UseStartup方法最终都是调用WebHostBuilder的ConfigureServices方法进行服务注册,所以最后调用的方法具有最高的优先级。至于根据指定启动程序集名称而创建出来的ConventionBasedStartup,针对它的注册信息会放在最前面,所以具有最低优先级。根据这个策略,上面这段程序最终选择的启动类是Startup2。 作者:蒋金楠 微信公众账号:大内老A 微博: www.weibo.com/artech 如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 原文链接

优秀的个人博客,低调大师

一脸懵逼学习Hdfs---动态增加节点和副本数量管理(Hdfs动态扩容)

1:按照上篇博客写的,将各个进程都启动起来: 集群规划: 主机名 IP 安装的软件 运行的进程 master 192.168.3.129 jdk、hadoop NameNode、DFSZKFailoverController(zkfc) slaver1 192.168.3.130 jdk、hadoop NameNode、DFSZKFailoverController(zkfc) slaver2 192.168.3.131 jdk、hadoop ResourceManager slaver3 192.168.3.132 jdk、hadoop ResourceManager slaver4 192.168.3.133 jdk、hadoop、zookeeper DataNode、NodeManager、JournalNode、QuorumPeerMain slaver5 192.168.3.134 jdk、hadoop、zookeeper DataNode、NodeManager、JournalNode、QuorumPeerMain slaver6 192.168.3.135 jdk、hadoop、zookeeper DataNode、NodeManager、JournalNode、QuorumPeerMain 2:开始测试动态增加节点和副本数量管理: 首先将master节点的datanode挂掉(即少了一个保存文件的副本): 注意:hadoop datanode节点超时时间设置: datanode进程死亡或者网络故障造成datanode无法与namenode通信,namenode不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长。HDFS默认的超时时长为10分钟+30秒。如果定义超时时间为timeout,则超时时长的计算公式为: timeout = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval。 而默认的heartbeat.recheck.interval 大小为5分钟,dfs.heartbeat.interval默认为3秒。 需要注意的是hdfs-site.xml 配置文件中的: heartbeat.recheck.interval的单位为毫秒, dfs.heartbeat.interval的单位为秒。 所以,举个例子,如果heartbeat.recheck.interval设置为5000(毫秒),dfs.heartbeat.interval设置为3(秒,默认),则总的超时时间为40秒。 hdfs-site.xml中的参数设置格式:<property><name>heartbeat.recheck.interval</name><value>2000</value></property><property><name>dfs.heartbeat.interval</name><value>1</value></property> 注意:HDFS冗余数据块的自动删除: 在日常维护hadoop集群的过程中发现这样一种情况: 某个节点由于网络故障或者DataNode进程死亡,被NameNode判定为死亡, HDFS马上自动开始数据块的容错拷贝; 当该节点重新添加到集群中时,由于该节点上的数据其实并没有损坏, 所以造成了HDFS上某些block的备份数超过了设定的备份数。 通过观察发现,这些多余的数据块经过很长的一段时间才会被完全删除掉, 那么这个时间取决于什么呢? 该时间的长短跟数据块报告的间隔时间有关。 Datanode会定期将当前该结点上所有的BLOCK信息报告给Namenode, 参数dfs.blockreport.intervalMsec就是控制这个报告间隔的参数。 hdfs-site.xml文件中有一个参数:<property><name>dfs.blockreport.intervalMsec</name><value>10000</value><description>Determines block reporting interval in milliseconds.</description></property> 其中3600000为默认设置,3600000毫秒,即1个小时,也就是说,块报告的时间间隔为1个小时,所以经过了很长时间这些多余的块才被删除掉。通过实际测试发现,当把该参数调整的稍小一点的时候(60秒),多余的数据块确实很快就被删除了。 3:停止一下集群,配置一下hadoop datanode节点超时时间设置和HDFS冗余数据块的自动删除,停止集群如下所示: 依次查看一下各个节点的进程启动情况: 然后将slaver5和slaver6的yarn进程停掉: 然后依次关掉zookeeper的进程:如master,slaver1和slaver2都一样,这里不再重复了: [root@master bin]# ./zkServer.sh stop 现在修改配置一下:hadoop datanode节点超时时间设置和HDFS冗余数据块的自动删除的配置文件hdfs-site.xml: hadoop datanode节点超时时间设置 hdfs-site.xml中的参数设置格式: <property> <name>heartbeat.recheck.interval</name> <value>2000</value> </property> <property> <name>dfs.heartbeat.interval</name> <value>1</value> </property> HDFS冗余数据块的自动删除 hdfs-site.xml文件中有一个参数: <property> <name>dfs.blockreport.intervalMsec</name> <value>10000</value> <description>Determines block reporting interval in milliseconds.</description> </property> 操作如下所示: [root@slaver3 hadoop]# vim hdfs-site.xml 将修改的hdfs-site.xml复制到其他6个节点上面,如下所示: 4:将集群启动起来: 4.1:启动zookeeper集群(分别在master、slaver1、slaver2上启动zookeeper): 4.2:启动journalnode(分别在master、slaver1、slaver2上执行) 4.3:千万不要执行格式化HDFS,千万不要执行格式化ZKFC(在slaver3上执行即可),不然还是报很多错误; 4.4:然后在slaver3启动start-dfs.sh 现在可以去其他节点看看,全部进程都可以正常启动,如果你想启动yarn进程,下面启动yarn进程,slaver5节点和slaver6节点操作一样,这里只贴slaver5即可: 如果你耐心十足,搞了一天,想吐,这里还是再贴一下jps查看的进程情况吧: 5:然后将master的namenode干掉,看看Live Nodes是否变化: 经过14s后,活着的node数目就由3变成了2: 如何新加一个datanode,再搞一个虚拟机(我再新建一个虚拟机,不知道我的电脑撑住撑不住,试试吧先),然后将hadoop的安装包复制过去,然后将datanode启动起来:好吧,最后没有弄出来,以后有机会好好补一下这点,动态增加节点和副本数量管理; 补充要点: 注意:hdfs动态扩容要点,将手动启动节点: hadoop-daemon.sh start namenode 启动namenode hadoop-daemon.sh start datanode 启动datanode. 即可以动态加入,只不过没写到slavers里面,下次重启以后,手动加入即可完成动态扩容了。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册