forum.bitel.ru
http://forum.bitel.ru/

Проблема при запуске глобального скрипта через планировщик
http://forum.bitel.ru/viewtopic.php?f=19&t=8895
Страница 1 из 1

Автор:  Yarlan Zey [ 30 янв 2014, 08:09 ]
Заголовок сообщения:  Проблема при запуске глобального скрипта через планировщик

Код:
GC overhead limit exceeded
java.lang.OutOfMemoryError: GC overhead limit exceeded

при запуске через планировщик отъедает 20 гигов оперативки и падает.
при запуске вручную нормально отрабатывает

Автор:  Artur [ 30 янв 2014, 11:03 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

Конкретно одного скрипта? Что за скрипт? Что у него внутри?

Автор:  Yarlan Zey [ 30 янв 2014, 11:05 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

у нас пока только один)

Код:
//Отправка СМС с напоминанием о приближающейся блокировке

import bitel.billing.server.contract.bean.BalanceUtils;
import bitel.billing.server.contract.bean.ContractStatus;
import bitel.billing.server.contract.bean.ContractStatusManager;
//import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import ru.bitel.bgbilling.modules.npay.server.Calculator;
import java.text.SimpleDateFormat;
import java.net.*;
import java.io.*;

public void main( setup, con, conSlave )
{

//Начало функции подсчета суммы оплаты за n-количество дней
public static double payday (StartDate, int days) {
    double result = 0;//переменная в которой будет содержаться результат
   payday = 0;
   paymonth = 0;
   paymonthtoday = 0;
   String DateQuery = StartDate;
    for (int i = 0; i < days; i++)
      {

//Достаем сумму списания в день на сегодня
querytoday =    "SELECT ROUND(SUM(REPLACE(data,'type&1%cost&',''))/EXTRACT(DAY FROM LAST_DAY('"+DateQuery+"')),3) as ap FROM module_tariff_tree as a " +
            "LEFT JOIN mtree_node AS b ON (a.id=b.mtree_id) " +
            "LEFT JOIN contract_tariff AS c ON (c.tpid=a.tree_id) " +
            "WHERE (a.mid=7)AND(type LIKE \"%cos%t\")AND(c.cid="+cid+")AND(c.date1<='"+DateQuery+"')AND((c.date2 is NULL)OR(c.date2>='"+DateQuery+"'))AND(type='day_cost')";
PreparedStatement psSelect = conSlave.prepareStatement(querytoday);
ResultSet rs = psSelect.executeQuery();
    while (rs.next())
       {
   payday = rs.getDouble(1);
      }

//Достаем сумму списания в месяц на сегодня
querytoday =    "SELECT IFNULL(ROUND(SUM(REPLACE(data,'type&0%cost&',''))/EXTRACT(DAY FROM LAST_DAY('"+DateQuery+"')),3),0) as ap FROM module_tariff_tree as a " +
            "LEFT JOIN mtree_node AS b ON (a.id=b.mtree_id) " +
            "LEFT JOIN contract_tariff AS c ON (c.tpid=a.tree_id) " +
            "WHERE (a.mid=7)AND(type LIKE \"%cos%t\")AND(c.cid="+cid+")AND(c.date1<='"+DateQuery+"')AND((c.date2 is NULL)OR(c.date2>='"+DateQuery+"'))AND(type='month_cost')AND(DAYOFMONTH('"+DateQuery+"')=1)";
PreparedStatement psSelect = conSlave.prepareStatement(querytoday);
ResultSet rs = psSelect.executeQuery();
    while (rs.next())
       {
   paymonth = rs.getDouble(1);
      }

result = result + payday + paymonth;

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
c.setTime(sdf.parse(DateQuery));
c.add(Calendar.DATE, 1);  // +1 день
DateQuery = sdf.format(c.getTime());  // Новая дата
    }
    return result;//возвращаю его
}
//Конец функции подсчета суммы оплаты за n-количество дней

//Достаем сегодняшнюю дату
Date currentDate = new Date();

//Достаем параметры договоров
String query = "SELECT a.id, b.value, c.summa1+c.summa2-c.summa3-c.summa4, SUBSTRING(f.title,1,1), CONCAT(e.house, '', e.frac), d.flat " +
            "FROM contract AS a " +
            "LEFT JOIN contract_parameter_type_phone AS b ON (b.cid=a.id) " +
            "LEFT JOIN contract_balance AS c ON ((c.cid=a.id) AND (c.mm=month(now())) AND (c.yy=year(now()))) " +
            "LEFT JOIN contract_parameter_type_2 AS d ON (d.cid=a.id) " +
            "LEFT JOIN address_house AS e ON (d.hid=e.id) " +
            "LEFT JOIN address_street AS f ON (f.id=e.streetid) " +
            "LEFT JOIN contract_module AS g ON (g.cid=a.id) " +
            "LEFT JOIN ipn_contract_status_9 AS h ON (h.cid=a.id) " +
            "WHERE (a.status=0) AND NOT ISNULL(b.value) AND ((c.summa1+c.summa2-c.summa3-c.summa4)>0) AND (g.mid=9) AND (h.status=0)";
   PreparedStatement contractPs = con.prepareStatement( query );
   ResultSet contractRs = contractPs.executeQuery();
   int cid;
   String ContractPhone = "";
   int ksms = 0;
   int ksms1 = 0;
   int ksms5 = 0;

while ( contractRs.next() )
    {
      cid = contractRs.getInt( 1 );
//print (cid +" start");
      ContractPhone = contractRs.getString( 2 );
      ContractPhone = ContractPhone.replace("; ", ",");//Заменяем точку с запятой и пробел на запятую (требование СМС пилота)
      balance = contractRs.getDouble( 3 );
      Street = contractRs.getString(4);
      H = contractRs.getBytes(5);
      String House = new String(H,"cp1251");
      Flat = contractRs.getString(6);
      Adress = Street + ". " + House + "-" + Flat;

SMSText2 = "";

//Применяем к дате маску для использования в СМС-Пилоте
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
senddt = sdf.format(currentDate);

//Забираем суммы оплат на ближайшие дни
double paytoday = payday(senddt,1);//Сумма оплаты на 1 день
double payto2day = payday(senddt,2);//Сумма оплаты на 2 дня
//double payto3day = payday(senddt,3);//Сумма оплаты на 3 дня
double payto5day = payday(senddt,5);//Сумма оплаты на 5 дней
double payto6day = payday(senddt,6);//Сумма оплаты на 6 дней

   if (balance < payto2day && balance >=paytoday) {
      SMSText2 = URLEncoder.encode(" руб. До блокировки 1 день.", "UTF-8") + "&to=";
      ksms1++;;
      }
/*   else if (balance < payto3day && balance >= payto2day) {
      SMSText2 = URLEncoder.encode(" руб. До блокировки 2 дня.", "UTF-8") + "&to=";
      }*/
   else if (balance < payto6day && balance >= payto5day) {
      SMSText2 = URLEncoder.encode(" руб. До блокировки 5 дней.", "UTF-8") + "&to=";
      ksms5++;
      }

   if (SMSText2 != "") {
balance = balance - paytoday;
balance = Math.rint(100.0 * balance) / 100.0;
SMSSend = "";
SMSSender = "Fialka";
APIKey = "";
SMSSend = "http://smspilot.ru/api.php?send=" + URLEncoder.encode("Баланс ", "UTF-8") + URLEncoder.encode(Adress, "UTF-8") + ": " + balance + SMSText2 + ContractPhone + "&from=" + SMSSender + "&apikey=" + APIKey + "&send_datetime=" + senddt + " 05:00:00";

// -- START SENDING SMS MESSAGE --
URL url = new URL(SMSSend);
URLConnection c = url.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(
c.getInputStream()));
String inputLine;

while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
// -- END SENDING SMS MESSAGE --

ksms++;
}
}
print("Кол-во отправленных СМСок " +ksms );
print("Из них:");
print("1 день " +ksms1 );
print("5 дней " +ksms5 );
contractRs.close();
contractPs.close();   
}

Автор:  Artur [ 30 янв 2014, 15:32 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

Проблему это не решит, конечно, но нужно закрывать PreparedStatement после каждого использования, либо для java 1.7 использовать блок try( Autocloseable instance). Это совет на каждый день, так сказать =)
Еще бы не помешало сделать снимок jvisualvm, когда задача отжирает доступную память.

Автор:  Yarlan Zey [ 30 янв 2014, 15:37 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

это первый скрипт, поэтому ошибок само собой море... почему тогда при "выполнить скрипт" выполняется как надо, а ночью так странно себя ведет?

Автор:  Artur [ 30 янв 2014, 15:55 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

Потому и следует выяснить, в этом ли месте проблема. Может у вас в совсем другой задаче происходит утечка.

Автор:  skyb [ 30 янв 2014, 16:48 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

у меня по шедулеру именно изза незакрытых стейтментов падало

Автор:  Yarlan Zey [ 30 янв 2014, 16:57 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

закрыл. заодно перенес только эту задачу на 2 часа. посмотрим

Автор:  barguzin2 [ 30 янв 2014, 21:04 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

Всё еще пишите на BSH - тогда мы идём к вам (с). Да еще какие-то странные типы данных double используете :) Дин.код вам в помощь - после его появления писать обработчики и глобальные скрипты поведения стало намного приятней.

Автор:  Yarlan Zey [ 31 янв 2014, 08:28 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

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

Автор:  Artur [ 31 янв 2014, 09:54 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

Т.е. все решилось закрытием незакрытых ресурсов?

Автор:  Yarlan Zey [ 31 янв 2014, 10:59 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

угу. спс

но вопрос почему в планировщике скрипты выполняются иначе чем вручную интересен

Автор:  Amir [ 03 фев 2014, 17:41 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

А как именно вручную? Как соединение к БД передаете?
Биллинг использует пул соединений Apache Commons DBCP. Пул является оберткой над реализациями соединений MySQL. В месте где происходит открытие/закрытие Statement'ов он сделан не очень удачно. Как минимум, при не закрытии использованных Statement, когда их набирается много, возрастает нагрузка на процессор.

Но ресурсы в любом случае нужно освобождать, поэтому сам DBCP не трогаем пока.

Автор:  Yarlan Zey [ 03 фев 2014, 22:21 ]
Заголовок сообщения:  Re: Проблема при запуске глобального скрипта через планировщ

в редакторе скрипта есть кнопочка для запуска. оттуда

как передаем? не знаю :-)

Страница 1 из 1 Часовой пояс: UTC + 5 часов [ Летнее время ]
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/