点评CAT在Spring-Cloud中的实践

作者在基于Spring Cloud微服务的架构时,一直苦于寻找一个可靠的性能监控平台,后在大神的推荐下,详细研究了点评CAT,其满足对应用性能监控的需求(包含SQL性能,URL响应性能等),将踩过的坑进行分享一下。 下载cat 3.0并启动由于微服务集群并不是很庞大,且服务器资源有限,所以暂时只采用了单点部署的CAT,集群部署和使用请参考CAT的github,这里暂不做分享 配置系统的JDK,以及下载对应的tomcat,本人使用的是JDK8和tomcat8.5.x版本(JDK的配置和tomcat的下载不做详细说明)CAT下载地址http://unidal.org/nexus/servi...修改tomcat的server.xml使其支持中文的URL <Connector port="8080" protocol="HTTP/1.1" URIEncoding="utf-8" connectionTimeout="20000" redirectPort="8443" /><!-- 增加 URIEncoding="utf-8" -->创建CAT使用的文件夹,并修改其配置 mkdir /datachmod -R 777 /data/ 修改CAT配置文件,创建/data/appdatas/cat/client.xml并修改如下 <?xml version="1.0" encoding="utf-8"?><config mode="client"> <servers> <server ip="127.0.0.1" port="2280" http-port="8080"/> </servers></config>修改cat的数据库配置文件/data/appdatas/cat/datasource.xml <?xml version="1.0" encoding="utf-8"?><data-sources> <data-source id="cat"> <maximum-pool-size>3</maximum-pool-size> <connection-timeout>1s</connection-timeout> <idle-timeout>10m</idle-timeout> <statement-cache-size>1000</statement-cache-size> <properties> <driver>com.mysql.jdbc.Driver</driver> <url><![CDATA[jdbc:mysql://127.0.0.1:3306/cat]]></url> <!-- 请替换为真实数据库URL及Port --> <user>root</user> <!-- 请替换为真实数据库用户名 --> <password>root</password> <!-- 请替换为真实数据库密码 --> <connectionProperties><![CDATA[useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&socketTimeout=120000]]></connectionProperties> </properties> </data-source></data-sources>运行CAT的SQL脚本初始化数据库 将CAT的war重命名为cat.war放到tomcat的webapps下,并启动tomcat(默认用户名密码admin:admin),即可通过服务器IP:8080/cat进行访问springboot集成cat clientmaven引入cat client <dependency> <groupId>com.dianping.cat</groupId> <artifactId>cat-client</artifactId> <version>3.0.0</version></dependency>使用SPI方式配置cat client 其中com.dianping.cat.configuration.ClientConfigProvider文件中填写完成实现类名称,实现类代码如下: public class CatClientConfigProvider implements ClientConfigProvider { @Override public ClientConfig getClientConfig() { List<Server> servers = Lists.newArrayList(); //cat 服务器地址,多个则需要使用,分割 String catServersStr = SpringUtils.getProperties("cat.servers"); if (catServersStr != null) { String[] catServers = catServersStr.split(","); for (String catServer : catServers) { servers.add(new Server(catServer)); } //domain直接去springboot的application name String domain = SpringUtils.getProperties("spring.application.name"); ClientConfig config = new ClientConfig(); config.setServers(servers); config.setDomain(domain); return config; } return null; }}app.properties文件中填写app.name=应用名称 ...

June 25, 2019 · 1 min · jiezi

调用链监控 CAT 之 URL埋点实践

URL监控埋点作用一个http请求来了之后,会自动打点,能够记录每个url的访问情况,并将以此请求后续的调用链路串起来,可以在cat上查看logview可以在cat Transaction及Event 页面上都看到URL和URL.Forward(如果有Forward请求的话)两类数据;Transaction数据中URL点进去的数据就是被访问的具体URL(去掉参数的前缀部分)请将catFilter存放filter的第一个,这样可以保证最大可能性监控所有的请求实践工程说明工程名端口作用cat-ui8082调用入口服务cat-business-consumer8083业务消费服务cat-order-service8084订单服务cat-storage-service8085库存服务上图是本节实例的埋点图,首先 cat-ui 的入口 和 调用点 加入cat埋点,cat-business-consumer的入口和调用点加入埋点,cat-order-service 和 cat-storage-service 不再调用其他微服务,所以只在入口加入埋点。通过这样的埋点,可以组成一条完整的调用链。关键代码调用链上下文通用类CatContextImpl.java/** * Cat.context接口实现类,用于context调用链传递,相关方法Cat.logRemoteCall()和Cat.logRemoteServer() /public class CatContextImpl implements Cat.Context { private Map<String, String> properties = new HashMap<>(16); @Override public void addProperty(String key, String value) { properties.put(key, value); } @Override public String getProperty(String key) { return properties.get(key); }}CatHttpConstants/* * 添加header常量,用于http协议传输rootId、parentId、childId三个context属性 /public class CatHttpConstants { /* * http header 常量 / public static final String CAT_HTTP_HEADER_ROOT_MESSAGE_ID = “X-CAT-ROOT-MESSAGE-ID”; public static final String CAT_HTTP_HEADER_PARENT_MESSAGE_ID = “X-CAT-ROOT-PARENT-ID”; public static final String CAT_HTTP_HEADER_CHILD_MESSAGE_ID = “X-CAT-ROOT-CHILD-ID”;}CatServletFilter/* * http协议传输,远程调用链目标端接收context的filter, * 通过header接收rootId、parentId、childId并放入CatContextImpl中,调用Cat.logRemoteCallServer()进行调用链关联 * 注:若不涉及调用链,则直接使用cat-client.jar中提供的filter即可 * 使用方法(视项目框架而定): * 1、web项目:在web.xml中引用此filter * 2、Springboot项目,通过注入bean的方式注入此filter */public class CatServletFilter implements Filter { private String[] urlPatterns = new String[0]; @Override public void init(FilterConfig filterConfig) throws ServletException { String patterns = filterConfig.getInitParameter(“CatHttpModuleUrlPatterns”); if (patterns != null) { patterns = patterns.trim(); urlPatterns = patterns.split(","); for (int i = 0; i < urlPatterns.length; i++) { urlPatterns[i] = urlPatterns[i].trim(); } } } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; String url = request.getRequestURL().toString(); for (String urlPattern : urlPatterns) { if (url.startsWith(urlPattern)) { url = urlPattern; } } CatContextImpl catContext = new CatContextImpl(); catContext.addProperty( Cat.Context.ROOT, request.getHeader(CatHttpConstants.CAT_HTTP_HEADER_ROOT_MESSAGE_ID)); catContext.addProperty(Cat.Context.PARENT, request.getHeader(CatHttpConstants.CAT_HTTP_HEADER_PARENT_MESSAGE_ID)); catContext.addProperty(Cat.Context.CHILD, request.getHeader(CatHttpConstants.CAT_HTTP_HEADER_CHILD_MESSAGE_ID)); Cat.logRemoteCallServer(catContext); Transaction t = Cat.newTransaction( CatConstants.TYPE_URL, url); try { Cat.logEvent(“Service.method”, request.getMethod(), Message.SUCCESS, request.getRequestURL().toString()); Cat.logEvent(“Service.client”, request.getRemoteHost()); filterChain.doFilter(servletRequest, servletResponse); t.setStatus(Transaction.SUCCESS); } catch (Exception ex) { t.setStatus(ex); Cat.logError(ex); throw ex; } finally { t.complete(); } } @Override public void destroy() { }}本节实例中每个工程都会用到调用链上下文通用类。cat-ui 工程CatRestInterceptor@Componentpublic class CatRestInterceptor implements ClientHttpRequestInterceptor { @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { Transaction t = Cat.newTransaction(CatConstants.TYPE_REMOTE_CALL, request.getURI().toString()); try { HttpHeaders headers = request.getHeaders(); // 保存和传递CAT调用链上下文 Cat.Context ctx = new CatContextImpl(); Cat.logRemoteCallClient(ctx); headers.add(CatHttpConstants.CAT_HTTP_HEADER_ROOT_MESSAGE_ID, ctx.getProperty(Cat.Context.ROOT)); headers.add(CatHttpConstants.CAT_HTTP_HEADER_PARENT_MESSAGE_ID, ctx.getProperty(Cat.Context.PARENT)); headers.add(CatHttpConstants.CAT_HTTP_HEADER_CHILD_MESSAGE_ID, ctx.getProperty(Cat.Context.CHILD)); // 保证请求继续被执行 ClientHttpResponse response = execution.execute(request, body); t.setStatus(Transaction.SUCCESS); return response; } catch (Exception e) { Cat.getProducer().logError(e); t.setStatus(e); throw e; } finally { t.complete(); } }}CatServletFilter 对 cat-ui 的入口进行了埋点,CatRestInterceptor 实现 ClientHttpRequestInterceptor接口 可以对 RestTemplate 发起的请求进行拦截,利用这一点对调用点埋点,同时在 Http Header 中存入 调用链的上下文,将调用链传递下去。cat-business-consumer、cat-order-service、cat-storage-service 中的埋点与 cat-ui 埋点的方式相同。测试发起请求curl http://127.0.0.1:8082/startcat 监控界面可以看到本节实例的服务。点开 “logView” 可以看到完整的调用链信息。点击 “Graph” 查看图表形式的调用链信息。源码https://github.com/gf-huanchu…参考https://github.com/dianping/c…欢迎扫码或微信搜索公众号《程序员果果》关注我,关注有惊喜~ ...

April 16, 2019 · 2 min · jiezi

调用链监控 CAT 之 入门

简介CAT 是一个实时和接近全量的监控系统,它侧重于对Java应用的监控,基本接入了美团上海所有核心应用。目前在中间件(MVC、RPC、数据库、缓存等)框架中得到广泛应用,为美团各业务线提供系统的性能指标、健康状况、监控告警等。优势实时处理:信息的价值会随时间锐减,尤其是事故处理过程中。全量数据:全量采集指标数据,便于深度分析故障案例。高可用:故障的还原与问题定位,需要高可用监控来支撑。故障容忍:故障不影响业务正常运转、对业务透明。高吞吐:海量监控数据的收集,需要高吞吐能力做保证。可扩展:支持分布式、跨 IDC 部署,横向扩展的监控系统。开源产品比较快速上手本地部署步骤1:部署tomcat准备一个tomcat,修改 tomcat conf 目录下 server.xml,防中文乱码。Connector port=“8080” protocol=“HTTP/1.1” URIEncoding=“utf-8” connectionTimeout=“20000” redirectPort=“8443” /> <!– 增加 URIEncoding=“utf-8” –>步骤2:程序对于/data/目录具体读写权限(重要)Linux要求/data/目录能进行读写操作,如果/data/目录不能写,建议使用linux的软链接链接到一个固定可写的目录。此目录会存一些CAT必要的配置文件以及运行时候的数据存储目录。CAT支持CAT_HOME环境变量,可以通过JVM参数修改默认的路径。mkdir /datachmod -R 777 /data/Windows对程序运行盘下的/data/appdatas/cat和/data/applogs/cat有读写权限。例如cat服务运行在e盘的tomcat中,则需要对e:/data/appdatas/cat和e:/data/applogs/cat有读写权限。步骤3: 配置/data/appdatas/cat/client.xml ($CAT_HOME/client.xml)<?xml version=“1.0” encoding=“utf-8”?><config mode=“client”> <servers> <server ip=“127.0.0.1” port=“2280” http-port=“8080”/> </servers></config>此配置文件的作用是所有的客户端都需要一个地址指向CAT的服务端。步骤4: 安装CAT的数据库下载cat源码包:https://codeload.github.com/d…解压后,数据库的脚本文件为 script/CatApplication.sqlmysql -uroot -Dcat < CatApplication.sql步骤5: 配置/data/appdatas/cat/datasources.xml($CAT_HOME/datasources.xml)<?xml version=“1.0” encoding=“utf-8”?><data-sources> <data-source id=“cat”> <maximum-pool-size>3</maximum-pool-size> <connection-timeout>1s</connection-timeout> <idle-timeout>10m</idle-timeout> <statement-cache-size>1000</statement-cache-size> <properties> <driver>com.mysql.jdbc.Driver</driver> <url><![CDATA[jdbc:mysql://127.0.0.1:3306/cat]]></url> <!– 请替换为真实数据库URL及Port –> <user>root</user> <!– 请替换为真实数据库用户名 –> <password>root</password> <!– 请替换为真实数据库密码 –> <connectionProperties><![CDATA[useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&socketTimeout=120000]]></connectionProperties> </properties> </data-source></data-sources>步骤6: war打包官方下载:http://unidal.org/nexus/servi…重命名为cat.war进行部署,注意此war是用jdk8,服务端请使用jdk8版本步骤7: war部署将上一步打包的war包部署到本机tomcat的webapps下。启动tomcat,打开控制台的URL,http://127.0.0.1:8080/cat/s/config?op=routerConfigUpdate 默认用户名:admin 默认密码:admin 。配置客户端路由。<?xml version=“1.0” encoding=“utf-8”?><router-config backup-server=“你的本机ip(不要用127.0.0.1)” backup-server-port=“2280”> <default-server id=“你的本机ip(不要用127.0.0.1)” weight=“1.0” port=“2280” enable=“true”/> <network-policy id=“default” title=“默认” block=“false” server-group=“default_group”> </network-policy> <server-group id=“default_group” title=“default-group”> <group-server id=“你的本机ip(不要用127.0.0.1)”/> </server-group> <domain id=“cat”> <group id=“default”> <server id=“你的本机ip(不要用127.0.0.1)” port=“2280” weight=“1.0”/> </group> </domain></router-config>提交后,重启tomcat,访问http://127.0.0.1:8080/cat,出现如下界面,说明搭建成功。测试安装jar包进入cat源码包的 lib/java/jar ,将cat-client-3.0.0.jar 包 安装到本地maven仓库。mvn install:install-file -DgroupId=com.dianping.cat -DartifactId=cat-client Dversion=3.0.0 -Dpackaging=jar -Dfile=cat-client-3.0.0.jar创建工程创建一个springboot 工程,关键代码如下。pom.xml<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><dependency> <groupId>com.dianping.cat</groupId> <artifactId>cat-client</artifactId> <version>3.0.0</version></dependency>app.properties需要在你的项目中创建 src/main/resources/META-INF/app.properties 文件, 并添加如下内容:app.name={appkey}appkey 只能包含英文字母 (a-z, A-Z)、数字 (0-9)、下划线 (_) 和中划线 (-)application.ymlserver: port: 8760spring: application: name: cat-simple启动类@SpringBootApplication@RestControllerpublic class CatSimpleApplication { public static void main(String[] args) { SpringApplication.run( CatSimpleApplication.class, args ); } @PostMapping("/hi") public String hi(HttpServletRequest request){ String url = request.getRequestURL().toString(); // 创建一个 Transaction Transaction transaction = Cat.newTransaction( “URL”, url ); try { // 处理业务 myBusiness(); // 设置状态 transaction.setStatus(Transaction.SUCCESS); } catch (Exception e) { // 设置错误状态 transaction.setStatus(e); // 记录错误信息 Cat.logError(e); } finally { // 结束 Transaction transaction.complete(); } return “hello”; } @PostMapping("/error") public String error(HttpServletRequest request){ String url = request.getRequestURL().toString(); // 创建一个 Transaction Transaction transaction = Cat.newTransaction( “URL”, url ); try { // 处理业务 int i = 1 / 0; // 设置状态 transaction.setStatus(Transaction.SUCCESS); } catch (Exception e) { // 设置错误状态 transaction.setStatus(e); // 记录错误信息 Cat.logError(e); } finally { // 结束 Transaction transaction.complete(); } return “500”; } private void myBusiness() { //模拟业务处理的时间 try { Thread.sleep( 500 ); } catch (InterruptedException e) { e.printStackTrace(); } }}请求 http://localhost:8760/hicurl -X POST http://localhost:8760/hi请求 http://localhost:8760/errorcurl -X POST http://localhost:8760/error查看监控信息进入 cat 控制台,点击 Transaction 按钮 ,之后点击全部,会看到有哪些客户端,如图:点击客户端 cat-simple ,出现如图:如上图,可以清晰的看到 请求的 总个数(tatal)、均值(avg)、最大/最小(max/min)、标准差(std)等,其他都比较直观,标准差稍微复杂一点,大家自己可以推演一下怎么做增量计算。那集合运算,比如95线(表示95%请求的完成时间)、999线(表示99.9%请求的完成时间)点击 “log View” 可以查看 错误信息,如图:源码https://github.com/gf-huanchu…参考https://github.com/dianping/c…关注我的公众号,精彩内容不能错过~ ...

April 11, 2019 · 2 min · jiezi

日志分析必备指令集【来自一段线上日志的查看的经历】

线上日志查看基础查看线上机器的一些信息和基础命令:du、df查看大小相关cat、zcat、less、tail、head查看文件内容grep、awk处理文件内容sort、uniq、wc统计scp文件传输du、df查看大小相关df 查看系统挂载磁盘大小df [选项]… [FILE]…文件-a, –all 包含所有的具有 0 Blocks 的文件系统文件–block-size={SIZE} 使用 {SIZE} 大小的 Blocks文件-h, –human-readable 使用人类可读的格式(预设值是不加这个选项的…)文件-H, –si 很像 -h, 但是用 1000 为单位而不是用 1024文件-i, –inodes 列出 inode 资讯,不列出已使用 block文件-k, –kilobytes 就像是 –block-size=1024文件-l, –local 限制列出的文件结构文件-m, –megabytes 就像 –block-size=1048576文件–no-sync 取得资讯前不 sync (预设值)文件-P, –portability 使用 POSIX 输出格式文件–sync 在取得资讯前 sync文件-t, –type=TYPE 限制列出文件系统的 TYPE文件-T, –print-type 显示文件系统的形式文件-x, –exclude-type=TYPE 限制列出文件系统不要显示 TYPE文件-v (忽略)常见使用实例:df -hdu会显示指定的目录或文件所占用的磁盘空间du [-abcDhHklmsSx][-L <符号连接>][-X <文件>][–block-size][–exclude=<目录或文件>][–max-depth=<目录层数>][–help][–version][目录或文件]参数说明:-a或-all 显示目录中个别文件的大小。-b或-bytes 显示目录或文件大小时,以byte为单位。-c或–total 除了显示个别目录或文件的大小外,同时也显示所有目录或文件的总和。-D或–dereference-args 显示指定符号连接的源文件大小。-h或–human-readable 以K,M,G为单位,提高信息的可读性。-H或–si 与-h参数相同,但是K,M,G是以1000为换算单位。-k或–kilobytes 以1024 bytes为单位。-l或–count-links 重复计算硬件连接的文件。-L<符号连接>或–dereference<符号连接> 显示选项中所指定符号连接的源文件大小。-m或–megabytes 以1MB为单位。-s或–summarize 仅显示总计。-S或–separate-dirs 显示个别目录的大小时,并不含其子目录的大小。-x或–one-file-xystem 以一开始处理时的文件系统为准,若遇上其它不同的文件系统目录则略过。-X<文件>或–exclude-from=<文件> 在<文件>指定目录或文件。–exclude=<目录或文件> 略过指定的目录或文件。–max-depth=<目录层数> 超过指定层数的目录后,予以忽略。使用实例:查看当前文件夹的一级内容大小du -h –max-depth=1cat、zcat、less、tail、head查看文件内容 cat 命令用于连接文件并打印到标准输出设备上cat [-AbeEnstTuv] [–help] [–version] fileName-n 或 --number:由 1 开始对所有输出的行数编号。-b 或 --number-nonblank:和 -n 相似,只不过对于空白行不编号。-s 或 --squeeze-blank:当遇到有连续两行以上的空白行,就代换为一行的空白行。-v 或 --show-nonprinting:使用 ^ 和 M- 符号,除了 LFD 和 TAB 之外。-E 或 --show-ends : 在每行结束处显示 $。-T 或 --show-tabs: 将 TAB 字符显示为 ^I。-A, --show-all:等价于 -vET。-e:等价于"-vE"选项;-t:等价于"-vT"选项;zcatt命令用于不真正解压缩文件,就能显示压缩包中文件的内容的场合。head显示档案的开头至标准输出中,默认head命令打印其相应文件的开头10行head [参数]… [文件]… -q 隐藏文件名-v 显示文件名-c&lt;字节&gt; 显示字节数-n&lt;行数&gt; 显示的行数tail用于查看文件的内容,有一个常用的参数 -f 常用于查阅正在改变的日志文件tail[必要参数][选择参数][文件] -f 循环读取-q 不显示处理信息-v 显示详细的处理信息-c&lt;数目&gt; 显示的字节数-n&lt;行数&gt; 显示行数--pid=PID 与-f合用,表示在进程ID,PID死掉之后结束. -q, --quiet, --silent 从不输出给出文件名的首部 -s, --sleep-interval=S 与-f合用,表示在每次反复的间隔休眠S秒 less可以随意浏览文件less [参数] 文件-b &lt;缓冲区大小&gt; 设置缓冲区的大小-e 当文件显示结束后,自动离开-f 强迫打开特殊文件,例如外围设备代号、目录和二进制文件-g 只标志最后搜索的关键词-i 忽略搜索时的大小写-m 显示类似more命令的百分比-N 显示每行的行号-o &lt;文件名&gt; 将less 输出的内容在指定文件中保存起来-Q 不使用警告音-s 显示连续空行为一行-S 行过长时间将超出部分舍弃-x &lt;数字&gt; 将“tab”键显示为规定的数字空格/字符串:向下搜索“字符串”的功能?字符串:向上搜索“字符串”的功能n:重复前一个搜索(与 / 或 ? 有关)N:反向重复前一个搜索(与 / 或 ? 有关)b 向后翻一页d 向后翻半页h 显示帮助界面Q 退出less 命令u 向前滚动半页y 向前滚动一行空格键 滚动一行回车键 滚动一页[pagedown]: 向下翻动一页[pageup]: 向上翻动一页grep、awk处理文件内容grep用于查找文件里符合条件的字符串。grep [-abcEFGhHilLnqrsvVwxy][-A<显示列数>][-B<显示列数>][-C<显示列数>][-d<进行动作>][-e<范本样式>][-f<范本文件>][–help][范本样式][文件或目录…]-a 或 –text : 不要忽略二进制的数据。-A<显示行数> 或 –after-context=<显示行数> : 除了显示符合范本样式的那一列之外,并显示该行之后的内容。-b 或 –byte-offset : 在显示符合样式的那一行之前,标示出该行第一个字符的编号。-B<显示行数> 或 –before-context=<显示行数> : 除了显示符合样式的那一行之外,并显示该行之前的内容。-c 或 –count : 计算符合样式的列数。-C<显示行数> 或 –context=<显示行数>或-<显示行数> : 除了显示符合样式的那一行之外,并显示该行之前后的内容。-d <动作> 或 –directories=<动作> : 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep指令将回报信息并停止动作。-e<范本样式> 或 –regexp=<范本样式> : 指定字符串做为查找文件内容的样式。-E 或 –extended-regexp : 将样式为延伸的普通表示法来使用。-f<规则文件> 或 –file=<规则文件> : 指定规则文件,其内容含有一个或多个规则样式,让grep查找符合规则条件的文件内容,格式为每行一个规则样式。-F 或 –fixed-regexp : 将样式视为固定字符串的列表。-G 或 –basic-regexp : 将样式视为普通的表示法来使用。-h 或 –no-filename : 在显示符合样式的那一行之前,不标示该行所属的文件名称。-H 或 –with-filename : 在显示符合样式的那一行之前,表示该行所属的文件名称。-i 或 –ignore-case : 忽略字符大小写的差别。-l 或 –file-with-matches : 列出文件内容符合指定的样式的文件名称。-L 或 –files-without-match : 列出文件内容不符合指定的样式的文件名称。-n 或 –line-number : 在显示符合样式的那一行之前,标示出该行的列数编号。-q 或 –quiet或–silent : 不显示任何信息。-r 或 –recursive : 此参数的效果和指定"-d recurse"参数相同。-s 或 –no-messages : 不显示错误信息。-v 或 –revert-match : 显示不包含匹配文本的所有行。-V 或 –version : 显示版本信息。-w 或 –word-regexp : 只显示全字符合的列。-x –line-regexp : 只显示全列符合的列。-y : 此参数的效果和指定"-i"参数相同。awk处理文本文件的语言,是一个强大的文本分析工具。awk ‘{pattern + action}’ {filenames}或者awk [-F field-separator] ‘commands’ input-file(s)awk -F, ‘$2 ~ /test/ {print $2"\t"$4}’ log.txt使用-F,的作用是每行按照,分割,$1-$2-$n就是分割的结果的对应顺序的值$2 ~ /th/就是需要分割的第二个数据需要和test匹配的上{print $2$4}输出分割结果的第二个和第四个处理的信息是log.txtawk -F ‘[:=]’ ‘{match($5,/.uc_name=(.)&extend=test./,a); print a[1]}’ log.txt-F ‘[:=]‘使用多个分隔符,先使用:分割,然后在对分割结果使用=二次分割。’{match($5,/.uc_name=(.)&extend=test./,a); print a[1]}‘对分割后的第五个结果处理,需要能够匹配上其中的正则,并把匹配结果放到数组a中,其中a数组的结果a[0]是全匹配的结果,a[1]是正则匹配的子表达式结果,并输出子表达式。sort、uniq、wc统计sort用于将文本文件内容加以排序。sort [-bcdfimMnr][-o<输出文件>][-t<分隔字符>][+<起始栏位>-<结束栏位>][–help][–verison][文件]-b 忽略每行前面开始出的空格字符。-c 检查文件是否已经按照顺序排序。-d 排序时,处理英文字母、数字及空格字符外,忽略其他的字符。-f 排序时,将小写字母视为大写字母。-i 排序时,除了040至176之间的ASCII字符外,忽略其他的字符。-m 将几个排序好的文件进行合并。-M 将前面3个字母依照月份的缩写进行排序。-n 依照数值的大小排序。-o<输出文件> 将排序后的结果存入指定的文件。-r 以相反的顺序来排序。-t<分隔字符> 指定排序时所用的栏位分隔字符。+<起始栏位>-<结束栏位> 以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。uniq用于检查及删除文本文件中重复出现的行列,需要与 sort 命令结合使用[一定要排序,不然去重无效,只会去除相邻的重复项]uniq [-cdu][-f<栏位>][-s<字符位置>][-w<字符位置>][–help][–version][输入文件][输出文件]-c或–count 在每列旁边显示该行重复出现的次数。-d或–repeated 仅显示重复出现的行列。-f<栏位>或–skip-fields=<栏位> 忽略比较指定的栏位。-s<字符位置>或–skip-chars=<字符位置> 忽略比较指定的字符。-u或–unique 仅显示出一次的行列。-w<字符位置>或–check-chars=<字符位置> 指定要比较的字符。wc计算文件的Byte数、字数、或是列数,若不指定文件名称、或是所给予的文件名为"-",则wc指令会从标准输入设备读取数据。uniq [-cdu][-f<栏位>][-s<字符位置>][-w<字符位置>][–help][–version][输入文件][输出文件]-c或–bytes或–chars 只显示Bytes数。-l或–lines 只显示行数。-w或–words 只显示字数。scp文件传输scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令[需要配置ssh登入,密码或者公钥免密]scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] [-l limit] [-o ssh_option] [-P port] [-S program] [[user@]host1:]file1 […] [[user@]host2:]file2-1: 强制scp命令使用协议ssh1-2: 强制scp命令使用协议ssh2-4: 强制scp命令只使用IPv4寻址-6: 强制scp命令只使用IPv6寻址-B: 使用批处理模式(传输过程中不询问传输口令或短语)-C: 允许压缩。(将-C标志传递给ssh,从而打开压缩功能)-p:保留原文件的修改时间,访问时间和访问权限。-q: 不显示传输进度条。-r: 递归复制整个目录。-v:详细方式显示输出。scp和ssh(1)会显示出整个过程的调试信息。这些信息用于调试连接,验证和配置问题。-c cipher: 以cipher将数据传输进行加密,这个选项将直接传递给ssh。-F ssh_config: 指定一个替代的ssh配置文件,此参数直接传递给ssh。-i identity_file: 从指定文件中读取传输时使用的密钥文件,此参数直接传递给ssh。-l limit: 限定用户所能使用的带宽,以Kbit/s为单位。-o ssh_option: 如果习惯于使用ssh_config(5)中的参数传递方式,-P port:注意是大写的P, port是指定数据传输用到的端口号-S program: 指定加密传输时所使用的程序。此程序必须能够理解ssh(1)的选项。实践线上日志结构:183.250.223.158 [16/Dec/2018:23:57:15 +0800] “GET /log?skdata=sdadadad111%22username%33%3ftestets%22fsfdsfssadadasd%34fdsfs%34 HTTP/1.0” 200 2 “-” “testiPhone/d64556” “120.188.90.136” “jsdgajdsad” “dasdadd” “test” “ceshi"分析数据命令:cat /home/logs/2018/12/access.2018-12-16.log | grep -E ‘skdata.*prodetail.*etype%2522%253A0.*eid.theme_prodetail.vs_theme’ | awk ‘{match($5,/.uc_name%2522%253A%2522(.)%2522%252C%2522etype./,a); print a[1]}’ | sort | uniq -c | wc -lcat查看某一天的日志文件,访问日志一般文件一天记录一份grep查看符合需求的访问日志,本实例使用正则匹配-E来筛选出符合要求的详情页访问日志,输出awk分析符合要求的详情页访问日志,把每行详情页访问日志中$5【空格分割的第五个字符串,本实例就是以/log?开头的字符串】去匹配一个正则.uc_name%2522%253A%2522(.)%2522%252C%2522etype.,并把结果放到变量a中【a[0]是全匹配,a[1]是第一个字表达式】,然后把匹配成功符合结果的a[1]输出sort将上述结果排序 [一定要排序,不然去重无效,只会去除相邻的重复项]uniq -c将上述结果去重wc -l查看总共结果数量 ...

December 18, 2018 · 2 min · jiezi

CAT 3.0 开源发布,支持多语言客户端及多项性能提升

项目背景CAT(Central Application Tracking),是美团点评基于 Java 开发的一套开源的分布式实时监控系统。美团点评基础架构部希望在基础存储、高性能通信、大规模在线访问、服务治理、实时监控、容器化及集群智能调度等领域提供业界领先的、统一的解决方案,CAT 目前在美团点评的产品定位是应用层的统一监控组件,在中间件(RPC、数据库、缓存、MQ 等)框架中得到广泛应用,为各业务线提供系统的性能指标、健康状况、实时告警等服务。本文会对 CAT 的客户端、性能等做详细深入的介绍,前不久我们也发过一篇 CAT 相关的文章,里面详细介绍了 CAT 客户端和服务端的设计思路,欲知更多细节,欢迎阅读《深度剖析开源分布式监控CAT》产品价值减少故障发现时间降低故障定位成本辅助应用程序优化技术优势实时处理:信息的价值会随时间锐减,尤其是在事故处理过程中全量数据:全量采集指标数据,便于深度分析故障案例高可用:故障的还原与问题定位,需要高可用监控来支撑故障容忍:故障不影响业务正常运转、对业务透明高吞吐:海量监控数据的收集,需要高吞吐能力做保证可扩展:支持分布式、跨 IDC 部署,横向扩展的监控系统使用现状目前,CAT 已经覆盖了美团点评的外卖、酒旅、出行、金融等核心业务线,几乎已经接入美团点评的所有核心应用,并在生产环境中大规模地得到使用。2016 年初至今,CAT 接入的应用增加了400%,机器数增加了 900%,每天处理的消息总量高达 3200 亿,存储消息量近 400TB,高峰期集群 QPS 达 650万/秒。面对流量的成倍增长,CAT 在通信、计算、存储方面都遇到了前所未有的挑战。整个系统架构也经历了一系列的升级和改造,包括消息采样聚合、消息存储、业务多维度指标监控、统一告警等等,项目最终稳定落地。为公司未来几年内业务流量的稳定增长,打下了坚定的基石。经过 7 年的持续建设,CAT 也在不断发展,我们也希望更好的回馈社区,将 CAT 提供的服务惠及更多的外部公司。我们今年将对开源版本进行较大的迭代与更新,未来也会持续把公司内部一些比较好的实践推广出去,欢迎大家跟我们一起共建这个开源社区。新版特性CAT 3.0.0 Release Notes多语言客户端随着业务的不断发展,很多产品和应用需要使用不同的语言,CAT 多语言客户端需求日益增多,除 Java 客户端外,目前提供了 C/C++、Python、Node.js、Golang 客户端,基本覆盖了主流的开发语言。对于多语言客户端,核心设计目标是利用 C 客户端提供核心 API 接口作为底层基石,封装其他语言 SDK。目前支持的主流语言使用指南:JavaC/C++PythonNode.jsGolang性能提升消息采样聚合消息采样聚合在客户端应对大流量时起到了至关重要的作用,当采样命中或者内存队列已满时都会经过采样聚合上报。采样聚合是对消息树拆分归类,利用本地内存做分类统计,将聚合之后的数据进行上报,减少客户端的消息量以及降低网络开销。通信协议优化CAT 客户端与服务端通信协议由自定义文本协议升级为自定义二进制协议,在大规模数据实时处理场景下性能提升显著。目前服务端同时支持两种版本的通信协议,向下兼容旧版客户端。测试环境:CentOS 6.5,4C8G 虚拟机测试结果:新版相比旧版,序列化耗时降低约 3 倍消息文件存储新版消息文件存储进行了重新设计,解决旧版本的文件存储索引、数据文件节点过多以及随机 IO 恶化的问题。新版消息文件存储为了同时兼顾读写性能,引入了二级索引存储方案,对同一个应用的 IP 节点进行合并,并且保证一定的顺序存储。下图是索引结构的最小单元,每个索引文件由若干个最小单元组成。每个单元分为 4×1024 个桶,第一个桶作为我们的一级索引 Header,存储 IP、消息序列号与分桶的映射信息。剩余 4×1024 - 1 个桶作为二级索引,存储消息的地址。新版消息文件存储文件节点数与应用数量成正比,有效减少随机 IO,消息实时存储的性能提升显著。以下为美团点评内部 CAT 线上环境单机消息存储的数据对比:未来规划技术栈升级拥抱主流技术栈,降低学习和开发成本,使用开源社区主流技术工具(Spring、Mybatis等),建设下一代开源产品。产品体验对产品、交互进行全新设计,提升用户体验。开源社区建设产品官网建设、组织技术交流。更多语言 SDK关于开源https://github.com/dianping/catCAT 自 2011 年开源以来,Github 收获 5900+ star,2400+ forks,被 100+ 公司企业使用,其中不乏携程、陆金所、猎聘网、平安等业内知名公司。在每年全球 Qcon 大会、全球架构与运维技术峰会等都有持续的技术输出,受到行业内认可,越来越多的企业伙伴加入了 CAT 的开源建设工作,为 CAT 的成长贡献了巨大的力量。美团点评基础架构部负责人黄斌强表示,在过去四年中,美团点评在架构中间件领域有比较多的积累沉淀,很多系统服务都经历过大规模线上业务实际运营的检验。我们在使用业界较多开源产品的同时,也希望能把积累的技术开源出去,一方面是回馈社区,贡献给整个行业生态;另一方面,让更多感兴趣的开发工程师也能参与进来,共同加速系统软件的升级与创新。所以,像 CAT 这样的优秀项目,我们将陆续开源输出并长期持续运营,保证开源软件本身的成熟度、支撑度与社区的活跃度,也欢迎大家给我们提出更多的宝贵意见和建议。结语这是一场没有终点的长跑,我们整个 CAT 项目组将长期有耐心地不断前行。愿同行的朋友积极参与我们,关注我们,共同打造一款企业级高可用、高可靠的分布式监控中间件产品,共同描绘 CAT 的新未来!这次开源仅仅是一个新的起点,如果你对 CAT 新版本有一些看法以及建议,欢迎联系我们:cat@dianping.com or Github issues招聘信息美团点评基础架构团队诚招 Java 高级、资深技术专家,Base北京、上海。我们是集团致力于研发公司级、业界领先基础架构组件的核心团队,涵盖分布式监控、服务治理、高性能通信、消息中间件、基础存储、容器化、集群调度等技术领域。欢迎有兴趣的同学投送简历到 yong.you@dianping.com。 ...

November 2, 2018 · 1 min · jiezi