专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

从0开始搭建SpringCloud项目分布式日志架构技术栈,

  一、简介
  分布式应用必须有一套日志采集功能,目的是将分布在各个服务器节点上的应用日志文件采集到统一的服务器上,方便日志的查看。springCloud本身提供了基于elk的日志采集,但是由于使用logstash,会加大运维成本。这里将使用轻量级的方案。二、思路
  我们的目的是提供轻量级的日志采集来代替logstash,日志最终还是会存进Elasticsearch。为了能轻量级的实现日志采集,并且避免对代码的侵入,我们可以扩展Logback的appender,也可以扩展log4j的appender。这样我们使用slf4j来记录日志的时候,日志自动会保存到Elasticsearch中,并且不用修改任何业务代码。三、自定义Logbackappender
  我们先来看一下Logback的appender的Uml图,我们可以发现两个对我们有借鉴意义的类
  UnsynchronizedAppenderBase提供了异步的日志记录DBAppender基于数据库的日志记录
  这两个类还是比较简单的,具体的代码我就不详细解说了,请自行查阅属性注入
  基本实现逻辑从UnsynchronizedAppenderBase和DBAppender已经能够知道了,现在把我们需要的信息注入到Appender中,这里需要如下的知识Logback标签注入属性
  我们可以直接在Xml中用标签配置属性,这些标签只要名称和appender中的成员变量名一致,则会自动把标签中的属性注入到成员变量中。
  我们举一个例子:
  xml这样配置profiletestprofileesTypedemoesTypewithJansitruewithJansiencoderpattern{CONSOLELOGPATTERNIDE}patterncharsetutf8charsetencoderappender
  其中ElasticsearchAppender是我们自己实现的Appender。这里有一个profile标签,我们需要ElasticsearchAppender中成员变量的名称和该标签名一致,这样就可以把test值注入到成员变量profile中。protectedStringprofile;运行环境Spring配置信息注入属性
  有些信息可能已经在spring中做了配置,我们不想要重复的配置,这个时候我们可以用springProperty标签来进行设置。scope:作用范围name:名称source:spring配置defaultValue:默认值,必须要指定
  然后在标签中用上面的name属性作为占位符,类中的成员变量名和标签名一致。
  我们举一个例子:
  xml这样配置springPropertyscopecontextnameapplicationNamesourcespring。application。namedefaultValuespringPropertyscopecontextnameprofilesourcespring。profiles。activedefaultValuedefaultspringPropertyscopecontextnameesUserNamesourceluminary。elasticsearch。usernamedefaultValueelasticspringPropertyscopecontextnameesPasswordsourceluminary。elasticsearch。passworddefaultValue123456springPropertyscopecontextnameesServersourceluminary。elasticsearch。serverdefaultValue127。0。0。1:9200springPropertyscopecontextnameesMultiThreadedsourceluminary。elasticsearch。multiThreadeddefaultValuetruespringPropertyscopecontextnameesMaxTotalConnectionsourceluminary。elasticsearch。maxTotalConnectiondefaultValue20springPropertyscopecontextnameesMaxTotalConnectionPerRoutesourceluminary。elasticsearch。maxTotalConnectionPerRoutedefaultValue5springPropertyscopecontextnameesDiscoveryEnabledsourceluminary。elasticsearch。discoveryEnableddefaultValuetruespringPropertyscopecontextnameesDiscorveryFrequencysourceluminary。elasticsearch。discorveryFrequencydefaultValue60{applicationName}applicationNameprofile{profile}profileesTypedemoesTypeusername{esUserName}usernamepassword{esPassword}passwordserver{esServer}servermultiThreaded{esMultiThreaded}multiThreadedmaxTotalConnection{esMaxTotalConnection}maxTotalConnectionmaxTotalConnectionPerRoute{esMaxTotalConnectionPerRoute}maxTotalConnectionPerRoutediscoveryEnabled{esDiscoveryEnabled}discoveryEnableddiscorveryFrequency{esDiscorveryFrequency}discorveryFrequencyappender
  yml这样配置spring:application:name:loggerdemoserverluminary:elasticsearch:username:elasticpassword:123456server:127。0。0。1:9200multiThreaded:truemaxTotalConnection:20maxTotalConnectionPerRoute:5discoveryEnabled:truediscorveryFrequency:60
  成员变量SetterprotectedStringesIndexjavalogdate;索引SetterprotectedStringesTypejavalog;类型SetterprotectedbooleanisLocationInfotrue;是否打印行号SetterprotectedStringapplicationName;SetterprotectedStringprofile;运行环境SetterprotectedStringesAddress;地址Logback代码注入属性
  这里还有一种情况,有些属性需要在运行时才知道,或者运行时会改变。这就需要能动态注入属性。我们可以使用log4j的MDC类来解决。
  我们可以通过相应的put,remove方法来动态设置属性。
  比如:MDC。put(TraceInfo。TRACEIDKEY,traceInfo。getTraceId());MDC。put(TraceInfo。RPCIDKEY,traceInfo。getRpcId());MDC。remove(TraceInfo。TRACEIDKEY);MDC。remove(TraceInfo。RPCIDKEY);
  获取属性值可以通过LoggingEvent的getMDCPropertyMap方法先获取属性的map,再根据键名从map中取出来。
  比如:privateStringgetRpcId(LoggingEventevent){MapString,StringmdcPropertyMapevent。getMDCPropertyMap();returnmdcPropertyMap。get(rpcId);}privateStringgetTraceId(LoggingEventevent){MapString,StringmdcPropertyMapevent。getMDCPropertyMap();returnmdcPropertyMap。get(traceId);}
  值得说明的是,mdcAdapter是一个静态的成员变量,但是它自身是线程安全的,我们可以看一下logback的实现privateMapString,StringduplicateAndInsertNewMap(MapString,StringoldMap){MapString,StringnewMapCollections。synchronizedMap(newHashMapString,String());if(oldMap!null){wedontwanttheparentthreadmodifyingoldMapwhileweareiteratingoveritsynchronized(oldMap){newMap。putAll(oldMap);}}copyOnThreadLocal。set(newMap);returnnewMap;}Elasticsearch模板设计
  最后日志保存在Elasticsearch中,我们希望索引名为javalog{date}的形式,type名为实际的微服务名
  最后我们对日志索引设置一个模板
  举一个例子:PUTtemplatejavalog{template:javalog,order:0,setting:{index:{refreshinterval:5s}},mappings:{default:{dynamictemplates:〔{messagefield:{matchmappingtype:string,pathmatch:message,mapping:{norms:false,type:text,analyzer:ikmaxword,searchanalyzer:ikmaxword}}},{throwablefield:{matchmappingtype:string,pathmatch:throwable,mapping:{norms:false,type:text,analyzer:ikmaxword,searchanalyzer:ikmaxword}}},{stringfield:{matchmappingtype:string,match:,mapping:{norms:false,type:text,analyzer:ikmaxword,searchanalyzer:ikmaxword,fields:{keyword:{type:keyword}}}}}〕,all:{enabled:false},properties:{applicationName:{norms:false,type:text,analyzer:ikmaxword,searchanalyzer:ikmaxword,fields:{keyword:{type:keyword,ignoreabove:256}}},profile:{type:keyword},host:{type:keyword},ip:{type:ip},level:{type:keyword},location:{properties:{line:{type:integer}}},dateTime:{type:date},traceId:{type:keyword},rpcId:{type:keyword}}}}}
  示例代码Slf4jpublicclassElasticsearchAppenderEextendsUnsynchronizedAppenderBaseEimplementsLuminaryLoggerAppenderE{privatestaticfinalFastDateFormatSIMPLEFORMATFastDateFormat。getInstance(yyyyMMdd);privatestaticfinalFastDateFormatISODATETIMETIMEZONEFORMATWITHMILLISFastDateFormat。getInstance(yyyyMMddTHH:mm:ss。SSSZZ);protectedJestClientjestClient;privatestaticfinalStringCONFIGPROPERTIESNAMEes。properties;可在xml中配置的属性SetterprotectedStringesIndexjavalogdate;索引SetterprotectedStringesTypejavalog;类型SetterprotectedbooleanisLocationInfotrue;是否打印行号SetterprotectedStringapplicationName;SetterprotectedStringprofile;运行环境SetterprotectedStringesAddress;地址Overridepublicvoidstart(){super。start();init();}Overridepublicvoidstop(){super。stop();关闭es客户端try{jestClient。close();}catch(IOExceptione){addStatus(newErrorStatus(closejestClientfail,this,e));}}Overrideprotectedvoidappend(Eevent){if(!isStarted()){return;}subAppend(event);}privatevoidsubAppend(Eevent){if(!isStarted()){return;}try{thisstepavoidsLBCLASSIC139if(eventinstanceofDeferredProcessingAware){((DeferredProcessingAware)event)。prepareForDeferredProcessing();}thesynchronizationpreventstheOutputStreamfrombeingclosedwhilewearewriting。Italsopreventsmultiplethreadsfromenteringthesameconverter。Convertersassumethattheyareinasynchronizedblock。save(event);}catch(Exceptionioe){assoonasanexceptionoccurs,movetononstartedstateandaddasingleErrorStatustotheSM。this。startedfalse;addStatus(newErrorStatus(IOfailureinappender,this,ioe));}}privatevoidsave(Eevent){if(eventinstanceofLoggingEvent){获得ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a数据EsLogVOesLogVOcreateData((LoggingEvent)event);保存到es中save(esLogVO);}else{addWarn(theerrortypeofevent!);}}privatevoidsave(EsLogVOesLogVO){GsongsonnewGson();StringjsonStringgson。toString();StringesIndexFormatesIndex。replace(date,SIMPLEFORMAT。format(Calendar。getInstance()。getTime()));IndexindexnewIndex。Builder(esLogVO)。index(esIndexFormat)。type(esType)。build();try{DocumentResultresultjestClient。execute(index);addStatus(newInfoStatus(esloggerresult:result。getJsonString(),this));}catch(Exceptione){addStatus(newErrorStatus(jestClientexecfail,this,e));}}privateEsLogVOcreateData(LoggingEventevent){EsLogVOesLogVOnewEsLogVO();获得applicationNameesLogVO。setApplicationName(applicationName);获得profileesLogVO。setProfile(profile);获得ipesLogVO。setIp(HostUtil。getIP());获得hostNameesLogVO。setHost(HostUtil。getHostName());获得时间longdateTimegetDateTime(event);esLogVO。setDateTime(ISODATETIMETIMEZONEFORMATWITHMILLIS。format(Calendar。getInstance()。getTime()));获得线程StringthreadNamegetThead(event);esLogVO。setThread(threadName);获得ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a等级StringlevelgetLevel(event);esLogVO。setLevel(level);获得调用信息EsLogVO。LocationlocationgetLocation(event);esLogVO。setLocation(location);获得ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志a信息StringmessagegetMessage(event);esLogVO。setMessage(message);获得异常信息StringthrowablegetThrowable(event);esLogVO。setThrowable(throwable);获得traceIdStringtraceIdgetTraceId(event);esLogVO。setTraceId(traceId);获得rpcIdStringrpcIdgetRpcId(event);esLogVO。setRpcId(rpcId);returnesLogVO;}privateStringgetRpcId(LoggingEventevent){MapString,StringmdcPropertyMapevent。getMDCPropertyMap();returnmdcPropertyMap。get(rpcId);}privateStringgetTraceId(LoggingEventevent){MapString,StringmdcPropertyMapevent。getMDCPropertyMap();returnmdcPropertyMap。get(traceId);}privateStringgetThrowable(LoggingEventevent){StringexceptionStack;IThrowableProxytpevent。getThrowableProxy();if(tpnull)return;StringBuildersbnewStringBuilder(2048);while(tp!null){StackTraceElementProxy〔〕stackArraytp。getStackTraceElementProxyArray();ThrowableProxyUtil。subjoinFirstLine(sb,tp);intcommonFramestp。getCommonFrames();StackTraceElementProxy〔〕stepArraytp。getStackTraceElementProxyArray();for(inti0;istepArray。lengthcommonFrames;i){sb。append();sb。append(CoreConstants。TAB);ThrowableProxyUtil。subjoinSTEP(sb,stepArray〔i〕);}if(commonFrames0){sb。append();sb。append(CoreConstants。TAB)。append(。。。)。append(commonFrames)。append(commonframesomitted);}sb。append();tptp。getCause();}returnsb。toString();}privateStringgetMessage(LoggingEventevent){returnevent。getFormattedMessage();}privateEsLogVO。LocationgetLocation(LoggingEventevent){EsLogVO。LocationlocationnewEsLogVO。Location();if(isLocationInfo){StackTraceElement〔〕cdaevent。getCallerData();if(cda!nullcda。length0){StackTraceElementimmediateCallerDatacda〔0〕;location。setClassName(immediateCallerData。getClassName());location。setMethod(immediateCallerData。getMethodName());location。setFile(immediateCallerData。getFileName());location。setLine(String。valueOf(immediateCallerData。getLineNumber()));}}returnlocation;}privateStringgetLevel(LoggingEventevent){returnevent。getLevel()。toString();}privateStringgetThead(LoggingEventevent){returnevent。getThreadName();}privatelonggetDateTime(LoggingEventevent){return((LoggingEvent)event)。getTimeStamp();}privatevoidinit(){try{ClassLoaderesClassLoaderElasticsearchAppender。class。getClassLoader();SetURLesConfigPathSetnewLinkedHashSetURL();EnumerationURLpaths;if(esClassLoadernull){pathsClassLoader。getSystemResources(CONFIGPROPERTIESNAME);}else{pathsesClassLoader。getResources(CONFIGPROPERTIESNAME);}while(paths。hasMoreElements()){URLpathpaths。nextElement();esConfigPathSet。add(path);}if(esConfigPathSet。size()0){subInit();if(jestClientnull){addWarn(没有获取到配置信息!);用默认信息初始化es客户端jestClientnewJestClientMgr()。getJestClient();}}else{if(esConfigPathSet。size()1){addWarn(获取到多个配置信息,将以第一个为准!);}URLpathesConfigPathSet。iterator()。next();try{PropertiesconfignewProperties();CleanupInputStreaminputnewFileInputStream(path。getPath());config。load(input);通过properties初始化es客户端jestClientnewJestClientMgr(config)。getJestClient();}catch(Exceptione){addStatus(newErrorStatus(configfail,this,e));}}}catch(Exceptione){addStatus(newErrorStatus(configfail,this,e));}}OverridepublicvoidsubInit(){templatemethod}}代码地址:
  https:github。comwulinfeng2luminarycomponent
  原文链接:https:mp。weixin。qq。comsDxkoOTBrFUAgnKGj7Y6Cg

希捷采用NVMe协议的HDD曝光配备U。2NVMe接口去年希捷(Seagate)在开放计算项目峰会上,展示了业界首款采用PCIe接口的机械硬盘(HDD)。与SSD一样,将采用NVMe协议,与其他SSD一起协同工作。虽然SSD和HDD是官方确认!长安深蓝SL03即将调价,预计上调20008000元12月11日,长安深蓝发布消息称,由于受到新能源汽车补贴政策调整以及主要原材料价格居高不下等因素的影响,决定在2023年对旗下长安深蓝SL03相关车型的指导价进行调整,预计上调幅度MIUI14版本更新计划官宣1月份可以直接升级中关村在线消息今天晚上7点,小米13系列以及MIUI14正式发布,今天发布的第一款产品是MIUI14。MIUI14部分功能总结,发版计划第一批2023年1月Xiaomi12SUlt就业互联网算法工程师比软件开发还香么?开发是雪中送炭,算法是锦上添花。商业社会为了价值最大化服务,资本更是逐利的排头兵。很少有人真为了技术的进阶付费,反而技术的变现能力才能吸引更多的投资。看了众多的回答,基本都在分析个阿根廷4队晋级!国足意外创历史,成亚洲唯一击败过四强的球队最近卡塔尔世界杯已经进入到白热化的阶段,随着英格兰和法国这场比赛落下帷幕之后,目前世界杯的四强名单已经全部出来。接下来半决赛法国将会对战摩洛哥,阿根廷将会对战克罗地亚。值得关注的是湖人接下来可能交易的3名球员当谈到交易传闻时,洛杉矶湖人队一直是头条新闻,随着12月15日交易窗口的逐渐临近,关于球队在交易场上有谁的传言越来越响亮。可以肯定地说,除了勒布朗詹姆斯和安东尼戴维斯,如果球队能给深扒一下这届世界杯里的套路,让你不再是伪球迷每届世界杯都有爆冷,但今年特别多。1世界杯最喜欢踢假球的是哪个国家?肯定是被称为足球王国的巴西!比较久的巴西假球事件98年世界杯决赛,06年卡洛斯系鞋带。各位小伙伴有兴趣的去网上查NBA里打架最厉害的五名球员是谁?阿泰斯特不敌另外四人曾经奥本山宫殿斗殴麦迪逊花园群殴范甘迪身抱莫宁大腿被拖行十几米巴克利抱摔奥尼尔查尔斯偷袭科比隆多保罗拳王争霸等等,虽然打架是NBA里不文明的一幕,但缺少斗殴的联盟确实令人感觉少了那47岁最神奇教练8月才接掌摩洛哥队4个月后就进世界杯4强要说本届世界杯最大的黑马,那就是北非球队摩洛哥队了。要说谁是本届世界杯最神奇教练?我看是摩洛哥队47岁的主教练雷格拉吉!要知道他8月才临时接下摩洛哥兵符,雷格拉吉先率队于2022卡为什么善良的人一生很苦为什么善良的人一生痛苦磨难很多有一天,我向一位德高望重的师傅请教一个问题现实中为什么那些善良的人活得很痛苦,而那些作恶多端的人却春风得意?师傅看了看我满怀慈悲得说一个人内心有痛苦,拯救者Y9000K评测论旗舰游戏本的自我修养如今,电子产品更新迭代程度越来越快,游戏本自然也不例外。不过对于大多数游戏本消费者而言,跟着厂商的节奏,每年更新迭代并不现实。入手一台性能足够强,还耐用的笔记本才是实打实的购买需求
联想小新Pro14162023开卖可选13代酷睿锐龙7000IT之家2月21日消息,联想小新Pro14162023笔记本首批型号今晚正式开卖,可选英特尔13代酷睿和AMDR77735HS处理器。小新Pro14162023酷睿版小新Pro14断网一个多月自动变手动说好的智能擦地机器人去哪儿了?新民晚报讯(记者房浩)市民潘女士向新民帮侬忙反映,她购买了一台iRobot擦地机器人,却因商家后台系统故障,导致设备断网一个多月,原本宣称的智能导航远程操控等黑科技,如今都成了空中焉耆19个新续建项目集中开复工记者杜建辉2月20日,巴音郭楞蒙古自治州焉耆回族自治县举行2023年2月份19个新续建项目集中开复工仪式,吹响了新一年经济高质量发展冲锋号。此次焉耆县集中开复工项目19个,总投资达柬埔寨整肃社会治安,净化投资环境2020年6月26日,人们在柬埔寨金边准备销毁毒品柬埔寨在打击人口贩卖非法偷渡贩毒等方面多次展开针对性行动,禁止网络赌博整顿博彩场所跨国联合打击电信诈骗,多拳出击,整肃社会治安,净智能手机市场大洗牌VO荣米格局已成出品子弹财观作者蓝齐编辑闪电美编倩倩过去十年,手机厂商的厮杀与竞争让国内智能手机得以大规模普及,而随着人人都可以用手机冲浪的愿望实现后,手机终端市场终于迎来了极寒时刻时隔十年,中国华为WATCHGTCyber表壳轻松换,时尚又百变智能手表的出现,很大程度上改变了我们的生活,不同于传统手表,智能手表除了查看时间外,还拥有记录运动监测健康等功能,而且表盘多样,个性化十足,华为作为智能手表的领军者,推出了多款深受斯莫格WaveW1C无线麦克风拆解,2。4G无线传输,360全指向拾音短视频平台的快速兴起,带动了全民参与视频分享生活的热情,随之用于辅助用户提升视频音频质量的相关配件产品也得到了快速发展。其中,体积小巧便携使用便捷的无线领夹麦克风获得了众多消费者的全国冬季两项冠军赛次日内蒙古队包揽女子10公里追逐项目前三今天(21日),正在甘肃省白银国家雪上项目训练基地进行的20222023全国冬季两项冠军赛进入第二个比赛日。在当天进行的男子12。5公里追逐赛中,来自辽宁省冬季运动管理中心的程方明春天干饭,八道下饭菜别错过,香辣入味锅气十足,三碗米饭不够吃大家好,这里是邱哥说美食,进入春天以来,万物复苏,草木生长,各种野花也在温暖的阳光下开放,到处都是生机勃勃的样子,鸟语而花香。在这种美好而舒适的环境下,我们每个人的胃口都变得特别地10道家常海鲜的做法,味道一流,每一道都拿得出手,做法简单10道家常海鲜的做法,味道一流,每一道都拿得出手,做法简单!海鲜是一种很常见的种类,也是夏天吃的最多的一种食物了。很多人都觉得海鲜很难处理,但是实际上只要掌握好正确的步骤,这海鲜不二月二龙抬头,别忘了吃3道头菜,寓意一年开个好头导语二月二龙抬头,别忘了吃3道头菜,寓意一年开个好头。大家好我是傻姐美食,生活中唯有美食和美景不可辜负。元宵节过后还有一个重要的节日二月二,二月二龙抬头,龙不抬头我抬头,小时候不知
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网