【问题标题】:liveness probe for microservice without http没有http的微服务的活跃度探测
【发布时间】:2020-09-22 21:53:15
【问题描述】:

我有一个不是网络服务的微服务。

它是一个 Spring Boot (1.5) CommandLineRunner 应用程序,不需要公开 API 或使用 http 做任何事情。

但是,我需要给它一个 Kubernetes 的活性探测。

这是否可以在不将其重构为 Web 服务应用程序的情况下完成?

我添加了这个配置来启用 Spring 的 info 端点

management:
  endpoint:
    health:
      enabled: true
    info:
      enabled: true

# https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#production-ready-endpoints
info:
  app:
    name: foo-parser
    description: parses binary files from S3 and updates the database

我实现了这个健康检查类

import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health.Builder;

@Component
public class HealthCheck extends AbstractHealthIndicator {

  Logger log = LoggerFactory.getLogger("jsonLogger");

  private final MySQLAccessor mySQLAccessor;
  private static final String FOO_TABLE = "foo";

  @Autowired
  public HealthCheck(final MySQLAccessor mySQLAccessor) {
    this.mySQLAccessor = mySQLAccessor;
  }

  @Override
  protected void doHealthCheck(Builder builder) throws Exception {
    boolean result = mySQLAccessor.healthCheck(FOO_TABLE);
    if (result) {
      log.info("HELLO! the health check is good!");
      builder.up().withDetail("test", "good");
    }
    else {
      log.info("HELLO! OH NOES the health check is ungood!");
      builder.down().withDetail("test", "bad");
    }
  }
}


这个想法可行吗?还是我必须重构它以服务 Web 请求?

感谢您提供任何线索

【问题讨论】:

  • 您可以定义一个 exec liveness probe 来运行 cmdline 命令来检查它是否有效。
  • 我想我应该澄清一下。我需要探针来检查与数据库的连接。从 Java 中可以很容易地做到这一点......但不确定如何正确连接它。我将编辑问题
  • 这很有挑战性,我见过一些应用程序实际上拉入执行器和一些 Web 组件只是为了进行这种监控。

标签: java spring-boot kubernetes health-check


【解决方案1】:

您可以使用 JMX 公开执行器端点详细信息,包括运行状况检查。

示例application.yml

management:
  endpoints:
    jmx:
      exposure:
        include: health,info,metrics,mappings

然后定义 liveness probe 以运行脚本(或 java 程序)来调用 JMX 端点并回答健康检查:

示例 k8s 配置

apiVersion: v1
kind: Pod
spec:
  containers:
  - name: liveness
    image: my-app 
    livenessProbe:
      exec:
        command:
        - /bin/sh
        - test_app_with_jmx.sh 
      initialDelaySeconds: 5
      periodSeconds: 5

【讨论】:

  • 我喜欢这个想法,并花了一上午的时间尝试实现一些可以从 bash 运行的东西来调用健康检查。不过遇到问题,会更新问题
  • 根据这个想法写了一个新的答案
【解决方案2】:

尝试stringy05的想法...

启用 jmx 端点:

management:
  endpoints:
    jmx:
      exposure:
        include: "*"
        exclude:
  endpoint:
    health:
      enabled: true
    info:
      enabled: true

使用这个答案:

Calling JMX MBean method from a shell script

我试过了:

import javax.management.*;
import javax.management.remote.*;

public class JMXInvoker {

  public static void main(String... args) throws Exception {
    Object result = JMXConnectorFactory.connect(new JMXServiceURL(args[0]))
        .getMBeanServerConnection().invoke(new ObjectName(args[1]), args[2], new Object[]{}, new String[]{});
    String status = "" + result;
    String state = status.substring(8,10);
    Boolean ok = state.compareTo("UP") == 0;
    if (!ok)
      System.exit(1);
  }
}

在主应用类中添加了一些 JMX 相关的 bean

@SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
public class FooParserApplication implements CommandLineRunner {

  Logger log = LoggerFactory.getLogger("jsonLogger");
  @Autowired
  private FooStuff fooStuff;

  @Bean
  public RmiRegistryFactoryBean rmi() {
    RmiRegistryFactoryBean rmi = new RmiRegistryFactoryBean();
    rmi.setPort(5555);
    return rmi;
  }

  @Bean
  public ConnectorServerFactoryBean server() throws Exception {
    ConnectorServerFactoryBean fb = new ConnectorServerFactoryBean();
    fb.setObjectName("connector:name=rmi");
    fb.setServiceUrl("service:jmx:rmi://localhost/jndi/rmi://localhost:5555/myconnector");
    return fb;
  }

  public static void main(final String[] args) {
    final SpringApplication springApplication = new SpringApplication(ECHParserApplication.class);
    springApplication.run(args);
  }

  @Override
  public void run(final String... args) {
     fooStuff.doIt()
  }
}

从 bash 调用它:

java -cp foo-parser.jar -Dloader.main=com.foo.JMXInvoker org.springframework.boot.loader.PropertiesLauncher service:jmx:rmi://localhost/jndi/rmi://localhost:5555/myconnector org.springframework.boot:type=Endpoint,name=Health health

现在我只需要将它放入 Kubernetes 的 bash 脚本中。

谢谢!

【讨论】:

猜你喜欢
  • 2020-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-27
  • 2021-01-28
  • 1970-01-01
相关资源
最近更新 更多