Запись исключений микросервиса Spring Cloud и сигнализация

задняя часть Микросервисы Spring Elasticsearch

предисловие

Когда наше приложение нормально работает в сети, нам не нужно ни о чем беспокоиться в обычных обстоятельствах, но неизбежно будут появляться ошибки; в это время нам нужен соответствующий механизм для обнаружения ошибок в нашей системе. уведомить соответствующий персонал, в противном случае об ошибке не будет известно до тех пор, пока пользователь не предоставит отзыв о том, что произошла ошибка, которая влияет на взаимодействие с пользователем и является неуправляемой, что является неприемлемым.

вводить

Моя команда в настоящее время использует наборы, связанные с Spring Cloud, для разработки микросервисов, поэтому мое введение и практика также выполняются в рамках этого стека технологий, и в то же время можно использовать elasticsearch.
Мы используем Spring MVC для развития бизнеса, притворяясь инфраструктурой удаленного вызова интерфейса restful, и zuul в качестве сервисного шлюза, чтобы открыть интерфейс для внешнего мира. Этот стек технологий очень распространен в командах, разрабатывающих Spring Cloud.

идеи

Потому что в начале мы записывали единый лог доступа на шлюзе и использовали filebeat для синхронизации его с elasticsearch для облегчения последующего запроса и анализа данных, но этого недостаточно, мы хотим иметь возможность напрямую судить по логу, является ли он В конце концов, возникает явное исключение, нам нужна точка или соответствующий порог, чтобы определить, что является ненормальным, могут быть ошибки, и необходимо выполнить соответствующие операции для предупреждения. Поэтому нам нужно написать несколько статей о ведении журналов, чтобы в журналах, которые мы записываем, было достаточно мощной и точной информации, чтобы мы могли судить, является ли это ненормальным, а затем запускать серию операций (сигналы тревоги и т. д.).
После определенного анализа я думаю, что исключение — хороший момент, чтобы судить о том, есть ли ошибка, потому что нет исключения без ошибки, но в запросе должна быть ошибка с перехваченным исключением или без него; поэтому используйте это как точка входа, чтобы пойти глубже думать.

выполнить

Настройка в разработке

Во-первых, наша инфраструктура указывает единый код ошибки для запроса внешнего мира, и в то же время бизнес-уровень выдает исключение для запроса внешнего мира.
Мы определяем это как:

public class DomainServerException extends Exception {
    // 平台定义错误码
    private int code;
    // http status
    private int status;
    // 具体错误信息,面向开发者的提示, Exception的message用于面向用户的提示
    private int error;
    // 相关异常的堆栈信息
    private int stack;

    public DomainServiceException(int code, String message, Throwable throwable) {
        super(message, throwable);
        this.code = code;
        if (isServerError())
            this.stack = ExceptionUtils.getStackTrace(throwable);
    }
}

Информация о стеке — это поле, добавленное для отслеживания исключений.http status为5**или平台定义错误码为服务器异常Когда соответствующая информация о стеке исключений загружается и значение устанавливается в поле стека. В частности, вDomainServiceExceptionКонструктор выполняет либоspring ErrorController(потому что мы используем исключения для выдачи кодов ошибок, поэтому мыspring MVCдефолтErrorControllerпо индивидуальному заказу).
мыErrorControllerТип возвращаемого значения определяется как

public class HttpErrorResponse implements Serializable {
    private Date timestamp;
    private Integer status;
    private String error;
    private String message;         
    private String stack;           // 异常堆栈  方便记录同时在前后端调试的时候信息也更加丰富
    private String exception;       // 异常类型
    private String path;            // 错误请求路径
    private Integer errorCode;      // 平台定义错误码
}

Для случаев ошибки мы бросаемDomainServerExceptionили другое неопрятное исключение,DomainServerExceptionПо умолчанию это наша бизнес-ошибка, и ее также можно использовать как ошибку-исключение, но мы обрабатываем ошибки-исключения какDomainServerExceptionОн передаст верхний стек исключений в конструктор для генерацииDomainServerExceptionобъект исключения (注意:此模式下一定不要去处理你不知道该怎么处理的异常,如果你处理不了就一直往外抛,ErroController能够正确的处理并记录他然后供报警使用).
В этот момент мы бросаемHttpErrorResponseМожет использоваться в двух местах:

  1. звонки между службами
  2. Запрос отправлен zuul
  • В первом случае, поскольку мы используемfeignДля совершения удаленных звонков между сервисами переписываемErrorDecoderвыполнятьHttpErrorResponseиDomainServerExceptionилиDomainServerException的子类(оценка типа выполняется через поле исключения) и выбрасывается. Каскадные вызовы и аналогии в конечном итоге перейдут на уровень шлюза для обработки. Таким образом, первый случай в конечном итоге станет вторым случаем.

  • Во втором случае мы, поскольку у нас есть определение кода ошибки, и мы также возвращаем ошибку при нормальных обстоятельствах, но нормальный результат не имеет кода ошибки, поэтому мы находимся вzuulпонялtype为“post”的filter来对返回值进行格式化,同时也对老的平台与新的平台进行输出格式化. Здесь мы оцениваем, является ли контент, возвращаемый службой, ненормальным, и записываем его (сохраняем соответствующую информацию вRequestContext) и, наконец, записать соответствующую информацию в унифицированный фильтр ведения журнала (включая обычный фильтр и фильтр исключений zuul). В то же время, поскольку мы также написали некоторые связующие интерфейсы в Zuul, мы реализовали ZuulErrorController в ErroController, который унаследовал общие службы, а также записал информацию об исключениях.

Хранение журнала и сигнализация

Как записывать лог определился, используем filebeat для передачи данных лога в elasticsearch. Теперь у нас есть код ошибки и информация о стеке в elasticsearch.Очевидно, что информация о стеке - очевидная информация об ошибке.Как только это поле появляется в Ziyao,значит проблема с нашим кодом.По этому можно звонить в полицию . Для информации о коде ошибки это может быть сложнее.В некоторых случаях нам нужно оценить порог.Когда мы превысим порог в некоторых случаях, мы подадим сигнал тревоги (в настоящее время применение этого блока требует дополнительных размышлений)
Инструменты для предупреждений запросов elasticsearch:elastalert, но я не очень холодно отношусь к этому инструменту, и я также устал иметь дело со сложными зависимостями развертывания Python.Я использую golang для разработки инструмента с более простыми функциями и меньшими затратами на обучение. Если это нормально для внутренних испытаний, исходный код должен быть открытым.

未完待续