описание проблемы
Обнаружена ошибка в проекте, работающем онлайн. В ходе расследования возникло подозрение, что бин в конфигурационном файле не был успешно прочитан. Обычно мой подход состоит в том, чтобы добавить строку журнала, а затем перестроить код. Например:log.info("WxDomainProperties:{}",wxDomainProperties);
Давайте посмотрим, как выглядят свойства этого объекта.
Но это, очевидно, относительно неэффективный способ. Ниже представлен способ использования arthas с открытым исходным кодом Ali для реализации онлайн-отладки.
Сначала посмотрите на соответствующий код
Bean-компонент, который, как предполагается, имеет проблемы, — это следующий bean-компонент, который в основном используется для настройки информации о доменном имени. Значение, настроенное через файл конфигурации. В разных средах, таких как dev, local, online будут разные значения.
/**
* 微信第三方平台域名配置
*
* @author yanghaolei
* @date 2019/08/07 下午4:04
*/
@Data
@Component
@ConfigurationProperties(prefix = WxDomainProperties.PREFIX)
public class WxDomainProperties {
public static final String PREFIX = "wx.domain";
/**
* 请求域名
*/
private List<String> requestDomainList = Lists.newArrayList();
/**
* WebSocket域名
*/
private List<String> wsRequestDomainList = Lists.newArrayList();
/**
* 上传域名
*/
private List<String> uploadDomainList = Lists.newArrayList();
/**
* 下载域名
*/
private List<String> downloadDomainList = Lists.newArrayList();
/**
* 业务域名
*/
private List<String> webviewDomainList = Lists.newArrayList();
}
Затем мы внедряем этот компонент в бизнес-код.
@Slf4j
@AllArgsConstructor
@Service
public class MaDomainService {
private final WxService wxService;
private final WxDomainProperties wxDomainProperties;
В методе setDoamin значение, сохраненное компонентом, по умолчанию загружается автоматически. И ошибка, с которой я столкнулся, заключалась в том, что по умолчанию все загруженные значения были нулевыми. Так что я подозреваю, что что-то не так со значениями, которые читает этот конфиг.
public WxOpenMaDomainResult setDomain(MaDomainSetDTO maDomainSetDTO) {
JSONObject requestJson = new JSONObject();
Integer status = maDomainSetDTO.getStatus();
String appId = maDomainSetDTO.getAppId();
// 1 启用默认配置 --> 强制覆盖成默认列表[初始化操作]
if (StatusEnum.TRUE.getValue().equals(status)) {
requestJson.put("action", SET_ACTION);
requestJson.put("requestdomain", JSONArray.parse(JSON.toJSONString(wxDomainProperties.getRequestDomainList())));
requestJson.put("wsrequestdomain", JSONArray.parseArray(JSON.toJSONString(wxDomainProperties.getWsRequestDomainList())));
requestJson.put("uploaddomain", JSONArray.parseArray(JSON.toJSONString(wxDomainProperties.getUploadDomainList())));
requestJson.put("downloaddomain", JSONArray.parseArray(JSON.toJSONString(wxDomainProperties.getDownloadDomainList())));
}
// 2 未启用默认配置 --> 可以add/delete/get[不允许自定义set]
else if (StatusEnum.FALSE.getValue().equals(status)) {
//不允许自定义覆盖
if (SET_ACTION.equals(maDomainSetDTO.getAction())) {
return new WxOpenMaDomainResult();
}
requestJson.put("requestdomain", getJsonArray(maDomainSetDTO.getRequestDomainList()));
requestJson.put("wsrequestdomain", getJsonArray(maDomainSetDTO.getWsRequestDomainList()));
requestJson.put("uploaddomain", getJsonArray(maDomainSetDTO.getUploadDomainList()));
requestJson.put("downloaddomain", getJsonArray(maDomainSetDTO.getDownloadDomainList()));
} else {
return new WxOpenMaDomainResult();
}
try {
String response = wxService.getMaService(appId).post(API_MODIFY_DOMAIN, requestJson.toJSONString());
return JSON.parseObject(response, WxOpenMaDomainResult.class);
} catch (Exception e) {
log.error("Error message:{},Error stackTrace:{}", e.getMessage(), e.getStackTrace());
return new WxOpenMaDomainResult();
}
}
Для того, чтобы убедиться, что с моим подозрением нет проблем, конечно, необходимо отладить, чтобы проверить это значение. Но это онлайн-код, как было сказано в начале, хлопотнее проверить значение, перезапустив лог. Поэтому я подумал об использовании Arthas для онлайн-отладки.
Артас в действии
Большая часть информации в Интернете по знакомству с Arthas посвящена установке и просмотру некоторой информации о консоли. Вот официальный сайт,Начало работы с Артасом. В основном я буду говорить о моем процессе проверки моих сомнений и, наконец, о нахождении причины с помощью артаса.
Здесь я использую команды watch и trace.
Команда watch выполняет наблюдение за данными, что позволяет нам легко наблюдать за вызовом указанного метода. Формат наблюдения: просмотр + совпадение выражения имени класса + имя метода + выражение + условное выражение. Я здесь, чтобы наблюдать, успешно ли значение wxDomainProperties считывается конфигурационным файлом во время вызова метода setDomain. Итак, мое выражение: watch + имя класса [com.bjyt.bange.module.wx.middleware.MaDomainService] + имя метода [setDomain] + выражение ['target.wxDomainProperties']. Здесь target представляет текущий объект. Условные выражения часто используются для указания точек наблюдения и времени наблюдения, поэтому здесь они не заполняются, поскольку не нужны. Вы можете увидеть результат выполнения:
Как видите, мои подозрения неверны, этот боб имеет ценность. Вот почему добавление журналов неэффективно, и потребуется много времени, чтобы проверить неправильное подозрение.
Затем я использовал команду trace, надеясь проследить, как этот метод работает внутри. Команда trace может отслеживать путь вызова внутри метода и выводить время, затрачиваемое на каждый узел пути метода. Разница между ним и стеком заключается в том, что вывод стека является путем вызова текущего метода. Формат трассировки также следующий: трассировка + имя класса + имя метода + выражение. Вот результат выполнения:
Здесь хорошо видно, что исключение выброшено в позиции предпоследней строки. После анализа я обнаружил, что мой код неверен. . . Наконец, по результатам arthas, мы завершили онлайн-отладку.
Напоследок: об использовании arthas в k8s или докере
Arthas должен запустить процесс jvm на текущей машине для работы. В реальной производственной среде все наши онлайн-машины должны быть развернуты в k8s или докере. То есть на эти онлайн-машины тоже нужно установить arthas. Это также специально упоминается в официальном руководстве Али по развертыванию артас в контейнерах.
На самом деле, я думаю, что разработчикам будет лучше установить Arthas локально. Затем подключитесь к Arthas в Docker через веб-консоль Arthas. Затем отлаживайте на удаленной линии через консоль. Это также подтверждается в официальном пользовательском кейсе.Документ, как использовать Arthas для удаленного доступа # 442. Таким образом, можно установить более эффективный режим разработки. И это может значительно уменьшить количество кода регистрации, такого как log.info в коде. Учитывая, что функция артха гораздо шире, следует сказать, что ее все же стоит рассмотреть.