Метод продолжает работать и отправлять одну и ту же информацию даже для разных запросов grpc - PullRequest
0 голосов
/ 04 апреля 2020

Я пытаюсь внедрить GRP C, и когда я делаю это, я получаю правильный ответ от сервера, и если я остановлю сервер и снова запущу его, и использую другой запрос, который я реализовал, он работает, однако, если я пытаюсь и сделать второй запрос сразу после того, как я сделал один из первого запроса, я получаю тот же ответ. Это как зацикливание. Это два метода, которые я использую от клиента:

     public void setSpaces(int id) {
          channel =ManagedChannelBuilder.forAddress("localhost", 3000)
                    // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
                    // needing certificates.
                    .usePlaintext()
                    .build();
          blockingStub = carParkServiceGrpc.newBlockingStub(channel);
            asyncStub = carParkServiceGrpc.newStub(channel);
             logger.info("Will try to get CarPark " + id + " ...");
             CarParkToUpdateRequest request = CarParkToUpdateRequest.newBuilder().setDeviceId(id).build();
             carParkResponse response;
             try {
                 response = blockingStub.setSpaces(request);
             }catch(StatusRuntimeException e) {
                 logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
                  return;
             }finally {
                    channel.shutdown();
                }
             logger.info("Carpark: " + response.getCarPark());
             spacesArea.append(response.getCarPark().toString());
     }

     public void setFull(int id) {
          channel =ManagedChannelBuilder.forAddress("localhost", 3000)
                    // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
                    // needing certificates.
                    .usePlaintext()
                    .build();
          blockingStub = carParkServiceGrpc.newBlockingStub(channel);
          asyncStub = carParkServiceGrpc.newStub(channel);
             logger.info("Will try to get CarPark " + id + " ...");
             CarParkToUpdateRequest request = CarParkToUpdateRequest.newBuilder().setDeviceId(id).build();
             carParkResponse response;
             try {
                 response = blockingStub.setFull(request);
             }catch(StatusRuntimeException e) {
                 logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
                  return;
             }finally {
                channel.shutdown();
             }
             logger.info("Carpark: " + response.getCarPark());
             fullArea.append(response.getCarPark().toString());
     }

Предполагается, что эти два метода отправят запрос на сервер, чтобы изменить статус «автостоянки», поэтому, если я отправлю запрос с setFull Я получаю ответ о том, что автостоянка заполнена и т. д. c.

Это методы с сервера:

    public void setSpaces(CarParkToUpdateRequest request, StreamObserver<carParkResponse> rStreamObserver) {
        ArrayList<CarParkOperations.proto.cp.CarPark> carList = Car.getInstance();
        for(int i=0; i<carList.size(); i++) {
            if(carList.get(i).getCarParkId() == request.getDeviceId()) {    
                CarParkOperations.proto.cp.CarPark heater_rec = (CarParkOperations.proto.cp.CarPark) carList.get(i);
                Car.carparkCar.clear();
                Car.carparkCar.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(heater_rec.getCarParkId()).setLocation(heater_rec.getLocation()).setStatus("Spaces").build());
            }
        }
        for(CarParkOperations.proto.cp.CarPark heater : Car.carparkCar) {
            carParkResponse response = carParkResponse.newBuilder().setCarPark(heater).build();
            rStreamObserver.onNext(response);
              rStreamObserver.onCompleted();
              return;
        }
    }
public void setFull(CarParkToUpdateRequest request, StreamObserver<carParkResponse> rStreamObserver) {
        ArrayList<CarParkOperations.proto.cp.CarPark> carList = Car.getInstance();
        for(int i=0; i<carList.size(); i++) {
                if(carList.get(i).getCarParkId() == request.getDeviceId()) {    
                    CarParkOperations.proto.cp.CarPark heater_rec = (CarParkOperations.proto.cp.CarPark) carList.get(i);
                    Car.carparkCar.clear();
                    Car.carparkCar.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(heater_rec.getCarParkId()).setLocation(heater_rec.getLocation()).setStatus("Full").build());
                }
        }
        for(CarParkOperations.proto.cp.CarPark heater : Car.carparkCar) {
            carParkResponse response = carParkResponse.newBuilder().setCarPark(heater).build();
            rStreamObserver.onNext(response);
            rStreamObserver.onCompleted();
            return;
        }
    }

Я думаю, что это скорее всего связано с методами сервера но не могу понять это. Вот где я храню данные:

package CarParkOperations.proto.cp;

import java.util.ArrayList;

import com.google.rpc.Status;


public class Car extends ArrayList<CarPark>{

    public static Car carparkCar;

    public static Car getInstance() {
        if(carparkCar == null) {
            carparkCar = new Car();
        }
        return carparkCar;

    }
    public Car() {
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(1).setStatus("Full").setLocation("Behind Building 1").build());
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(2).setStatus("Full").setLocation("Behind Building 1").build());
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(3).setStatus("Full").setLocation("Behind Building 4").build());
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(4).setStatus("Full").setLocation("Behind Building 3").build());
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(5).setStatus("Full").setLocation("Behind Building 2").build());
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(6).setStatus("Full").setLocation("Behind Building 1").build());
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(7).setStatus("Full").setLocation("Behind Building 1").build());
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(10).setStatus("Full").setLocation("Behind Building 6").build());
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(11).setStatus("Full").setLocation("Behind Building 1").build());
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(12).setStatus("Spaces").setLocation("Behind Building 1").build());
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(13).setStatus("Spaces").setLocation("Behind Building 1").build());
        this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(14).setStatus("Spaces").setLocation("Behind Building 1").build());        
    }
}


Любые предложения будут высоко оценены.

1 Ответ

0 голосов
/ 08 апреля 2020

Вам может потребоваться синхронизировать метод Car.getInstance (), потому что без правильной синхронизации, если он вызывается разными потоками, он может неожиданно возвращать разные экземпляры!

public static synchronized Car getInstance() {
    if(carparkCar == null) {
        carparkCar = new Car();
    }
    return carparkCar;

}

Также ваш класс Car не является потоковым безопасно, потому что расширяет ArrayList, который не является потокобезопасным. Вместо этого вы должны позволить вашему классу Car расширять что-то вроде ConcurrentLinkedQueue или позволить вашему классу Car составлять поле list = Collections.synchronizedList (new ArrayList ()) вместо расширения ArrayList.

...