从零开始学MYSQL - MYSQL安装(上)
前言 这个专栏也可以认为是学习笔记,由于之前的专栏学习的是网络上的培训机构教程,学习完成之后发现虽然讲到一些有一些深入的东西,但是讲的都不是特别深,所以从这一节开始将会从零开始来全盘了解MYSQL,这里找了一本书《从根上理解Mysql》,个人也十分推荐读者去看看这边书,不仅有新特性对接讲解,也有很多的干货,同时讲的也十分好,作为支持个人后面也买了一本实体书(虽然基本都是拿pdf看的)。思维导图(持续更新)www.mubucm.com/doc/7DDOY0C…图片地址:p3-juejin.byteimg.com/tos-cn-i-k3…参考资料:英文mysql5.7官方文档:dev.mysql.com/doc/refman/…中文对应翻译网站(机翻):www.docs4dev.com/docs/zh/mys…概述认识mysql的客户端和服务端是怎么一回事了解安装mysql的注意事项,以及回顾mysql个人简要介绍关于mysql启动的常见四个命令以及具体的作用mysqldmysqld_safemysql.servermysqld_multi认识客户端和服务端 由于是Mysql的专栏,这里就不牵扯什么TCP/IP,什么网络传输协议了,总之我们只需要了解mysql是分为客户端和服务端的,通常我们访问页面或者浏览数据就是一次数据库的访问过程(当然现在多数东西都静态化了),所以连接的这一方被称为客户端而接受请求的这一方面被称为服务端.mysql的基本任务通常我们使用MYSQL基本都是干这些事情:连接数据库。查询数据库的数据,客户端发送请求给服务端,服务端根据命令找到数据回送给客户端。和数据库断开连接。mysql实例 说完了上面的废话之后,我们来说下mysql实例,实例也在操作系统的层面叫做进程,而进程可以看做是处理器,内存,IO设备的抽象,我们不需要知道这个进程底层是如何传输数据存储数据的,我们只需要了解他需要一个端口,并且每一个实例都有一个 进程ID的东西,在数据库实例运行的时候系统会分配一个进程ID给它并且保证唯一,而每一个进程都有自己的名字,这个名称是安装的时候由程序员自己设置的,但是如果没有分配则会使用MYSQL自己默认设置的名称。我们启动的 MySQL 服务器进程的默认名称为 mysqld , 而我们常用的 MySQL 客户端进程的默认名称为 mysql 。从这个名称我们也可以推测出为什么我们启动一个服务通常会使用Mysqld,而我们连接数据库通常使用mysql。每一个文件就是对于IO设备的抽象虚拟内存是对内存和IO设备的抽象进程:则是对处理器,虚拟内存和IO设备的抽象安装Mysql的注意事项 安装Mysql十分简单但是实际上如果全手动安装细节还是比较多的,通常情况下我们自己使用直接用EXE程序或者直接使用BIN包等,但很多时候对于Linux的软件很多人都会推荐使用 源码安装,源码安装的好处不仅仅是缩小体积,经过不少的实验证明源码的安装方式效率会有所提升,所以正式环境下 尽可能使用源码安装,最后需要注意的一点是:Linux下使用RPM包会有单独的服务器和客户端RPM包,需要分别安装。安装目录位置的区别 下面是具体的Mysql安装目录,当然下面这里只做参考,个人mac电脑使用的是brew install mysql加上m1的的芯片安装的,适配性未知,所以为了保证笔记的可靠,这里用回了windows系统来进行实际测试和演练,下面是不同的操作系统在mysql的安装目录存储位置存在细微的不同,但是一定要十分清楚mysql真实的安装位置,这对于自己捣鼓各种命令以及设置参数很重要。macOS 操作系统上的安装目录:
/usr/local/mysql/
Windows 操作系统上的安装目录:
C:\Program Files\MySQL\MySQL Server 5.7Mysql安装windows安装过程 安装过程就不演示了,网上的教程一抓一大把,为了稳妥起见这里个人使用的mysql版本是5.7的版本,同时使用了默认exe程序安装,如果你使用了mysql-installxx.exe安装,有的时候会出现下面的命令:'mysql' 不是内部或外部命令,也不是可运行的程序 看到这个提示之后,第一反应是进入power shell的管理员模式:PS C:\Windows\system32> mysql -uroot -p
mysql : 无法将“mysql”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正
确,然后再试一次。
所在位置 行:1 字符: 1
+ mysql -uroot -p
+ ~~~~~
+ CategoryInfo : ObjectNotFound: (mysql:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException 发现还是报错,然后我跑去服务看了下mysql是否有启动,发现mysql又是启动的,这里有点奇怪 然后这里找了下网络上的解决办法,其实加个环境变量就行了,然后使用power shell直接安装即可,最后我们照常输入命令就可以发现mysql正常安装完毕了:PS C:\Windows\system32> mysql -uroot -pxxxxxx
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.35-log MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>关于绝对路径和相对路径启动问题:绝对路径:如果你的系统环境变量里面访问不到你的应用程序命令,这时候就需要进入到相关的目录执行命令,比如上面我没有配置环境变量就需要进入到C:\Program Files\MySQL\MySQL Server 5.7\bin目录下进行操作,也可以正常使用mysql,但是每次这样弄很麻烦,所以基本是个正常人都会使用环境变量,如果你不知道环境变量是什么,额。。。。请自行百度相对路径:配置完环境变量之后,我们敲命令会根据系统环境变量配置的 先后顺序找到我们的命令并且执行,但是这点在mysql有点特别,后续会讲到如果多个系统参数配置会默认使用 最后读到的配置参数为准。macos安装过程 Mac本子个人也是24分期才敢碰的神物,我相信用的人也不多,所以这里直接放个帖子: www.cnblogs.com/nickchen121…Linux安装过程 由于个人使用云服务器搭建mysql比较多,这里提供了一个阿里云rpm包的安装方式,版本是centeros7,centeros6同样可以使用,不过需要修改部分命令。 juejin.cn/post/689525…
github403的问题解决办法
问题点:在自己github推送代码的时候,突然爆出如下的错误:LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443问题原因 使用了科学的上网工具更改了代理的地址,导致github使用了代理的方式进行处理。不一定是污染了hosts文件。解决办法:首先参考了:juejin.cn/post/684490… 这一篇博客的处理方式,内容可以简化为最后的部分,在hosts文件里面增加如下的配置信息:# github start
140.82.112.3 github.com
199.232.5.194 github.global.ssl.fastly.net
185.199.108.153 assets-cdn.github.com
185.199.109.153 assets-cdn.github.com
185.199.110.153 assets-cdn.github.com
185.199.111.153 assets-cdn.github.com由于个人使用的是 MAC电脑,所以需要刷新一下dns的记录信息,执行下面的命令之后,会出现一段“广播“,所以后面的命令不输入即可,另外命令不建议手敲,没什么意义还容易出错,比如我就出错了=-=sudo killall -HUP mDNSResponder;say DNS cache has been flushed最后,可以先尝试改改注释推送一下看下是否成功,如果还是LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443,我们可以使用下面的命令把github的代理去掉:git config --global --unset http.proxy;
git config --global --unset https.proxy;最后可以配合软件:switchHost 使用(mac系统的软件)总结 用科学上网的工具不可避免的会出现这种情况,有时候还比较坑甚至找不到原因,这里做一个记录希望给读者有帮助。
springboot + dockerfile-maven-plugin 整合
1. 在maven的pom.xml文件中增加配置<properties>
<docker.image.prefix>xd</docker.image.prefix>
</properties>
<build>
<finalName>docker-demo</finalName>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>配置讲解 Spotify 的 docker-maven-plugin 插件是用maven插件方式构建docker镜像的。project.build.finalName??产出物名称,缺省为??{project.build.finalName}** 产出物名称,缺省为**project.build.finalName??产出物名称,缺省为??{project.artifactId}-${project.version}2. 打包SpringCloud镜像并上传私有仓库并部署什么是dockerFile 什么是Dockerfile : 由一系列命令和参数构成的脚本,这些命令应用于基础镜像, 最终创建一个新的镜像 创建 Dockerfile 添加内容 (默认是根目录, 可以修改为src/main/docker/Dockerfile,如果修则需要制定路径) 下面是dockfile的内容:FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]参数讲解:FROM : 需要一个基础镜像,可以是公共的或者是私有的, 后续构建会基于此镜像,如果同一个Dockerfile中建立多个镜像时,可以使用多个FROM指令VOLUME 配置一个具有持久化功能的目录,主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp。改步骤是可选的,如果涉及到文件系统的应用就很有必要了。/tmp目录用来持久化到 Docker 数据文件夹,因为 Spring Boot 使用的内嵌 Tomcat 容器默认使用/tmp作为工作目录ARG:设置编译镜像时加入的参数, ENV 是设置容器的环境变量COPY : 只支持将本地文件复制到容器 ,还有个ADD更强大但复杂点ENTRYPOINT:容器启动时执行的命令EXPOSE 8080:暴露镜像端口3. 构建镜像mvn install dockerfile:build
mvn install dockerfile:build -Dmaven.test.skip=true 补充: 如何在阿里云上的linux如何打包上去4. 在maven 安装目录的setting文件中加入配置<server>
<id>docker-registry</id>
<username>*******</username>
<password>******</password>
</server>5. 修改阿里云centeros7 Docker配置开放远程访问vi /usr/lib/systemd/system/docker.service ExecStart这一行后面加上 -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock最终效果:ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock6. 重启systemctl daemon-reload
systemctl start docker7. 服务器验证是否开始监听netstat -anp|grep 2375
curl 127.0.0.1:2375/info8. windows系统环境变量中新建DOCKER_HOST, 值为 tcp://[修改成你的远程服务器端口号]:23759. 打标签docker tag a1b9fc71720d registry.cn-shenzhen.aliyuncs.com/xd/xd_images:docker-demo-v20180810. 推送到镜像仓库docker push registry.cn-shenzhen.aliyuncs.com/xd/xd_images:docker-demo-v20180811. 应用服务器拉取镜像docker pull registry.cn-shenzhen.aliyuncs.com/xd/xd_images:docker-demo-v20180812. 启动docker run -d --name xd_docker_demo1 -p 8099:8080 a1b9fc71720d13. 查看启动日志docker logs -f containerid14. 访问http://[IP]:8099/find/userdocker整合注册中心1. 新增maven插件<properties>
<docker.image.prefix>xd</docker.image.prefix>
</properties>
<build>
<finalName>docker-demo</finalName>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>2. 新建DockerfileFROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]3. 打包mvn install dockerfile:build
mvn install -Dmaven.test.skip=true dockerfile:build4. 推送阿里云镜像仓库阿里云镜像仓库:dev.aliyun.com/search.htmldocker tag 062d2ddf272a registry.cn-shenzhen.aliyuncs.com/xd/xd_images:eureka-v20180825
docker push registry.cn-shenzhen.aliyuncs.com/xd/xd_images:eureka-v20180825
docker pull registry.cn-shenzhen.aliyuncs.com/xd/xd_images:eureka-v201808255、查看日志docker logs -f containerid6. 运行docker run -d --name docker-eureka-server -p 8761:8761 e7f687f101a7Docker Redis安装1. 搜索镜像docker search redis2. 拉取docker pull docker.io/redis3. 启动docker run --name "xd_redis" -p 6379:6379 -d 4e8db158f18d参考:docker run --name "xd_redis" -p 6379:6379 -d 4e8db158f18d --requirepass "123456" -v $PWD/data:/data4. 访问redis容器里面,进行操作docker exec -it 295058d2b92e redis-cli
《高性能Mysql》学习笔记(二)(上)
前言 接续上文继续介绍:《高性能Mysql》学习笔记(一)。mysql 时间线基准测试为什么需要基准测试基准测试策略基于mysql 单独测试 - 单组件式对整个系统整体测试 - 集成式使用整个系统测试原因主要如下 如果不需要关注整体应用,只关注msyql 性能测试指标吞吐量响应时间或者延迟并发性可扩展性应当避免以下情况再进行基准测试获取系统性能和状态获取基准测试结果运行基准测试并分析结果使用 shell , php, perl 都可以实现结果分析图表gnuplot > plot "qps-per-5-seconds" using 5 w lines title "qps"基准测试工具apach ABhttp_loadjmeter单组件式测试工具mysqlslap包含在mysql5.1 的发行包当中,会自动生成查询schema的select 语句mysql benchmark suite (sql-bench)优点:单线程,测试服务器执行查询的速度。有大量预定义的测试缺点:单用户模式,测试数据集很小而且无法指定数据无法测试多cpu能力super mack用于 mysql 和 postgresql 基准测试工具database test suite类似工业标准的测试工具dbt2 免费的toc-c oltp 测试工具percona's tpcc-mysql toolmysql 高性能并发作者自己制作sysbench多线程系统压测工具支持lua 语言msyql 的 benchmark() 函数Mysql 内置,可以测试某些特定操作的执行速度方便的测试某些特定操作性能,比如md5() 比 sha1() 函数快基准测试案例: 重点熟悉 sysbench 测试 ,因为和mysql 自身的设计最为贴合服务器性能剖析性能优化简介 一句话概括:性能即响应时间原则一定的工作负载之下尽可能的降低响应时间无法测量就无法有效优化忌讳错误的时间启动和停止测量测量的是聚合后的信息,而不是目标活动本身完成一项任务可以分成两部分执行时间:优化通过测量定位不同的子任务花费的时间,优化一些子任务,降低子任务的执行效率或者提升等待时间如何判断测量是正确的?测量到底有多么不准确,记住一点,使用的测量数据而不是实际数据,测量数据也有多种表现。很容易推导出错误的结论性能剖析进行优化 任务结束时间减去启动时间得到响应时间性能剖析两种类型基于时间分析某时候执行时间就是在等待比如i/o或者查询等待时间过久基于等待分析理解性能剖析 将最重要的任务展示在前面,但是没有显示的信息也很重要值得优化的查询:一些只占总响应时间比重很小的查询不值得优化如果优化成本大于收益,要停止优化!异常情况: 某些任务没有性能剖析输出也要优化,比如某些任务执行次数很少,但每次都很慢未知的未知 好的剖析工具尽可能显示“丢失的时间” 丢失的时间: 任务的总时间和实际测量时间时间的差被掩藏的细节: 平均值不能完全相信和作为根据应用程序的性能剖析: 对于任何需要消耗时间的任务都可以进行性能分析实用软件: New Relic捕获查询到日志文件当中mysql 5.0 之前, 慢查询日志的响应时间是秒mysql 5.1 之后,慢查询被加强,可以做到微秒级别的查询 慢查询日志是进度最高测量查询的日志,开销几乎可以忽略不计,但是会消耗大量磁盘空间,percona server 慢查询日志通过--processlist 选项不断查看 show full processlist 的输出通过抓取 tcp 网络包,根据mysql 客户端 /服务端 通信协议进行剖析建议: 在服务器上使用慢查询日志捕获所有的查询 应该首先生成一个剖析报告,在进行慢查询剖析报告剖析单条查询1. 使用 show profilemysql 5.1 之后版本引入,默认是禁用的,但是可以通过服务器变量在连接中动态更改mysql> set profiling = 1开启后会测量查询执行相关操作的状态可能被 performance scheema 取代该工具会讲剖析信息做成一张临时表示例执行下列语句返回997行数据继续看待下面输出如果不使用上面方法,则使用下列方法2. 使用 show status 该命令返回了一些计数器,既有 服务器界别全局计数器,也有基于某个连接的会话级别计数器,show global status 可以查询服务器启动时候开计算查询次数的统计全局计数器也会出现在show status猜测操作代价或者消耗时间较多的,可以使用句柄计数器, 临时文件和表计算器示例3. 使用慢查询日志(重点)通过 pt_query_digest 发现“坏查询”# query 1 :0 ops, 0x concurrency, ID oxeexxxs at byte 3214 ___使用下面方法查看详情tail -c +3214 /path/to/query.log | head -n1004. 使用performance Schema mysql 5.5 之后新增还不支持查询级别的剖析信息下面是显示系统等待主要原因的查询:
ELK技术栈 - logstash学习笔记(三)
读取 Syslog 数据syslog 可能是运维领域最流行的数据传输协议了。当你想从设备上收集系统日志的时候,syslog 应该会是你的第一选择。尤其是网络设备,比如思科 —— syslog 几乎是唯一可行的办法。我们这里不解释如何配置你的 syslog.conf, rsyslog.conf 或者 syslog-ng.conf 来发送数据,而只讲如何把 logstash 配置成一个 syslog 服务器来接收数据。有关 rsyslog 的用法,稍后的类型项目一节中,会有更详细的介绍。配置示例input {
syslog {
port => "514"
}
}运行结果作为最简单的测试,我们先暂停一下本机的 syslogd (或 rsyslogd )进程,然后启动 logstash 进程(这样就不会有端口冲突问题)。现在,本机的 syslog 就会默认发送到 logstash 里了。我们可以用自带的 logger 命令行工具发送一条 "Hello World"信息到 syslog 里(即 logstash 里)。看到的 logstash 输出像下面这样:{
"message" => "Hello World",
"@version" => "1",
"@timestamp" => "2014-08-08T09:01:15.911Z",
"host" => "127.0.0.1",
"priority" => 31,
"timestamp" => "Aug 8 17:01:15",
"logsource" => "raochenlindeMacBook-Air.local",
"program" => "com.apple.metadata.mdflagwriter",
"pid" => "381",
"severity" => 7,
"facility" => 3,
"facility_label" => "system",
"severity_label" => "Debug"
}解释Logstash 是用 UDPSocket, TCPServer 和 LogStash::Filters::Grok 来实现 LogStash::Inputs::Syslog 的。所以你其实可以直接用 logstash 配置实现一样的效果:input {
tcp {
port => "8514"
}
}
filter {
grok {
match => ["message", %{SYSLOGLINE} ]
}
syslog_pri { }
}最佳实践建议在使用 LogStash::Inputs::Syslog 的时候走 TCP 协议来传输数据。因为具体实现中,UDP 监听器只用了一个线程,而 TCP 监听器会在接收每个连接的时候都启动新的线程来处理后续步骤。如果你已经在使用 UDP 监听器收集日志,用下行命令检查你的 UDP 接收队列大小:# netstat -plnu | awk 'NR==1 || $4~/:514$/{print $2}'
Recv-Q
228096228096 是 UDP 接收队列的默认最大大小,这时候 linux 内核开始丢弃数据包了!强烈建议使用LogStash::Inputs::TCP和 LogStash::Filters::Grok 配合实现同样的 syslog 功能!虽然 LogStash::Inputs::Syslog 在使用 TCPServer 的时候可以采用多线程处理数据的接收,但是在同一个客户端数据的处理中,其 grok 和 date 是一直在该线程中完成的,这会导致总体上的处理性能几何级的下降 —— 经过测试,TCPServer 每秒可以接收 50000 条数据,而在同一线程中启用 grok 后每秒只能处理 5000 条,再加上 date 只能达到 500 条!才将这两步拆分到 filters 阶段后,logstash 支持对该阶段插件单独设置多线程运行,大大提高了总体处理性能。在相同环境下, logstash -f tcp.conf -w 20 的测试中,总体处理性能可以达到每秒 30000 条数据!注:测试采用 logstash 作者提供的 yes "<44>May 19 18:30:17 snack jls: foo bar 32" | nc localhost 3000命令。出处见:github.com/jordansisse…小贴士如果你实在没法切换到 TCP 协议,你可以自己写程序,或者使用其他基于异步 IO 框架(比如 libev )的项目。下面是一个简单的异步 IO 实现 UDP 监听数据输入 Elasticsearch 的示例:gist.github.com/chenryn/7c9…读取 Redis 数据Redis 服务器是 logstash 官方推荐的 broker 选择。Broker 角色也就意味着会同时存在输入和输出俩个插件。这里我们先学习输入插件。LogStash::Inputs::Redis 支持三种 data_type(实际上是redis_type),不同的数据类型会导致实际采用不同的 Redis 命令操作:list => BLPOPchannel => SUBSCRIBEpattern_channel => PSUBSCRIBE注意到了么?这里面没有 GET 命令!Redis 服务器通常都是用作 NoSQL 数据库,不过 logstash 只是用来做消息队列。所以不要担心 logstash 里的 Redis 会撑爆你的内存和磁盘。配置示例input {
redis {
data_type => "pattern_channel"
key => "logstash-*"
host => "192.168.0.2"
port => 6379
threads => 5
}
}使用方式基本方法首先确认你设置的 host 服务器上已经运行了 redis-server 服务,然后打开终端运行 logstash 进程等待输入数据,然后打开另一个终端,输入 redis-cli 命令(先安装好 redis 软件包),在交互式提示符后面输入PUBLISH logstash-demochan "hello world":# redis-cli
127.0.0.1:6379> PUBLISH logstash-demochan "hello world"你会在第一个终端里看到 logstash 进程输出类似下面这样的内容:{
"message" => "hello world",
"@version" => "1",
"@timestamp" => "2014-08-08T16:26:29.399Z"
}注意:这个事件里没有 host 字段!(或许这算是 bug……)输入 JSON 数据如果你想通过 redis 的频道给 logstash 事件添加更多字段,直接向频道发布 JSON 字符串就可以了。 LogStash::Inputs::Redis 会直接把 JSON 转换成事件。继续在第二个终端的交互式提示符下输入如下内容:127.0.0.1:6379> PUBLISH logstash-chan '{"message":"hello world","@version":"1","@timestamp":"2014-08-08T16:34:21.865Z","host":"raochenlindeMacBook-Air.local","key1":"value1"}'你会看到第一个终端里的 logstash 进程随即也返回新的内容,如下所示:{
"message" => "hello world",
"@version" => "1",
"@timestamp" => "2014-08-09T00:34:21.865+08:00",
"host" => "raochenlindeMacBook-Air.local",
"key1" => "value1"
}看,新的字段出现了!现在,你可以要求开发工程师直接向你的 redis 频道发送信息好了,一切自动搞定。小贴士这里我们建议的是使用 pattern_channel 作为输入插件的 data_type 设置值。因为实际使用中,你的 redis 频道可能有很多不同的 keys,一般命名成 logstash-chan-%{type} 这样的形式。这时候 pattern_channel 类型就可以帮助你一次订阅全部 logstash 相关频道!扩展方式如上段"小贴士"提到的,之前两个使用场景采用了同样的配置,即数据类型为频道发布订阅方式。这种方式在需要扩展 logstash 成多节点集群的时候,会出现一个问题:通过频道发布的一条信息,会被所有订阅了该频道的 logstash 进程同时接收到,然后输出重复内容!你可以尝试再做一次上面的实验,这次在两个终端同时启动 logstash -f redis-input.conf 进程,结果会是两个终端都输出消息。这种时候,就需要用 list 类型。在这种类型下,数据输入到 redis 服务器上暂存,logstash 则连上 redis 服务器取走 (BLPOP 命令,所以只要 logstash 不堵塞,redis 服务器上也不会有数据堆积占用空间)数据。配置示例input {
redis {
batch_count => 1
data_type => "list"
key => "logstash-list"
host => "192.168.0.2"
port => 6379
threads => 5
}
}使用方式这次我们同时在两个终端运行 logstash -f redis-input-list.conf 进程。然后在第三个终端里启动 redis-cli 命令交互:$ redis-cli
127.0.0.1:6379> RPUSH logstash-list "hello world"
(integer) 1这时候你可以看到,只有一个终端输出了结果。连续 RPUSH 几次,可以看到两个终端近乎各自输出一半条目。小贴士RPUSH 支持 batch 方式,修改 logstash 配置中的 batch_count 值,作为示例这里只改到 2,实际运用中可以更大(事实上 LogStash::Outputs::Redis 对应这点的 batch_event 配置默认值就是 50)。重启 logstash 进程后,redis-cli 命令中改成如下发送:127.0.0.1:6379> RPUSH logstash-list "hello world" "hello world" "hello world" "hello world" "hello world" "hello world"
(integer) 3可以看到,两个终端也各自输出一部分结果。而你只用了一次 RPUSH 命令。推荐阅读redis.iocollectd简述collectd 是一个守护(daemon)进程,用来收集系统性能和提供各种存储方式来存储不同值的机制。它会在系统运行和存储信息时周期性的统计系统的相关统计信息。利用这些信息有助于查找当前系统性能瓶颈(如作为性能分析 performance analysis)和预测系统未来的 load(如能力部署capacity planning)等下面简单介绍一下: collectd的部署以及与logstash对接的相关配置实例collectd的安装解决依赖rpm -ivh "http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm"
yum -y install libcurl libcurl-devel rrdtool rrdtool-devel perl-rrdtool rrdtool-prel libgcrypt-devel gcc make gcc-c++ liboping liboping-devel perl-CPAN net-snmp net-snmp-devel源码安装collectdwget http://collectd.org/files/collectd-5.4.1.tar.gz
tar zxvf collectd-5.4.1.tar.gz
cd collectd-5.4.1
./configure --prefix=/usr/local/software/collectd --sysconfdir=/etc --localstatedir=/var --libdir=/usr/lib --mandir=/usr/share/man --enable-all-plugins
make && make install安装启动脚本cp contrib/redhat/init.d-collectd /etc/init.d/collectd
chmod +x /etc/init.d/collectd启动collectdservice collectd startcollectd的配置以下配置可以实现对服务器基本的CPU、内存、网卡流量、磁盘 IO 以及磁盘空间占用情况的监控:Hostname "host.example.com"
LoadPlugin interface
LoadPlugin cpu
LoadPlugin memory
LoadPlugin network
LoadPlugin df
LoadPlugin disk
<Plugin interface>
Interface "eth0"
IgnoreSelected false
</Plugin>
<Plugin network>
<Server "10.0.0.1" "25826"> ## logstash 的 IP 地址和 collectd 的数据接收端口号
</Server>
</Plugin>logstash的配置以下配置实现通过 logstash 监听 25826 端口,接收从 collectd 发送过来的各项检测数据:示例一:input {
collectd {
port => 25826 ## 端口号与发送端对应
type => collectd
}示例二:(推荐)udp {
port => 25826
buffer_size => 1452
workers => 3 # Default is 2
queue_size => 30000 # Default is 2000
codec => collectd { }
type => "collectd"
}运行结果下面是简单的一个输出结果:{
"_index": "logstash-2014.12.11",
"_type": "collectd",
"_id": "dS6vVz4aRtK5xS86kwjZnw",
"_score": null,
"_source": {
"host": "host.example.com",
"@timestamp": "2014-12-11T06:28:52.118Z",
"plugin": "interface",
"plugin_instance": "eth0",
"collectd_type": "if_packets",
"rx": 19147144,
"tx": 3608629,
"@version": "1",
"type": "collectd",
"tags": [
"_grokparsefailure"
]
},
"sort": [
1418279332118
]
}
ELK技术栈 - logstash学习笔记(二)
标准输入最好使用一个配置文件进行运行配置示例input {
stdin {
add_field => {"key" => "value"}
codec => "plain"
tags => ["add"]
type => "std"
}
}
output {
stdout {
codec=>rubydebug
}
}输出内容{
"@timestamp" => 2018-11-22T12:59:34.166Z,
"@version" => "1",
"host" => "izwz99gyct1a1rh6iblyucz",
"message" => "helloworld",
"type" => "std",
"key" => "value",
"tags" => [
[0] "add"
]
}常用用法input {
stdin {
type => "web"
}
}
filter {
if [type] == "web" {
grok {
match => ["message", %{COMBINEDAPACHELOG}]
}
}
}
output {
if "_grokparsefailure" in [tags] {
nagios_nsca {
nagios_status => "1"
}
} else {
elasticsearch {
}
}
}读取文件Logstash使用一个名叫FileWatch的Ruby Gem库来监听文件变化。这个库支持glob展开文件路径,而且会记录一个叫*.sincedb*的数据库文件来跟踪被监听的日志文件的当前读取位置。所以,不要担心logstash会漏过你的数据。配置示例input
file {
path => ["/var/log/*.log", "/var/log/message"]
type => "system"
start_position => "beginning"
}
}解释有一些比较有用的配置项,可以用来指定FileWatch库的行为:discover_intervallogstash每隔多久去检查一次被监听的path下是否有新文件。默认值是15秒。排除不想被监听的文件可以排除出去,这里跟path一样支持glob展开。sincedb_path如果你不想用默认的$HOME/.sincedb(Windows平台上在C:\Windows\System32\config\systemprofile\.sincedb),可以通过这个配置定义sincedb文件到其他位置。sincedb_write_intervallogstash每隔多久写一次sincedb文件,默认是15秒。stat_intervallogstash每隔多久检查一次被监听文件状态(是否有更新),默认是1秒。START_POSITIONlogstash从什么位置开始读取文件数据,默认是结束位置,也就是说logstash进程会以类似tail -F的形式运行。如果你是要导入原有数据,把这个设定改成“开始”,logstash进程就从头开始读取,有点类似cat,但是读到最后一行不会终止,而是继续变成tail -F。注意通常你要导入原有数据进Elasticsearch的话,你还需要过滤/日期插件来修改默认的“@timestamp”字段值。稍后会学习这方面的知识。FileWatch只请立即获取iTunes文件的绝对路径,而且会不自动递归目录。所以有需要的话,请用数组方式都写明具体哪些文件。LogStash :: Inputs :: File只是在进程运行的注册阶段初始化一个FileWatch对象。所以它不能支持类似fluentd那样的path => "/path/to/%{+yyyy/MM/dd/hh}.log"写法。达到相同目的,你只能写成path => "/path/to/*/*/*/*.log"。start_position 仅在该文件从未被监听过的时候起作用。如果sincedb文件中已经有这个文件的inode记录了,那么logstash依然会从记录过的pos开始读取数据。所以重复测试的时候每回需要删除sincedb文件。因为windows平台上没有inode的概念,Logstash某些版本在windows平台上监听文件不是很靠谱.windows平台上,推荐考虑使用nxlog作为收集端,参阅本书稍后章节。读取网络数据(TCP)未来你可能会用Redis服务器或者其他的消息队列系统来作为logstash broker的角色。不过Logstash其实也有自己的TCP / UDP插件,在临时任务的时候,也算能用,尤其是测试环境。小贴士:虽然LogStash::Inputs::TCP用Ruby的Socket和OpenSSL库实现了高级的SSL功能,但Logstash本身只能在SizedQueue中缓存20个事件。这就是我们建议在生产环境中换用其他消息队列的原因。配置示例input {
tcp {
port => 8888
mode => "server"
ssl_enable => false
}
}常见场景目前来看,LogStash::Inputs::TCP最常见的用法就是配合nc命令导入旧数据。在启动logstash进程后,在另一个终端运行如下命令即可导入数据:# nc 127.0.0.1 8888 < olddata这种做法比用LogStash::Inputs::File好,因为当nc命令结束,我们就知道数据导入完毕了。而用输入/文件方式,logstash进程还会一直等待新数据输入被监听的文件,不能直接看出是否任务完成了。生成测试数据(Generator)实际运行的时候这个插件是派不上用途的,但这个插件依然是非常重要的插件之一。因为每一个使用 ELK stack 的运维人员都应该清楚一个道理:数据是支持操作的唯一真理(否则你也用不着 ELK)。所以在上线之前,你一定会需要在自己的实际环境中,测试 Logstash 和 Elasticsearch 的性能状况。这时候,这个用来生成测试数据的插件就有用了!配置示例input {
generator {
count => 10000000
message => '{"key1":"value1","key2":[1,2],"key3":{"subkey1":"subvalue1"}}'
codec => json
}
}插件的默认生成数据,message 内容是 "hello world"。你可以根据自己的实际需要这里来写其他内容。使用方式做测试有两种主要方式:配合 LogStash::Outputs::Nullinputs/generator 是无中生有,output/null 则是锯嘴葫芦。事件流转到这里直接就略过,什么操作都不做。相当于只测试 Logstash 的 pipe 和 filter 效率。测试过程非常简单:$ time ./bin/logstash -f generator_null.conf
real 3m0.864s
user 3m39.031s
sys 0m51.621s
# 自己的配置
real 0m46.086s
user 0m22.083s
sys 0m0.663s使用 pv 命令配合 LogStash::Outputs::Stdout 和 LogStash::Codecs::Dots上面的这种方式虽然想法挺好,不过有个小漏洞:logstash 是在 JVM 上运行的,有一个明显的启动时间,运行也有一段事件的预热后才算稳定运行。所以,要想更真实的反应 logstash 在长期运行时候的效率,还有另一种方法:output {
stdout {
codec => dots
}
}LogStash::Codecs::Dots 也是一个另类的 codec 插件,他的作用是:把每个 event 都变成一个点(.)。这样,在输出的时候,就变成了一个一个的 . 在屏幕上。显然这也是一个为了测试而存在的插件。下面就要介绍 pv 命令了。这个命令的作用,就是作实时的标准输入、标准输出监控。我们这里就用它来监控标准输出:$ ./bin/logstash -f generator_dots.conf | pv -abt > /dev/null
2.2MiB 0:03:00 [12.5kiB/s]可以很明显的看到在前几秒中,速度是 0 B/s,因为 JVM 还没启动起来呢。开始运行的时候,速度依然不快。慢慢增长到比较稳定的状态,这时候的才是你需要的数据。这里单位是 B/s,但是因为一个 event 就输出一个 .,也就是 1B。所以 12.5kiB/s 就相当于是 12.5k event/s。注:如果你在 CentOS 上通过 yum 安装的 pv 命令,版本较低,可能还不支持 -a 参数。单纯靠 -bt 参数看起来还是有点累的。额外的话既然单独花这么一节来说测试,这里想额外谈谈一个很常见的话题: ELK 的性能怎么样?其实这压根就是一个不正确的提问。ELK 并不是一个软件而是一个并不耦合的套件。所以,我们需要分拆开讨论这三个软件的性能如何?怎么优化?LogStash 的性能,是最让新人迷惑的地方。因为 LogStash 本身并不维护队列,所以整个日志流转中任意环节的问题,都可能看起来像是 LogStash 的问题。这里,需要熟练使用本节说的测试方法,针对自己的每一段配置,都确定其性能。另一方面,就是本书之前提到过的,LogStash 给自己的线程都设置了单独的线程名称,你可以在 top -H 结果中查看具体线程的负载情况。Elasticsearch 的性能。这里最需要强调的是:Elasticsearch 是一个分布式系统。从来没有分布式系统要跟人比较单机处理能力的说法。所以,更需要关注的是:在确定的单机处理能力的前提下,性能是否能做到线性扩展。当然,这不意味着说提高处理能力只能靠加机器了——有效利用 mapping API 是非常重要的。不过暂时就在这里讲述了。Kibana 的性能。通常来说,Kibana 只是一个单页 Web 应用,只需要 nginx 发布静态文件即可,没什么性能问题。页面加载缓慢,基本上是因为 Elasticsearch 的请求响应时间本身不够快导致的。不过一定要细究的话,也能找出点 Kibana 本身性能相关的话题:因为 Kibana3 默认是连接固定的一个 ES 节点的 IP 端口的,所以这里会涉及一个浏览器的同一 IP 并发连接数的限制。其次,就是 Kibana 用的 AngularJS 使用了 Promise.then 的方式来处理 HTTP 请求响应。这是异步的。
CentOS 8 网络配置详细版
物理机网络配置:虚拟机网络连接使用NAT模式,物理机网络连接使用Vmnet8。虚拟机设置里面——网络适配器,网络连接选择NAT模式。虚拟机菜单栏—编辑—虚拟网络编辑器,选择Vmnet8 NAT模式,1.在最下面子网设置ip为192.168.66.0 子网掩码255.255.255.02.NAT设置里面网关IP为192.168.66.23.使用本地DHCP服务将IP地址分配给虚拟机不勾选设置完成后点击应用退出。物理机网络连接VMNet8 手动设置ip地址 192.168.66.1 子网掩码255.255.255.0网关和DNS地址为192.168.66.2(即虚拟机NAT的网关地址)编辑linux网卡eth0的配置文件1#vi /etc/sysconfig/network-scripts/ifcfg-ens33输入上述命令后回车,打开配置文件,使用方向键移动光标到最后一行,按字母键“O”,进入编辑模式,输入以下内容:IPADDR=192.168.66.99NETMASK=255.255.255.0GATEWAY=192.168.66.2另外光标移动到”ONBOOT=no”这一行,更改为ONBOOT=yes“BOOTPROTO=dhcp”,更改为BOOTPROTO=none或者static完成后,按一下键盘左上角ESC键,输入:wq 在屏幕的左下方可以看到,输入回车保存配置文件。如果上一步配置了DNS这一步可以不配置,直接重启网络即可如果ping不通百度,就必须设置下面的DNS配置设置DNS地址,运行命令#vi /etc/resolv.conf光标移动到空行,按“O”键,输入 nameserver 192.168.66.2 退出按ESC键,输入:wq 回车保存配置文件。重启网络服务CentOS 7命令 : #service network restart注意:1.新安装的系统默认网卡ONBOOT=no,都需要更改2.重启网卡, centos 8不能使用service和systemctl3.重启网卡方法:nmcli c reload +网卡名方法一:nmcli c reload ifcfg-xxx方法二:nmcli c load /etc/sysconfig/network-scripts/ifcfg-xxx方法三:nmcli c load /etc/sysconfig/network-scripts/route-xxx如果以上方法没有生效,重启虚拟机系统,再看一下,就没问题了4.立即重启网卡生效有3种方法(推荐使用)nmcli c up 网卡名nmcli d reapply 网卡名nmcli d connect 网卡名重启之后#ifconfig 或者 ip a查看配置的ip地址,物理机ping这个地址测试是否能通.
写正则不再是噩梦:SLS数据加工GROK使用梳理
背景由于正则表达式较为复杂,推荐您优先使用GROK函数。GROK是一种采用组合多个预定义的正则表达式,用来匹配分割文本并映射到关键字的工具。可以将文本格式的字符串,转换成为具体的结构化的数据。您可以在 GROK 里预定义好命名正则表达式,在稍后(grok参数或者其他正则表达式里)引用它。GROK适用于syslog logs,apache和一些其他的webserver logs,以及mysql logs。grok有很多定义好pattern,当然也可以自己定义。阿里云日志服务介绍日志服务(Log Service,简称SLS)是针对日志类数据的一站式服务,在阿里巴巴集团经历大量大数据场景锤炼而成。您无需开发就能快捷完成日志数据采集、消费、投递以及查询分析等功能,提升运维、运营效率,建立DT时代海量日志处理能力。数据加工服务是阿里云SLS推出的面向日志ETL处理的服务,主要解决数据加工过程中转换、过滤、分发、富化等场景。SLS数据加工DSL是专门为日志实时行处理定制的一套语言(Python语法子集),本文档的目的也是让快速掌握该DSL,解决日志分析的问题。数据加工中经常需要用到正则表达式从非结构化数据提取字段,所以可以在 GROK 里预定义好命名正则表达式,在GROK参数或者其他正则表达式里引用它。SLS数据加工提供了70+常用的GROK,例如身份证号、邮箱、MAC地址、IPV4、IPV6、时间解析、URL解析等,直接可以使用,具体可参见GROK模式参考。当然,GROK还可以进一步自定义扩展,这里主要介绍GROK函数。GROK的使用GROK语法%{SYNTAX:SEMANTIC}SYNTAX表示grok定义好的pattern,SEMANTIC表示自定义的字段。例如192.168.0.100用%{IP:client}可以将IP定义为client假如现在某webserver log中的内容为以下格式:55.3.244.1 GET /index.html 15824 0.043我们完全可以利用grok将这些信息定义成以下字段%{IP:client}%{WORD:method}%{URIPATHPARAM:request}%{NUMBER:bytes}%{NUMBER:duration}grok过滤后得到的信息成了以下这样子:client: 55.3.244.1method: GETrequest: /index.htmlbytes: 15824duration: 0.043如何自定义Pattern语法:(?the pattern here)假如有以下内容“begin 123.456 end我们希望将123.456定义成request_time字段,可以向下面这样写这个正则表达式\s+(?\d+(?:\.\d+)?)\s+解释:\s:匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。+表示匹配次数为1次或者多次(? ):这个是grok语法,request_time表示要将捕获的字符定义成的字段名\d+:匹配一个或者多个数字(?:\.\d+):为正则表达式,(?: pattern):非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。\.\d+:表示点后面跟一个或者多个 数字,(?:\.\d+)?表示点后面跟一个或多个数字这种情况出现0次或者多次,如果为0次,则request_time为一个整数。所以匹配到的结果可能为123.456或者123或者123.4.5.6,这些都满足条件GROK函数格式grok(pattern, escape=False, extend=None)参数说明参数名称参数类型是否必填说明patternString是以上所述GROK语法。也可以参见GROK模式参考。escapeBool否是否将其他非GROK pattern中的正则相关特殊字符做转义,默认不转义。extendDict否用户自定义的GROK表达式。GROK有两种分组模式:捕获分组模式GROK模式中部分是自带命名分组捕获的,所以针对这种模式只能使用%{SYNTAX}方式的语法。此类模式常见于语句解析。"%{SYSLOGBASE}" ? ? ? ?"%{COMMONAPACHELOG}"?"%{COMBINEDAPACHELOG}""%{HTTPD20_ERRORLOG}""%{HTTPD24_ERRORLOG}""%{HTTPD_ERRORLOG}"...非捕获分组模式"%{INT}" ? ?"%{YEAR}""%{HOUR}"...您可以将GROK函数与正则表达式函数混合使用,如下所示:e_match("content", grok(r"\w+: (%{IP})")) #匹配abc: 192.168.0.0或者xyz: 192.168.1.1等形式。 e_match("content", grok(r"\w+: (%{IP})", escape=True)) #不会匹配abc: 192.168.0.0,而是匹配\w+: 192.168.0.0。数据加工中GROK使用举例场景一 提取日期和引用内容原始日志截取content: 2019 June 24 "I am iron man"加工规则e_regex('content',grok('%{YEAR:year} %{MONTH:month} %{MONTHDAY:day} %{QUOTEDSTRING:motto}'))加工结果场景二 提取HTTP请求日志原始日志截取content: 10.0.0.0 GET /index.html 15824 0.043加工规则e_regex('content',grok('%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}'))加工结果场景三 提取Apache日志原始日志截取content: 127.0.0.1 - - [13/Apr/2015:17:22:03 +0800] "GET /router.php HTTP/1.1" 404 285 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.15.3 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"加工规则e_regex('content',grok('%{COMBINEDAPACHELOG}'))加工结果场景四 Syslog默认格式日志。原始日志截取content: May 29 16:37:11 sadness logger: hello world加工规则e_regex('content',grok('%{SYSLOGBASE} %{DATA:message}'))加工结果场景五 转义特殊字符。原始日志截取content: Nov ?1 21:14:23 scorn kernel: pid 84558 (expect), uid 30206: exited on signal 3加工规则e_regex('content',grok(r'%{SYSLOGBASE} pid %{NUMBER:pid} \(%{WORD:program}\), uid %{NUMBER:uid}: exited on signal %{NUMBER:signal}'))因为加工规则中包含了正则特殊字符括号(),如果您不使用转义符,则添加escape=True参数即可,如下所示:e_regex('content',grok('%{SYSLOGBASE} pid %{NUMBER:pid} (%{WORD:program}), uid %{NUMBER:uid}: exited on signal %{NUMBER:signal}', escape=True))加工结果场景六 用户自定义GROK表达式。原始日志截取content: Beijing-1104,gary 25 "never quit"加工规则e_regex('content',grok('%{ID:user_id},%{WORD:name} %{INT:age} %{QUOTEDSTRING:motto}',extend={'ID': '%{WORD}-%{INT}'}))加工结果场景七 匹配JSON数据。原始日志截取content: 2019-10-29 16:41:39,218 - INFO: owt.AudioFrameConstructor - McsStats: {"event":"mediaStats","connectionId":"331578616547393100","durationMs":"5000","rtpPackets":"250","rtpBytes":"36945","nackPackets":"0","nackBytes":"0","rtpIntervalAvg":"20","rtpIntervalMax":"104","rtpIntervalVar":"4","rtcpRecvPackets":"0","rtcpRecvBytes":"0","rtcpSendPackets":"1","rtcpSendBytes":"32","frame":"250","frameBytes":"36945","timeStampOutOfOrder":"0","frameIntervalAvg":"20","frameIntervalMax":"104","frameIntervalVar":"4","timeStampIntervalAvg":"960","timeStampIntervalMax":"960","timeStampIntervalVar":"0"}加工规则e_regex('content',grok('%{EXTRACTJSON}'))加工结果场景八 解析标准w3c格式日志。原始日志截取content: 2018-12-26 00:00:00 W3SVC2 application001 192.168.0.0 HEAD / - 8000 - 10.0.0.0 HTTP/1.0 - - - - 404 0 64 0 19 0加工规则w3c中没有的字段使用了短划线(-)替代,在GROK中也使用短划线(-)去匹配这些字段。e_regex("content",grok('%{DATE:data} %{TIME:time} %{WORD:s_sitename} %{WORD:s_computername} %{IP:s_ip} %{WORD:cs_method} %{NOTSPACE:cs_uri_stem} - %{NUMBER:s_port} - %{IP:c_ip} %{NOTSPACE:cs_version} - - - - %{NUMBER:sc_status} %{NUMBER:sc_substatus} %{NUMBER:sc_win32_status} %{NUMBER:sc_bytes} %{NUMBER:cs_bytes} %{NUMBER:time_taken}')) 加工结果其他参考SLS目前暂支持73个GROK,GROK模式参考 https://help.aliyun.com/document_detail/129387.htm#concept-1597616
游戏灰度发布
背景快速可以说是互联网的最大特点了,唯快不破,快速响应,快速发布,快速部署,快速上线但上线,毕竟还是有风险的,怎么能又快速响应,又能降低风险范围呢前人,现人,后人们都在寻找着银弹部署方式就进化了有很多次,蓝绿部署、滚动部署、灰度发布、金丝雀发布。。。这些都是为了应对互联网的快速响应需求游戏的发布现在还是比较粗暴的,对开发,运维也比较简单。制定一个版本计划,开发,与运营沟通,确定版本内容,到了时间,所有游戏区全部关闭入口,停止服务器,发布,部署,重启,开放入口,一气呵成,快哉!等等,理想很丰满,现实很骨感在版本发布最后一天,开发人员在凌晨1、 2点时,还在开发,修复bug,好不容易打包,回家睡觉第二天运维在8点开始停机发布新版本;duang,怎么游戏服起不来了,开发请起床,查问题迷迷糊糊的开发在梦境中惊醒,终于搞定,打包,发版本,启动服务(有时可能要一上午查问题,通知运营方,延长维护时间)duang,玩家反馈,新功能有问题...此时,回滚?还是。。。;好汉不回头,哪来的回滚紧急停机,再寻找问题,修复,上线......整个游戏的链条上,似乎大家都已经习惯,开发习惯,玩家也习惯习惯麻痹了一切,没有提出更好的策略,大家都这么玩啊,无所谓啦~方案细思极恐,我们应该,也需要做得更好灰度发布/金丝雀发布灰度发布是在原有版本可用的情况下,同时部署一个新版本应用作为“金丝雀”(金丝雀对瓦斯极敏感,矿井工人携带金丝雀,以便及时发发现危险),测试新版本的性能和表现,以保障整体系统稳定的情况下,尽早发现、调整问题。灰度发布/金丝雀发布由以下几个步骤组成:准备好部署各个阶段的工件,包括:构建工件,测试脚本,配置文件和部署清单文件。从负载均衡列表中移除掉“金丝雀”服务器。升级“金丝雀”应用(排掉原有流量并进行部署)。对应用进行自动化测试。将“金丝雀”服务器重新添加到负载均衡列表中(连通性和健康检查)。如果“金丝雀”在线使用测试成功,升级剩余的其他服务器。(否则就回滚)游戏架构这个架构图比现实丰满不少,真实情况组件可能是单点的,数据层也就是单个mysql,一切都是那么脆弱。流程图玩家首先登陆游戏运营平台,鉴权完毕,选择区服,通过网关服务器获取到真实game-server信息,通过TCP,玩家与game-server建立起长连接。通过这个流程,就知道玩家与game-server直接牵手,强依赖的,如果gameserver重启,tcp连接是一定会断的,虽然前端可能尝试重新连接,但对玩家是有感的,不可能对玩家透明。改进怎么才能对玩家无感,切换版本呢?在之前的架构图中,稍作修改,在玩家与Gameserver之间增加一层ha-proxy,这样就有了灰度发布的基础玩家不再直接与game-server直连,而是与ha-proxy透明性对玩家来说,发版本就是透明的,发版本时,不再需要停机,入口也不需要关闭,7*24玩耍流量灵活切换灰度百分比,可以灵活控制,这里面又涉及到路由规则,复杂了,可以先百分百切换快速迭代玩家无感,出现bug,可以快速修复,快速上线快速回滚一旦新版本有问题,可以马上切回老版本,版本之间无逢切换难点加了ha-proxy,多了更多的灵活性ha-proxy的难点,高可用,高可靠,高性能高可用最重要的一点,不能单点;如果ha-proxy挂了,怎么办?就算game-server正常运行,也不能再提供服务,自己坑了自己所以ha-proxy不能单点,哪是集群,还是主从?每台物理机上都部署,还是集中几台部署?高可靠在新旧版本同时在线时,流量是否平滑过渡? 玩家操作是否保持完整性?一个玩家操作横跨新旧版本时,数据一致性如何保障?高性能游戏服都是尽量压榨单台服务的能力,现在多了一层通讯,IO会不会影响性能?结论对于以上方案,不论是哪一种实现方式,仁者见仁,条条大路通罗马。也可能你觉得这种想法本身就是个多余。能卖1块钱的豆腐,为什么要卖5毛?
Ansible自动化采集数据并生成巡检报告
前段时间在GitHub上发现了一个Ansible巡检服务的Roles, 今天给大家分享一下!Ansible自动化实现巡检思路:通过使用Ansible Role的方式对Linux系统进行资源巡检,生成巡检报告后通过邮件发送给接收人。测试的环境ansible [core 2.12.2]
os `Centos 7 X64`
python version = 3.10.2 (main, Feb 2 2022, 06:19:27)oss-check Roles的依赖过滤器插件 filter_plugins/os-check.py [get_check_data]目标机bash说明,此处的过滤器插件要放在ansible指定的filter_plugins的位置,我这里习惯将ansible的配置文件放在ansible的统一配置仓库下,便于迁移以及适应环境:oss-check Roles的执行流程使用脚本roles/oss_check/files/check_linux.sh在目标节点执行获取资源数据,并以json结构体返回。使用jinja2模板将获取的数据渲染到模板文件中roles/oss_check/templates/report-cssinline.html,生成的文件存放在指定的目录中。report-cssinline.html 是将css设置以inline的方式存储的html文件,report.html才是源模板文件,修改完源模板文件后,使用Responsive Email CSS Inliner进行转换下,才能更好的兼容邮件显示。其模板中使用的get_check_data过滤器是从hostvars中获取每台主机的脚本执行结果,进行分析整理传递给模板,使用传递回来的数据进行渲染。获取生成的模板文件内容,并通过smtp发送给接收人。oss-check Roles采集的指标信息HostnameMain IPOS VersionCPU UsedCPU LoadAvgMem UsedSwap UsedDisk Size UsedDisk Inode UsedTcp Connection UsedTimestampOss-check Roles数据阈值的分组采集出的数据,会通过设置好的阈值分为三个档次,OK: < 80Bad评判条件: 80 <= 使用率 < 90,Critical评判条件: 使用率 >= 90定期执行扫描集群节点扫描一般都是主动查看集群运行状态,主观判断的集群节点运行的状态,一般都会在节假日之前进行扫描一次,当然也可以通过自动化工具进行定期扫描,比如jenkins.如何跑起来?克隆好项目之后,将roles放置在自己ansible项目的roles目录下确认ansible.cfg配置文件中filter_plugin的位置,将克隆项目的filter_plugins/os-check.py放在配置文件指定的filter_plugin中创建oss-check运行的playbooks---
- name: 服务器巡检
hosts: qa_unix
gather_facts: false
vars:
check_report_path: /tmp
check_mail_host: "smtp.163.com"
check_mail_port: "465"
check_mail_username: "
[email protected]"
check_mail_password: "demo@163.com邮箱的密码"
check_mail_to: [ "接收人的邮箱地址" ]
check_email_title: "Ansible 集群巡检报告"
check_email_env: "QA"
roles:
- os-checkinventory/qa.ini是待执行环境的inventory,最后执行就OK了,/usr/bin/ansible-playbook -i inventory/qa.ini playbooks/os_check_qa.yaml如果执行遇到问题,那就通过-v查看信息吧,v的数量越多,信息量就越大希望能帮助到你,感谢一键三连,分享给更多需要的人别让自己太忙,一文详解 Ansible 的自动化运维没有集群照样学Ansible:托管的容器环境(实用)Ansible-tower 你还没用起来吗?