2016-10-08 6 views
0

Я реализую REST-API с JavaEE-Techniques, к которому будут доступны мобильные приложения и ответы с некоторыми JSON-Data в ответ на их запросы. Пока все замечательно, пока мы не заметили, что вопрос очень необычный. Сначала я подумал, что это «сложный» запрос базы данных, который работает так долго, но после некоторой отладки он указал, что доступ к thumbnailpicture из полученных данных методом ImageIO.read (URL) является причиной запроса до принять поэтому длинный.ImageIO.read (URL) берет навсегда загрузку изображения

Через запрос базы данных Я получаю URL-адрес, указывающий на данные изображения (миниатюр), которые я хочу получить. Прежде чем я создам JSON-Data объекта для отправки его клиенту, я собираюсь кодировать изображение как base64-String.

Мой код выглядит следующим образом (я знаю, что он не такой приятный на данный момент, но так, как я его до сих пор работаю, я знаю, что могу использовать блоки try-resource и, вероятно, должен преобразовать запись в срубы уровень отладки, и я собираюсь):

public class Base64Utility 
{ 
    public static String encodeBase64FromUrl(final URL pImageUrl, final ThumbnailPictureDbo pThumbnailPicture) 
    { 
     BufferedImage img = null; 
     String base64EncodedImageString = null; 
     final ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     byte[] imageBytes = null; 

     try 
     { 
      logger.info("Starting to convert the image!"); 

      final Long start = System.currentTimeMillis(); 

      // The Sucker! 
      img = ImageIO.read(pImageUrl); 
      final Long imageLoadTime = System.currentTimeMillis() - start; 
      logger.info("Loaded Image from url {} in: {}", pImageUrl, imageLoadTime); 

      final Long start2 = System.currentTimeMillis(); 
      ImageIO.write(img, "png", bos); 
      imageBytes = bos.toByteArray(); 

      final Long imageWriteTime = System.currentTimeMillis() - start2; 
      logger.info("Wrote Image in: {}", imageWriteTime); 
      bos.close(); 

      final Long start3 = System.currentTimeMillis(); 
      // What to return when img == null?! 
      base64EncodedImageString = imageBytes != null ? Base64.getEncoder() 
       .encodeToString(imageBytes) : ""; 

      final Long imageEncodeTime= System.currentTimeMillis() - start3; 
      logger.info("Encoded Image in: {}", imageEncodeTime); 

      pThumbnailPicture.setBase64EncodedImage(base64EncodedImageString); 

      logger.info("Finished converting the image!"); 
      logger.info("Took total time: " + (System.currentTimeMillis() - start)); 
      return base64EncodedImageString; 
     } 
     catch (final IOException e) 
     { 
      e.printStackTrace(); 
     } 
    return base64EncodedImageString; 
} 

The изображений размещаются на же машине расположена база данных и код работает на. Таким образом, URL-парам содержит имя хоста, но также может быть доступен через «localhost» или в виде файла (но он хранится с именем хоста в базе данных. Для удобства я его не конвертирую, найдя также очень удобный ImageIO .read (URL).) Таким образом, сеть также не должна быть узким местом.
Очень странное поведение: ImageIO занимает 10-60 секунд, обращаясь к изображению по первому вызову. После этого (несколько данных результата в одном и том же запросе-клиенте) требуется всего 100 миллисекунд.
По новому новому запросу он ведет себя одинаково (первый вызов занимает ненормальный длинный и на следующих очень короткий). Это выход из некоторых журналов (в течение одного запроса клиента!):

Starting to convert the image! 
Loaded Image from url <URL>/Logo-KF-transparent-1500-1024x992.png in: 21810 
Wrote Image in: 973 
Encoded Image in: 3 
Finished converting the image! 
Took total time: 22787 

Starting to convert the image! 
Loaded Image from url <URL>/IMG_1026_905.jpg in: 157 
Wrote Image in: 440 
Encoded Image in: 7 
Finished converting the image! 
Took total time: 605 

Starting to convert the image! 
Loaded Image from url <URL>/WorkshopS2_KaffeeFabrik_1200x800-500x300.jpg in: 23 
Wrote Image in: 101 
Encoded Image in: 2 
Finished converting the image! 
Took total time: 127 

Starting to convert the image! 
Loaded Image from url <URL>/kaffeezumabnehmen.jpg in: 226 
Wrote Image in: 98 
Encoded Image in: 4 
Finished converting the image! 
Took total time: 329 

Starting to convert the image! 
Loaded Image from url <URL>/kaffee_apa.jpg in: 12 
Wrote Image in: 60 
Encoded Image in: 2 
Finished converting the image! 
Took total time: 75 

Того самое поведение не зависит от в изображениях ни на формате Изображения в, это всегда первый доступ/которая занимает так много времени! У кого-нибудь есть идея или решение? Мне тоже хорошо с другим подходом к чтению/загрузке изображений, это была только моя первая попытка и первый результат некоторых исследований. Возможно, для этого существует совершенно другой и лучший подход.

Я звоню утилиту из фасоли RequestScoped-КДИ следующим образом:

@RequestScoped 
public class LocationPersistenceServiceImpl implements LocationPersistenceService 
{ 
    // Some other attributes and methods... 

    @Override 
    public List<LocationData> findLocations(final QueryParams[] pQueryParams) 
    { 
     final QueryBuilder<LocationDbo> qb = new QueryBuilder<>(pQueryParams, emf, LocationDbo.class); 
     final List<LocationDbo> locationDboQueryResults = qb.getResultList(); 
     for (LocationDbo retrievedLocDbo : locationDboQueryResults) 
     { 
      retrievedLocDbo = enhanceRetrievedLocationDboMetaInformation(retrievedLocDbo); 
     } 
     return dboToData.convert(locationDboQueryResults); 
    } 

    private LocationDbo enhanceRetrievedLocationDboMetaInformation(LocationDbo pRetrievedLocDbo) 
    { 
     final List<PostMetaInformationDbo> postMetaInfos = pPs.retrievePostMetaInfomationsById(pRetrievedLocDbo.getPostId()); 
     pRetrievedLocDbo = addRetrievedLocationMetaInfosFromLocationPost(pRetrievedLocDbo, postMetaInfos); 
     return pRetrievedLocDbo; 
    } 

    private LocationDbo addRetrievedLocationMetaInfosFromLocationPost(final LocationDbo pLocDbo, final List<PostMetaInformationDbo> pPostMeta) 
    { 
     for (final PostMetaInformationDbo p : pPostMeta) 
     { 
      // Some code... 
     } 
     if ((pLocDbo.getThumbnailPicture() != null) && (!StringUtils.isBlank(pLocDbo.getThumbnailPicture() 
      .getGuid()))) 
     { 
      Base64Utility.encodeBase64FromUrl(pLocDbo.getThumbnailPicture() 
       .getGuid(), pLocDbo.getThumbnailPicture()); 
     } 
     return pLocDbo; 
    } 
} 

Еще одна моя идея будет аннотировать класс Base64Utility как Stateless боба и ввести его в класс обслуживания. Возможно, это может улучшить некоторые процедуры кэширования/подключения или поддерживать параллельное выполнение/потоки или подобное (еще не пробовал).

Возможно, у кого-то были подобные проблемы или у вас возникли очевидные нарушения при работе с ImageIO и он может поделиться своим знанием.

Спасибо и с наилучшими пожеланиями!

P.S.: весь код работает на сервере приложений Wildlfy (8.2.Final и на Java 8). Таким образом, запуск некоторых потоков вручную при работе с ImageIO (как показывают некоторые сообщения в моем исследовании) не должно быть отличной идеей.

+0

Вы пытались загрузить URL-адрес изображения с помощью веб-браузера или другого инструмента (завиток, wget и т. Д.), Чтобы узнать, загружаются ли они быстрее? В любом случае последующие чтения быстрее, потому что URL-адрес кэшируется. Кроме того, ByteArrayOutputStream.toByteArray() * never * возвращает null. – VGR

+0

Да, конечно. Но я, наверное, обманул. Открытие URL-адреса с помощью firefox, казалось, сработало мгновенно -> Img, скорее всего, был кэширован. Доступ к URL-адресу на закрытой вкладке занял у меня 27 сек. Редактировать: Также wget на удаленной машине (на которой размещены изображения) занял 10 - 20 секунд. – Sebsen36

+0

Голосование, чтобы закрыть этот вопрос, поскольку реальная проблема, похоже, заключается в генерации изображений на сервере и/или сетевом вводе-выводе, а не напрямую связана с ImageIO.read. – haraldK

ответ

0

Как уже указывалось, проблема с ImageIO не была напрямую проблемой, кроме того, она была связана с медленным/неправильно сконфигурированным сервером Apache. Просто перезагрузив сервер Apache, который обслуживает изображения, я решил свою проблему.