Quick disclaimer, I am very new to gRPC and RPC in general, so please have patience
I have two gRPC servers running on the same java application, Service A and Service B.
Service A creates multiple clients of Service B which then synchronously makes calls to the various instances of Service B
The server
Service A has a rpc call defined by the .proto file as
rpc notifyPeers(NotifyPeersRequest) returns (NotifyPeersResponse);
the server side implementation,
#Override
public void notifyPeers(NotifyPeersRequest request, StreamObserver<NotifyPeersResponse> responseObserver) {
logger.debug("gRPC 'notifyPeers' request received");
String host = request.getHost();
for (PeerClient c : clients.values()) {
c.addPeer(host); // <---- this call
}
NotifyPeersResponse response = NotifyPeersResponse.newBuilder()
.setResult(result)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
The list of peers, clients are built up in previous rpc calls.
ManagedChannel channel = ManagedChannelBuilder.forTarget(peer).usePlaintext().build();
ClientB client = new ClientB(channel);
clients.put(peer, client);
The client
rpc addPeer(AddPeerRequest) returns (AddPeerResponse);rpc addPeer(AddPeerRequest) returns (AddPeerResponse);
the server side implementation,
#Override
public void addPeer(AddPeerRequest addPeerRequest, StreamObserver<AddPeerResponse> responseObserver) {
logger.info("gRPC 'addPeer' request received");
boolean result = peer.addPeer(host);
AddPeerResponse response = AddPeerResponse.newBuilder()
.setResponse(result)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
the client side implementation,
public boolean addPeer(String host) {
AddPeerRequest request = AddPeerRequest.newBuilder().setHost(host).build();
logger.info("Sending 'addPeer' request");
AddPeerResponse response = blockingStub.addPeer(request);
return response.getResponse();
}
When I run this application, and an RPC is made to Service A and the client connection is created that calls addPeer, an ambiguous exception is thrown, io.grpc.StatusRuntimeException: UNKNOWN which then causes the JVM to shut down. I have no idea how to fix this, or whether it is even possible to create an gRPC client connection within a gRPC server
for all of my gRPC server implementations I'm using blocking stubs.
<grpc.version>1.16.1</grpc.version>
<java.version>1.8</java.version>
I've pretty much hit a brick wall, so any information will be appreciated
The UNKNOWN message is an exception on the server side that was not passed to the client.
You probably need to increase the log level on the server to try to find the root cause.
In this post here ,
creating the channel like below, enable it to see a more meaningful error message:
ManagedChannel channel = NettyChannelBuilder.forAddress( host, port )
.protocolNegotiator(ProtocolNegotiators.serverPlaintext() )
If A and B are in the same application have you considered making direct function calls or at least using the InProcessChannelBuilder and InProcessServerBuilder?
As mentioned elsewhere, in the current setup you can try increasing the log level on the server side (in B) to see the source of the exception.
Related
I am using Mina V2.1.3 for a network application; especially I have a udp session problem: I want to publish messages to specific "ips" and "ports" of some receivers via Udp. But I don't know (and I dont care) if such receivers are really listening to their ports and really received the packages.
In case that no receiver is listening to its port, Mina will receive an ICMP-Package back, which means, that the port is unreachable. Mina caughts this Package and throws an UnreachablePortException. Then Mina closes the session object and stops sending. My aim is to ignore the "destination unreachable" packages and therefore i want to still send udp packages ("fire-and-forget principle").
Here is my approach (some kind of pseudo code):
NioDatagramConnector connector = new NioDatagramConnector();
((DatagramSessionConfig) connector.getSessionConfig()).setCloseOnPortUnreachable(false);
connector.getStatistics().setThroughputCalculationInterval(1);
connector.getFilterChain().addLast("logger", new LoggingFilter());
DefaultIoFilterChainBuilder filterChainBuilder = connector.getFilterChain();
filterChainBuilder.addFilter(...);
connector.setHandler(this);
for (UDPClient client : udpClients) {
((NioDatagramConnector)connector).connect(new InetSocketAddress(client.getIP(), client.getPort()));
}
//Sending data
while(true) {
connector.broadcast("Message");
Thread.sleep(10);
}
public void sessionClosed(IoSession session) throws Exception {
System.out.println("Called after ICMP package is received");
}
//Further methods which are based of IoHandler
Based on debugging, I can see that Mina will remove this session and finally calls the closeSession()-method (given from IoHandler).
As discussed in the bug report https://issues.apache.org/jira/browse/DIRMINA-1137
A UDP server socket needs to be open on the remote device at the remote port otherwise you will get UnreachablePortException. This exception is not done by MINA or JAVA but rather POSIX and is universal.
I have a standalone zookeeper server running.
client = CuratorFrameworkFactory.newClient(zkHostPorts, retryPolicy);
client.start();
assertThat(client.checkExists().forPath("/")).isNotNull(); // working
listener = new LeaderSelectorListenerAdapter() {
#Override
public void takeLeadership(CuratorFramework client) throws Exception {
System.out.println("This method is never called! :( ");
Thread.sleep(5000);
}
};
String path = "/somepath";
leaderSelector = new LeaderSelector(client, path, listener);
leaderSelector.autoRequeue();
leaderSelector.start();
I am connecting to the server successfully, defining a listener and starting leader election.
Note: There is only 1 client.
But my client app is never taking leadership. I am not able to figure out what I am doing wrong. Also this is a trivial single client scenario. Shouldn't the client already be a leader
EDIT:
It works if I use TestingServer from curator-test library instead of starting my Zookeeper server, like below -
TestingServer server = new TestingServer();
client = CuratorFrameworkFactory.newClient(server.getConnectString(), retryPolicy);
...
Does this mean there is something wrong with my zookeeper server.
This is my zoo.cfg -
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper/ex1
clientPort=2181
Also, the server appears to be working fine as I am able to connect to it using cli and am able to create/delete zNodes.
I am novice in soap and jax-ws.
After reading many information I knew that eclipse can catch soap messages, But I have problem with it.
my publisher
public static void main(String[] args) {
Endpoint.publish("http://localhost:8081/WS/Greeting",
new GreetingImpl());
}
my cient
public static void main(String[] args) {
GreetingImplService service = new GreetingImplService();
Greeting greeting = service.getGreetingImplPort();
System.out.println("------->> Call Started");
System.out.println(greeting.sayHello("friend !!!"));
System.out.println("------->> Call Ended");
}
When I invoke client in Console I see
------->> Call Started
Hello, Welcom to jax-ws friend !!!
------->> Call Ended
Therefore it is working service.
But in TCP|IP monitor I see empty list.
my configuration of TCP|IP monitor
What Do I make wrong?
please, help)
I think that the probelm is that your client is pointing directly to port 8081 (the port of the ws) so the tcp/ip monitor does not come into play. Since the monitor is listening on port 8080, your client should use this endpoint:
http://localhost:8080/WS/Greeting
The TCP/IP monitor will receive the http request and then it will forward the message to
http://localhost:8081/WS/Greeting
To alter the endpoint used by the client you have 2 possibilities:
If the client uses a local wsdl document (for example you have saved a copy of the wsdl on your file system and used it to call wsimport), you can modify the endpoint in it (look at the element service at the end of the wsdl). The stub returned by service.getGreetingImplPort() reads the endpoint from the wsdl.
You can use this instruction in the main method of the client
((BindingProvider) greeting).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,"http://localhost:8080/WS/Greeting");
I'm using Jersey to simply connect and grab a web resource, but after it finishes, the client doesn't "disconnect" and just hangs.
public String getResource() {
Client client = Client.create(config);
WebResource resource = client.resource(someURI);
return resource.path("path").path("to").path("resource").accept(....).get(String.class);
}
If I call this method from a main, it does return the proper resource, but the program doesn't exit afterward.
if you have now pending responses and want to free your resorce, you should use client.destroy().
I have to implement a webservice client to a given WSDL file.
I used the SDK's 'wsimport' tool to create Java classes from the WSDL as well as a class that wrap's the webservice's only method (enhanceAddress(auth, param, address)) into a simple java method. So far, so good. The webservice is functional and returning results correcty. The code looks like this:
try {
EnhancedAddressList uniservResponse = getWebservicePort().enhanceAddress(m_auth, m_param, uniservAddress);
//Where the Port^ is the HTTP Soap 1.2 Endpoint
}catch (Throwable e) {
throw new AddressValidationException("Error during uniserv webservice request.", e);
}
The Problem now: I need to get Information about the connection and any error that might occur in order to populate various JMX values (such as COUNT_READ_TIMEOUT, COUNT_CONNECT_TIMEOUT, ...)
Unfortunately, the method does not officially throw any Exceptions, so in order to get details about a ConnectException, i need to use getCause() on the ClientTransportException that will be thrown.
Even worse: I tried to test the read timeout value, but there is none. I changed the service's location in the wsdl file to post the request to a php script that simply waits forever and does not return. Guess what: The web service client does not time out but waits forever as well (I killed the app after 30+ minutes of waiting). That is not an option for my application as i eventually run out of tcp connections if some of them get 'stuck'.
The enhanceAddress(auth, param, address) method is not implemented but annotated with javax.jws.* Annotations, meaning that i cannot see/change/inspect the code that is actually executed.
Do i have any option but to throw the whole wsimport/javax.jsw-stuff away and implement my own soap client?
to setup read-timeout and connect timeouts you can configure the binding parameters when you setup your Service and Port instances:
Service = new Service();
Port = Service.getPort();
((BindingProvider) Port).getRequestContext().put(
BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"http://localhost:8080/service");
((BindingProvider) Port).getRequestContext().put(
BindingProviderProperties.CONNECT_TIMEOUT,
30);
((BindingProvider) Port).getRequestContext().put(
BindingProviderProperties.REQUEST_TIMEOUT,
30);
now whenever you execute a service via "Port" you will get response timeouts and/or connection timeouts if the backend is slow to respond. the values follow the timeout values of the Socket Class.
when these timeouts are exceeded you will get timeout exeption or a connection exception and you can put counter-code to keep track of how many you get.