简体   繁体   English

Java Web服务并发问题

[英]Java web-services concurrency issues

I have a java method calling on a web service and making changes to the database based on the response. 我有一个java方法调用Web服务并根据响应更改数据库。 My task is to eliminate concurrency errors when several users use this application simultaneously. 我的任务是在多个用户同时使用此应用程序时消除并发错误。

I was trying to use various types of database locking all day but nothing worked. 我试图整天使用各种类型的数据库锁定,但没有任何工作。 I finally tried to use synchronized in the process request method and it all worked. 我终于尝试在进程请求方法中使用synchronized,这一切都奏效了。

My whole application is single-threaded. 我的整个应用程序是单线程的。 Why does synchronized solve this? 为什么同步解决这个问题?

Edit: Added Code. 编辑:添加代码。

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) {
            }
        }

  }

My whole application is single-threaded. 我的整个应用程序是单线程的。 Why does synchronized solve this? 为什么同步解决这个问题?

No it is not single threaded. 不,它不是单线程的。 The web service is called by multiple threads receiving the client requests. Web服务由接收客户端请求的多个线程调用。

The web service method implementation must take care of all synchronization issues same as in a servlet implementation receiving multiple requests, care must be taken to ensure thread safety. Web服务方法实现必须处理与接收多个请求的servlet实现相同的所有同步问题,必须注意确保线程安全。

In your case, by adding synchronized you made sure that concurrent processing of web service client request did not result in corruption due to thread issues and you are esentially serializing the client requests (and there of access to the DB). 在您的情况下,通过添加synchronized,您确保Web服务客户端请求的并发处理不会因线程问题而导致损坏,并且您实际上是序列化客户端请求(以及对数据库的访问)。

You have not posted any code to see what you are doing wrong, but since synchronized at the web method level solves your problem, you either did not do the synchronized at the DB level as you say properly or threading issues corrupted common variables at the web service layer accessing the DB. 你没有发布任何代码来查看你做错了什么,但是由于web方法级别的同步解决了你的问题,你要么没有像你说的那样在数据库级别进行同步,要么线程在网络上发布损坏的公共变量服务层访问数据库。

By synchronizing at the web method, the code is thread safe, but the performance will deteriorate since you will serve 1 client at a time. 通过Web方法synchronizing ,代码是线程安全的,但性能会恶化,因为您一次只能为1个客户端服务。

Depends on what your requirements are 取决于您的要求

Just move private DbBean db = new DbBean(); 只需移动private DbBean db = new DbBean(); into the servlet method, this should solve the problem concurrency problem: 进入servlet方法,这应该解决问题并发问题:

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

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

...
}

Nevertheless, you should properly clean all database resources in a finally block. 但是,您应该正确清理finally块中的所有数据库资源。 A fairly simplified example, but I hope you get what I mean: 一个相当简单的例子,但我希望你明白我的意思:

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() */
  }

...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM