ВНИМАНИЕ: сбой RPC: статус {code = NOT_FOUND, description = Not found, cause = null} при попытке использовать GRPC в java и Nodejs

В настоящее время я пытаюсь отправить запрос на сервер nodejs от созданного мной java-клиента, но получаю сообщение об ошибке, показанное выше. Я провел некоторое исследование по этому поводу, но, кажется, могу понять, почему это происходит. Сервер, который я создал в nodejs:

var grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader')
const packageDefinition = protoLoader.loadSync('AirConditioningDevice.proto')

var AirConditioningDeviceproto = grpc.loadPackageDefinition(packageDefinition);

var AirConditioningDevice = [{
    device_id: 1,
    name: 'Device1',
    location: 'room1',
    status: 'On',
    new_tempature: 11
}];

var server = new grpc.Server();
server.addService(AirConditioningDeviceproto.AirConditioningDevice.Airconditioning_service.service,{
    currentDetails: function(call, callback){
        console.log(call.request.device_id);
        for(var i =0; i <AirConditioningDevice.length; i++){
            console.log(call.request.device_id);
             if(AirConditioningDevice[i].device_id == call.request.device_id){
                console.log(call.request.device_id);
                 return callback(null, AirConditioningDevice [i]);
             }
             console.log(call.request.device_id);
        }
        console.log(call.request.device_id);
        callback({
            code: grpc.status.NOT_FOUND,
            details: 'Not found'
        });
    },
    setTemp: function(call, callback){
        for(var i =0; i <AirConditioningDevice.length; i++){
             if(AirConditioningDevice[i].device_id == call.request.device_id){

                 AirConditioningDevice[i].new_tempature == call.request.new_tempature;
                 return callback(null, AirConditioningDevice[i]);
             }
        }
        callback({
            code: grpc.status.NOT_FOUND,
            details: 'Not found'
        });

    },
    setOff: function(call, callback){
        for(var i =0; i <AirConditioningDevice.length; i++){
             if(AirConditioningDevice[i].device_id == call.request.device_id && AirConditioningDevice[i].status == 'on'){
                 AirConditioningDevice[i].status == 'off';
                 return callback(null, AirConditioningDevice[i]);
             }else{
                 AirConditioningDevice[i].status == 'on';
                 return callback(null, AirConditioningDevice[i]);
             }
        }
        callback({
            code: grpc.status.NOT_FOUND,
            details: 'Not found'
        });
    }
});

server.bind('localhost:3000', grpc.ServerCredentials.createInsecure());
server.start();

Это клиент, который я создал на java:

package com.air.grpc;

import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import com.air.grpc.Airconditioning_serviceGrpc;

import com.air.grpc.GrpcClient;
import com.air.grpc.deviceIDRequest;
import com.air.grpc.ACResponse;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;

public class GrpcClient {
    private static final Logger logger = Logger.getLogger(GrpcClient.class.getName());
    private final ManagedChannel channel;
    private final Airconditioning_serviceGrpc.Airconditioning_serviceBlockingStub blockingStub;
     private final Airconditioning_serviceGrpc.Airconditioning_serviceStub asyncStub;

     public GrpcClient(String host, int port) {
            this(ManagedChannelBuilder.forAddress(host, port)
                // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
                // needing certificates.
                .usePlaintext()
                .build());
          }
     GrpcClient(ManagedChannel channel) {
            this.channel = channel;
            blockingStub = Airconditioning_serviceGrpc.newBlockingStub(channel);
            asyncStub = Airconditioning_serviceGrpc.newStub(channel);
          }
     public void shutdown() throws InterruptedException {
            channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
          }

     public void currentDetails(int id) {
         logger.info("Will try to get device " + id + " ...");
         deviceIDRequest deviceid = deviceIDRequest.newBuilder().setDeviceId(id).build();
         ACResponse response;
         try {
             response =blockingStub.currentDetails(deviceid);

         }catch(StatusRuntimeException e) {
             logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
              return;
         }
          logger.info("Device: " + response.getAirConditioning ());

     }
     public static void main(String[] args) throws Exception {
         GrpcClient client = new GrpcClient("localhost", 3000);
         try {
             client.currentDetails(1);
         }finally {
            client.shutdown();
        }



          }




}

Прямо сейчас единственный, который я тестировал, потому что он самый простой - currentdetails. Как видите, я создал объект AirConditioningDevice. Я пытаюсь получить подробности об этом, набрав 1 в текстовое поле, которое является идентификатором, но, как я уже сказал, когда я отправляю его, я получаю сообщение об ошибке в заголовке. Это прототип, который я создал:

syntax = "proto3";


package AirConditioningDevice;

option java_package = "AircondioningDevice.proto.ac";


service Airconditioning_service{
rpc currentDetails(deviceIDRequest) returns (ACResponse) {};
rpc setTemp( TempRequest ) returns (ACResponse) {};
rpc setOff(deviceIDRequest) returns (ACResponse) {};



}

message AirConditioning{
int32 device_id =1;
string name = 2;
string location = 3;
string status = 4;
int32 new_tempature = 5;
}

message deviceIDRequest{
int32 device_id =1;

}

message TempRequest {
    int32 device_id = 1;
    int32 new_temp = 2;
}

message ACResponse {
    AirConditioning airConditioning = 1;
}

наконец, это все, что я возвращаю в консоль:

Apr 02, 2020 4:23:29 PM AircondioningDevice.proto.ac.AirConClient currentDetails
INFO: Will try to get device 1 ...
Apr 02, 2020 4:23:30 PM AircondioningDevice.proto.ac.AirConClient currentDetails
WARNING: RPC failed: Status{code=NOT_FOUND, description=Not found, cause=null}

Я не знаю, полностью ли я отключен или ошибка небольшая. Какие-либо предложения? Еще одна вещь: у меня один и тот же прото-файл в java-клиенте и на сервере узлов, я не знаю, имеет ли это значение. И последнее: я также получаю это, когда запускаю свой сервер: DeprecationWarning: grpc.load: используйте модуль @ grpc / proto-loader с grpc.loadPackageDefinition вместо этого Я не знаю, имеет ли это какое-либо отношение с этим.


person Gavin Smith    schedule 02.04.2020    source источник
comment
Было бы намного проще выяснить, что идет не так, если бы вы могли показать некоторый минимальный код, воспроизводящий проблему, которую вы видите. В частности, создайте клиента, который ничего не делает, кроме выполнения определенных запросов, которые приводят к этой ошибке, без всего кода графического интерфейса или всего, что у вас есть.   -  person murgatroid99    schedule 02.04.2020
comment
хорошо, я редактирую мой вопрос сейчас   -  person Gavin Smith    schedule 02.04.2020
comment
извините, что редактирование заняло так много времени, у меня были проблемы с моими зависимостями, но в любом случае я добавил простой простой клиент с жестко закодированным запросом идентификатора. Однако я все еще получаю ту же ошибку.   -  person Gavin Smith    schedule 02.04.2020
comment
Я не уверен, что это усугубляет проблему, но отсутствие фигурных скобок вокруг содержимого цикла for и оператора if в обработчике службы затрудняет отслеживание.   -  person murgatroid99    schedule 03.04.2020
comment
Извините, я очистил его, так что, надеюсь, теперь его легче читать, но, к сожалению, это не было проблемой.   -  person Gavin Smith    schedule 03.04.2020


Ответы (1)


В вашем .proto файле вы объявляете deviceIDRequest с полем device_id, но вы проверяете call.request.id в обработчике currentDetails. Если вы посмотрите прямо на call.request.id, вероятно, это undefined.

Вы также еще не дошли до этого бита, но обратный вызов успеха использует массив books вместо массива AirConditioningDevice.

person murgatroid99    schedule 02.04.2020
comment
Они определенно вызвали бы ошибку на следующем этапе, поэтому спасибо, но я внес изменения, которые вы предложили, и я все еще получаю ту же ошибку :( - person Gavin Smith; 03.04.2020
comment
Имеет ли это какое-либо отношение к тому, что у меня есть прото-файл в java-клиенте и прото-файл на сервере узлов? - person Gavin Smith; 03.04.2020
comment
Я предполагаю, вы имеете в виду, что вы изменили обработчик на сервере, чтобы проверить call.request.device_id. Каково значение этого в функции-обработчике? - person murgatroid99; 03.04.2020
comment
Я изменил все, что сказал id на device_id, я отредактирую свой вопрос, чтобы показать вам :) - person Gavin Smith; 03.04.2020
comment
Какое значение call.request.device_id в функции-обработчике? - person murgatroid99; 03.04.2020
comment
У меня он установлен на 1. - person Gavin Smith; 03.04.2020
comment
Хорошо, добавьте пару вызовов console.log в функцию-обработчик. Зарегистрируйте call.request.device_id, device_id каждого члена AirConditioningDevice в цикле, и добавьте строки журнала в оператор if перед вызовом обратного вызова успеха и прямо перед вызовом обратного вызова ошибки. Проверьте вывод, чтобы увидеть, что происходит. - person murgatroid99; 03.04.2020
comment
Я ввел 4 журнала консоли во все места, о которых вы сказали, и когда я запустил клиент, я получил 4 вывода на сервере с надписью undefined. Я снова запустил клиент и получил еще 4, говорящих то же самое. Не знаю, поможет ли это? - person Gavin Smith; 03.04.2020
comment
Ладно, этого не должно быть. Просто отредактируйте эти вызовы журнала в своем вопросе, и я посмотрю. - person murgatroid99; 03.04.2020
comment
Во-первых, call.request.device_id быть undefined определенно проблемой. Добавьте console.log(call.request) в начало, чтобы увидеть, что там. Кроме того, вы должны регистрировать разные вещи в этих разных строках, чтобы знать, какой результат соответствует какой строке журнала. Нет смысла регистрировать call.request.device_id несколько раз, потому что вы никогда не меняете его. Вы должны регистрировать AirConditioningDevice[i].device_id в первой строке журнала в цикле, а другие данные - в других строках журнала. - person murgatroid99; 03.04.2020
comment
когда я делаю console.log(call.request) в начале функции, он говорит { deviceId: 1 }, что, на мой взгляд, хорошо, поскольку я знаю, что он отправляется. когда я делаю console.log(AirConditioningDevice[i].device_id) в цикле, вывод не определен, и я также добавил `console.log (call.request.device_id); под этим, и там также написано undefined. - person Gavin Smith; 03.04.2020
comment
Я изменил его на сервере на deviceId, и все ответы были 1 год. Огромное спасибо. единственное, ответ почему-то был пустым. - person Gavin Smith; 03.04.2020
comment
О, теперь я вижу проблему. См. Документацию для пакета proto-loader о keepCase опции. Кроме того, возможно, попробуйте удалить пробел между AirConditioningDevice и [i], где вы вызываете обратный вызов успеха. - person murgatroid99; 03.04.2020
comment
Я добавил опцию сохранения футляра, спасибо. Я также переместил [i] рядом с AirConditioningDevice, но, к сожалению, он все еще пуст, вероятно, что-то маленькое. - person Gavin Smith; 03.04.2020
comment
О, теперь я вижу проблему. Вы объявили ACResponse как сообщение с единственным полем airConditioning, которое содержит AirConditioning сообщение. Вы должны вернуть объект с такой структурой. - person murgatroid99; 03.04.2020
comment
хм, это может быть глупый вопрос, но я действительно не понимаю, что вы имеете в виду, не могли бы вы объяснить, пожалуйста? - person Gavin Smith; 03.04.2020
comment
вы имеете в виду использование: повторяется? - person Gavin Smith; 03.04.2020
comment
Я имею в виду, что элементы массива AirConditioningDevice имеют структуру, соответствующую сообщению AirConditioning. Тип ответа currentDetails (на самом деле, всех ваших методов) - это не сообщение AirConditioning. Это ACResponse, сообщение с полем airConditioning, содержащим AirConditioning. Таким образом, объект, который вы передаете в обратный вызов, должен быть объектом с полем airConditioning, которое содержит объект с той же структурой, что и сообщение AirConditioning. Другими словами, вы хотите callback(nulll, { airConditioning: AirConditioningDevice[i] }). - person murgatroid99; 03.04.2020
comment
да, это сработало. Большое спасибо за вашу помощь, я уверен, что многие люди уже ушли бы, лол. Я пометил этот ответ как полный. - person Gavin Smith; 03.04.2020