没有http的微服务的活性探测

liveness probe for microservice without http

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

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

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

是否可以在不将其重构为网络服务应用程序的情况下实现这一目标?

我添加了此配置以启用 Spring 的信息端点

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

我实施了这个健康检查class

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");
    }
  }
}


这个想法可行吗?或者我是否必须重构它来处理网络请求?

感谢您提供任何线索

您可以公开执行器端点详细信息,包括使用 JMX 的健康检查。

示例application.yml

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

然后将活性探测定义为 运行 脚本(或 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

正在尝试 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 class

@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 脚本中。

谢谢!