스프링 클라우드 슬루스: 분산 추적 도구

스프링 클라우드 슬루스 소개

스프링 클라우드 슬루스는 스프링 클라우드용 분산 추적 도구입니다. 이 도구는 Dapper, Zipkin, HTrace의 개념을 차용하여 개발되었습니다.

빠른 시작

스프링 부트 애플리케이션의 클래스패스에 슬루스를 추가하면(메이븐과 그래들 예제는 "프로젝트에 슬루스 추가" 참조), 요청을 로깅하는 경우 상관 데이터가 로그에 수집되는 것을 볼 수 있습니다.

예를 들어, 다음 HTTP 핸들러를 고려해 보세요:


@RestController
public class DemoController {
    private static Logger log = LoggerFactory.getLogger(DemoController.class);
    
    @RequestMapping("/")
    public String home() {
        log.info("홈 페이지 처리 중");
        ...
        return "안녕하세요, 세계!";
    }
}

이 핸들러를 컨트롤러에 추가하면 home() 호출이 로그와 Zipkin에서 추적되는 것을 볼 수 있으며, Zipkin이 구성된 경우에도 마찬가지입니다.

핸들러에서 명시적으로 요청을 로깅하는 대신, `logging.level.org.springframework.web.servlet.DispatcherServlet=DEBUG`를 설정할 수 있습니다.

서비스 이름뿐만 아니라 추적 및 스팬 ID를 보려면 `spring.application.name=내서비스`(예)를 설정하세요.

Zipkin을 사용하는 경우, `spring.sleuth.sampler.probability`를 설정하여 내보내는 스팬의 확률을 구성하세요(기본값: 0.1, 즉 10%). 그렇지 않으면 일부 스팬이 생략되는 것으로 생각하여 슬루스가 작동하지 않는다고 오해할 수 있습니다.

용어 설명

스프링 클라우드 슬루스는 Dapper의 용어를 차용합니다.

스팬(Span)

작업의 기본 단위입니다. 예를 들어, RPC를 보내는 것은 새로운 스팬이며, RPC에 응답을 보내는 것도 새로운 스팬입니다. 스팬은 스팬에 대한 고유한 64비트 ID와 스팬이 속한 추적에 대한 또 다른 64비트 ID로 식별됩니다. 스팬에는 설명, 타임스탬프 이벤트, 키-값 주석(태그), 스팬을 유발한 스팬의 ID, 프로세스 ID(일반적으로 IP 주소) 등 다른 데이터도 있습니다.

스팬은 시작하고 중지할 수 있으며, 타이밍 정보를 추적합니다. 스팬을 생성한 경우 나중에 반드시 중지해야 합니다.

추적을 시작하는 초기 스팬은 '루트 스팬'이라고 합니다. 해당 스팬의 ID 값은 추적 ID와 동일합니다.

추적(Trace)

트리 구조를 형성하는 스팬의 집합입니다. 예를 들어, 분산 빅데이터 저장소를 실행하는 경우 PUT 요청으로 추적이 형성될 수 있습니다.

주석(Annotation)

시간의 이벤트 존재를 기록하는 데 사용됩니다. Brave 계측을 사용하면 더 이상 Zipkin이 클라이언트와 서버, 요청 시작 위치 및 종료 위치를 이해하도록 특별한 이벤트를 설정할 필요가 없습니다. 학습 목적으로는 이러한 이벤트를 표시하여 어떤 종류의 작업이 발생했는지 강조합니다.

  • cs(Client Sent): 클라이언트가 요청을 보냈습니다. 이 주석은 스팬의 시작을 나타냅니다.
  • sr(Server Received): 서버 측에서 요청을 받아 처리를 시작했습니다. cs 타임스탬프에서 이 타임스탬프를 빼면 네트워크 지연 시간이 나옵니다.
  • ss(Server Sent): 요청 처리 완료 시(응답이 클라이언트에게 다시 보내졌을 때) 주석이 추가됩니다. sr 타임스탬프에서 이 타임스탬프를 빼면 서버 측에서 요청을 처리하는 데 필요한 시간이 나옵니다.
  • cr(Client Received): 스팬의 끝을 의미합니다. 클라이언트가 서버 측에서 응답을 성공적으로 받았습니다. cs 타임스탬프에서 이 타임스탬프를 빼면 클라이언트가 서버에서 응답을 받는 데 필요한 전체 시간이 나옵니다.

목적

Zipkin을 사용한 분산 추적

이 예제에는 일곱 개의 스팬이 있습니다. Zipkin의 추적으로 이동하면 두 번째 추적에서 이 숫자를 볼 수 있습니다.

그러나 특정 추적을 선택하면 네 개의 스팬이 표시됩니다.

이 경우 일곱 개와 네 개의 스팬 간의 차이가 있는 이유는 무엇일까요?

  • 두 개의 스팬은 `http:/start` 스팬에서 옵니다. 이 스팬에는 Server Received(sr)와 Server Sent(ss) 주석이 있습니다.
  • 두 개의 스팬은 `service1`에서 `service2`로 `http:/foo` 엔드포인트로 RPC 호출에서 옵니다. Client Sent(cs)와 Client Received(cr) 이벤트가 `service1` 측에서 발생했습니다. Server Received(sr)와 Server Sent(ss) 이벤트가 `service2` 측에서 발생했습니다. 이 두 스팬은 RPC 호출과 관련된 논리적 스팬을 형성합니다.
  • 두 개의 스팬은 `service2`에서 `service3`로 `http:/bar` 엔드포인트로 RPC 호출에서 옵니다. Client Sent(cs)와 Client Received(cr) 이벤트가 `service2` 측에서 발생했습니다. Server Received(sr)와 Server Sent(ss) 이벤트가 `service3` 측에서 발생했습니다. 이 두 스팬은 RPC 호출과 관련된 논리적 스팬을 형성합니다.
  • 두 개의 스팬은 `service2`에서 `service4`로 `http:/baz` 엔드포인트로 RPC 호출에서 옵니다. Client Sent(cs)와 Client Received(cr) 이벤트가 `service2` 측에서 발생했습니다. Server Received(sr)와 Server Sent(ss) 이벤트가 `service4` 측에서 발생했습니다. 이 두 스팬은 RPC 호출과 관련된 논리적 스팬을 형성합니다.

따라서 물리적 스팬을 총계하면 `service1`에 대한 들어오는 요청과 관련된 하나의 스팬과 세 개의 RPC 호출 관련 스팬이 총 네 개의 스팬이 있습니다.

오류 시각화

Zipkin을 사용하면 추적에서 오류를 시각화할 수 있습니다. 예외가 발생하고 잡히지 않은 경우, 스팬에 적절한 태그를 설정하여 Zipkin이 올바르게 색상을 지정할 수 있습니다. 추적 목록에서 빨간색으로 표시된 하나의 추적을 볼 수 있습니다. 이는 예외가 발생했기 때문입니다.

Brave를 사용한 분산 추적

버전 `2.0.0`부터 스프링 클라우드 슬루스는 추적 라이브러리로 Brave를 사용합니다. 따라서 슬루스는 더 이상 컨텍스트 저장을 담당하지 않고 해당 작업을 Brave에 위임합니다.

슬루스가 Brave와 다른 명명 및 태깅 규칙을 가졌기 때문에, 이제부터 Brave의 규칙을 따르기로 결정했습니다. 그러나 레거시 슬루스 접근 방식을 사용하려면 `spring.sleuth.http.legacy.enabled` 속성을 `true`로 설정할 수 있습니다.

로그 상관 관계

grep을 사용하여 추적 ID가 (예) `2485ec27856c56f4`와 같은 네 개의 애플리케이션 로그를 읽으면 다음과 유사한 출력이 나옵니다:


service1.log:2016-02-26 11:15:47.561  INFO [service1,2485ec27856c56f4,2485ec27856c56f4,true] 68058 --- [nio-8081-exec-1] i.s.c.sleuth.docs.service1.Application   : service1에서 인사합니다. service2 호출 중
service2.log:2016-02-26 11:15:47.710  INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application   : service2에서 인사합니다. 그다음 service3와 service4 호출 중
service3.log:2016-02-26 11:15:47.895  INFO [service3,2485ec27856c56f4,1210be13194bfe5,true] 68060 --- [nio-8083-exec-1] i.s.c.sleuth.docs.service3.Application   : service3에서 인사합니다
service2.log:2016-02-26 11:15:47.924  INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application   : service3에서 응답 받음 [Hello from service3]
service4.log:2016-02-26 11:15:48.134  INFO [service4,2485ec27856c56f4,1b1845262ffba49d,true] 68061 --- [nio-8084-exec-1] i.s.c.sleuth.docs.service4.Application   : service4에서 인사합니다
service2.log:2016-02-26 11:15:48.156  INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application   : service4에서 응답 받음 [Hello from service4]
service1.log:2016-02-26 11:15:48.182  INFO [service1,2485ec27856c56f4,2485ec27856c56f4,true] 68058 --- [nio-8081-exec-1] i.s.c.sleuth.docs.service1.Application   : service2에서 응답 받음 [Hello from service2, response from service3 [Hello from service3] and from service4 [Hello from service4]]

로그 집계 도구(Kibana, Splunk 등)를 사용하면 발생한 이벤트를 정렬할 수 있습니다. Kibana의 예는 다음과 유사합니다.

JSON Logback with Logstash

종종 로그를 텍스트 파일이 아닌 Logstash가 즉시 선택할 수 있는 JSON 파일에 저장하고 싶을 수 있습니다. 이를 위해 다음과 같이 해야 합니다(가독성을 위해 groupId:artifactId:version 표기법으로 의존성을 전달합니다).

종속성 설정

  1. Logback이 클래스패스에 있는지 확인합니다(`ch.qos.logback:logback-core`).
  2. Logstash Logback 인코더를 추가합니다. 예를 들어 버전 `4.6`을 사용하려면 `net.logstash.logback:logstash-logback-encoder:4.6`을 추가합니다.

Logback 설정

다음은 Logback 구성 파일(logback-spring.xml이라고 함)의 예입니다.


<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>
    <!-- 프로젝트의 빌드 폴더에 로깅하는 예제 -->
    <property name="LOG_FILE" value="${BUILD_FOLDER:-build}/${springAppName}"/>
    
    <!-- 이를 재정의하여 사용자 정의 패턴을 가질 수 있습니다 -->
    <property name="CONSOLE_LOG_PATTERN" 
              value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
    
    <!-- 콘솔에 로그하는 Appender -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <!-- 콘솔 로그에 표시될 최소 로깅 수준 -->
            <level>DEBUG</level>
        </filter>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>
    
    <!-- 파일에 로그하는 Appender -->
    <appender name="flatfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>
    
    <!-- JSON 형식으로 파일에 로그하는 Appender -->
    <appender name="logstash" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}.json</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.json.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>UTC</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        "severity": "%level",
                        "service": "${springAppName:-}",
                        "trace": "%X{X-B3-TraceId:-}",
                        "span": "%X{X-B3-SpanId:-}",
                        "parent": "%X{X-B3-ParentSpanId:-}",
                        "exportable": "%X{X-Span-Export:-}",
                        "pid": "${PID:-}",
                        "thread": "%thread",
                        "class": "%logger{40}",
                        "rest": "%message"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>
    
    <root level="INFO">
        <appender-ref ref="console"/>
        <!-- JSON 로그를 사용하려면 다음을 주석 해제하세요 -->
        <!--<appender-ref ref="logstash"/>-->
        <!--<appender-ref ref="flatfile"/>-->
    </root>
</configuration>

이 Logback 구성 파일은:

  • 애플리케이션에서 JSON 형식으로 정보를 `build/${spring.application.name}.json` 파일에 로깅합니다.
  • 콘솔 및 표준 로그 파일이라는 두 개의 추가 Appender가 주석 처리되어 있습니다.
  • 이전 섹션에 제시된 것과 동일한 로깅 패턴을 가집니다.

사용자 정의 `logback-spring.xml`을 사용하는 경우, 속성 파일에서 `spring.application.name`을 `bootstrap`이 아닌 `application` 속성 파일에 전달해야 합니다. 그렇지 않으면 사용자 정의 logback 파일이 속성을 올바르게 읽지 못합니다.

스팬 컨텍스트 전파

스팬 컨텍스트는 프로세스 경계를 넘어 모든 하위 스팬으로 전파되어야 하는 상태입니다. 스팬 컨텍스트의 일부는 Baggage입니다. 추적 ID와 스팬 ID는 스팬 컨텍스트의 필수 부분입니다. Baggage는 선택적 부분입니다.

Baggage는 스팬 컨텍스트에 저장된 키:값 쌍의 집합입니다. Baggage는 추적과 함께 이동하며 모든 스팬에 첨부됩니다. 스프링 클라우드 슬루스는 HTTP 헤더가 `baggage-`로 접두사가 붙은 경우 해당 헤더가 baggage 관련이라고 이해합니다. 메시징의 경우 `baggage_`로 시작합니다.

현재 baggage 항목의 수나 크기에 대한 제한은 없습니다. 그러나 너무 많은 baggage는 시스템 처리량을 줄이거나 RPC 지연 시간을 증가시킬 수 있습니다. 극단적인 경우에는 운송 수준의 메시지나 헤더 용량을 초과하여 애플리케이션 충돌을 일으킬 수 있습니다.

다음 예제는 스팬에 baggage를 설정하는 방법을 보여줍니다:


Span initialSpan = this.tracer.nextSpan().name("span").start();
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(initialSpan)) {
    ExtraFieldPropagation.set("foo", "bar");
    ExtraFieldPropagation.set("UPPER_CASE", "someValue");
}

Baggage versus 스팬 태그

Baggage는 추적과 함께 이동합니다(모든 하위 스팬에는 부모의 baggage가 포함됨). Zipkin은 baggage에 대한 지식이 없으며 해당 정보를 받지 않습니다.

태그는 특정 스팬에 첨부됩니다. 다른 말로, 그들은 특정 스팬에 대해서만 표시됩니다. 그러나 검색된 태그 값을 가진 스팬이 있다고 가정하면 태그로 검색하여 추적을 찾을 수 있습니다.

baggage를 기반으로 스팬을 조회할 수 있도록 하려면 루트 스팬에 해당 항목을 태그로 추가해야 합니다.

스팬이 범위 내에 있어야 합니다.

프로젝트에 슬루스 추가

이 섹션은 메이븐 또는 그래들을 사용하여 프로젝트에 슬루스를 추가하는 방법을 다룹니다.

애플리케이션 이름이 Zipkin에 올바르게 표시되도록 하려면 `bootstrap.yml`에서 `spring.application.name` 속성을 설정하세요.

슬루스만 로그 상관 관계

Zipkin 통합 없이 스프링 클라우드 슬루스만 사용하려면 `spring-cloud-starter-sleuth` 모듈을 프로젝트에 추가하세요.

메이븐으로 슬루스 추가


<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${release.train.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

그래들로 슬루스 추가


dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${releaseTrainVersion}"
    }
}

dependencies {
    compile "org.springframework.cloud:spring-cloud-starter-sleuth"
}

HTTP를 통한 Zipkin과 함께 슬루스

슬루스와 Zipkin을 모두 사용하려면 `spring-cloud-starter-zipkin` 종속성을 추가하세요.

메이븐으로 Zipkin과 슬루스 추가


<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${release.train.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

그래들로 Zipkin과 슬루스 추가


dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${releaseTrainVersion}"
    }
}

dependencies {
    compile "org.springframework.cloud:spring-cloud-starter-zipkin"
}

RabbitMQ 또는 Kafka를 통한 Zipkin과 함께 슬루스

RabbitMQ 또는 Kafka를 HTTP 대신 사용하려면 `spring-rabbit` 또는 `spring-kafka` 종속성을 추가하세요. 기본 대상 이름은 `zipkin`입니다.

`spring-cloud-sleuth-stream`은 더 이상 사용되지 않으며 이 대상과 호환되지 않습니다.

RabbitMQ를 사용하여 슬루스를 사용하려면 `spring-cloud-starter-zipkin` 및 `spring-rabbit` 종속성을 추가하세요.

메이븐으로 RabbitMQ와 슬루스 추가


<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${release.train.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
</dependency>

그래들로 RabbitMQ와 슬루스 추가


dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${releaseTrainVersion}"
    }
}

dependencies {
    compile "org.springframework.cloud:spring-cloud-starter-zipkin"
    compile "org.springframework.amqp:spring-rabbit"
}

슬루스의 주요 기능

  • Slf4J MDC에 추적 및 스팬 ID를 추가하여 로그 집계기에서 주어진 추적 또는 스팬의 모든 로그를 추출할 수 있습니다.
  • 일반적인 분산 추적 데이터 모델에 대한 추상화를 제공합니다: 추적, 스팬(DAG 형성), 주석 및 키-값 주석. 스프링 클라우드 슬루스는 HTrace를 기반으로 하지만 Zipkin(Dapper)과 호환됩니다.
  • 지연 분석을 지원하기 위해 타이밍 정보를 기록합니다. 슬루스를 사용하면 애플리케이션의 지연 원인을 정확히 파악할 수 있습니다.
  • 너무 많이 로깅하거나 프로덕션 애플리케이션을 충돌시키지 않도록 설계되었습니다. 이를 위해 슬루스는 호출 그래프의 구조적 데이터를 인밴드로 전파하고 나머지는 아웃오브밴드로 전파합니다.
  • HTTP와 같은 계층에 대한 의견이 분할된 계측을 포함합니다.
  • 볼륨을 관리하기 위한 샘플링 정책을 포함합니다.
  • Zipkin 시스템에 쿼리 및 시각화를 보고할 수 있습니다.
  • 스프링 애플리케이션의 일반적인 입구 및 출구 지점을 계측합니다(서블릿 필터, 비동기 엔드포인트, rest 템플릿, 예약된 작업, 메시지 채널, Zuul 필터, Feign 클라이언트).
  • HTTP 또는 메시징 경계를 통해 추적을 조인하는 기본 로직을 포함합니다.
  • 컨텍스트(또는 baggage라고도 함)를 프로세스 간에 전파할 수 있습니다.
  • 주석을 통해 스팬을 생성하거나 계속하고 태그와 로그를 추가하는 방법을 제공합니다.
  • 클래스패스에 `spring-cloud-sleuth-zipkin`이 있는 경우, 앱이 Zipkin과 호환되는 추적을 생성하고 수집합니다. 기본적으로 localhost(포트 9411)의 Zipkin 서버로 HTTP를 통해 전송합니다. `spring.zipkin.baseUrl`을 설정하여 서비스 위치를 구성할 수 있습니다.

Zipkin을 사용하는 경우, `spring.sleuth.sampler.probability`를 설정하여 내보내는 스팬의 확률을 구성하세요(기본값: 0.1, 즉 10%). 그렇지 않으면 일부 스팬이 생략되는 것으로 생각하여 슬루스가 작동하지 않는다고 오해할 수 있습니다.

SLF4J MDC는 항상 설정되며, logback 사용자는 즉시 로그에서 추적 및 스팬 ID를 볼 수 있습니다. 다른 로깅 시스템은 동일한 결과를 얻기 위해 자체 포매터를 구성해야 합니다. 기본값은 다음과 같습니다: `logging.pattern.level`이 `%5p [${spring.zipkin.service.name:${spring.application.name:-}},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]`로 설정됩니다(이는 logback 사용자를 위한 스프링 부트 기능입니다). SLF4J를 사용하지 않으면 이 패턴은 자동으로 적용되지 않습니다.

빌드 방법

기본 컴파일 및 테스트

소스를 빌드하려면 JDK 1.7을 설치해야 합니다.

스프링 클라우드는 대부분의 빌드 관련 활동에 메이븐을 사용하며, 관심 있는 프로젝트를 복제하고 다음을 입력하여 빠르게 시작할 수 있습니다:


$ ./mvnw install

직접 메이븐(>=3.3.3)을 설치하고 아래 예제에서 `./mvnw` 대신 `mvn` 명령을 실행할 수도 있습니다. 그렇게 할 경우 로컬 메이븐 설정에 스프링 프리리리즈 아티팩트에 대한 저장소 선언이 포함되어 있지 않은 경우 `-P spring`을 추가해야 할 수도 있습니다.

Maven에 사용 가능한 메모리 양을 `MAVEN_OPTS` 환경 변수를 설정하여 `-Xmx512m -XX:MaxPermSize=128m`과 같은 값으로 늘려야 할 수도 있다는 점에 주의하세요. 이는 `.mvn` 구성에서 다루려고 하므로, 빌드를 성공시키기 위해 이 작업을 해야 하는 경우 설정을 소스 제어에 추가하기 위해 티켓을 제기하세요.

기여 방법

스프링 클라우드는 비제한적인 Apache 2.0 라이선스로 릴리스되며, 표준 Github 개발 프로세스를 따르고 Github 트래커를 사용하여 이슈를 관리하고 풀 요청을 마스터로 병합합니다. 아주 사소한 것이라도 기여하고 싶다면 주저하지 말고 아래 가이드라인을 따르세요.

기여자 라이선스 계약에 서명

중요한 패치나 풀 요청을 받아들이기 전에 기여자 라이선스 계약에 서명해야 합니다. 기여자 계약에 서명하는 것은 메인 저장소에 커밋 권한을 부여하지 않지만, 기여를 받을 수 있다는 의미이며, 그렇게 한다면 작성자 크레딧을 얻게 됩니다. 활발한 기여자는 코어 팀에 합류하도록 요청받을 수 있으며, 풀 요청을 병합할 수 있는 능력을 부여받을 수 있습니다.

행동 강령

이 프로젝트는 기여자 계약 행동 강령을 따릅니다. 참여함으로써 이 강령을 준수할 것으로 예상됩니다. 허용되지 않는 행동을 spring-code-of-conduct@pivotal.io에 보고하세요.

코드 규칙 및 관리

이 중 어느 것도 풀 요청에 필수는 아니지만 모두 도움이 됩니다. 원래 풀 요청 후 병합 전에 추가할 수도 있습니다.

  • 스프링 프레임워크 코드 형식 규칙을 사용하세요. Eclipse를 사용하는 경우 `eclipse-code-formatter.xml` 파일을 스프링 클라우드 빌드 프로젝트에서 가져와서 포매터 설정을 가져올 수 있습니다. IntelliJ를 사용하는 경우 동일한 파일을 가져오기 위해 Eclipse 코드 포매터 플러그인을 사용할 수 있습니다.
  • 모든 새 `.java` 파일에 적어도 자신을 식별하는 `@author` 태그가 있는 간단한 Javadoc 클래스 주석이 있는지 확인하세요.
  • 모든 새 `.java` 파일에 ASF 라이선스 헤더 주석을 추가하세요(프로젝트의 기존 파일에서 복사).
  • 상당히 수정한 `.java` 파일(단순한 코스메틱 변경 이상)에 자신을 `@author`로 추가하세요.
  • 일부 Javadoc을 추가하고, 네임스페이스를 변경하는 경우 일부 XSD doc 요소를 추가하세요.
  • 몇 가지 단위 테스트도 큰 도움이 될 것입니다 — 누군가는 해야 합니다.
  • 다른 사람이 브랜치를 사용하지 않는 경우, 현재 마스터(또는 메인 프로젝트의 다른 대상 브랜치)에 대해 리베이스하세요.
  • 커밋 메시지를 작성할 때 다음 규칙을 따르세요. 기존 이슈를 수정하는 경우 커밋 메시지 끝에 `Fixes gh-XXXX`를 추가하세요(XXXX는 이슈 번호).

태그: 스프링클라우드-슬루스 분산추적 자바 마이크로서비스 Zipkin

7월 15일 01:52에 게시됨