注:本文的项目使用ELK框架,实现两个功能:

1.Elasticsearch实现查询

2.ELK实现日志管理

在编写完带有ELK的SpringBoot项目后,启动发现控制台无输出直接

Process finished with exit code 1

为了找到原因,尝试了给启动类try catch的方式:

```

@SpringBootApplication

public class DemoApplication {

    public static void main(String[] args) {

        try {

            SpringApplication.run(DemoApplication.class, args);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

```

结果输出:

```

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'taskController': Unsatisfied dependency expressed through field 'taskService': Error creating bean with name 'taskService': Unsatisfied dependency expressed through field 'esTaskRepository': Error creating bean with name 'esTaskRepository' defined in com.test.simpleLoginRegister.repository.EsTaskRepository defined in @EnableElasticsearchRepositories declared on ElasticsearchRepositoriesRegistrar.EnableElasticsearchRepositoriesConfiguration: Failed to instantiate [org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository]: Constructor threw exception

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:788)

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:768)

    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:146)

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:509)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1445)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)

    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:339)

    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:347)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:337)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.instantiateSingleton(DefaultListableBeanFactory.java:1155)

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingleton(DefaultListableBeanFactory.java:1121)

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:1056)

    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:987)

    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:627)

    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)

    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752)

    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439)

    at org.springframework.boot.SpringApplication.run(SpringApplication.java:318)

    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361)

    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350)

    at com.test.simpleLoginRegister.SpringTestApplication.main(SpringTestApplication.java:11)

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'taskService': Unsatisfied dependency expressed through field 'esTaskRepository': Error creating bean with name 'esTaskRepository' defined in com.test.simpleLoginRegister.repository.EsTaskRepository defined in @EnableElasticsearchRepositories declared on ElasticsearchRepositoriesRegistrar.EnableElasticsearchRepositoriesConfiguration: Failed to instantiate [org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository]: Constructor threw exception

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:788)

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:768)

    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:146)

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:509)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1445)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)

    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:339)

    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:347)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:337)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1609)

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1555)

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:785)

    ... 22 more

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'esTaskRepository' defined in com.test.simpleLoginRegister.repository.EsTaskRepository defined in @EnableElasticsearchRepositories declared on ElasticsearchRepositoriesRegistrar.EnableElasticsearchRepositoriesConfiguration: Failed to instantiate [org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository]: Constructor threw exception

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1812)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)

    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:339)

    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:347)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:337)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1609)

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1555)

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:785)

    ... 35 more

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository]: Constructor threw exception

    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:222)

    at org.springframework.data.repository.core.support.RepositoryFactorySupport.lambda$instantiateClass$5(RepositoryFactorySupport.java:657)

    at java.base/java.util.Optional.map(Optional.java:260)

    at org.springframework.data.repository.core.support.RepositoryFactorySupport.instantiateClass(RepositoryFactorySupport.java:657)

    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getTargetRepositoryViaReflection(RepositoryFactorySupport.java:622)

    at org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactory.getTargetRepository(ElasticsearchRepositoryFactory.java:80)

    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:377)

    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$4(RepositoryFactoryBeanSupport.java:350)

    at org.springframework.data.util.Lazy.getNullable(Lazy.java:135)

    at org.springframework.data.util.Lazy.get(Lazy.java:113)

    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:356)

    at org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactoryBean.afterPropertiesSet(ElasticsearchRepositoryFactoryBean.java:69)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1859)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1808)

    ... 44 more

Caused by: org.springframework.dao.DataAccessResourceFailureException: Connection is closed

    at org.springframework.data.elasticsearch.client.elc.ElasticsearchExceptionTranslator.translateExceptionIfPossible(ElasticsearchExceptionTranslator.java:111)

    at org.springframework.data.elasticsearch.client.elc.ElasticsearchExceptionTranslator.translateException(ElasticsearchExceptionTranslator.java:65)

    at org.springframework.data.elasticsearch.client.elc.ChildTemplate.execute(ChildTemplate.java:73)

    at org.springframework.data.elasticsearch.client.elc.IndicesTemplate.doExists(IndicesTemplate.java:179)

    at org.springframework.data.elasticsearch.client.elc.IndicesTemplate.exists(IndicesTemplate.java:171)

    at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.createIndexAndMappingIfNeeded(SimpleElasticsearchRepository.java:93)

    at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.<init>(SimpleElasticsearchRepository.java:87)

    at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:67)

    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)

    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:483)

    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:209)

    ... 57 more

Caused by: java.lang.RuntimeException: Connection is closed

    at org.springframework.data.elasticsearch.client.elc.ElasticsearchExceptionTranslator.translateException(ElasticsearchExceptionTranslator.java:64)

    ... 66 more

Caused by: org.apache.http.ConnectionClosedException: Connection is closed

    at org.elasticsearch.client.RestClient.extractAndWrapCause(RestClient.java:924)

    at org.elasticsearch.client.RestClient.performRequest(RestClient.java:304)

    at org.elasticsearch.client.RestClient.performRequest(RestClient.java:292)

    at co.elastic.clients.transport.rest_client.RestClientHttpClient.performRequest(RestClientHttpClient.java:91)

    at co.elastic.clients.transport.ElasticsearchTransportBase.performRequest(ElasticsearchTransportBase.java:144)

    at co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient.exists(ElasticsearchIndicesClient.java:682)

    at org.springframework.data.elasticsearch.client.elc.IndicesTemplate.lambda$doExists$2(IndicesTemplate.java:179)

    at org.springframework.data.elasticsearch.client.elc.ChildTemplate.execute(ChildTemplate.java:71)

    ... 65 more

Caused by: org.apache.http.ConnectionClosedException: Connection is closed

    at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.endOfInput(HttpAsyncRequestExecutor.java:356)

    at org.apache.http.impl.nio.client.InternalRequestExecutor.endOfInput(InternalRequestExecutor.java:132)

    at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:261)

    at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:87)

    at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:40)

    at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:114)

    at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)

    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)

    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)

    at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)

    at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)

    at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591)

    at java.base/java.lang.Thread.run(Thread.java:833)

```

检查发现问题出自在ES上,回忆ES的配置过程,发现ES启用了 xpack 安全性和 SSL,因此需要在 Spring Boot 的配置文件中添加相应的设置。

### Spring Boot 配置

如果ELK架构是正常运行的,建议依据Logstash的配置来编写Spring Boot 配置

比如我的Logstash配置的结构,可以依据Logstash配置了什么选项,然后去Spring Boot进行 配置:

```

output {

  elasticsearch {

    hosts => ["localhost:9200"]

    user => ""

    password => ""

    ssl_enabled => true

    ssl_verification_mode => full

    ca_trusted_fingerprint => ""

    index => "app-logs-%{+YYYY.MM.dd}"

  }

}

```

### 配置参考(仅参考,与上文的Logstash配置不是对应关系):

1.在 `application.yml` 或 `application.properties` 中添加以下配置:

#### 使用 `application.yml`

```

# Elasticsearch配置

spring:

  elastic:

    host: localhost:9200

    user: elastic

    password: 123

    fingerprint: 123

# 禁用默认的自动配置

data:

  elasticsearch:

    enabled: false

```

#### 使用 `application.properties`

```

# Elasticsearch配置

spring.elastic.host=localhost:9200

spring.elastic.user=elastic

spring.elastic.password=123

spring.elastic.fingerprint=123

# 禁用默认的自动配置

data.elasticsearch.enabled=false

```

编写ElasticConfig

```

@Configuration

public class ElasticConfig extends ElasticsearchConfiguration {

    @Value("${spring.elastic.host}")

    private String host;

    @Value("${spring.elastic.user}")

    private String user;

    @Value("${spring.elastic.password}")

    private String password;

    @Value("${spring.elastic.fingerprint}")

    private String fingerprint;

    @Override

    public ClientConfiguration clientConfiguration() {

        SSLContext sslContext;

        try {

            sslContext = buildSslContext();

        } catch (Exception e) {

            throw new RuntimeException("Failed to create SSL context", e);

        }

        HttpHeaders headers = new HttpHeaders();

        headers.setBasicAuth(user, password);

        return ClientConfiguration.builder()

                .connectedTo(host)

                .usingSsl(sslContext)

                .withDefaultHeaders(headers)

                .withBasicAuth(user, password)

                .withSocketTimeout(60_000)

                .build();

    }

    private SSLContext buildSslContext() throws Exception {

        return SSLContextBuilder.create()

                .loadTrustMaterial(new TrustSelfSignedStrategy() {

                    @Override

                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {

                        if (chain == null || chain.length == 0) {

                            throw new CertificateException("Certificate chain is empty");

                        }

                        // 只验证叶子证书(第一个证书)

                        X509Certificate leafCert = chain[0];

                        try {

                            String actualFingerprint = getSha256Fingerprint(leafCert);

                            if (!fingerprint.equalsIgnoreCase(actualFingerprint)) {

                                throw new CertificateException("Certificate fingerprint mismatch. Expected: "

                                        + fingerprint + ", Actual: " + actualFingerprint);

                            }

                        } catch (NoSuchAlgorithmException | CertificateEncodingException e) {

                            throw new CertificateException("Failed to calculate fingerprint", e);

                        }

                        return true;

                    }

                })

                .build();

    }

    private String getSha256Fingerprint(X509Certificate cert)

            throws NoSuchAlgorithmException, CertificateEncodingException {

        MessageDigest md = MessageDigest.getInstance("SHA-256");

        byte[] der = cert.getEncoded();

        md.update(der);

        byte[] digest = md.digest();

        return bytesToHex(digest);

    }

    private String bytesToHex(byte[] bytes) {

        StringBuilder sb = new StringBuilder();

        for (byte b : bytes) {

            sb.append(String.format("%02x", b));

        }

        return sb.toString();

    }

}

```




 

更多推荐