High CPU usage on PI on kaa client start - kaa

When I start the KAA client SDK ( JAVA ) on a raspberry PI the CPU usage shoots up to 100%. As soon as I kill the process the CPU usage drops back to normal
Below is the code snippet using to start the kaa where i am starting the kaa client on a raspberry pi
public class NotificationSystemTestApp {
private static final Logger LOG = LoggerFactory.getLogger(NotificationSystemTestApp.class);
public static void main(String[] args) throws InterruptedException {
/*System.out.println(encryptString("abcd", "12332sd1133sdssd45"));
return;*/
new NotificationSystemTestApp().launch();
}
private void launch() throws InterruptedException {
// Create client for Kaa SDK
final KaaClient kaaClient;
DesktopKaaPlatformContext desktopKaaPlatformContext = new DesktopKaaPlatformContext();
final CountDownLatch startupLatch = new CountDownLatch(1);
kaaClient = Kaa.newClient(desktopKaaPlatformContext, new SimpleKaaClientStateListener() {
#Override
public void onStarted() {
LOG.info("--= Kaa client started =--");
startupLatch.countDown();
}
#Override
public void onStopped() {
LOG.info("--= Kaa client stopped =--");
}
}, true);
kaaClient.setProfileContainer(new ProfileContainer() {
public ClientProfile getProfile() {
return new ClientProfile() {{
setClientProfileInfo(new ProfileInfo() {{
setRidlrId("R_00001");
setStationName("Mumbai");
setEquipmentId("EQ0006");
setStationId("5");
}});
}};
}
});
// Registering listener for topic updates
kaaClient.start();
startupLatch.await();
kaaClient.addTopicListListener(new NotificationTopicListListener() {
public void onListUpdated(List<Topic> topicList) {
System.out.println("Topic list updated!");
for (Topic topic : topicList) {
LOG.info("Received topic with id {} and name {}", topic.getId(), topic.getName());
}
}
});
final ScanInfo scanInfo = new ScanInfo() {{
setDestinationId("12");
setSourceId("3");
setEquipmentId("R_00001");
setScanTime(System.currentTimeMillis() / 1000);
setEvent("ENTRY");
setTransactionId(UUID.randomUUID().toString());
}};
kaaClient.attachEndpoint(new EndpointAccessToken("1234"), new OnAttachEndpointOperationCallback() {
#Override
public void onAttach(SyncResponseResultType result, EndpointKeyHash resultContext) {
}
});
kaaClient.attachUser("user1", "1234", new UserAttachCallback() {
public void onAttachResult(UserAttachResponse response) {
System.out.println("Attach User Success - " + response.getResult());
}
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
LOG.error("FATA", e);
}
LOG.debug("End Point key hash - " + kaaClient.getEndpointKeyHash());
while (true) {
kaaClient.addLogRecord(new LoggerSchema() {{
setData("");
setMessageType("");
}});
Thread.sleep(10);
}
}
}
Thanks,
Rizwan

As I see, you use constant addition of log records for upload to the Kaa server. The delay is just 10 milliseconds which might be too short for the Raspberry PI system you are running the application on.
Depending on the configuration, the Kaa Client might add considerable processing overhead for each log record with processing in other Java threads causing CPU to constantly spin adding and processing new records.
Try increasing the delay in your 'while (true)' loop and check the CPU usage with different log upload settings.
Should this information be not enough for you to fix the issue, please add logs from the Kaa client and Kaa server for investigation.

Related

rewrite an IHostedService to stop after all tasks finished

I have an application that normally should be a simple console application to be programmed as a scheduled task from time to time called by the windows task scheduler.
The program should launch some updates on two databases, one service per one database. Say ContosoDatabase should be updated by the ContosoService.
Finally it was written as an .NET Core app using, and maybe is not the best choice, the IHostedServices as base for the service, like this:
public class ContosoService : IHostedService {
private readonly ILogger<ContosoService> _log;
private readonly IContosoRepository _repository;
private Task executingTask;
public ContosoService(
ILogger<ContosoService> log,
IContosoRepository repository,
string mode) {
_log = log;
_repository = repository;
}
public Task StartAsync(CancellationToken cancellationToken) {
_log.LogInformation(">>> {serviceName} started <<<", nameof(ContosoService));
executingTask = ExcecuteAsync(cancellationToken);
// If the task is completed then return it,
// this should bubble cancellation and failure to the caller
if (executingTask.IsCompleted)
return executingTask;
// Otherwise it's running
// >> don't want it to run!
// >> it should end after all task finished!
return Task.CompletedTask;
}
private async Task<bool> ExcecuteAsync(CancellationToken cancellationToken) {
var myUsers = _repository.GetMyUsers();
if (myUsers == null || myUsers.Count() == 0) {
_log.LogWarning("{serviceName} has any entry to process, will stop", this.GetType().Name);
return false;
}
else {
// on mets à jour la liste des employés Agresso obtenue
await _repository.UpdateUsersAsync(myUsers);
}
_log.LogInformation(">>> {serviceName} finished its tasks <<<", nameof(ContosoService));
return true;
}
public Task StopAsync(CancellationToken cancellationToken) {
_log.LogInformation(">>> {serviceName} stopped <<<", nameof(ContosoService));
return Task.CompletedTask;
}
}
and I call it from main like this:
public static void Main(string[] args)
{
try {
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex) {
Log.Fatal(ex, ">>> the application could not start <<<");
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host
.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) => {
var config = hostContext.Configuration;
if (args.Contains("Alonso")) {
services
.AddHostedService(provider =>
new AlonsoService(
provider.GetService<ILogger<AlonsoService>>(),
provider.GetService<IAlonsoRepository>()));
}
// if there also Cedig in the list, they can be run in parallel
if (args.Contains("Contoso")) {
services
.AddHostedService(provider =>
new ContosoService(
provider.GetService<ILogger<ContosoService>>(),
provider.GetService<IContosoRepository>()));
}
});
Now, the problem, is surely, that the application will not stop once all updates finished.
Is there a way to quickly rewrite the application in order to make it stop after the second service finishes its tasks?
I tried to put the Environment.Exit(0); at the end
public static void Main(string[] args) {
try {
CreateHostBuilder(filteredArgs.ToArray()).Build().Run();
}
catch (Exception ex) {
//Log....
}
Environment.Exit(0); // here
}
but it does not seem to help: the application is still running after all task are completed.
Following #Maxim's suggestion, I found this dirty but working workaround, by injecting the IHostApplicationLifetime and the lastService boolean:
public ConsosoService(
IHostApplicationLifetime hostApplicationLifetime,
// ...
bool lastService)
{ ... }
public async Task StartAsync(CancellationToken cancellationToken)
{
// do the job
if (_lastService)
_hostApplicationLifetime.StopApplication();
// stops the application and cancel/stops other services as well
}
HostedServices are background services. It's the other way around: they can react to application start and stop events, so that they can end gracefully. They are not meant to stop your main application when finished, they potentially live as long as the application does.
I'd say you will be better served with simple Tasks and awaiting all of them. Or send some events when your background jobs finishes its work and handle them in main.
Whatever trigger you may choose you can stop .net app by injecting IHostApplicationLifetime and calling StopApplication() method on it. In earlier versions it's just IApplicationLifetime.
Looking at IHost Interface documentation the method run() does not stop until the host is shutdown. seems that StopAsync() did not stop the service. so Environment.Exit(0); was never reached. maybe use CancellationToken to forcefully end the host, or inject Environment.Exit(0); in ContosoService class if possible even though not optimal.
Here is another approach without need for creating hosted service
using var host = CreateHostBuilder(args).Build();
await host.StartAsync();
using var scope = host.Services.CreateScope();
var worker = scope.ServiceProvider.GetService<Worker>();
await worker!.Run();
await host.StopAsync();
IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(services => ConfigureServices(services));
void ConfigureServices(IServiceCollection services)
{
//main class which does the work
services.AddScoped<Worker>();
//do some DB operations
services.AddScoped<DbCtxt>();
}
Complete code https://github.com/raghavan-mk/dotnet/tree/main/DIInConsole

Open and close channel in the gRPC client with every request

I have a gRPC client in a kafka application. This means the client will constantly open and close channels.
public class UserAgentClient {
protected final Logger logger = LoggerFactory.getLogger(getClass());
private static final Config uaparserConfig = ConfigFactory.load().getConfig(ua);
private final ManagedChannel channel;
private final UserAgentServiceGrpc.UserAgentServiceBlockingStub userAgentBlockingStub;
public UserAgentParserClient() {
this(ManagedChannelBuilder.forAddress(uaConfig.getString("host"), uaConfig.getInt("port")).usePlaintext());
}
public UserAgentClient(ManagedChannelBuilder<?> usePlaintext) {
channel = usePlaintext.build();
userAgentBlockingStub = UserAgentServiceGrpc.newBlockingStub(channel);
}
public UserAgentParseResponse getUserAgent(String userAgent ) {
UserAgentRequest request = UserAgentRequest.newBuilder().setUserAgent(userAgent).build();
UserAgentParseResponse response = null;
try {
response = userAgentBlockingStub.parseUserAgent(request);
} catch(Exception e) {
logger.warn("An exception has occurred during gRPC call to the user agent.", e.getMessage());
}
shutdown();
return response;
}
public void shutdown() {
try {
channel.shutdown();
} catch (InterruptedException ie) {
logger.warn("Interrupted exception during gRPC channel close", ie);
}
}
}
I was wondering if I can keep the channel open the whole time? Or do I have to open a channel every time I make a new call? I was wondering because I was testing the performance and it seems to improve drastically if I just keep the channel open. On the other hand is there something that I'm missing?
creating a new channel has huge overhead, you should keep the channel open as long as possible.
Since the opening and closing of channel is expensive I removed the channel = usePlaintext.build(); completely from my client
Instead I'm opening and closing it in my kafka Transformer. In my class UserAgentDataEnricher that implements Transformer.
public class UserAgentDataEnricher implements Transformer<byte[], EnrichedData, KeyValue<byte[], EnrichedData>> {
private UserAgentParserClient userAgentParserClient;
#Override
public void init(ProcessorContext context) {
this.context = context;
open();
// schedule a punctuate() method every 15 minutes
this.context.schedule(900000, PunctuationType.WALL_CLOCK_TIME, (timestamp) -> {
close();
open();
logger.info("Re-opening of user agent channel is initialized");
});
}
#Override
public void close() {
userAgentParserClient.shutdown();
}
private void open() {
channel = ManagedChannelBuilder.forAddress("localhost", 50051).usePlaintext().build();
userAgentClient = new UserAgentClient(channel);
}
...
}
and now I initialize my client like that:
public UserAgentClient(ManagedChannel channel) {
this.channel = channel;
userAgentBlockingStub = UserAgentServiceGrpc.newBlockingStub(channel);
}

How to use ContainerStoppingErrorHandler in #KafkaListener to terminate application incase of Kafka server DisconnectException

I want to handle the Server DisconnectException and terminate the application when the server DisconnectException occurs
how to catch this error and stop the application?
#KafkaListener(topics = { "${kafka.status-topic}", "${kafka.start-topic}" }, containerFactory = "kafkaListenerContainerFactory")
public void listen(#Payload final String message,
#Header(KafkaHeaders.RECEIVED_TOPIC) final String topic) {
log.debug("Received '{}'-message {} from Kafka", topic, message);
LinkedList<IMessageListener> topicListeners = listeners.get(topic);
for (final IMessageListener l : topicListeners) {
// call listeners in a separate thread
executor.execute(new Runnable() {
#Override
public void run() {
l.messageReceived(topic, message);
}
});
}
}
You can try catching the exception and then calling System.exit(0) inside catch block

How to send objects over a network using Kryonet?

I am new to networking, and I am trying to network a board game that I have created using java.A friend of mine pointed me towards the Kryonet library. So far, it's great. I don't have to deal with sockets!
The problem I'm coming across is sending objects. Mainly, I have a Board type object. This object contains other objects, such as ArrayList objects and Fort objects.
I tried just registering the Board object, but I received these errors:
Exception in thread "Server" com.esotericsoftware.kryo.KryoException: java.lang.
IllegalArgumentException: Class is not registered: Game.Tile
Note: To register this class use: kryo.register(Game.Tile.class);
Serialization trace:
t0 (Game.Board)
at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:585)
at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:213)
at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:571)
at com.esotericsoftware.kryonet.KryoSerialization.write(KryoSerializatio
n.java:50)
at com.esotericsoftware.kryonet.TcpConnection.send(TcpConnection.java:192)
etc....
Ok fine, Then I will also register Tile.class,
More errors, but then I need to register ArrayList.class - so I register it, and again more errors, so I register Fort.class.
When I register Fort.class, I enter into an infinite loop and get a ton of errors like this:
at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:564)
at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:213)
at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:504)
at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:564)
at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:213)
at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:504)
at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:564)
This leads me to believe I don't quite understand how to register properly and I can't find much information about how to register nested objects. My Fort class is actually an enumerated class but I'm not sure if that makes a difference? Any help would be greatly appreciated!
I have included a class with most of my networking code so you can see an idea of what I am trying to do.
This is my code for the networking:
public class Network extends Listener {
private Server server;
private Client client;
private boolean isServer;
private boolean messageReceived;
private PacketMessage message;
private Board board;
public Network(boolean isServer, Board board) throws IOException {
messageReceived = false;
this.board = board;
this.isServer = isServer;
if (isServer) {
initServer();
// receive();
} else {
initClient();
//probably want to run this in main
client();
}
}
private void initServer() throws IOException {
// 127.0.0.1 means myself
// ports up to 1024 are special and reserved
server = new Server();
registerClasses(server.getKryo());
server.bind(8000, 8001);
// starting a new thread
server.start();
// call my received and my connected
server.addListener(this);
}
private void initClient() throws IOException {
// 127.0.0.1 means myself
// ports up to 1024 are special and reserved
client = new Client();
registerClasses(client.getKryo());
// starting a new thread
client.start();
client.connect(5000, "127.0.0.1", 8000, 8001);
// call my received and call my connected
client.addListener(this);
}
//call in main
//
public void client(){
while(true){
sendRequest();
receive();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// tell Kryo what things it's going to have to send
private void registerClasses(Kryo kryo) {
kryo.register(Request.class);
kryo.register(PacketMessage.class);
kryo.register(Fort.class);
kryo.register(ArrayList.class);
kryo.register(Tile.class);
kryo.register(Board.class);
}
private void sendRequest() {
client.sendTCP(new Request());
}
private void receive() {
messageReceived = false;
while (!messageReceived) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// message.message is really packet.message
System.out.println("Received a message from the host: "
+ message.message);
}
public void received(Connection c, Object p) {
System.out.println("Received Message");
// Is the received packet the same class as PacketMessage.class?
if (p instanceof PacketMessage) {
// Cast it so we can access the message within
// PacketMessage packet =(PacketMessage) p;
// System.out.println("Received a message from the host: "+pa cket.message);
message = (PacketMessage) p;
// We have now received the message!
messageReceived = true;
}
else if (p instanceof Request){
// Create a message packet
PacketMessage packetMessage = new PacketMessage();
// Assign the message text
packetMessage.message = "Hello friend! The time is: "
+ new Date().toString();
// Send the message
//probably want another method to send
c.sendTCP(packetMessage);
c.sendTCP(board);
}
}
// This is run when a connection is received!
public void connected(Connection c) {
System.out.println("Received a connection from "
+ c.getRemoteAddressTCP().getHostString());
}
}
What is likely happening is that your Fort class contains a member of type Board, and this circular reference causes an infinite loop when serializing Fort.
Use the transient keyword to exclude members from serialization, or remove the circular reference altogether.

Netty: What is the right way to share NioClientSocketChannelFactory among multiple Netty Clients

I am new to Netty. I am using “Netty 3.6.2.Final”. I have created a Netty Client (MyClient) that talks to a remote server (The server implements a custom protocol based on TCP). I create a new ClientBootstrap instance for each MyClient instance (within the constructor).
My question is if I share “NioClientSocketChannelFactory” factory object among all the instances of MyClient then when/how do I release all the resources associated with the “NioClientSocketChannelFactory”?
In other words, since my Netty Client runs inside a JBOSS container running 24x7, should I release all resources by calling “bootstrap.releaseExternalResources();” and when/where should I do so?
More Info: My Netty Client is called from two scenarios inside a JBOSS container. First, in an infinite for loop with each time passing the string that needs to be sent to the remote server (in effect similar to below code)
for( ; ; ){
//Prepare the stringToSend
//Send a string and receive a string
String returnedString=new MyClient().handle(stringToSend);
}
Another scenarios is my Netty Client is called within concurrent threads with each thread calling “new MyClient().handle(stringToSend);”.
I have given the skeleton code below. It is very similar to the TelnetClient example at Netty website.
MyClient
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
public class MyClient {
//Instantiate this only once per application
private final static Timer timer = new HashedWheelTimer();
//All below must come from configuration
private final String host ="127.0.0.1";
private final int port =9699;
private final InetSocketAddress address = new InetSocketAddress(host, port);
private ClientBootstrap bootstrap;
//Timeout when the server sends nothing for n seconds.
static final int READ_TIMEOUT = 5;
public MyClient(){
bootstrap = new ClientBootstrap(NioClientSocketFactorySingleton.getInstance());
}
public String handle(String messageToSend){
bootstrap.setOption("connectTimeoutMillis", 20000);
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("keepAlive", true);
bootstrap.setOption("remoteAddress", address);
bootstrap.setPipelineFactory(new MyClientPipelineFactory(messageToSend,bootstrap,timer));
// Start the connection attempt.
ChannelFuture future = bootstrap.connect();
// Wait until the connection attempt succeeds or fails.
channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
return null;
}
// Wait until the connection is closed or the connection attempt fails.
channel.getCloseFuture().awaitUninterruptibly();
MyClientHandler myClientHandler=(MyClientHandler)channel.getPipeline().getLast();
String messageReceived=myClientHandler.getMessageReceived();
return messageReceived;
}
}
Singleton NioClientSocketChannelFactory
public class NioClientSocketFactorySingleton {
private static NioClientSocketChannelFactory nioClientSocketChannelFactory;
private NioClientSocketFactorySingleton() {
}
public static synchronized NioClientSocketChannelFactory getInstance() {
if ( nioClientSocketChannelFactory == null) {
nioClientSocketChannelFactory=new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
}
return nioClientSocketChannelFactory;
}
protected void finalize() throws Throwable {
try{
if(nioClientSocketChannelFactory!=null){
// Shut down thread pools to exit.
nioClientSocketChannelFactory.releaseExternalResources();
}
}catch(Exception e){
//Can't do anything much
}
}
}
MyClientPipelineFactory
public class MyClientPipelineFactory implements ChannelPipelineFactory {
private String messageToSend;
private ClientBootstrap bootstrap;
private Timer timer;
public MyClientPipelineFactory(){
}
public MyClientPipelineFactory(String messageToSend){
this.messageToSend=messageToSend;
}
public MyClientPipelineFactory(String messageToSend,ClientBootstrap bootstrap, Timer timer){
this.messageToSend=messageToSend;
this.bootstrap=bootstrap;
this.timer=timer;
}
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
// Add the text line codec combination first,
//pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
//Add readtimeout
pipeline.addLast("timeout", new ReadTimeoutHandler(timer, MyClient.READ_TIMEOUT));
// and then business logic.
pipeline.addLast("handler", new MyClientHandler(messageToSend,bootstrap));
return pipeline;
}
}
MyClientHandler
public class MyClientHandler extends SimpleChannelUpstreamHandler {
private String messageToSend="";
private String messageReceived="";
public MyClientHandler(String messageToSend,ClientBootstrap bootstrap) {
this.messageToSend=messageToSend;
this.bootstrap=bootstrap;
}
#Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e){
e.getChannel().write(messageToSend);
}
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e){
messageReceived=e.getMessage().toString();
//This take the control back to the MyClient
e.getChannel().close();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
e.getChannel().close();
}
}
You should only call releaseExternalResources() once you are sure you not need it anymore. This may be for example when the application gets stopped or undeployed.

Resources