具有多个客户端调用的RESTApi问题

时间:2019-05-18 15:52:40

标签: rest web-services jersey synchronization

我是静止的新手,正在尝试编写一个简单的rest api,将一些量从一个源转移到另一个源。我没有数据库,使用地图作为数据源。我的服务只是检查源是否有足够的金额可转移,如果是,那么我会同时更新源和目标。问题是我同时关注多个请求。因为当有多个请求时,它们都可以使用相同的源值同时进行验证,这会导致错误的行为。

示例:来源有金额100,并且有2个请求以金额70进行转帐。处理这两个请求时,它们都同时检查了来源有金额100,然后可以执行转帐。

1)我的资源:

 public class MyResource {

    @Inject
    TransferService transferService;


    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public Transfer transfer(Transfer transfer){

        return transferService.transfer(transfer);
    }
}

2)来源POJO

public class Source {

    private String sourceId;
    private double balance;

    ....

}

3)源服务

public class SourceServiceImp implements SourceService {


    @Override
    public Source getSource(String sourceId) {

        Source source = EmbeddedSources.getSource(sourceId);

        return source;

    }


    public boolean deposit(String sourceId, double amount ){

        Source source = getSource(sourceId);
        source.setBalance(source.getBalance() + amount);

        EmbeddedSources.updateSource(sourceId, source);
        return  true;
    }


    public boolean withdraw(String sourceId, double amount ){

        Source source = getSource(sourceId);
        source.setBalance(source.getBalance() - amount);

        EmbeddedSources.updateSource(sourceId, source);
        return  true;
    }


}

4)TransferService

public class TransferServiceImpl implements TransferService {


    private static SourceService sourceService ;


    public TransferServiceImpl(SourceService sourceService){
        this.sourceService = sourceService;
    }


    @Override
    public Transfer transfer(Transfer transfer) {

        Source sourceSource = sourceService.getSource(transfer.getSourceSourceId());
        Source destSource = sourceService.getSource(transfer.getDestSourceId());
        double amount = transfer.getAmount();



        if(isBalanceEnough(sourceSource, destSource, amount)){
            sourceService.withdraw(sourceSource.getSourceId(), amount);
            sourceService.deposit(destSource.getSourceId(), amount);     
        }

        transfer.setStatus("VALID");
        return transfer;

    }

}

5)嵌入式数据库

public class EmbeddedSources {

    private static Map<String, Source> sourceMap = new ConcurrentHashMap<>();
    private static Map<String, Transfer> transferMap = new ConcurrentHashMap<>();


    public static Source getSource(String sourceId){
        return sourceMap.get(sourceId);
    }

    public static void updateSource(String sourceId, Source source){
        sourceMap.put(sourceId, source);
    }


    public static void addSource(Source source){
        sourceMap.put(source.getSourceId(), source.deepCopy());
    }

}

我考虑过使用队列进行请求,但是我认为这不是一个好的解决方案。我也考虑过将volatile用于源类字段,但仍然不能避免对同一sourceId的多次请求。

如何防止此问题并使多个请求的服务安全?

0 个答案:

没有答案