Jenkins Consistency Hash 노드 스케줄링

9671 단어 Devop

Jenkins Consistency Hash 노드 스케줄링

  • Consistency Hash
  • 가 필요한 이유
  • 일관성 Hash
  • 일관성 Hash가 필요한 이유


    이 화제는 좀 넓지만 지속적인 통합 분야에서 젠킨스를 CICD로 사용하는 것은 거의 하나의 표준이 되었다.지속적인 통합은 사용자의 측면에서 볼 때 매우 중요한 지표가 있다. 신속한 피드백을 주목한다. 예를 들어 사용자가 코드를 제출한 후에 개발하거나 테스트를 하면 코드의 질을 신속하게 알고 테스트 환경에 배치할 수 있다.
    어떻게 해야만 Jenkins에서 사용자의 피드백 속도를 높일 수 있습니까?사실 구축 속도는 어느 정도 캐시에 따라 달라집니다.
  • 코드는 Maven/Gradle Cache
  • 와 같은 캐시에 의존합니다.
  • Workspace 작업 디렉토리
  • Jenkins 작업을 만들고 한 번 실행하면 상기 캐시를 생성합니다. 만약에 상기 캐시를 사용할 수 없다면 이 캐시된 데이터를 슬레이브에서 다시 생성해야 한다는 것을 의미합니다. 이것은 매우 긴 시간 비용입니다.
    우리는 Jenkins가 Slave를 통해 규모의 구축 관리를 하고 더 많은 Salve를 추가함으로써 그 연산 능력을 확대하며 모든 구축은 알고리즘을 통해 Salve에 스케줄링되어 실행되는 것을 알고 있다.
    여기에서 알 수 있듯이, 만약 같은 작업의 여러 번 구축이 같은 슬레이브로 스케줄링될 수 있다면, 상술한 캐시를 다시 사용할 수 있다.우리가 얻고 싶은 똑똑한 Jenkins 개발자들도 Jenkins는 어떤 알고리즘을 통해 같은 Slave로 우선적으로 스케줄링할 수 있을까?답안이 제목과 같다.

    일관성 Hash


    만약 당신이 일치성 해시 알고리즘을 아직 이해하지 못한다면 이 글을 좀 읽어 보십시오. 비교적 통속적이고 알기 쉽게 쓰십시오. 5분 동안 일치성 해시 알고리즘을 이해하십시오.
    구체적인 알고리즘 응용을 이해하기 전에 두 가지 중요한 개념이 있다.
  • ExecutorChunk: 노드(Slave)에서 사용할 수 있는 Executors
  • 를 나타냅니다.
  • WorkChunk: 현재 구축이 같은 슬레이브에서 실행되는 모든sub-task
  • 를 나타냅니다.
    이 두 목록은 하나의 클래스에 유지됩니다: MappingWorksheet.그것의 임무는 모든 Work Chunk에서 Executor Chunk까지의 映射 관계를 유지하는 것이다. 즉, 어떤 Work Chunk가 그 Executor Chunk로 스케줄링되어 실행되어야 한다는 것이다.
    이 매핑 관계는 다른 확장된 LoadBalancer에서 일관성 Hash 알고리즘을 호출하여 생성됩니다.사용자 정의 스케줄링 알고리즘이 필요하다면, 자신의 LoadBalancer를 확장해서 실현할 수도 있다.
    이 Hash 알고리즘 자체의 응용으로 돌아가 두 단계로 나뉜다.
  • 일치성 Hash링 Hash링의 모든 노드는 하나의 ExecutorChunk를 대표하고 LoadBalancer는 모든 예비 ExecutorChunk(예를 들어 Label을 통해)을 이 링에 추가한다. 물론 더 좋은 산열성을 위해 같은 ExecutorChunk에 대해 여러 개의 Hash값을 생성하고 링의 여러 노드(가상 노드)에 대응한다.링의 노드는 사실Hash값에 따라 정렬된 그룹입니다. 노드의Hash값은 현재ExecutorChunk가 있는 슬레이브의 이름 + 번호로 생성된md5값입니다.
  • List<ExecutorChunk> chunks = ws.works(i).applicableExecutorChunks();
    Map<ExecutorChunk, Integer> toAdd = Maps.newHashMapWithExpectedSize(chunks.size());
    for (ExecutorChunk ec : chunks) {
       toAdd.put(ec, ec.size()*100);
    }
    hash.addAll(toAdd);
    
  • 링에서 대응하는 노드(Slave)를 찾아 일치성 Hash의hash링을 생성한 후 모든 Work Chunk에 대해 작업 이름(display Name)에 따라 Hash 전송을 생성하고 링에서 Hash 값보다 큰 모든 노드(즉 Executor Chunk)를 발견한다
  • private boolean assignGreedily(Mapping m, Task task, List<ConsistentHash<ExecutorChunk>> hashes, int i) {
        if (i==hashes.size())   return true;    // fully assigned
    
        String key;
        try {
            key = task.getAffinityKey();
        } catch (RuntimeException e) {
            LOGGER.log(Level.FINE, null, e);
            // Default implementation of Queue.Task.getAffinityKey, we assume it doesn't fail.
            key = task.getFullDisplayName();
        }
        key += i > 0 ? String.valueOf(i) : "";
    
        for (ExecutorChunk ec : hashes.get(i).list(key)) {
            // let's attempt this assignment
            m.assign(i,ec);
    
            if (m.isPartiallyValid() && assignGreedily(m,task,hashes,i+1))
                return true;    // successful greedily allocation
    
            // otherwise 'ec' wasn't a good fit for us. try next.
        }
    
        // every attempt failed
        m.assign(i,null);
        return false;
    }
    

    좋은 웹페이지 즐겨찾기