Как генерировать изображения веб-страниц в высокопроизводительной среде? - PullRequest
0 голосов
/ 20 февраля 2019

Я пытаюсь создать изображения веб-страниц за секунду в серверной среде.Запросы могут поступать параллельно, в то же время из Интернета.Для этого я использую библиотеку Puppeteer-Sharp , которая работает довольно хорошо.С другой стороны, он использует Chromium для загрузки страницы, а затем снимает скриншот.

Проблема в том, что для начала требуется некоторое время.Например, обратите внимание на время (с моего компьютера) из примера кода readme.md:

var options = new new LaunchOptions {Headless = true, ExecutablePath = @"c:\foo\chrome.exe"};
var browser = await Puppeteer.LaunchAsync(options).Result;    //  ~500ms
var page = browser.NewPageAsync().Result;                     //  ~215ms
var webPage = page.GoToAsync("http://www.google.com").Result; //  ~500ms
var screenshot = page.ScreenshotAsync(outputFile);            
screenshot.wait();                                            //  ~300ms   

Как вы можете видеть, оно легко длится более секунды.Я не знаю, как работает Chromium, поэтому у меня есть пара вопросов, касающихся решений, о которых я думаю.

  1. Является ли объект PuppeteerSharp.Browser поточно-ориентированным и / или повторно входящим?Могу ли я использовать один и тот же объект браузера из разных потоков?Я не думаю, потому что это связано с конкретным случаем хрома в памяти.
  2. Если я исключу .LaunchAsync и .NetPageAsync из каждого запроса, это значительно ускорит операцию.Будет ли работать пул PuppeteerSharp.Browser объектов?Например, я могу предварительно выделить 5 из них и выполнить .NetPageAsync для них.Тогда входящие запросы будут использовать объекты из пула.Это жизнеспособный подход?

1 Ответ

0 голосов
/ 20 февраля 2019

Хотя по-прежнему происходит множество улучшений , Puppeteer-Sharp является поточно-ориентированным.Чтобы улучшить производительность загрузки, есть несколько подходов, которые вы можете использовать.

Запустите один браузер и затем подключитесь к нему

Вы можете запустить один (настоящий) браузер и затемиспользуйте метод ConnectAsync для подключения к нему.

await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
    Headless = false,
});

var theBrowser1 = await Puppeteer.ConnectAsync(new ConnectOptions { BrowserWSEndpoint = browser.WebSocketEndpoint });
var theBrowser2 = await Puppeteer.ConnectAsync(new ConnectOptions { BrowserWSEndpoint = browser.WebSocketEndpoint });
var page1 = await theBrowser1.NewPageAsync();
var page2 = await theBrowser2.NewPageAsync();

await Task.WhenAll(
    page1.GoToAsync("https://www.stackoverflow.com"),
    page2.GoToAsync("https://serverfault.com/")
);

Я знаю, что код не работает параллельно, но вы поймете, как повторно использовать тот же браузер.

Создание новых страниц в одном браузере

Если вы используете TPL , у вас не должно возникнуть проблем при создании новых страниц из разных потоков с использованием одного и того же браузера.

await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
    Headless = false,
});

var urls = new string[]
{
    "https://www.stackoverflow.com",
    "https://www.stackoverflow.com",
    "https://www.stackoverflow.com",
    "https://www.stackoverflow.com",
    "https://www.stackoverflow.com",
    "https://www.stackoverflow.com",
    "https://www.stackoverflow.com",
    "https://www.stackoverflow.com",
    "https://www.stackoverflow.com",
    "https://www.stackoverflow.com",
    "https://www.stackoverflow.com"
};

await Task.WhenAll(
    urls.Select(url => Task.Factory.StartNew(async () =>
    {
        var page = await browser.NewPageAsync();
        return page.GoToAsync(url);
    })));

Опять же, этот пример просто для того, чтобы дать вам представление о том, как это можно сделать.

Очередь страниц

Есть один пользователь, которыйсоздал очередь из X страниц (для x от 0 до X => NewPage), а затем он брал страницы из этой очереди.Вы можете увидеть пример здесь .

...