1. 상위 계층 시스템에서 도입된 잘못된 매개변수. 잘못된 매개변수로 인해 발생한 오류의 경우 매개변수 확인 및 전제 조건 확인을 통해 오류를 차단할 수 있습니다.
2. 하위 계층과의 상호 작용으로 인해 발생하는 오류에는 두 가지 유형이 있습니다.
a 하위 계층 시스템이 성공적으로 처리되었지만 통신이 잘못되어 하위 시스템 간의 데이터 불일치가 발생합니다.
이 경우 시간 초과가 발생합니다. 보상 메커니즘을 사용하여 작업을 미리 기록하고 나중에 예약된 작업을 통해 데이터를 수정할 수 있습니다.
더 나은 디자인 솔루션이 있으면 메시지를 남길 수도 있습니다.
b. 통신은 성공했지만, 하위 레이어 처리에서 오류가 발생했습니다.
이 경우 하위 시스템 간의 상호 작용을 조정하기 위해 하위 개발자와 통신해야 합니다.
하위 개발자가 반환한 오류 코드 및 오류 설명을 기반으로 적절한 처리를 수행하거나 합리적인 프롬프트 정보를 제공해야 합니다. -레벨 레이어.
두 경우 모두 기본 시스템의 신뢰성이 평균이라고 가정하고 오류에 대한 설계 고려 사항을 고려해야 합니다.
3. 이 수준에서는 시스템 처리에 오류가 있습니다.
이 시스템 오류의 원인:
원인 1: 부주의로 인해 발생합니다. 생략은 프로그래머가 그러한 오류를 피할 수 있었지만 그렇게 하지 못했다는 것을 의미합니다. 예를 들어 &에는 &&가 입력되었고, =;에는 ==가 입력되었습니다. 과실은 프로그래머가 피곤하거나, 밤샘 야근을 하거나, 회의 중에 프로그램을 작성하는 등 집중력이 부족하거나, 프로그램의 견고성을 고려하지 않고 서둘러 기능을 구현하기 때문입니다.
개선 조치: 코드 정적 분석 도구와 단위 테스트 라인 커버리지를 사용하여 이러한 문제를 효과적으로 방지합니다.
이유 2: 오류 및 예외 처리가 부족하여 발생합니다. 예를 들어 질문을 입력합니다. 두 숫자의 덧셈을 계산할 때 계산 오버플로 문제뿐만 아니라 잘못된 입력 상황도 고려해야 합니다. 전자의 경우 이해, 실수, 경험을 통해 피할 수 있는 반면, 후자의 경우 정규식을 사용하여 불법 입력을 걸러내는 등 우리의 IQ가 제어할 수 있는 범위 내로 제한해야 합니다. 정규식을 테스트해야 합니다. 불법적인 입력에 대해서는 최대한 자세하고 이해하기 쉬우며 친근한 프롬프트 정보, 이유 및 제안을 제공하십시오.
개선 조치: 다양한 오류 상황 및 예외 처리를 최대한 철저하게 고려합니다. 기본 프로세스를 구현한 후 가능한 다양한 오류와 예외를 신중하게 고려하고 합리적인 오류 코드와 오류 설명을 반환하는 단계를 추가합니다. 각 인터페이스 또는 모듈은 자체 오류 및 예외를 효과적으로 처리하므로 복잡한 장면 상호 작용으로 인해 발생하는 버그를 효과적으로 방지할 수 있습니다.
예를 들어 비즈니스 사용 사례는 시나리오 A.B.C.에 의해 대화형으로 완료됩니다. A.B의 실제 실행은 성공적이지만 C는 실패합니다. 이때 B는 C가 반환한 합리적인 코드와 메시지를 롤백하고 A에게 합리적인 코드와 메시지를 반환해야 합니다. A는 B의 반환을 기반으로 롤백하고 합리적인 코드와 메시지를 반환합니다. 클라이언트에게. 이는 각 시나리오에서 비정상적인 상황에서 롤백을 고려해야 하는 분할된 롤백 메커니즘입니다.
이유 3: 긴밀한 논리적 결합으로 인해 발생합니다. 비즈니스 로직의 긴밀한 결합으로 인해 소프트웨어 제품이 단계적으로 발전함에 따라 다양한 논리적 관계가 복잡하고 복잡해져서 전체적인 상황을 파악하기 어렵고, 로컬 수정의 영향이 글로벌 범위로 확산되어 예측할 수 없는 문제가 발생합니다. .
개선 조치: 짧은 함수와 짧은 메서드를 작성합니다. 각 함수나 메서드에 대해 50줄을 넘지 않는 것이 좋습니다. 상태 비저장 함수 및 메서드, 읽기 전용 전역 상태를 작성하고 동일한 전제 조건은 항상 동일한 결과를 출력하며 외부 상태에 따라 동작을 변경하지 않습니다. 인터페이스 간 연결을 만들기 위해 합리적인 구조, 인터페이스 및 논리 세그먼트를 정의해야 합니다. 가능한 한 직교하고 낮은 결합을 유지해야 하며, 서비스 계층의 경우 단순하고 직교하는 인터페이스를 최대한 제공해야 하며, 애플리케이션을 모듈화하고 느슨하게 결합하고 논리적 종속성을 명확히 하기 위해 지속적인 재구성을 수행해야 합니다.
많은 수의 비즈니스 인터페이스가 서로 상호 작용하는 상황에서는 각 비즈니스 인터페이스의 논리적 프로세스와 상호 의존성을 분류하고 많은 수의 상태를 가진 엔터티에 대해 전체적으로 최적화해야 합니다. 관련 비즈니스 인터페이스를 정리하고 상태 변환 관계를 정리하는 데 필요합니다.
이유 4: 잘못된 알고리즘으로 인해 발생합니다.
개선 조치: 먼저 알고리즘을 애플리케이션에서 분리합니다. 알고리즘에 여러 구현이 있는 경우 정렬 작업과 같은 교차 검사의 단위 테스트를 통해 알 수 있으며, 알고리즘에 가역적 속성이 있는 경우 암호화 및 암호 해독 작업과 같은 가역 검사의 단위 테스트를 통해 확인할 수 있습니다. .
원인 5: 동일한 유형의 매개변수가 잘못된 순서로 전달되었습니다. 예를 들어, 수정Flow(int rx, int tx), 실제 호출은 수정Flow(tx,rx)
입니다. 개선 조치: 유형을 최대한 구체적으로 만드세요. 사용해야 할 때는 부동 소수점 숫자를 사용하고, 문자열을 사용해야 할 때는 문자열을 사용하고, 사용해야 할 때는 특정 객체 유형을 사용하십시오. 만족스럽다면 인터페이스 테스트를 통해 검증해야 하며, 인터페이스 매개변수 값은 달라야 합니다.
6번째 이유: Null 포인터 예외. Null 포인터 예외는 일반적으로 개체가 올바르게 초기화되지 않았거나 개체를 사용하기 전에 개체가 Null이 아닌지 여부를 확인하지 않을 때 발생합니다.
개선 조치: 구성 개체의 경우 성공적으로 초기화되었는지 확인하고, 일반 개체의 경우 사용할 엔터티 개체를 얻기 전에 비어 있지 않은지 확인하세요.
원인 7: 네트워크 통신 오류. 네트워크 통신 오류는 일반적으로 네트워크 지연, 혼잡 또는 차단으로 인해 발생합니다. 네트워크 통신 오류는 일반적으로 확률이 낮은 이벤트이지만 확률이 낮은 이벤트는 재현하기 어려운 대규모 장애 및 버그로 이어질 가능성이 높습니다.
개선 조치: 이전 하위 시스템의 끝점과 다음 하위 시스템의 진입점에 각각 INFO 로그를 만듭니다. 둘 사이의 시간차가 단서를 제공한다.
원인 8: 트랜잭션 및 동시성 오류. 트랜잭션과 동시성을 결합하면 찾기가 매우 어려운 오류가 쉽게 발생할 수 있습니다.
개선 조치: 공유 변수 및 중요한 상태 수정과 관련된 프로그램의 동시 작업의 경우 INFO 로그를 추가해야 합니다.
더 효과적인 방법이 있다면 메시지로 남겨주세요.
원인 9: 구성 오류입니다.
개선 조치: 애플리케이션을 시작하거나 해당 구성을 시작할 때 모든 구성 항목을 감지하고 해당 INFO 로그를 인쇄하여 모든 구성이 성공적으로 로드되었는지 확인하세요.
이유 10: 비즈니스에 대한 익숙하지 않음으로 인한 오류. 중형 및 대규모 시스템에서는 일부 비즈니스 로직과 비즈니스 상호 작용이 상대적으로 복잡할 수 있으며 전체 비즈니스 로직은 여러 개발 학생의 두뇌에 존재할 수 있으며 모든 사람의 이해가 불완전합니다. 이는 쉽게 비즈니스 코딩 오류로 이어질 수 있습니다.
개선 조치: 여러 사람과의 토론과 소통을 통해 올바른 비즈니스 사용 사례를 설계하고, 비즈니스 사용 사례를 기반으로 비즈니스 로직을 작성 및 구현합니다. 최종 비즈니스 로직과 비즈니스 사용 사례는 비즈니스 이름을 완전히 보관해야 합니다. 비즈니스 인터페이스 전제 조건, 처리 논리, 사후 검증 및 예방 조치, 비즈니스 변경 시 비즈니스 의견을 동시에 업데이트해야 합니다. 비즈니스 주석은 비즈니스 인터페이스를 위한 중요한 문서이며 비즈니스 이해에 중요한 캐싱 역할을 합니다.
원인 11: 설계 문제로 인해 발생한 오류입니다. 예를 들어, 동기식 직렬 방식은 성능과 느린 응답 문제가 있는 반면 동시 비동기식 방식은 성능과 느린 응답 문제를 해결할 수 있지만 보안과 정확성에 숨겨진 위험을 가져옵니다. 비동기식 접근 방식은 프로그래밍 모델의 변경으로 이어지며 비동기식 메시지 푸시 및 수신과 같은 새로운 문제가 추가됩니다. 캐시를 사용하면 성능이 향상될 수 있지만 캐시 업데이트에 문제가 있습니다.
개선 조치: 디자인 문서를 작성하고 신중하게 검토하세요. 설계 문서에는 배경, 요구 사항, 달성할 비즈니스 목표, 달성할 비즈니스 성과 지표, 가능한 영향, 전반적인 설계 아이디어, 세부 계획, 테스트 및 승인을 통해 계획의 장점, 단점 및 가능한 영향을 예측하는 내용이 기술되어야 합니다. 변경 사항이 있는지 확인하십시오. 디자인 솔루션이 비즈니스 목표와 비즈니스 성과 지표를 충족하는지 확인하십시오.
원인 12: 알 수 없는 세부정보로 인해 발생한 오류입니다. 버퍼 오버플로 및 SQL 주입 공격 등이 있습니다. 기능적인 측면에서는 문제가 없으나, 악의적인 이용 측면에서는 허점이 있습니다. 또 다른 예로, JSON 문자열 구문 분석을 위해 jackson 라이브러리를 선택하면 기본적으로 새 필드가 객체에 추가될 때 구문 분석 오류가 발생합니다. 변경 사항에 올바르게 응답하려면 @JsonIgnoreProperties(ignoreUnknown = true) 주석을 개체에 추가해야 합니다. 다른 JSON 라이브러리를 선택하면 이 문제가 발생하지 않을 수 있습니다.
개선 조치: 한편으로는 경험을 축적하는 동시에 보안 문제와 예외 사항을 고려하고 성숙하고 엄격하게 테스트된 라이브러리를 선택해야 합니다.
이유 13: 시간이 지남에 따라 나타나는 버그. 과거에는 훌륭해 보였던 솔루션이 현재 또는 미래의 시나리오에서 다루기 힘들거나 심지어 쓸모 없게 되는 것은 드문 일이 아닙니다. 예를 들어, 암호화 및 복호화 알고리즘은 과거에는 완벽하다고 간주되었을 수 있지만 크랙이 발생한 후에는 주의해서 사용해야 합니다.
개선 조치: 변경 사항 및 취약점 수정 소식에 주의를 기울이고, 오래된 코드, 라이브러리, 동작을 즉시 수정하세요.
원인 Fourteen: 하드웨어 관련 오류. 예를 들어 메모리 누수, 저장 공간 부족, OutOfMemoryError 등이 있습니다.
개선 조치: 응용 시스템의 CPU/메모리/네트워크 등 중요 지표에 대한 성능 모니터링을 추가합니다.
시스템의 일반적인 오류:
데이터베이스에 엔터티 레코드가 없습니다. 어떤 엔터티 또는 엔터티 식별자를 지정해야 합니다.
엔터티 구성이 잘못되었습니다. 문제, 올바른 구성
엔터티 리소스가 조건을 충족하지 않는 경우 현재 리소스가 무엇인지, 리소스 요구 사항이 무엇인지 지정해야 합니다.
엔터티 작업의 전제 조건은 다음과 같습니다. 충족해야 하는 전제 조건과 현재 상태를 지정해야 합니다.
엔터티 작업의 사후 확인이 충족되어야 하는 항목과 현재 상태가 무엇인지 지정해야 합니다.
성능 문제로 인해 시간 초과가 발생하는 경우 향후 최적화 방법을 지정해야 합니다.
여러 하위 시스템의 대화형 통신 오류로 인해 상태 또는 데이터가 일치하지 않습니까?
일반적으로 찾기 어려운 오류는 상대적으로 낮은 수준의 위치에 나타납니다. 맨 아래 계층은 특정 비즈니스 시나리오를 예측할 수 없기 때문에 제공된 오류 메시지는 비교적 일반적입니다.
이를 위해서는 비즈니스의 상위 수준에서 최대한 많은 단서를 제공해야 합니다. 오류는 여러 시스템이나 계층이 상호 작용하는 동안 스택의 특정 계층에서 전제 조건이 충족되지 않아 발생해야 합니다. 프로그래밍할 때 스택의 각 계층에서 필요한 모든 전제 조건이 충족되는지 확인하고, 잘못된 매개 변수를 맨 아래 계층에 최대한 전달하지 말고, 비즈니스 계층에서 오류를 최대한 차단하세요.
대부분의 오류는 여러 가지 이유로 인해 발생합니다. 그러나 모든 실수에는 원인이 있습니다. 오류를 해결한 후 오류가 어떻게 발생했는지, 오류가 다시 발생하지 않도록 하는 방법에 대한 심층 분석을 수행합니다. 열심히 노력하면 성공할 수 있지만 반성해야만 발전할 수 있습니다! 권장사항: Java의 우아한 로깅: log4j 실무 장
문제 해결을 더 쉽게 만드는 오류 로그 작성 방법
오류 로깅의 기본 원칙:
최대한 완벽하게. 각 오류 로그에는 어떤 시나리오에서 어떤 오류가 발생했는지, 원인(또는 가능한 이유), 해결 방법(또는 해결 방법)이 자세히 설명되어 있습니다.
최대한 구체적으로 설명하세요. 예를 들어, NC 자원이 부족한 경우, 구체적으로 어떤 자원 부족을 의미합니까? 프로그램을 통해 직접 지정할 수 있습니까? VM NOT EXIST와 같은 일반적인 오류의 경우 발생하는 시나리오를 지정해야 합니다. 후속 통계 작업을 용이하게 할 수 있습니다.
최대한 직접적으로 이야기하세요. 이상적인 오류 로그는 실제 원인을 찾기 위해 여러 단계를 거치기보다는 사람들이 첫 번째 직관에서 원인과 해결 방법을 알 수 있도록 해야 합니다.
기존 경험을 시스템에 직접 통합. 해결된 모든 문제와 경험은 다른 곳에 묻혀있지 않고 신입사원들에게 더 나은 팁을 줄 수 있도록 최대한 친근하게 시스템에 통합되어야 합니다.
레이아웃은 깔끔하고 정돈되어 있어야 하며, 형식은 통일되고 표준화되어야 합니다. 촘촘하고 에세이 같은 로그는 보기에 가슴 아프고, 상당히 불친절하며, 문제 해결에 불편합니다.
여러 키워드를 사용하여 요청을 고유하게 식별하고 키워드를 강조 표시하세요: 시간, 엔터티 식별자(예: vmname), 작업 이름.
로그인부터 로그 파일 열기까지. 응용프로그램 서버가 여러 개 있기 때문에 하나씩 로그인해서 보기에는 불편합니다. 모든 서버 로그를 AG에서 직접 확인하고 필요한 오류 로그를 직접 필터링하려면 도구를 작성하여 AG에 배치해야 합니다.
오류 로그 위치를 찾아보세요. 현재 로그 레이아웃은 조밀하게 구성되어 있어 오류 로그를 찾기가 어렵습니다. 일반적으로 먼저 "시간"을 사용하여 오류 로그 앞부분 근처의 위치를 찾은 다음 엔터티 키워드/작업 이름 조합을 사용하여 오류 로그 위치를 잠글 수 있습니다. requestId를 기반으로 오류 로그를 찾는 것이 더 전통적이지만 먼저 requestId를 찾아야 하며 설명적이지 않습니다. 시간/내용 키워드를 기반으로 직접 오류 로그 위치를 찾는 것이 가장 좋습니다.
오류 로그를 분석하세요. 오류 로그의 내용은 보다 직접적이고 명확해야 하며, 현재 조사해야 할 문제의 특성과 일치함을 명확하게 나타내고 중요한 단서를 제공해야 합니다.
일반적으로 프로그램 오류 로그의 문제점은 로그 내용이 현재 코드 컨텍스트를 통해서만 이해할 수 있다는 것입니다. 그러나 코드 컨텍스트를 벗어나면 항상 불완전하게 작성되고 반 영어 형식으로 작성됩니다. , 무슨 말인지 알기 어렵습니다. 로그의 의미를 이해하려면 사람들이 그것에 대해 생각하게 하거나 코드를 살펴봐야 합니다. 이것은 자해의 고통이 아닌가? 확장: Java의 주류 로깅 도구 라이브러리에 대해 자세히 설명합니다.예:if ((storageType == StorageType.dfs1 || storageType == StorageType.dfs2) && (zone.hasStorageType(StorageType.io3) || zone.hasStorageType(StorageType.io4))) { // 进入dfs1 和dfs2 在io3 io4 存储。 } else { log.info("zone storage type not support, zone: " + zone.getZoneId() + ", storageType: " + storageType.name()); throw new BizException(DeviceErrorCode.ZONE_STORAGE_TYPE_NOT_SUPPORT); }
오류 로그는 다음과 같아야 합니다. 코드 컨텍스트를 떠날 때에도 무슨 일이 일어났는지 설명해야 합니다. .
또한 오류 로그에서 직접 이유를 명확하게 설명할 수 있으면 검사 로그를 작성할 때 수고를 덜 수 있습니다. 어떤 의미에서 오류 로그는 다양한 불법 실행 사례를 기록하는 매우 유용한 문서이기도 합니다. 현재 프로그램 오류 로그의 내용에는 다음과 같은 문제가 있을 수 있습니다.1. 오류 로그는 오류 매개변수 및 내용을 지정하지 않습니다.
catch(Exception ex){ log.error("control ip insert failed", ex); return new ResultSet<AddControlIpResponse>( ControlIpErrorCode.ERROR_CONTROL_IP_INSERT_FAILURE); }
log.error("Get some errors when insert subnet and its IPs into database. Add subnet or IP failure.", e);
解决方案:使用 String.format("Some msg to ErrorObj: %s", errobj) 方法指明错误参数及内容。
这通常要求对 DO 对象编写可读的 toString 方法。
2.错误场景不明确:
log.error("nc has exist, nc ip" + request.getIp());
在 createNc 中检测到 NC 已经存在报错。但是日志上没有指明错误场景, 让人猜测,为什么会报NC已存在错误。
可以改为
log.error("nc has exist when want to create nc, please check nc parameters. Given nc ip: " + request.getIp()); log.error("[create nc] nc has exist, please check nc parameters. Given nc ip: " + request.getIp());
类似的还有:
log.error("not all vm destroyed, nc id " + request.getNcId());
改成
log.error("[delete nc] some vms [%s] in the nc are not destroyed. nc id: %s", vmNames, request.getNcId());
解决方案:错误消息加上 when 字句, 或者错误消息前加上 【接口名】, 指明错误场景,直接从错误日志就知道明白了。
一般能够知道 executor 的可以加上 【接口名】, service 加上 when 字句。
3.内容不明确, 或不明其义:
if(aliMonitorReporter == null) { log.error("aliMonitorReporter is null!"); } else { aliMonitorReporter.attach(new ThreadPoolMonitor(namePrefix, asynTaskThreadPool.getThreadPoolExecutor())); }
改为:
log.error("aliMonitorReporter is null, probably not initialized properly, please check configuration in file xxx.");
类似的还有:
if (diskWbps == null && diskRbps == null && diskWiops == null && diskRiops == null) { log.error("none of attribute is specified for modifying"); throw new BizException(DeviceErrorCode.NO_ATTRIBUTE_FOR_MODIFY); }
改为
log.error("[modify disk attribute] None of [diskWbps,diskRbps,diskWiops,diskRiops] is specified for disk id:" + diskId);
解决方案:更清晰贴切地描述错误内容。
4.排查问题的引导内容不明确:
log.error("get gw group ip segment failed. zkPath: " + LockResource.getGwGroupIpSegmnetLockPath(request.getGwGroupId()));
zkPath ? 如何去排查这个问题?我该去找谁?到哪里去查找更具体的线索?
解决方案:加上相应的背景知识和引导排查措施。
5.错误内容不够具体细致:
if (!ncResourceService.isNcResourceEnough(ncResourceDO, vmResourceCondition)) { log.error("disk space is not enough at vm's nc, nc id:" + vmDO.getNcId()); throw new BizException(ResourceErrorCode.ERROR_RESOURCE_NOT_ENOUGH); }
究竟是什么资源不够?目前剩余多少?现在需要多少?值得注意的是, 要指明这些要额外做一些事情, 可能会稍微影响性能。这时候需要权衡性能和可调试性。
解决方案:通过改进程序或程序技巧, 尽可能揭示出具体的差异所在, 减少人工比对的操作。
6.半英文句式读起来不够清晰明白,需要思考来拼凑起完整的意思:
log.warn("cache status conflict, device id "+deviceDO.getId()+" db status "+deviceDO.getStatus() +", nc status "+ status);
改为:
log.warn(String.format("[query cache status] device cache status conflicts between regiondb and nc, status of device '%s' in regiondb is %s , but is %s in nc.", deviceDO.getId(), deviceDO.getStatus(), status));
解决方案:改为自然可读的英文句式。
总结起来, 错误日志格式可以为:
log.error("[接口名或操作名] [Some Error Msg] happens. [params] [Probably Because]. [Probably need to do]."); log.error(String.format("[接口名或操作名] [Some Error Msg] happens. [%s]. [Probably Because]. [Probably need to do].", params));
或
log.error("[Some Error Msg] happens to 错误参数或内容 when [in some condition]. [Probably Because]. [Probably need to do]."); log.error(String.format("[Some Error Msg] happens to %s when [in some condition]. [Probably Because]. [Probably need to do].", parameters));
[Probably Reason]. [Probably need to do]. 在某些情况下可以省略;在一些重要接口和场景下最好能说明一下。
每一条错误日志都是独立的,尽可能完整、具体、直接说明何种场景下发生了什么错误,由什么原因导致,要采用什么措施或步骤。
问题:
1.String.format 的性能会影响打日志吗?
一般来说, 错误日志应该是比较少的, 使用 String.format 的频度并不会太高,不会对应用和日志造成影响。
2.开发时间非常紧张时, 有时间去斟酌字句吗?
建立一个标准化的内容格式,将内容往格式套,可以节省斟酌字句的时间。
3.什么时候使用 info, warn , error ?
info 用于打印程序应该出现的正常状态信息, 便于追踪定位;
warn 表明系统出现轻微的不合理但不影响运行和使用;
error 表明出现了系统错误和异常,无法正常完成目标操作。
错误日志是排查问题的重要手段之一。当我们编程实现一项功能时, 通常会考虑可能发生的各种错误及相应原因:
要排查出相应的原因, 就需要一些关键描述来定位原因。
这就会形成三元组:
错误现象 -> 错误关键描述 -> 最终的错误原因。
需要针对每一种错误尽可能提供相应的错误关键描述,从而定位到相应的错误原因。
위 내용은 Java 프로젝트에서 오류 로그를 인쇄하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!