2017-02-20 20 views
4

Я развернул приложение Spring 4 на сервер tomcat, который размещен в облаке Digital Ocean, VM CentOS. Приложение представляет собой мобильное бэкэнд-приложение, в основном Rest API. JDK - версия openjdk «1.8.0_111» Рабочая среда OpenJDK (сборка 1.8.0_111-b15) 64-разрядная виртуальная машина OpenJDK (сборка 25.111-b15, смешанный режим) вместе с Apache Tomcat/7.0.54 и база данных размещена в другой ВМ.Необычное поведение в приложении Java, развернутое в tomcat

Приложение работает как обычно, но иногда в приложении наблюдается необычное поведение. Я зарегистрировал каждый REST Controller вызов из frontend (i.e.Mobile) с помощью Log4j, и я использую tail -f /usr/share/tomcat/logs/someapp/info.log для просмотра журнала во время выполнения. API-интерфейсы Frontend обычно асинхронны, и поведение сервера соответствует ожиданиям. Но при тестировании на каком-то устройстве поведение странно. Когда устройство вызывает вызов API, журнал не распечатывает запись вызова API, а также ответ также неверен. Итак, я сделал удаленную отладку от Eclipse, но очень медленно (требуется минут, чтобы попасть в точку останова, не знаю, как быстро сделать), у меня есть JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -Djava.awt.headless=true -Xmx3072m -XX:MaxPermSize=256m -XX:+UseConcMarkSweepGC -Xdebug -agentlib:jdwp=transport=dt_socket,address=8090,server=y,suspend=n" в tomcat.conf. Даже при подключении отладчика поведение такое же, ответ присутствует во внешнем интерфейсе, но не журнал, а также не попадает на точку останова и неверные данные. Но когда тот же API вызывается от Postman, он попадает, а также записывается журнал, и данные также верны. Фронтальный вызов является асинхронным и одновременно вызывает несколько API. Я попытался воспроизвести поведение на своей локальной машине, но не смог реплицировать, поведение как ожидалось, и данные ответов также верны.

Но когда выполняется одиночный/(или менее) вызов, вызов API записывается как ожидалось, очень странно.

Совершает ли JVM кэширование? или он дает такое поведение по нескольким вызовам API одновременно? Или нужна какая-то конфигурация?

Справка, рекомендации .. оценен.

Мой код: Контроллер:

@RequestMapping(value="/get_VIP_requests/{fbId}", method = RequestMethod.GET) 
    public ResponseEntity<ServiceResponse> getVIPRequests(@RequestHeader HttpHeaders headers,@PathVariable("fbId") Long fbId){ 
     try { 
      HeaderDto headerDto = new HeaderDto(); 
      GeneralUtil.fillHeaderCredential(headers, headerDto, GeneralUtil.ACCESS_TOKEN); 
      ServiceResponse serviceResponse = new ServiceResponse("Users have been retrieved successfully"); 
      serviceResponse.addParam("users",clientService.listVIPRequests(fbId)); 
      return new ResponseEntity<ServiceResponse>(serviceResponse, HttpStatus.OK); 

     } catch (Exception e){ 
      GeneralUtil.logError(log, "Error Occurred while getting users", e); 
      HttpHeaders httpHeaders = ServiceResponse.generateRuntimeErrors(e); 
      return new ResponseEntity<ServiceResponse>(httpHeaders, HttpStatus.EXPECTATION_FAILED); 
     } 
    } 

Услуги:

@Override 
    public List<UserEntity> listVIPRequests(Long vipFbId) throws Exception { 

     List<UserEntity> requesterList = myVIPDao.listVIPRequestsNormal(vipFbId); 

     List<UserEntity> blockedUsers = userFriendshipDao.listUsersByStatus(vipFbId, UserFriendshipStatus.BLOCKED); 
     List<UserEntity> usersWhoHaveBlockedMe = userFriendshipDao.listUsersWhoHaveBlockedMe(vipFbId, UserFriendshipStatus.BLOCKED); 
     requesterList.removeAll(blockedUsers); 
     requesterList.removeAll(usersWhoHaveBlockedMe); 

     List<UserEntity> responseList = new ArrayList<>(); 
     for (UserEntity user : requesterList) { 
      UserEntity returnUser = new UserEntity(); 
      returnUser.setEntityId(user.getEntityId()); 
      returnUser.setFacebookId(user.getFacebookId()); 
      returnUser.setFullName(user.getFullName()); 
      returnUser.setEmail(user.getEmail()); 
      returnUser.setGender(user.getGender()); 
      returnUser.setPushNotificationStatus(null); 
      returnUser.setProfileImageUrl(user.getProfileImageUrl()); 
      returnUser.setInfo(user.getInfo()); 
      responseList.add(returnUser); 
     } 

     List<BusinessEntity> businessRequesterList = myVIPDao.listVIPRequestsBusiness(vipFbId); 

     if(businessRequesterList!=null & !businessRequesterList.isEmpty()){ 
      businessRequesterList.stream().forEach(b -> { 
       UserEntity returnUser = new UserEntity(); 
       returnUser.setBusinessId(b.getEntityId());     //To identify if the request is from business a/c or normal a/c                 
       returnUser.setEntityId(b.getEntityId()); 
       returnUser.setFacebookId(b.getOwner().getFacebookId()); 
       returnUser.setFullName(b.getBusinessName()); 
       returnUser.setEmail(b.getWebUrl()); 
       returnUser.setGender(Gender.Male); 
       returnUser.setPushNotificationStatus(null); 
       returnUser.setProfileImageUrl(b.getProfileImage()); 
       returnUser.setInfo(b.getDescription()); 
       responseList.add(returnUser); 
      }); 
     } 
     return responseList; 
    } 

DAO:

@SuppressWarnings("unchecked") 
    @Override 
    public List<UserEntity> listVIPRequestsNormal(Long vipFbId) throws Exception { 

     Criteria criteria = getCurrentSession().createCriteria(MyVipEntity.class, "v1"); 
     criteria.createAlias("v1.friend", "vip"); 
     criteria.createAlias("v1.organizer", "organizer"); 
     criteria.add(Restrictions.eq("v1.requestStatus", VIPStatus.REQUESTED)); 
     criteria.add(Restrictions.eq("vip.facebookId", vipFbId)); 
     criteria.add(Restrictions.isNull("v1.business")); 
     criteria.setProjection(Projections.property("organizer")); 
     criteria.addOrder(Order.asc("organizer.fullName")); 

     return (List<UserEntity>) criteria.list(); 
    } 

@SuppressWarnings("unchecked") 
    @Override 
    public List<BusinessEntity> listVIPRequestsBusiness(Long vipFbId) throws Exception { 

     Criteria criteria = getCurrentSession().createCriteria(MyVipEntity.class, "v1"); 
     criteria.createAlias("v1.friend", "vip"); 
     criteria.createAlias("v1.business", "business"); 
     criteria.add(Restrictions.eq("v1.requestStatus", VIPStatus.REQUESTED)); 
     criteria.add(Restrictions.eq("vip.facebookId", vipFbId)); 
     criteria.add(Restrictions.isNotNull("v1.business")); 
     criteria.setProjection(Projections.property("v1.business")); 
     criteria.addOrder(Order.asc("business.businessName")); 

     return (List<BusinessEntity>) criteria.list(); 
    } 
+0

Когда вы звоните с другого устройства и журналы не печатались, ответ, который вы получаете, имеет одинаковую структуру? это ответные изменения или статический ответ приходит каждый раз? – arjun

+0

Да, журналы не печатались.И структура ответа такая же, но данные неверны. Иногда реакция меняется и некоторое время всегда одинаково реагирует. – SudeepShakya

+0

перезапустите ваш tomcat, а не прямой доступ с устройства, с которого вы столкнулись, проверьте, правильно ли вы ответили или неверны – arjun

ответ

2

Одной из возможных причин может быть Cache-Control заголовок.

Я считаю, что по умолчанию он правильно установлен в Cache-Control: no-cache, no-store, max-age=0, must-revalidate, который будет направлять клиентское приложение, чтобы не кэшировать запрос/ответ.

Быстрый способ проверить это, чтобы проверить заголовки ответов. Если заголовок ответа Cache-Control предлагает кешировать ответ, вы можете настроить весну, чтобы легко изменить это поведение.

Вот подробная статья на сайте Mozilla, об этом заголовке: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control

+0

Привет, одна вещь, которую я нашел: 1) Когда я останавливаю размещенное приложение (например: app_abc), если выполняется несколько запросов, интерфейс получает ответ, я имею в виду, если я ударил один раз, никакого ответа, снова и снова ударил, дает ответ. 2) Если я остановлю Tomcat, тогда никакого ответа даже в нескольких хитах. – SudeepShakya

+1

Когда вы вызываете свою услугу через POSTMAN, вы получаете ответный заголовок Cache-Control? –

+0

Нет, я не получаю заголовок Cache-Control в ответ. Ответ «{ « date »:« Thu, 02 Mar 2017 02:39:31 GMT », « сервер »:« Apache-Coyote/1.1 », « передача-кодирование »:« chunked », « content-type ":" application/json; charset = UTF-8 " }' Но я сказал, что интерфейс добавит заголовок Cache-Control в запросе для no-cache. – SudeepShakya

1

вы ожидающие данные, чтобы быть в теле или заголовке? вам может не хватать тег @ResponseBody при возврате.

+0

Данные находятся в теле, а также в заголовке. И у меня есть тег @ResponseBody. Так что это не проблема. Но спасибо за ответ. – SudeepShakya

Смежные вопросы