Công việc nền tảng NodeJS

Phân phối công việc bị trì hoãn trong nodejs. Resque là một hệ thống công việc nền được hỗ trợ bởi Redis (phiên bản 2. 6. 0 trở lên bắt buộc). Nó bao gồm hàng đợi ưu tiên, plugin, khóa, công việc bị trì hoãn, v.v. Dự án này rất có ý kiến ​​nhưng tương thích với API với Resque và Sidekiq (hãy cẩn thận). Chúng tôi cũng triển khai một số plugin Resque phổ biến, bao gồm resque-scheduler và resque-retry

Tài liệu API đầy đủ cho gói này được tạo tự động từ

options = {
  looping: true,
  timeout: 5000,
  queues: "*",
  name: os.hostname() + ":" + process.pid,
};
4 thông qua nhánh typedoc và được xuất bản lên https. // nút-resque. anh hùng hành động. com/

Nhà máy Resque (Cách thức hoạt động)

Tổng quan

Resque là một hệ thống xử lý tác vụ dựa trên hàng đợi có thể được coi là một nhà máy kiểu "Kanban". Công nhân trong nhà máy này mỗi người chỉ có thể làm một Công việc tại một thời điểm. Họ lấy Công việc từ Hàng đợi và hoàn thành chúng (hoặc thất bại). Mỗi công việc có hai phần. hướng dẫn về cách hoàn thành công việc (hàm

options = {
  looping: true,
  timeout: 5000,
  queues: "*",
  name: os.hostname() + ":" + process.pid,
};
5) và bất kỳ thông tin đầu vào nào cần thiết để hoàn thành Công việc

hàng đợi

Trong ví dụ về nhà máy của chúng tôi, Hàng đợi tương tự như băng tải. Công việc được đặt trên dây đai (Hàng đợi) và được giữ theo thứ tự chờ Công nhân đến lấy chúng. Có ba loại hàng đợi. hàng đợi công việc thường xuyên, hàng đợi công việc bị trì hoãn và hàng đợi công việc thất bại. Hàng đợi công việc bị trì hoãn chứa các định nghĩa công việc dự định sẽ được thực hiện tại hoặc trong một thời gian xác định. Hàng đợi Công việc Thất bại là nơi Công nhân đặt bất kỳ Công việc nào bị lỗi trong quá trình thực hiện

công nhân

Công nhân của chúng tôi là trái tim của nhà máy. Mỗi Công nhân được chỉ định một hoặc nhiều Hàng đợi để kiểm tra công việc. Sau khi nhận một Công việc từ Hàng đợi, Công nhân cố gắng hoàn thành Công việc. Nếu thành công, họ quay lại để kiểm tra thêm công việc từ Hàng đợi. Tuy nhiên, nếu có lỗi, Công nhân sẽ ghi lại công việc và thông tin đầu vào của công việc đó trong Hàng đợi Công việc Không thành công trước khi quay lại để thực hiện thêm công việc

Người lập kế hoạch

Bộ lập lịch có thể được coi là một loại Công nhân chuyên biệt. Không giống như các Công nhân khác, Trình lập lịch biểu không thực thi bất kỳ Công việc nào, thay vào đó, nó quản lý Hàng đợi Công việc bị trì hoãn. Vì các định nghĩa Công việc được thêm vào Hàng đợi Công việc bị Trì hoãn, chúng phải chỉ định khi nào chúng có thể sẵn sàng để thực hiện. Bộ lập lịch liên tục kiểm tra xem liệu có bất kỳ Công việc bị trì hoãn nào đã sẵn sàng để thực thi hay không. Khi một Công việc bị trì hoãn sẵn sàng để thực thi, Trình lập lịch biểu sẽ đặt một phiên bản mới của Công việc đó vào Hàng đợi đã xác định của nó

Tài liệu API

Bạn có thể đọc tài liệu API cho Node Resque @ node-resque. anh hùng hành động. com. Chúng được tạo tự động từ nhánh chính thông qua TypeDoc

Ghi chú phiên bản

  • Phiên bản redis yêu cầu là >= 2. 6. 0 khi chúng tôi sử dụng tập lệnh lua để tạo các hoạt động nguyên tử tùy chỉnh
  • ‼️Phiên bản 6+ của Node Resque sử dụng TypeScript. Chúng tôi vẫn sẽ bao gồm mã được dịch mã JavaScript trong các bản phát hành NPM, nhưng chúng sẽ được tạo từ nguồn TypeScript. Chức năng giữa nút-resque v5 và v6 phải giống nhau
  • ‼️Phiên bản 5+ của Node Resque sử dụng async/await. Không có đường dẫn nâng cấp từ các phiên bản trước. Nút v8. 0. 0+ là bắt buộc

Cách sử dụng

Tôi học tốt nhất bằng các ví dụ

import { Worker, Plugins, Scheduler, Queue } from "node-resque";

async function boot() {
  // ////////////////////////
  // SET UP THE CONNECTION //
  // ////////////////////////

  const connectionDetails = {
    pkg: "ioredis",
    host: "127.0.0.1",
    password: null,
    port: 6379,
    database: 0,
    // namespace: 'resque',
    // looping: true,
    // options: {password: 'abc'},
  };

  // ///////////////////////////
  // DEFINE YOUR WORKER TASKS //
  // ///////////////////////////

  let jobsToComplete = 0;

  const jobs = {
    add: {
      plugins: [Plugins.JobLock],
      pluginOptions: {
        JobLock: { reEnqueue: true },
      },
      perform: async (a, b) => {
        await new Promise((resolve) => {
          setTimeout(resolve, 1000);
        });
        jobsToComplete--;
        tryShutdown();

        const answer = a + b;
        return answer;
      },
    },
    subtract: {
      perform: (a, b) => {
        jobsToComplete--;
        tryShutdown();

        const answer = a - b;
        return answer;
      },
    },
  };

  // just a helper for this demo
  async function tryShutdown() {
    if (jobsToComplete === 0) {
      await new Promise((resolve) => {
        setTimeout(resolve, 500);
      });
      await scheduler.end();
      await worker.end();
      process.exit();
    }
  }

  // /////////////////
  // START A WORKER //
  // /////////////////

  const worker = new Worker(
    { connection: connectionDetails, queues: ["math", "otherQueue"] },
    jobs
  );
  await worker.connect();
  worker.start();

  // ////////////////////
  // START A SCHEDULER //
  // ////////////////////

  const scheduler = new Scheduler({ connection: connectionDetails });
  await scheduler.connect();
  scheduler.start();

  // //////////////////////
  // REGISTER FOR EVENTS //
  // //////////////////////

  worker.on("start", () => {
    console.log("worker started");
  });
  worker.on("end", () => {
    console.log("worker ended");
  });
  worker.on("cleaning_worker", (worker, pid) => {
    console.log(`cleaning old worker ${worker}`);
  });
  worker.on("poll", (queue) => {
    console.log(`worker polling ${queue}`);
  });
  worker.on("ping", (time) => {
    console.log(`worker check in @ ${time}`);
  });
  worker.on("job", (queue, job) => {
    console.log(`working job ${queue} ${JSON.stringify(job)}`);
  });
  worker.on("reEnqueue", (queue, job, plugin) => {
    console.log(`reEnqueue job (${plugin}) ${queue} ${JSON.stringify(job)}`);
  });
  worker.on("success", (queue, job, result, duration) => {
    console.log(
      `job success ${queue} ${JSON.stringify(job)} >> ${result} (${duration}ms)`
    );
  });
  worker.on("failure", (queue, job, failure, duration) => {
    console.log(
      `job failure ${queue} ${JSON.stringify(
        job
      )} >> ${failure} (${duration}ms)`
    );
  });
  worker.on("error", (error, queue, job) => {
    console.log(`error ${queue} ${JSON.stringify(job)}  >> ${error}`);
  });
  worker.on("pause", () => {
    console.log("worker paused");
  });

  scheduler.on("start", () => {
    console.log("scheduler started");
  });
  scheduler.on("end", () => {
    console.log("scheduler ended");
  });
  scheduler.on("poll", () => {
    console.log("scheduler polling");
  });
  scheduler.on("leader", () => {
    console.log("scheduler became leader");
  });
  scheduler.on("error", (error) => {
    console.log(`scheduler error >> ${error}`);
  });
  scheduler.on("cleanStuckWorker", (workerName, errorPayload, delta) => {
    console.log(
      `failing ${workerName} (stuck for ${delta}s) and failing job ${errorPayload}`
    );
  });
  scheduler.on("workingTimestamp", (timestamp) => {
    console.log(`scheduler working timestamp ${timestamp}`);
  });
  scheduler.on("transferredJob", (timestamp, job) => {
    console.log(`scheduler enquing job ${timestamp} >> ${JSON.stringify(job)}`);
  });

  // //////////////////////
  // CONNECT TO A QUEUE //
  // //////////////////////

  const queue = new Queue({ connection: connectionDetails }, jobs);
  queue.on("error", function (error) {
    console.log(error);
  });
  await queue.connect();
  await queue.enqueue("math", "add", [1, 2]);
  await queue.enqueue("math", "add", [1, 2]);
  await queue.enqueue("math", "add", [2, 3]);
  await queue.enqueueIn(3000, "math", "subtract", [2, 1]);
  jobsToComplete = 4;
}

boot();

// and when you are done
// await queue.end()
// await scheduler.end()
// await worker.end()

Giao diện yêu cầu nút. Hàng đợi, Công nhân và Trình lập lịch biểu

Có 3 lớp học chính trong

options = {
  looping: true,
  timeout: 5000,
  queues: "*",
  name: os.hostname() + ":" + process.pid,
};
6. Hàng đợi, Công nhân và Trình lập lịch biểu

  • Xếp hàng. Đây là giao diện mà chương trình của bạn sử dụng để tương tác với hàng đợi của resque - để chèn công việc, kiểm tra hiệu suất của mọi thứ và thường quản lý các công việc nền của bạn
  • Công nhân. Giao diện này là cách các công việc được xử lý. Công nhân được bắt đầu và sau đó họ kiểm tra các công việc được sắp xếp vào các hàng đợi khác nhau và hoàn thành chúng. Nếu có lỗi, họ sẽ ghi vào hàng đợi
    options = {
      looping: true,
      timeout: 5000,
      queues: "*",
      name: os.hostname() + ":" + process.pid,
    };
    7
    • Có một lớp đặc biệt gọi là
      options = {
        looping: true,
        timeout: 5000,
        queues: "*",
        name: os.hostname() + ":" + process.pid,
      };
      8 trong Node Resque sẽ chạy nhiều công nhân cùng một lúc cho bạn (xem bên dưới)
  • Người lập kế hoạch. Bộ lập lịch có thể được coi là điều phối viên cho Node Resque. Nó chủ yếu chịu trách nhiệm kiểm tra khi các công việc được yêu cầu chạy sau (với
    options = {
      looping: true,
      timeout: 5000,
      queues: "*",
      name: os.hostname() + ":" + process.pid,
    };
    9 hoặc
    const connectionDetails = {
      pkg: "ioredis",
      host: "127.0.0.1",
      password: "",
      port: 6379,
      database: 0,
      namespace: "resque", // Also allow array of strings
    };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    // await worker.end()
    0) nên được xử lý, nhưng nó thực hiện một số công việc khác như kiểm tra nhân viên 'bị mắc kẹt' và dọn dẹp cụm chung
    • Bạn có thể (và nên) chạy nhiều phiên bản của lớp trình lập lịch trình cùng một lúc, nhưng chỉ một phiên bản sẽ được chọn làm 'lãnh đạo' và thực sự hoạt động
    • 'Độ trễ' được xác định trên một công việc đã lên lịch không chỉ định khi nào công việc sẽ được chạy, mà là khi nào công việc sẽ được xử lý. Điều này có nghĩa là
      options = {
        looping: true,
        timeout: 5000,
        queues: "*",
        name: os.hostname() + ":" + process.pid,
      };
      6 không thể đảm bảo khi nào một công việc sẽ được thực thi, chỉ khi nào công việc đó sẽ sẵn sàng để thực thi (được thêm vào Hàng đợi)

Tùy chọn cấu hình

  • const connectionDetails = {
      pkg: "ioredis",
      host: "127.0.0.1",
      password: "",
      port: 6379,
      database: 0,
      namespace: "resque", // Also allow array of strings
    };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    // await worker.end()
    2 chỉ yêu cầu đặt biến "queue". Nếu bạn định chạy với móc
    const connectionDetails = {
      pkg: "ioredis",
      host: "127.0.0.1",
      password: "",
      port: 6379,
      database: 0,
      namespace: "resque", // Also allow array of strings
    };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    // await worker.end()
    3 hoặc
    const connectionDetails = {
      pkg: "ioredis",
      host: "127.0.0.1",
      password: "",
      port: 6379,
      database: 0,
      namespace: "resque", // Also allow array of strings
    };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    // await worker.end()
    4, bạn cũng nên truyền đối tượng
    const connectionDetails = {
      pkg: "ioredis",
      host: "127.0.0.1",
      password: "",
      port: 6379,
      database: 0,
      namespace: "resque", // Also allow array of strings
    };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    // await worker.end()
    5 cho nó
  • const connectionDetails = {
      pkg: "ioredis",
      host: "127.0.0.1",
      password: "",
      port: 6379,
      database: 0,
      namespace: "resque", // Also allow array of strings
    };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    // await worker.end()
    6 có một số tùy chọn bổ sung

options = {
  looping: true,
  timeout: 5000,
  queues: "*",
  name: os.hostname() + ":" + process.pid,
};

Lưu ý rằng khi sử dụng hàng đợi

const connectionDetails = {
  pkg: "ioredis",
  host: "127.0.0.1",
  password: "",
  port: 6379,
  database: 0,
  namespace: "resque", // Also allow array of strings
};

const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math" },
  jobs
);

worker.on("error", (error) => {
  // handler errors
});

await worker.connect();
worker.start();

// and when you are done
// await worker.end()
7

  • có tác động hiệu suất nhỏ để kiểm tra hàng đợi
  • hàng đợi được xử lý theo thứ tự không xác định

Băm cấu hình được chuyển đến

const connectionDetails = {
  pkg: "ioredis",
  host: "127.0.0.1",
  password: "",
  port: 6379,
  database: 0,
  namespace: "resque", // Also allow array of strings
};

const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math" },
  jobs
);

worker.on("error", (error) => {
  // handler errors
});

await worker.connect();
worker.start();

// and when you are done
// await worker.end()
8,
const connectionDetails = {
  pkg: "ioredis",
  host: "127.0.0.1",
  password: "",
  port: 6379,
  database: 0,
  namespace: "resque", // Also allow array of strings
};

const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math" },
  jobs
);

worker.on("error", (error) => {
  // handler errors
});

await worker.connect();
worker.start();

// and when you are done
// await worker.end()
9 hoặc
// assume you already initialized redis client before
// the "redis" key can be IORedis.Redis or IORedis.Cluster instance

const redisClient = new Redis();
const connectionDetails = { redis: redisClient };

// or

const redisCluster = new Cluster();
const connectionDetails = { redis: redisCluster };

const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math" },
  jobs
);

worker.on("error", (error) => {
  // handler errors
});

await worker.connect();
worker.start();

// and when you are done
await worker.end();
0 cũng có thể có tùy chọn
// assume you already initialized redis client before
// the "redis" key can be IORedis.Redis or IORedis.Cluster instance

const redisClient = new Redis();
const connectionDetails = { redis: redisClient };

// or

const redisCluster = new Cluster();
const connectionDetails = { redis: redisCluster };

const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math" },
  jobs
);

worker.on("error", (error) => {
  // handler errors
});

await worker.connect();
worker.start();

// and when you are done
await worker.end();
1

const connectionDetails = {
  pkg: "ioredis",
  host: "127.0.0.1",
  password: "",
  port: 6379,
  database: 0,
  namespace: "resque", // Also allow array of strings
};

const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math" },
  jobs
);

worker.on("error", (error) => {
  // handler errors
});

await worker.connect();
worker.start();

// and when you are done
// await worker.end()

Bạn cũng có thể chuyển trực tiếp ứng dụng khách redis

// assume you already initialized redis client before
// the "redis" key can be IORedis.Redis or IORedis.Cluster instance

const redisClient = new Redis();
const connectionDetails = { redis: redisClient };

// or

const redisCluster = new Cluster();
const connectionDetails = { redis: redisCluster };

const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math" },
  jobs
);

worker.on("error", (error) => {
  // handler errors
});

await worker.connect();
worker.start();

// and when you are done
await worker.end();

ghi chú

  • Hãy nhớ gọi cho
    // assume you already initialized redis client before
    // the "redis" key can be IORedis.Redis or IORedis.Cluster instance
    
    const redisClient = new Redis();
    const connectionDetails = { redis: redisClient };
    
    // or
    
    const redisCluster = new Cluster();
    const connectionDetails = { redis: redisCluster };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    await worker.end();
    2,
    // assume you already initialized redis client before
    // the "redis" key can be IORedis.Redis or IORedis.Cluster instance
    
    const redisClient = new Redis();
    const connectionDetails = { redis: redisClient };
    
    // or
    
    const redisCluster = new Cluster();
    const connectionDetails = { redis: redisCluster };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    await worker.end();
    3 và
    // assume you already initialized redis client before
    // the "redis" key can be IORedis.Redis or IORedis.Cluster instance
    
    const redisClient = new Redis();
    const connectionDetails = { redis: redisClient };
    
    // or
    
    const redisCluster = new Cluster();
    const connectionDetails = { redis: redisCluster };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    await worker.end();
    4 trước khi đóng đơn đăng ký của bạn nếu bạn muốn xóa chính xác tình trạng công nhân của mình khỏi yêu cầu
  • Khi kết thúc ứng dụng của bạn, hãy đảm bảo cho phép nhân viên của bạn có thời gian để hoàn thành những gì họ đang làm
  • Dự án này triển khai phần "trình lập lịch biểu" của trình lập lịch trình cứu hộ (trình nền có thể đưa các công việc bị trì hoãn vào hàng đợi vào hàng đợi công việc khi đến lúc), nhưng không phải là proxy của trình lập lịch biểu CRON. Để tìm hiểu thêm về cách sử dụng bộ lập lịch giống CRON, hãy đọc phần của tài liệu này
  • "Không gian tên" là một chuỗi được thêm vào phía trước các khóa của bạn trong redis. Thông thường, nó là "resque". Điều này hữu ích nếu bạn muốn lưu trữ nhiều hàng đợi công việc trong một cơ sở dữ liệu redis. Không sử dụng
    // assume you already initialized redis client before
    // the "redis" key can be IORedis.Redis or IORedis.Cluster instance
    
    const redisClient = new Redis();
    const connectionDetails = { redis: redisClient };
    
    // or
    
    const redisCluster = new Cluster();
    const connectionDetails = { redis: redisCluster };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    await worker.end();
    5 nếu bạn đang sử dụng trình điều khiển redis
    // assume you already initialized redis client before
    // the "redis" key can be IORedis.Redis or IORedis.Cluster instance
    
    const redisClient = new Redis();
    const connectionDetails = { redis: redisClient };
    
    // or
    
    const redisCluster = new Cluster();
    const connectionDetails = { redis: redisCluster };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    await worker.end();
    6 (mặc định) trong dự án này (xem #245 để biết thêm thông tin. )
  • Nếu bạn đang sử dụng bất kỳ phần bổ trợ nào có tác dụng
    const connectionDetails = {
      pkg: "ioredis",
      host: "127.0.0.1",
      password: "",
      port: 6379,
      database: 0,
      namespace: "resque", // Also allow array of strings
    };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    // await worker.end()
    3 hoặc
    const connectionDetails = {
      pkg: "ioredis",
      host: "127.0.0.1",
      password: "",
      port: 6379,
      database: 0,
      namespace: "resque", // Also allow array of strings
    };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    // await worker.end()
    4, hãy đảm bảo chuyển đối số
    const connectionDetails = {
      pkg: "ioredis",
      host: "127.0.0.1",
      password: "",
      port: 6379,
      database: 0,
      namespace: "resque", // Also allow array of strings
    };
    
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math" },
      jobs
    );
    
    worker.on("error", (error) => {
      // handler errors
    });
    
    await worker.connect();
    worker.start();
    
    // and when you are done
    // await worker.end()
    5 cho phương thức khởi tạo
    const name = os.hostname() + ":" + process.pid + "+" + counter;
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math", name: name },
      jobs
    );
    0
  • Nếu một công việc không thành công, nó sẽ được thêm vào hàng đợi
    const name = os.hostname() + ":" + process.pid + "+" + counter;
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math", name: name },
      jobs
    );
    1 đặc biệt. Sau đó, bạn có thể kiểm tra các công việc này, viết plugin để quản lý chúng, chuyển chúng trở lại hàng đợi thông thường, v.v. Hành vi thất bại theo mặc định là chỉ vào hàng đợi
    const name = os.hostname() + ":" + process.pid + "+" + counter;
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math", name: name },
      jobs
    );
    1, nhưng có nhiều tùy chọn. Hãy xem những ví dụ này từ hệ sinh thái ruby ​​để lấy cảm hứng
    • https. //github. com/lantins/resque-thử lại
    • https. //github. com/resque/resque/wiki/Failure-Backends
  • Nếu bạn dự định chạy nhiều hơn một công nhân trên mỗi quy trình nodejs, hãy đảm bảo đặt tên cho chúng một cái gì đó khác biệt. Tên phải theo mẫu
    const name = os.hostname() + ":" + process.pid + "+" + counter;
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math", name: name },
      jobs
    );
    3. Ví dụ
  • Đối với plugin Thử lại, một thông báo thành công sẽ được phát ra từ nhân viên trong mỗi lần thử (ngay cả khi công việc không thành công) ngoại trừ lần thử lại cuối cùng. Thay vào đó, lần thử lại cuối cùng sẽ phát ra thông báo lỗi

Nếu bạn muốn tìm hiểu thêm về cách chạy Node-Resque với docker, vui lòng xem các ví dụ tại đây. https. //github. com/actionhero/node-resque/tree/master/examples/docker

const name = os.hostname() + ":" + process.pid + "+" + counter;
const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math", name: name },
  jobs
);

Worker#performInline

KHÔNG SỬ DỤNG NÀY TRONG SẢN XUẤT. Trong các bài kiểm tra hoặc trường hợp đặc biệt, bạn có thể muốn xử lý/xử lý một công việc trực tuyến. Để làm như vậy, bạn có thể sử dụng

const name = os.hostname() + ":" + process.pid + "+" + counter;
const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math", name: name },
  jobs
);
4. Nếu bạn đang có kế hoạch chạy một công việc thông qua #performInline, thì cũng không nên bắt đầu công việc này cũng như không nên sử dụng các trình phát sự kiện để giám sát công việc này. Phương pháp này cũng sẽ không ghi vào redis, bao gồm lỗi ghi nhật ký, sửa đổi số liệu thống kê của resque, v.v.

Quản lý hàng đợi

const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
await queue.connect();

Có thể tìm thấy tài liệu API cho các phương thức chính mà bạn sẽ sử dụng để sắp xếp các công việc cần thực hiện tại @ node-resque. anh hùng hành động. com

Quản lý công việc thất bại

Đôi khi, công việc/công nhân của bạn có thể thất bại. Công nhân yêu cầu sẽ chuyển các công việc thất bại sang hàng đợi

const name = os.hostname() + ":" + process.pid + "+" + counter;
const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math", name: name },
  jobs
);
1 đặc biệt sẽ lưu trữ các đối số ban đầu của công việc của bạn, dấu vết ngăn xếp thất bại và siêu dữ liệu bổ sung

Công việc nền tảng NodeJS

Bạn có thể làm việc với những công việc thất bại này bằng các phương pháp sau

const name = os.hostname() + ":" + process.pid + "+" + counter;
const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math", name: name },
  jobs
);
6

  • const name = os.hostname() + ":" + process.pid + "+" + counter;
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math", name: name },
      jobs
    );
    7 là số lượng công việc trong hàng đợi không thành công

const name = os.hostname() + ":" + process.pid + "+" + counter;
const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math", name: name },
  jobs
);
8

  • const name = os.hostname() + ":" + process.pid + "+" + counter;
    const worker = new NodeResque.Worker(
      { connection: connectionDetails, queues: "math", name: name },
      jobs
    );
    9 là một mảng liệt kê dữ liệu của các công việc thất bại. Mỗi yếu tố trông giống như.
    const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
    await queue.connect();
    0
  • Để truy xuất tất cả các công việc không thành công, hãy sử dụng đối số.
    const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
    await queue.connect();
    1

thất bại trong công việc

Chúng tôi sử dụng mẫu thử/bắt để phát hiện lỗi trong công việc của bạn. Nếu bất kỳ công việc nào đưa ra một ngoại lệ chưa được phát hiện, nó sẽ bị bắt và trọng tải của công việc được chuyển đến hàng đợi lỗi để kiểm tra. Không sử dụng tên miền, hoặc bất kỳ phương pháp nào khác để "bắt" sự cố quy trình

Tải trọng lỗi trông giống như

{ worker: 'busted-worker-3',
  queue: 'busted-queue',
  payload: { class: 'busted_job', queue: 'busted-queue', args: [ 1, 2, 3 ] },
  exception: 'ERROR_NAME',
  error: 'I broke',
  failed_at: 'Sun Apr 26 2015 14:00:44 GMT+0100 (BST)' }

const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
await queue.connect();
2

  • đầu vào
    const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
    await queue.connect();
    3 là một đối tượng nút mở rộng đại diện cho công việc không thành công, được truy xuất qua
    const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
    await queue.connect();
    4

const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
await queue.connect();
5

  • đầu vào
    const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
    await queue.connect();
    3 là một đối tượng nút mở rộng đại diện cho công việc không thành công, được truy xuất qua
    const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
    await queue.connect();
    4
  • phương pháp này sẽ ngay lập tức đưa một công việc không thành công trở lại hàng đợi ban đầu của nó và xóa mục nhập không thành công cho công việc đó

Quản lý công nhân thất bại

tự động

Theo mặc định, bộ lập lịch sẽ kiểm tra các worker chưa ping redis trong 60 phút. Nếu điều này xảy ra, chúng tôi sẽ cho rằng quá trình bị lỗi và xóa nó khỏi redis. Nếu nhân viên này đang thực hiện một công việc, chúng tôi sẽ xếp công việc đó vào hàng đợi thất bại để kiểm tra sau. Mỗi worker có một bộ đếm thời gian chạy trong đó nó cập nhật một khóa trong redis mỗi

const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
await queue.connect();
8 (mặc định. 5 giây). Nếu công việc của bạn chậm, nhưng không đồng bộ, sẽ không có vấn đề gì. Tuy nhiên, nếu công việc của bạn tiêu tốn 100% CPU của quy trình, bộ đếm thời gian này có thể không kích hoạt

Để sửa đổi kiểm tra 60 phút, hãy thay đổi

const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
await queue.connect();
9 khi định cấu hình bộ lập lịch của bạn, tức là

const scheduler = new NodeResque.Scheduler({
  stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
  connection: connectionDetails
})

Đặt

{ worker: 'busted-worker-3',
  queue: 'busted-queue',
  payload: { class: 'busted_job', queue: 'busted-queue', args: [ 1, 2, 3 ] },
  exception: 'ERROR_NAME',
  error: 'I broke',
  failed_at: 'Sun Apr 26 2015 14:00:44 GMT+0100 (BST)' }
0 của trình lập lịch trình của bạn để tắt hành vi này

const scheduler = new NodeResque.Scheduler({
  stuckWorkerTimeout: false // will not fail jobs which haven't pinged redis
  connection: connectionDetails
})

thủ công

Đôi khi một công nhân gặp sự cố là một cách nghiêm trọng và không có thời gian/cơ hội để thông báo cho redis rằng họ đang rời khỏi nhóm (điều này xảy ra mọi lúc đối với các nhà cung cấp PAAS như Heroku). Khi điều này xảy ra, bạn không chỉ cần trích xuất công việc từ trạng thái "đang làm việc" của nhân viên zombie hiện tại mà còn phải xóa nhân viên bị mắc kẹt. Để hỗ trợ bạn trong những trường hợp khó khăn này, có sẵn

{ worker: 'busted-worker-3',
  queue: 'busted-queue',
  payload: { class: 'busted_job', queue: 'busted-queue', args: [ 1, 2, 3 ] },
  exception: 'ERROR_NAME',
  error: 'I broke',
  failed_at: 'Sun Apr 26 2015 14:00:44 GMT+0100 (BST)' }
1

Vì không có 'nhịp tim' trong resque nên ứng dụng không thể biết được công nhân đã làm việc lâu hay đã chết. Bạn được yêu cầu cung cấp "tuổi" cho thời gian một công nhân đã "làm việc" và tất cả những người lớn hơn độ tuổi đó sẽ bị xóa và công việc họ đang làm được chuyển sang hàng đợi lỗi (khi đó bạn có thể sử dụng

{ worker: 'busted-worker-3',
  queue: 'busted-queue',
  payload: { class: 'busted_job', queue: 'busted-queue', args: [ 1, 2, 3 ] },
  exception: 'ERROR_NAME',
  error: 'I broke',
  failed_at: 'Sun Apr 26 2015 14:00:44 GMT+0100 (BST)' }
2

Nếu bạn biết tên của một worker cần được xóa, bạn cũng có thể gọi trực tiếp

{ worker: 'busted-worker-3',
  queue: 'busted-queue',
  payload: { class: 'busted_job', queue: 'busted-queue', args: [ 1, 2, 3 ] },
  exception: 'ERROR_NAME',
  error: 'I broke',
  failed_at: 'Sun Apr 26 2015 14:00:44 GMT+0100 (BST)' }
3 và điều đó cũng sẽ xóa worker đó và chuyển bất kỳ công việc nào mà nó đang thực hiện vào hàng đợi lỗi. Phương pháp này sẽ vẫn tiếp tục đối với các công nhân chỉ làm lại một phần, cho thấy lỗi kết nối trước đó. Trong trường hợp này, công việc mà người lao động đang làm bị mất không thể phục hồi được

lịch trình công việc

Bạn có thể muốn sử dụng node-resque để lên lịch công việc mỗi phút/giờ/ngày, giống như hệ thống CRON phân tán. Có một số gói nút tuyệt vời để giúp bạn với điều này, như lịch trình nút và nút-cron. Node-resque giúp bạn có thể sử dụng gói bạn chọn để lên lịch công việc với

Giả sử bạn đang chạy node-resque trên nhiều máy, bạn sẽ cần đảm bảo rằng chỉ một trong số các quy trình của bạn thực sự lên lịch cho các công việc. Để giúp bạn làm điều này, bạn có thể kiểm tra quy trình lập lịch biểu nào hiện đang đóng vai trò là người dẫn đầu và chỉ gắn cờ cho quy trình lập lịch trình chính để chạy lịch trình. Một ví dụ đầy đủ có thể được tìm thấy tại /examples/scheduledJobs. ts, nhưng phần có liên quan là

const NodeResque = require("node-resque");
const schedule = require("node-schedule");
const queue = new NodeResque.Queue({ connection: connectionDetails }, jobs);
const scheduler = new NodeResque.Scheduler({ connection: connectionDetails });
await scheduler.connect();
scheduler.start();

schedule.scheduleJob("10,20,30,40,50 * * * * *", async () => {
  // do this job every 10 seconds, CRON style
  // we want to ensure that only one instance of this job is scheduled in our environment at once,
  // no matter how many schedulers we have running
  if (scheduler.leader) {
    console.log(">>> enqueuing a job");
    await queue.enqueue("time", "ticktock", new Date().toString());
  }
});

bổ sung

Cũng giống như resque của ruby, bạn có thể viết worker plugin. Họ trông như thế này. 4 cái móc bạn có là

const connectionDetails = {
  pkg: "ioredis",
  host: "127.0.0.1",
  password: "",
  port: 6379,
  database: 0,
  namespace: "resque", // Also allow array of strings
};

const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math" },
  jobs
);

worker.on("error", (error) => {
  // handler errors
});

await worker.connect();
worker.start();

// and when you are done
// await worker.end()
3,
const connectionDetails = {
  pkg: "ioredis",
  host: "127.0.0.1",
  password: "",
  port: 6379,
  database: 0,
  namespace: "resque", // Also allow array of strings
};

const worker = new NodeResque.Worker(
  { connection: connectionDetails, queues: "math" },
  jobs
);

worker.on("error", (error) => {
  // handler errors
});

await worker.connect();
worker.start();

// and when you are done
// await worker.end()
4,
{ worker: 'busted-worker-3',
  queue: 'busted-queue',
  payload: { class: 'busted_job', queue: 'busted-queue', args: [ 1, 2, 3 ] },
  exception: 'ERROR_NAME',
  error: 'I broke',
  failed_at: 'Sun Apr 26 2015 14:00:44 GMT+0100 (BST)' }
6 và
{ worker: 'busted-worker-3',
  queue: 'busted-queue',
  payload: { class: 'busted_job', queue: 'busted-queue', args: [ 1, 2, 3 ] },
  exception: 'ERROR_NAME',
  error: 'I broke',
  failed_at: 'Sun Apr 26 2015 14:00:44 GMT+0100 (BST)' }
7. Các plugin là
{ worker: 'busted-worker-3',
  queue: 'busted-queue',
  payload: { class: 'busted_job', queue: 'busted-queue', args: [ 1, 2, 3 ] },
  exception: 'ERROR_NAME',
  error: 'I broke',
  failed_at: 'Sun Apr 26 2015 14:00:44 GMT+0100 (BST)' }
8 mở rộng
{ worker: 'busted-worker-3',
  queue: 'busted-queue',
  payload: { class: 'busted_job', queue: 'busted-queue', args: [ 1, 2, 3 ] },
  exception: 'ERROR_NAME',
  error: 'I broke',
  failed_at: 'Sun Apr 26 2015 14:00:44 GMT+0100 (BST)' }
9

options = {
  looping: true,
  timeout: 5000,
  queues: "*",
  name: os.hostname() + ":" + process.pid,
};
0

Và sau đó plugin của bạn có thể được gọi trong một công việc như thế này

options = {
  looping: true,
  timeout: 5000,
  queues: "*",
  name: os.hostname() + ":" + process.pid,
};
1

ghi chú

  • Bạn cần trả lại
    const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
      connection: connectionDetails
    })
    0 hoặc
    const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
      connection: connectionDetails
    })
    1 trên các móc trước.
    const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
      connection: connectionDetails
    })
    0 chỉ ra rằng hành động nên tiếp tục và
    const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
      connection: connectionDetails
    })
    1 ngăn chặn hành động đó. Đây được gọi là
    const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
      connection: connectionDetails
    })
    4
  • Nếu bạn đang viết một plugin để xử lý các lỗi có thể xảy ra trong quá trình resque của mình, bạn có thể kiểm tra và sửa đổi
    const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
      connection: connectionDetails
    })
    5 trong plugin của mình. Nếu
    const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
      connection: connectionDetails
    })
    5 là null, sẽ không có lỗi nào được ghi vào hàng đợi lỗi resque
  • Có một vài plugin đi kèm, tất cả đều nằm trong thư mục
    const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
      connection: connectionDetails
    })
    7. Bạn có thể viết của riêng bạn và bao gồm nó như thế này

options = {
  looping: true,
  timeout: 5000,
  queues: "*",
  name: os.hostname() + ":" + process.pid,
};
2

Các plugin được bao gồm trong gói này là

  • const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
      connection: connectionDetails
    })
    8
    • Nếu một công việc có cùng tên, hàng đợi và đối số đã có trong (các) hàng đợi bị trì hoãn, đừng đưa nó vào hàng đợi một lần nữa
  • const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
      connection: connectionDetails
    })
    9
    • Nếu một công việc có cùng tên, hàng đợi và đối số đang chạy, hãy đưa công việc này trở lại hàng đợi và thử lại sau
  • const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: false // will not fail jobs which haven't pinged redis
      connection: connectionDetails
    })
    0
    • Nếu một công việc có cùng tên, hàng đợi và đối số đã có trong hàng đợi, đừng đưa nó vào hàng đợi một lần nữa
  • const scheduler = new NodeResque.Scheduler({
      stuckWorkerTimeout: false // will not fail jobs which haven't pinged redis
      connection: connectionDetails
    })
    1
    • Nếu một công việc không thành công, hãy thử lại N lần trước khi đặt nó vào hàng đợi thất bại

nhiều công nhân

options = {
  looping: true,
  timeout: 5000,
  queues: "*",
  name: os.hostname() + ":" + process.pid,
};
6 cung cấp một trình bao bọc xung quanh lớp
const scheduler = new NodeResque.Scheduler({
  stuckWorkerTimeout: false // will not fail jobs which haven't pinged redis
  connection: connectionDetails
})
3 sẽ tự động điều chỉnh số lượng công nhân yêu cầu. Điều này sẽ xử lý nhiều công việc cùng một lúc miễn là có CPU nhàn rỗi trong vòng lặp sự kiện. Ví dụ: nếu bạn có một công việc chậm gửi email qua SMTP (với chi phí thấp), chúng tôi có thể xử lý nhiều công việc cùng một lúc, nhưng nếu bạn có một hoạt động nặng về toán học, chúng tôi sẽ xử lý 1.
const scheduler = new NodeResque.Scheduler({
  stuckWorkerTimeout: false // will not fail jobs which haven't pinged redis
  connection: connectionDetails
})
4 xử lý việc này bằng cách sinh ra ngày càng nhiều công nhân có yêu cầu nút và quản lý nhóm

Nút js hoạt động ở chế độ nền như thế nào?

Nút. js duy trì một nhóm công nhân. Các hoạt động chạy trong thời gian dài được chuyển sang nhóm công nhân này và nhóm sự kiện chỉ xử lý phản hồi từ nhóm công nhân này khi hoàn thành nhiệm vụ . Nhóm công nhân làm việc với hệ điều hành để thực hiện các công việc nặng nhọc và quản lý lập lịch các nhiệm vụ.

Tôi có thể kiếm một công việc với Nodejs không?

Triển vọng công việc và lĩnh vực ứng dụng cho sự nghiệp trong Node. js. Việc làm của nhà phát triển phần mềm luôn có nhu cầu . Phát triển front-end, phát triển UX/UI, quản lý máy chủ cũng như phát triển back-end, tất cả các lĩnh vực phụ này đều có nhu cầu về lực lượng lao động có trình độ và kỹ năng tốt.

Nút JS có chạy ở chế độ nền không?

Chạy nút trong nền - Sử dụng PM2 . Trình quản lý quy trình này có bộ cân bằng tải tích hợp cho phép ứng dụng nút js tồn tại mãi mãi mà không có thời gian chết ngay cả khi máy chủ khởi động lại. Để cài đặt PM2 trên toàn cầu, hãy chạy lệnh npm install pm2 -g trong một thiết bị đầu cuối. You can run PM2 on all Linux, Windows & macOS. This process manager has a built-in load balancer which allow the node js app keep alive forever without downtime even if the server restart. To install PM2 globally run the command npm install pm2 -g in a terminal.

Công việc nền có sử dụng hàng đợi không?

Các công việc nền không phải lúc nào cũng được máy chủ ứng dụng xếp hàng . Một công nhân đang xử lý một công việc cũng có thể xếp hàng một công việc khác. Trong khi họ xếp hàng công việc dựa trên các sự kiện như tương tác của người dùng hoặc một số dữ liệu bị thay đổi, bộ lập lịch có thể xếp hàng công việc dựa trên thời gian (ví dụ: để sao lưu hàng ngày).