环境准备

本次实验共需要用到三台主机,两台部署elasticsearch、一台部署logstash和logstash,主机分配如下:
192.168.1.15 es-master
192.168.1.16 es-node
192.168.1.17 logstash-kibana

修改主机名

192.168.1.15主机

hostnamectl set-hostname es-master

192.168.1.16主机

hostnamectl set-hostname es-node

192.168.1.17主机

hostnamectl set-hostname logstash-kibana

下载软件包

192.168.1.15和192.168.1.16主机执行如下命令下载elasticsearch软件包

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.14.1-linux-x86_64.tar.gz

192.168.1.17主机执行如下命令下载logstash和kibana软件包

wget https://artifacts.elastic.co/downloads/logstash/logstash-7.14.1-linux-x86_64.tar.gz
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.14.1-linux-x86_64.tar.gz

部署elasticsearch集群

解压elasticsearch压缩包到指定目录

192.168.1.15和192.168.1.16主机执行如下命令

tar -xf /root/elasticsearch-7.14.1-linux-x86_64.tar.gz -C /usr/local/

修改配置文件

192.168.1.15主机执行如下命令

vi /usr/local/elasticsearch-7.14.1/config/elasticsearch.yml
cluster.name: es-test    #elasticsearch集群名称
node.name: es-master  #结群节点名称建议写主机名
path.data: /elasticsearch/data  #elasticsearch索引数据存放路径
path.logs: /elasticsearch/logs   #elasticsearch日志存放路径
network.host: 0.0.0.0   #设置所有地址监听访问
http.port: 9200   #elasticsearch服务端口
discovery.seed_hosts: ["192.168.1.15", "192.168.1.16"]  #集群地址池若配置了主机名称解析该地方也可以写主机名
cluster.initial_master_nodes: ["192.168.1.15"]  #声明主节点

192.168.1.16主机执行如下命令

vi /usr/local/elasticsearch-7.14.1/config/elasticsearch.yml
cluster.name: es-test    #elasticsearch集群名称
node.name: es-node  #结群节点名称建议写主机名
path.data: /elasticsearch/data  #elasticsearch索引数据存放路径
path.logs: /elasticsearch/logs   #elasticsearch日志存放路径
network.host: 0.0.0.0   #设置所有地址监听访问
http.port: 9200   #elasticsearch服务端口
discovery.seed_hosts: ["192.168.1.15", "192.168.1.16"]  #集群地址池若配置了主机名称解析该地方也可以写主机名
cluster.initial_master_nodes: ["192.168.1.15"]  #声明主节点

配置elasticsearch集群认证

在主节点192.168.1.15主机操作

生成证书

cd /usr/local/elasticsearch-7.14.1/bin/
./elasticsearch-certutil ca

image-1676856036837
查看证书文件
image-1676856210924

设置连接证书私钥文件

cd /usr/local/elasticsearch-7.14.1/bin/
./elasticsearch-certutil cert --ca elastic-stack-ca.p12

1676857197444
查看证书私钥文件
image-1676856801025

将证书文件和私钥文件拷贝到node节点192.168.1.16主机

scp  /usr/local/elasticsearch-7.14.1/elastic-* 192.168.1.16:/usr/local/elasticsearch-7.14.1/

将证书文件加入到elasticsearch集群

对elasticsearch安装目录进行授权192.168.1.15和192.168.1.16主机操作

useradd es
chown -R es:es /usr/local/elasticsearch-7.14.1

证书加入集群,192.168.1.15和192.168.1.16主机操作

./elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password

image-1676858393252

./elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password

image-1676858472216

证书文件加入完成后,重新对elasticsearch安装目录授权es用户

chown -R es:es /usr/local/elasticsearch-7.14.1

elasticsearch证书文件移动到对应目录,192.168.1.15和192.168.1.16操作

如果不断移动到安装目录的config目录下,在启动elasticsearch服务实会报错,会提示证书文件应该放在elasticsearch安装目录的config目录下

mv /usr/local/elasticsearch-7.14.1/elastic-* /usr/local/elasticsearch-7.14.1/config/

elasticsearch添加xpack认证,192.168.1.15和192.168.1.16主机操作,在配置文件末尾添加如下几行

vi /usr/local/elasticsearch-7.14.1/config/elasticsearch.yml
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: none
xpack.security.transport.ssl.keystore.path: /usr/local/elasticsearch-7.14.1/config/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: /usr/local/elasticsearch-7.14.1/config/elastic-certificates.p12
ingest.geoip.downloader.enabled: false

创建elasticsearch配置文件指定的索引日志目录和日志文件目录,192.168.1.15和192.168.1.16主机操作如下

mkdir -p /elasticsearch/data /elasticsearch/logs
chown -R es:es /elasticsearch

启动elasticsearch服务,先启动主节点192.168.1.15再启动192.168.1.16从节点

su es
cd /usr/local/elasticsearch-7.14.1/bin/
 ./elasticsearch -d

如果启动报如下错误

image-1676860765068
编辑如下配置文件,文件末尾添加如下几行

vi /etc/security/limits.conf
* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096

执行如下一行操作命令

sudo sysctl -w vm.max_map_count=262144

修改上面的配置之后,启动elasticsearch服务(先启动192.168.1.15,再启动192.168.1.16)

./elasticsearch -d

授权连接访问elasticsearch服务账号以及密码,在主节点192.168.1.15主机操作

./elasticsearch-setup-passwords interactive -u 'http://192.168.1.15:9200'

image-1676861686949

验证账号及其密码,验证成功后此时elasticsearch集群部署完成

curl --user elastic:111qqq 192.168.1.15:9200/_cluster/health?pretty

image-1676861863180

部署logstash服务

解压logstash软件包到对应目录,192.168.1.17主机操作

 tar -xf logstash-7.14.1-linux-x86_64.tar.gz -C /usr/local/logstash-7.14.1/

被分析的java日志,这里截图一部分作为演示

2023-02-16 16:01:50.568  INFO 12845 --- [qtp1338958728-7681] r.h.app.handler.file.LocalFileHandler    : Uploading file: [1676534461460.jpg] to directory: [upload/2023/02/1676534461460.jpg]
2023-02-16 16:01:50.576  WARN 12845 --- [qtp1338958728-7681] r.h.app.handler.file.LocalFileHandler    : Failed to fetch image meta data

javax.imageio.IIOException: Not a JPEG file: starts with 0x89 0x50
        at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readImageHeader(Native Method) ~[na:na]
        at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readNativeHeader(JPEGImageReader.java:731) ~[na:na]
        at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.checkTablesOnly(JPEGImageReader.java:347) ~[na:na]
        at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.gotoImage(JPEGImageReader.java:496) ~[na:na]
        at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readHeader(JPEGImageReader.java:724) ~[na:na]
        at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.getWidth(JPEGImageReader.java:838) ~[na:na]
        at run.halo.app.handler.file.FileHandler.handleImageMetadata(FileHandler.java:88) ~[classes!/:1.5.3]
        at run.halo.app.handler.file.LocalFileHandler.upload(LocalFileHandler.java:125) ~[classes!/:1.5.3]
        at run.halo.app.handler.file.FileHandlers.upload(FileHandlers.java:53) ~[classes!/:1.5.3]
        at run.halo.app.service.impl.AttachmentServiceImpl.upload(AttachmentServiceImpl.java:116) ~[classes!/:1.5.3]
        at run.halo.app.service.impl.AttachmentServiceImpl$$FastClassBySpringCGLIB$$2d9c80b9.invoke(<generated>) ~[classes!/:1.5.3]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at run.halo.app.service.impl.AttachmentServiceImpl$$EnhancerBySpringCGLIB$$a01d20fb.upload(<generated>) ~[classes!/:1.5.3]
        at run.halo.app.controller.admin.api.AttachmentController.uploadAttachment(AttachmentController.java:84) ~[classes!/:1.5.3]
        at run.halo.app.controller.admin.api.AttachmentController$$FastClassBySpringCGLIB$$8f3ff968.invoke(<generated>) ~[classes!/:1.5.3]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at run.halo.app.core.ControllerLogAop.controller(ControllerLogAop.java:48) ~[classes!/:1.5.3]
        at jdk.internal.reflect.GeneratedMethodAccessor360.invoke(Unknown Source) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698) ~[spring-aop-5.3.18.jar!/:5.3.18]
        at run.halo.app.controller.admin.api.AttachmentController$$EnhancerBySpringCGLIB$$7caad889.uploadAttachment(<generated>) ~[classes!/:1.5.3]
        at jdk.internal.reflect.GeneratedMethodAccessor525.invoke(Unknown Source) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.18.jar!/:5.3.18]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.18.jar!/:5.3.18]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.18.jar!/:5.3.18]
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.18.jar!/:5.3.18]
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.18.jar!/:5.3.18]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.18.jar!/:5.3.18]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.18.jar!/:5.3.18]
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.18.jar!/:5.3.18]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:517) ~[jakarta.servlet-api-4.0.4.jar!/:4.0.4]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.18.jar!/:5.3.18]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:584) ~[jakarta.servlet-api-4.0.4.jar!/:4.0.4]
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1631) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:230) ~[websocket-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at run.halo.app.security.filter.AdminAuthenticationFilter.doAuthenticate(AdminAuthenticationFilter.java:120) ~[classes!/:1.5.3]
        at run.halo.app.security.filter.AbstractAuthenticationFilter.doFilterInternal(AbstractAuthenticationFilter.java:229) ~[classes!/:1.5.3]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at run.halo.app.filter.CorsFilter.doFilter(CorsFilter.java:53) ~[classes!/:1.5.3]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96) ~[spring-boot-actuator-2.5.12.jar!/:2.5.12]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at run.halo.app.filter.LogFilter.doFilterInternal(LogFilter.java:40) ~[classes!/:1.5.3]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar!/:5.3.18]
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:548) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:600) ~[jetty-security-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:501) ~[jetty-servlet-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.Server.handle(Server.java:516) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277) ~[jetty-server-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) ~[jetty-io-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) ~[jetty-io-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104) ~[jetty-io-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338) ~[jetty-util-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315) ~[jetty-util-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173) ~[jetty-util-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131) ~[jetty-util-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409) ~[jetty-util-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883) ~[jetty-util-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034) ~[jetty-util-9.4.45.v20220203.jar!/:9.4.45.v20220203]
        at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]

编辑logstash.conf配置文件

第一种分析方法使用自定义正则分析日志

vi /usr/local/logstash-7.14.1/config/logstash.conf
filter {
     grok {
         match => {
             "message" => "(?<list1>^(\d{4}).*?\d{3})\s+(?<list2>[A-Z]{4,5})\s+(?<list3>\d+)\s+(?<list4>\-\-\-)\s+(?<list5>\[\w+\-\d+\])\s+(?<list6>[\.|\w+]+)\s+(?<list7>\:)\s+(?<list8>\w+[\s+|\:].*)"    #自定义正则写法“(?<自定义名称>正则表达式)正则表达式”,其中“<>”为显示标头格式。
         }
     }
}
input {  #输入日志
     file {
         path => "/logstash/java-test-log/spring.log.2023-02-16.0"  #日志存放目录
         codec => multiline{   #启用cedec插件
             pattern => "^%{TIMESTAMP_ISO8601}"  #输入日志以正则宏时间戳作为分割每一行
             negate => true   #ture若输入的行匹配失败进行合并;flase匹配失败,则不合并
             what => previous  #previous表示合并到前面一行,next表示合并到后面一行
         }
         start_position => "beginning"    #每次启动logstash从开头读取日志此处写end就是从上次结束的标识处开始 ,注意如果不写下面的 sincedb_path => /dev/null每次重启还是从上次结束的标识处开始,若需要每次从文件的行首读取需要加入sincedb_path => /dev/null参数
         sincedb_path => "/dev/null"    
         stat_interval => "3"
     }
}
output {
    stdout { codec => "rubydebug" }  #开启调试模式,分析内容不输出到logstash
}

第二种分析方法使用官方的正则宏分析java日志示例

vi /usr/local/logstash-7.14.1/config/logstash.conf
filter {        #分析日志
     grok {
         match => { "message" => "\s*%{TIMESTAMP_ISO8601:time}" }   #调用正则宏
     }
     date {
         match => ["time", "yyyy-MM-dd HH:mm:ss.SSS"]       #按照时间戳为分隔符区分每一条日志(不通日志需要注意在此处的时间戳格式)
             target => "@timestamp"
     }
}
input {       #输入日志
     file {
         type => "test-java-log"  #类型可以在output调用同时区分不同的日志环境
         path => "/logstash/java-test-log/spring.log.2023-02-16.0"  #读入日志文件的路径
         codec => multiline{     #把当前行的数据放在前面一行的后面
             pattern => "^%{TIMESTAMP_ISO8601}"  #输入日志以正则宏时间戳作为分割每一行
             negate => true #ture若输入的行匹配失败进行合并;flase匹配失败,则不合并
             what => previous   #previous表示合并到前面一行,next表示合并到后面一行
         }
         ignore_older => 86400   #logstash每隔多久监听一下文件状态
         start_position => "beginning"    #每次启动logstash从开头读取日志此处写end就是从上次结束的标识处开始 ,注意如果不写下面的 sincedb_path => /dev/null每次重启还是从上次结束的标识处开始,若需要每次从文件的行首读取需要加入sincedb_path => /dev/null参数
         sincedb_path => “/dev/null”       
         stat_interval => "3"  
     }
}
output {    #输出 将日志输出到elasticsearch索引库
    if [type] == "test-java-log"  {  #此处可以调用input的type
        elasticsearch {    #elasticsearch信息
            hosts => ["http://192.168.1.15:9200"]   #elasticsearch主机地址和端口
            index => "test-java-%{+YYYY.MM.dd}"  #生成的索引名称格式
            user => "elastic"     #访问elasticsearch的账号
            password => "111qqq"  #访问elasticsearch的elastic的密码
        }
    }
}

启动logstash并进行测试

./logstash -f /usr/local/logstash-7.14.1/config/logstash.conf

由于上面使用官方正则宏分析没有开启调试模式,不在这里截图展示,可自己开启调试模式进行测试,这里作为示例看一下使用自定义正则分析出来的日志结果
image-1677053231494
启动成功后查看elasticsearch索引,若失败检查处理分析日志文件logstash.conf是否正确,如果logstash分析没有问题,则执行启动放入后台运行,操作如下

mkdir /logstash/logstash-log/   #用于存放logstash日志文件
nohup /usr/local/logstash-7.14.1/bin/logstash -f /usr/local/logstash-7.14.1/config/logstash.conf  > /logstash/logstash-log/logstash.log 2>&1 &

查看elasticsearch是否生成索引

curl --user elastic:111qqq 192.168.1.15:9200/_cat/indices?v

image-1676943571498
出现此条索引表示日志分析成功

部署kibana

解压kibana到指定目录

tar -xf kibana-7.14.1-linux-x86_64.tar.gz -C /usr/local/

修改kibana配置文件

vi /usr/local/kibana-7.14.1-linux-x86_64/config/kibana.yml
server.port: 5601     #kibana启动和访问端口
server.host: "0.0.0.0"  #允许所有地址监听访问
elasticsearch.hosts: ["http://192.168.1.15:9200"]   #elasticsearch地址获取索引
elasticsearch.username: "kibana_system"     #连接elasticsearch的账号不建议写elastic,elastic权限过大
elasticsearch.password: "111qqq"   #账号kibana_system密码
pid.file: /run/kibana/kibana.pid   #pid文件路径
mkdir /run/kibana  #上面配置文件指定的pid存放目录不存在需要进行创建

启动kibana服务

/usr/local/kibana-7.14.1-linux-x86_64/bin/kibana --allow-root  > /var/log/kibana7.log 2>&1 &

浏览器访问kibana服务

image-1676945595626

登录kibana

账号:elastic
密码:111qqq
image-1676945710798

kibana添加数据

点击 “Explore on my own”
image-1676946519369
点击左侧菜单栏
image-1676946584697
点击"Management"
image-1676946648446
点击“Stack Managemeng”
image-1676946965920
点击”Index Patterns“
image-1676947108324
点击”Create index pattern“
image-1676947205235
可以看到指针指向地方kibana获取的elasticsearch的索引源
image-1676947371041
在图中指针指向地方为正则匹配索引,对不同的日志进行区分
image-1676947533142
点击Next Step
image-1676947639065
点击下拉框,选择”@timestamp“
image-1676947711551
点击”create index pattern“
image-1676947801390
看到下图则创建成功
image-1676947876879
查看创建的索引信息,点击左侧菜单栏,点击”Discover“
image-1676947994731
点击”metrices-“,选择创建的”test-java
image-1676948082740
查看日志区间范围按照下图操作即可
image-1676948423275

常见错误类型分析

elasticsearch运行主机磁盘使用率达到90%会出现报错

解决方法:释放磁盘,清理日志索引存储

eleaticserch由于jvm内存不足无法启动问题

解决方法修改如下配置文件修改jav参数,注意修改此参数会分掉内存,实际情况按照主机内存合理进行分配jvm参数,配置文件默认为4g

vi /usr/local/elasticsearch-7.14.1/config/jvm.options
 -Xms8g     
 -Xmx8g

添加elasticsearch索引分片不足报错

解决方法增加索引分片数,执行如下操作

 curl --user elastic:111qqq -XPUT -H "Content-Type:application/json" -d '{"transient":{"cluster":{"max_shards_per_node":50000}}}' 'http://192.168.1.15:9200/_cluster/settings'

其中50000为索引分片数,实际需求根据实际情况合理分配

内存限制导致elasticsearch报错

解决方法执行如下操作

curl --user elastic:111qqq -XPUT "192.168.1.15:9200/_cluster/settings" -H 'Content-Type: application/json' -d '{ "persistent" : { "indices.breaker.fielddata.limit" : "40%" } }'

其中40%为内存限制

集群频繁进行主节点选举

查看日志,发现节点每过固定时间后会丢失对其他节点的连接,集群重新进行主节点选举,选举期间客户端连接超时
原因:elasticsearch节点之间是tcp长连接,当集群长时间无操作时,tcp连接可能被防火墙中断,但elasticsearch节点仍然尝试使用该tcp进行通信,导致节点间连接失败直到使用新的tcp连接时,集群才逐渐恢复使用
解决方法执行如下操作
1、修改tcp的keepalive参数vi /etc/sysctl.conf (如果部署了keeplived方案可参考)
net.ipv4.tcp_keepalive_time = 600 #keepalive间隔时间应小于防火墙的中断时间
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 6
保存后执行sysctl -p生效
2、重启es节点