Pregunta

Soy bastante nuevo en Spring Framework y durante todo el Spring-* comencé a sumergirme en Spring Boot y evaluarlo como candidato para un nuevo producto basado en servicios REST.

De momento me interesa lo que se expone a través del "solenoide", listo para usar, sé que puedo recopilar información (/info), un enlace de monitoreo (/health) e incluso un punto final de apagado, todo desacoplado del servidor principal al proporcionar una opción de configuración para colocar esos puntos finales en un puerto específico y 'espacio de nombres'

management.port=9000
management.contextPath=/admin

Estoy buscando una sugerencia para agregar mi propio punto final a los ya definidos (NB, no quiero enriquecer el punto final existente como lo que se propone con HealthIndicator, pero realmente quiero agregar uno nuevo como, por ejemplo, '/admin/get_me_out_of_load_balancers ')

Puedo ver que todos los puntos finales existentes extienden AbstractEndpoint pero no logré que mi punto final esté disponible en la ruta contextual de administración...

¿Fue útil?

Solución

Exponga una instancia de su Endpoint clase como frijol;Configuración automática del actuador de Spring Boot lo descubrirá automáticamente.Por ejemplo:

package demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public static Endpoint exampleEndpoint() {
        return new Endpoint<String>() {
            @Override
            public String getId() {
                return "example";
            }

            @Override
            public boolean isEnabled() {
                return true;
            }

            @Override
            public boolean isSensitive() {
                return false;
            }

            @Override
            public String invoke() {
                return "example";
            }
        };
    }
}

Otros consejos

Puede implementarlo fácilmente en una clase separada con AbstractMvcEndpoint y use @RequestMapping para simplificar o agregar parámetros al punto final, por lo que puede buscar información de otros servicios:

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.endpoint.mvc.AbstractMvcEndpoint;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.LoadBalancerStats;
import com.netflix.loadbalancer.Server;
import lombok.Builder;

@Configuration
public class BalancingEndpoint extends AbstractMvcEndpoint {

    @Value("${spring.application.name}")
    private String localServiceName;

    @Autowired
    private SpringClientFactory springClientFactory;

    @Autowired
    private DiscoveryClient discoveryClient;

    public BalancingEndpoint() {
        super("/balancing", false);
    }

    @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public BalancingResponse get() {
        return getEndpointContent(localServiceName);
    }

    @RequestMapping(value = "/{serviceName}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public BalancingResponse get(@PathVariable("serviceName") String serviceName) {
        return getEndpointContent(serviceName);
    }

    private BalancingResponse getEndpointContent(String serviceName) {

        DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) springClientFactory.getLoadBalancer(serviceName);

        return BalancingResponse.builder()
            .discovery(discoveryClient.getLocalServiceInstance())
            .loadBalancerStats(loadBalancer.getLoadBalancerStats())
            .loadBalancerAllServers(loadBalancer.getAllServers())
            .build();
    }

    @Builder
    @JsonPropertyOrder({"discovery", "loadBalancerStats", "loadBalancerAllServers"})
    public static class BalancingResponse {

        @JsonProperty
        ServiceInstance discovery;

        @JsonProperty
        private LoadBalancerStats loadBalancerStats;

        @JsonProperty
        private List<Server> loadBalancerAllServers;
    }
}

Además, es interesante considerar esto ( + info ):

Si está haciendo esto como una característica de la biblioteca, considere agregar un Clase de configuración anotada con @ManagementContextConfiguration a / Meta-inf/spring.factories bajo la llave org.springFramework.boot.actuate.autoconfigure.ManagementContextConfiguración. Si lo hace, entonces el punto final se moverá a un contexto secundario con todos Los otros puntos finales de MVC si sus usuarios solicitan una administración por separado puerto o dirección. Una configuración declarada de esta manera puede ser una WebConfigurerAdapter Si quiere agregar recursos estáticos (para instancia) a los puntos finales de gestión.

para la bota de primavera 2 Eche un vistazo a la muestra: Actuador de arranque de primavera: 5.2.Endpoint personalizado

@Component
@Endpoint(id = "custom-endpoint")
public class CustomEndpoint{

  @ReadOperation
  public String custom() {
    return "custom-end-point";
  }

  @ReadOperation
  public String customEndPointByName(@Selector String name) {
    return "custom-end-point";
  }

  @WriteOperation
  public void writeOperation(@Selector String name) {
    //perform write operation
  }

  @DeleteOperation
  public void deleteOperation(@Selector String name){
    //delete operation
  }
}

También vea Introducción de puntos finales del actuador en la bota de resorte 2.0

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top