Проблемы параллелизма веб-сервисов Java - PullRequest
0 голосов
/ 30 октября 2011

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

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

Все мое приложение однопоточное. Почему синхронизированные решают эту проблему?

Редактировать: добавлен код.

public class ProcessMakePaymentServlet extends HttpServlet {

    private DbBean db = new DbBean();

    protected synchronized void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // defining variables...

        try {

            // initialize parameters for invoking remote method

            db.connect(); 
            startTransaction(); //autocommit=0; START TRANSACTION;
            // process debit
            //this method gets the method using a select...for update. 
            //it then updates it with the new value
            successfulDebit = debitAccount(userId, amt);
            if (successfulDebit) {
                // contact payment gateway by invoking remote pay web service method here.

                // create new instances of remote Service objects
                org.tempuri.Service service = new org.tempuri.Service();
                org.tempuri.ServiceSoap port = service.getServiceSoap();

                // invoke the remote method by calling port.pay().
                // port.pay() may time out if the remote service is down and throw an exception
                successfullyInformedPaymentGateway = port.pay(bankId, bankPwd, payeeId, referenceId, amt);

                if (successfullyInformedPaymentGateway) {
                    // insert payment record
                    recordPaymentMade(userId, amt, referenceId); 
                    //call to the database to record the transaction. Simple update statement.
                    out.println("<br/>-----<br/>");
                    //getTotalPaymentMade does a select to sum all the payment amounts
                    out.println("Total payment made so far to gateway: " + getTotalPaymentMade());
                    commitTransaction();// calls COMMIT
                    db.close(); //connection closed.
                } else {
                    rollbackTransaction();//calls ROLLBACK
                    db.close();
                    successfulDebit = false;
                    out.println("<br/>-----<br/>");
                    out.println("Incorrect bank details.");
                }
            } else {
                rollbackTransaction();//calls ROLLBACK
                db.close();
                out.println("<br/>-----<br/>");
                out.println("Invalid payment amount.");
            }


        } catch (Exception ex) {
            try {
                rollbackTransaction();//calls ROLLBACK
                db.close();
            } catch (Exception ex1) {
            }
        }

  }

Ответы [ 2 ]

2 голосов
/ 30 октября 2011

Все мое приложение однопоточное. Почему синхронизированное решение это? * * 1002

Нет, это не однопоточный. Веб-сервис вызывается несколькими потоками, получающими клиентские запросы.

Реализация метода веб-службы должна заботиться о всех проблемах синхронизации так же, как и в реализации сервлета, получающей несколько запросов, необходимо следить за безопасностью потока.

В вашем случае, добавив синхронизированный, вы убедились, что одновременная обработка запроса клиента веб-службы не привела к повреждению из-за проблем с потоками, и вы по существу сериализуете клиентские запросы (и существует доступ к БД).

Вы не опубликовали никакого кода, чтобы увидеть, что вы делаете неправильно, но поскольку синхронизация на уровне веб-методов решает вашу проблему, вы либо не выполняли синхронизацию на уровне БД, как вы говорите правильно, либо проблемы с потоками повредили общие переменные на уровне веб-сервисов, обращающихся к БД.

При использовании synchronizing в веб-методе код является поточно-ориентированным, но производительность будет ухудшаться, поскольку вы будете одновременно обслуживать 1 клиента.

Зависит от ваших требований

0 голосов
/ 30 октября 2011

Просто переместите private DbBean db = new DbBean(); в метод сервлета, это должно решить проблему параллелизма:

protected void processRequest(HttpServletRequest request, ...) {

  // defining variables...
  DbBean db = new DbBean();

...
}

Тем не менее, вы должны правильно очистить все ресурсы базы данных в блоке finally. Довольно упрощенный пример, но я надеюсь, вы понимаете, что я имею в виду:

protected void processRequest(HttpServletRequest request, ...) {

  // defining variables...
  DbBean db = null;
  boolean commit = false;

  try {
    db = new DbBean();
  } catch (SomeException e) {
    commit = false;
  } finally{
    db.release(commit); /* close database connection => java.sql.Connection#close() */
  }

...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...