날짜 비워 두기: BazelCon 2023이 10월 24~25일에 Google 뮌헨에서 열립니다. 자세히 알아보기

멀티플렉스 작업자 (실험적 기능)

문제 신고 소스 보기

이 페이지에서는 멀티플렉스 작업자, 멀티플렉스 호환 규칙을 작성하는 방법, 특정 제한사항에 대한 해결 방법을 설명합니다.

멀티플렉스 작업자를 사용하면 Bazel이 단일 작업자 프로세스로 여러 요청을 처리할 수 있습니다. 다중 스레드 작업자의 경우 Bazel은 더 적은 리소스를 사용하여 동일하거나 더 나은 성능을 달성할 수 있습니다. 예를 들어 Bazel은 작업자당 하나의 작업자 프로세스를 사용하는 대신 4개의 다중 작업자가 동일한 작업자 프로세스와 통신하도록 하여 요청을 동시에 처리할 수 있습니다. 자바 및 Scala와 같은 언어의 경우 JVM 준비 시간과 JIT 컴파일 시간이 절약되며 일반적으로 동일한 유형의 모든 작업자 간에 하나의 공유 캐시를 사용할 수 있습니다.

개요

Bazel 서버와 작업자 프로세스 사이에는 두 가지 레이어가 있습니다. 프로세스를 동시에 실행할 수 있는 특정 연상 기호의 경우 Bazel은 작업자 풀에서 WorkerProxy를 가져옵니다. WorkerProxyrequest_id와 함께 순차적으로 작업자 프로세스로 요청을 전달하고 작업자 프로세스는 요청을 처리하고 WorkerMultiplexer에 응답을 보냅니다. WorkerMultiplexer는 응답을 수신하면 request_id를 파싱한 다음 응답을 올바른 WorkerProxy에 다시 전달합니다. 멀티플렉싱되지 않은 작업자와 마찬가지로 모든 통신은 표준 in/out을 통해 실행되지만 도구는 사용자에게 표시되는 출력에 stderr를 사용할 수 없습니다(아래 참고).

각 작업자에는 키가 있습니다. Bazel은 키의 해시 코드 (환경 변수, 실행 루트, 연상 기호로 구성됨)를 사용하여 사용할 WorkerMultiplexer를 결정합니다. WorkerProxy은 동일한 해시 코드가 있는 경우 동일한 WorkerMultiplexer와 통신합니다. 따라서 단일 Bazel 호출에서 환경 변수와 실행 루트가 동일하다면 각각의 고유 니모닉은 하나의 WorkerMultiplexer와 하나의 작업자 프로세스만 가질 수 있습니다. 일반 작업자와 WorkerProxy를 포함한 총 작업자 수는 여전히 --worker_max_instances에 의해 제한됩니다.

멀티플렉스 호환 규칙 작성

멀티플렉스 작업자의 이점을 활용하려면 규칙의 작업자 프로세스를 멀티스레드해야 합니다. Protobuf를 사용하면 스트림에서 여러 요청이 쌓이더라도 규칙 세트가 단일 요청을 파싱할 수 있습니다. 작업자 프로세스는 스트림의 요청을 파싱할 때마다 새 스레드에서 요청을 처리해야 합니다. 서로 다른 스레드는 동시에 스트림을 작성하고 스트림에 쓸 수 있으므로 작업자 프로세스는 응답이 원자적으로 작성되었는지 확인해야 합니다 (메시지가 겹치지 않음). 응답에는 처리 중인 요청의 request_id가 포함되어야 합니다.

멀티플렉스 출력 처리

멀티플렉스 작업자는 싱글플렉스 작업자보다 출력을 처리하는 데 더 신중해야 합니다. stderr에 전송된 모든 항목은 같은 유형의 모든 WorkerProxy 간에 공유되는 단일 로그 파일에 들어가며, 동시 요청 간에 무작위로 인터리브 처리됩니다. stdoutstderr로 리디렉션하는 것이 좋습니다. 하지만 이 출력을 WorkResponseoutput 필드에 수집하면 안 됩니다. 이 경우 사용자의 출력 화면이 손상될 수 있습니다. 도구에서 사용자 중심 출력을 stdout 또는 stderr로만 전송하는 경우 멀티플렉스 작업자를 사용 설정하기 전에 이 동작을 변경해야 합니다.

멀티플렉스 작업자 지원

멀티플렉스 작업자는 기본적으로 사용 설정되지 않습니다. 규칙 세트에서 supports-workers 태그가 일반 작업자를 사용 설정하는 것처럼 작업의 execution_requirementssupports-multiplex-workers 태그를 사용하여 멀티플렉스 작업자를 사용 설정할 수 있습니다. 일반 작업자를 사용하는 경우와 마찬가지로 작업자 수준은 규칙 세트 수준 (예: --strategy=[some_mnemonic]=worker) 또는 일반적으로 전략 수준 (예: --dynamic_local_strategy=worker,standalone)에서 지정해야 합니다. 추가 플래그는 필요하지 않으며 supports-multiplex-workerssupports-workers 둘 다인 경우 둘 다 우선 적용됩니다. --noexperimental_worker_multiplex를 전달하여 멀티플렉스 작업자를 전역적으로 사용 중지할 수 있습니다.

가능한 경우 멀티플렉스 작업자를 사용하여 메모리 압력을 줄이고 성능을 개선하는 것이 좋습니다. 그러나 멀티플렉스 작업자는 멀티플렉스 샌드박스를 구현하지 않는 한 현재 동적 실행과 호환되지 않습니다. 동적 실행으로 샌드박스 처리되지 않은 멀티플렉스 작업자를 실행하려고 시도하면 샌드박스 처리된 단일 플렉스 작업자가 자동으로 사용됩니다.

멀티플렉스 샌드박스

멀티플렉스 작업자는 작업자 구현에 명시적인 지원을 추가하여 샌드박스화할 수 있습니다. 싱글플렉스 작업자 샌드박스는 각 작업자 프로세스를 자체 샌드박스에서 실행하여 실행할 수 있지만 다중 작업자는 여러 동시 요청 간에 프로세스 작업 디렉터리를 공유합니다. 멀티플렉스 작업자의 샌드박스를 허용하려면 작업자가 작업 디렉터리에서 직접 이동하는 대신 각 요청에 지정된 하위 디렉터리에 대한 읽기 및 쓰기를 지원해야 합니다.

멀티플렉스 샌드박스를 지원하려면 작업자는 WorkRequestsandbox_dir 필드를 사용하고 이 필드를 모든 파일 읽기 및 쓰기의 프리픽스로 사용해야 합니다. argumentsinputs 필드는 샌드박스 처리되지 않은 요청에서 변경되지 않지만 실제 입력은 sandbox_dir를 기준으로 합니다. 작업자는 수정된 경로에서 읽기 위해 argumentsinputs에 있는 파일 경로를 변환하고 sandbox_dir를 기준으로 모든 출력도 작성해야 합니다. 여기에는 '.'와 같은 경로 및 인수에 지정된 파일 (예: "argfile" 인수)에서 찾은 경로가 포함됩니다.

작업자가 멀티플렉스 샌드박스를 지원하면 규칙 세트에서 supports-multiplex-sandboxing를 작업의 execution_requirements에 추가하여 이 지원을 선언할 수 있습니다. --experimental_worker_multiplex_sandboxing 플래그가 전달되거나 작업자가 동적 실행과 함께 사용되는 경우 Bazel은 멀티플렉스 샌드박스를 사용합니다.

샌드박스 처리된 멀티플렉스 작업자의 작업자 파일은 작업자 프로세스의 작업 디렉터리를 기준으로 합니다. 따라서 파일이 작업자 실행과 입력으로 모두 사용되는 경우 플래그 파일 인수와 tools, executable, runfiles에 모두 입력으로 지정되어야 합니다.