Websocket Servlet thread-safe - multithreading

I'am playing around with WebSocketServlet (tomcat) and I have some question about doing it properly without race condition problems.
I have an instance variable (so non thread-safe) that will keep track of all the websocket connections
HashMap<String,MyServers> myNonThreadSafeVariable = HashMap<String,MyServers>
This is what the HashMap will contain (roughly...)
private final class MyServers extends MessageInbound {
final Set<MyClients> clients = new CopyOnWriteArraySet<MyClients>();
private String serverName;
#Override
protected void onOpen(WsOutbound outbound) {}
#Override
protected void onClose(WsOutbound outbound) {}
#Override
protected void onText(WsOutbound outbound) {}
}
private final class Clients extends MessageInbound {
private int clientID;
#Override
protected void onOpen(WsOutbound outbound) {}
#Override
protected void onClose(WsOutbound outbound) {}
#Override
protected void onText(WsOutbound outbound) {}
}
So now.. during my servlet life time, I am looping through myNonThreadSafeVariable and then maybe also will loop through myNonThreadSafeVariable.clients and then maybe also modified or add a clients or server etc...
For example when a server connect, in his onOpen there will be something like
myNonThreadSafeVariable.put(key,this);
or When a client connects in his onOpen (quit concern about this one)
server = myNonThreadSafeVariable,get(key);
sever.clients.add(this);
Or sometimes when I have to ping all the clients of all the servers:
for (Entry<String, MyServers> entry : myNonThreadSafeVariable.entrySet()) {
MyServers server = entry.getValue();
server.sendMessage("ping||");
for (MyClients member : entry.getValue().clients) {
client.sendMessage("")
}
}
So If I undertand correctly as myNonThreadSafeVariable is global so will myNonThreadSafeVariable.clients etc..
So my question is what is a good practice to avoid race condition in this scenario ?
Using mutex and synchronized on them when access ether the myNonThreadSafeVariable and myNonThreadSafeVariable.clients ? Or should I avoid using an instance variable at all ? But how ?
thanks !

You could use a ReadWriteLock: you block readers and writers when writing, you block only writers when reading:
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
...
writeLock.lock();
try
{
myNonThreadSafeVariable.put(key,this);
}
finally
{
writeLock.unlock();
}
...
writeLock.lock();
try
{
server = myNonThreadSafeVariable,get(key);
sever.clients.add(this);
}
finally
{
writeLock.unlock();
}
...
readLock.lock();
try
{
for (Entry<String, MyServers> entry : myNonThreadSafeVariable.entrySet())
{
MyServers server = entry.getValue();
server.sendMessage("ping||");
for (MyClients member : entry.getValue().clients)
{
client.sendMessage("")
}
}
}
finally
{
readLock.unlock();
}
Moreover if you want to avoid the read lock you can copy the whole collection and scan the copy, letting the possibility for the original collection to be changed while notifying.

Related

Netty ChannelInboundHandlerAdapter async/multithreading

I'm having trouble grasping the concepts behind multithreading in netty, EventLoopGroup (MultithreadEventLoopGroup), MultithreadEventExecutorGroup, DefaultEventExecutorGroup
I am trying to understand how the server handles multiple clients simultaneously sending requests that will execute some business logic and CRUD operations that add to RTT. Below is my netty server code which works, but I am trying to understand exactly how it will work with concurrent users and multiple open channels.
I have a simple ServerBootstrap
#Component
#RequiredArgsConstructor
public class SocketServer {
private final ContextAwareLogger logger;
private final ServerInitializer serverInitializer;
private final NioEventLoopGroup bossGroup;
private final NioEventLoopGroup workerGroup;
private Channel mainChannel;
#PostConstruct
public void start() {
try {
ServerBootstrap bootstrap = init();
mainChannel = bootstrap.bind(8484).sync().channel(); // save the main channel so we can cleanly close it when app is shutdown
logger.info("Netty server started...");
} catch (Exception e) {
e.printStackTrace();
}
}
#PreDestroy
public void stop() throws InterruptedException {
logger.info("Shutting down Netty server");
bossGroup.shutdownGracefully().sync();
workerGroup.shutdownGracefully().sync();
mainChannel.closeFuture().sync();
logger.info("Netty Server shutdown complete.");
}
private ServerBootstrap init() {
return new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 5000)
.option(ChannelOption.TCP_NODELAY, true)
.option(ChannelOption.SO_KEEPALIVE, true)
.childHandler(serverInitializer);
}
}
ChannelInitializer:
#Component
#RequiredArgsConstructor
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
private final PacketDecoder packetDecoder;
private final ServerHandler serverHandler;
private final PacketEncoder packetEncoder;
#Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline()
.addLast("decoder", packetDecoder) // ByteArrayDecoder
.addLast("encoder", packetEncoder) // ByteArrayEncoder
.addLast("inbound", serverHandler); // ChannelInboundHandlerAdapter
}
}
ChannelInboundHandlerAdapter:
#Component
#Sharable
public class ServerHandler extends ChannelInboundHandlerAdapter {
#Autowired
private SomeService someService;
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// contains db access
byte[] accept = someService.validateClient(ctx.channel());
ctx.channel().writeAndFlush(accept);
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// may contain db access
byte[] response = someService.processPacket(ctx.channel(), msg));
ctx.channel().writeAndFlush(response);
}
}
Now when a client connects, I understand that a new Channel will opened and the handlers will be reused. Requirement is each client request/response needs to process immediately without waiting for some other client's CRUD operations to finish.
Are my channelRead and channelActive, etc, async because I am using NioEventLoopGroup (ie will each client's channel operations be run independent of each other)?
If a single client sends multiple requests in series, are they guaranteed to be handled in the same order?
Do I need to specific DefaultEventExecutorGroup for my inbound handler? (https://stackoverflow.com/a/28305019/1738539)
You either would need to use a DefaultEventExecutorGroup for your ServerHandler or dispatch the validateClient(...) / processPacket(...) to your own ThreadPool. Failing todo so will cause the EventLoop thread to block and so no other IO can be processed for this EventLoop until the blocking operation completes.

Spring boot multithreaded async not working

The task is to call a database, retrieve certain records update and save them.
As the amount of records if fairly large we want to do this Async, however, this doesn't seem to be implemented correctly.
The main class:
#SpringBootApplication
#EnableAsync
MainApplication() {
#Bean("threadPoolExecutor")
public TaskExecutor getAsyncExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(DataSourceConfig.getTHREAD_POOL_SIZE());
executor.setMaxPoolSize(DataSourceConfig.getTHREAD_POOL_SIZE());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setThreadNamePrefix("RetryEnhancement-");
return executor;
}
}
Method in the first service:
#Service
public class FirstService() {
#Transactional
public void fullProcess() {
for(int counter = 0; counter < ConfigFile.getTHREADS(); counter++){
secondaryService.threads();
}
}
}
Method in the second service:
#Service
public class SecondService () {
#Async("threadPoolExecutor")
public void threads() {
while(thirdService.threadMethod()) {
//doNothing
}
}
}
Method in the third service:
#Service
public class ThirdService() {
#Transactional
public boolean threads() {
Record record = repository.fetchRecord();
if(record!=null) {
updateRecord(record);
saveRecord(record);
return true;
} else {
return false;
}
}
}
Repository:
public interface repository extends CrudRepository<Record, long> {
#Lock(LockModeType.PESSIMISTIC_WRITE)
Record fetchRecord();
}
The issue I'm finding is that, while the code executes perfectly fine, it seems to have a Synchronous execution (found by adding a .sleep and watching the execution in the logger).
The seperate threads seem to be waiting until the other is executed.
I'm probably doing something wrong and if another thread already explains the issue, than please refer it, though I have not been able to find this issue in a different thread.
Your solution is way to complex. Ditch all of that and just inject the TaskExecutor and do the updateRecord in a separate thread (you might need to retrieve it again as you are now using a different thread and thus connection.
Something like this should do the trick
private final TaskExecutor executor; // injected through constructor
public void process() {
Stream<Record> records = repository.fetchRecords(); // Using a stream gives you a lazy cursor!
records.forEach(this::processRecord);
}
private void processRecord(Record record) {
executor.submit({
updateRecord(record);
saveRecord(record);
});
}
You might want to put the processRecord into another object and make it #Transactional or wrap it in a TransactionTemplate to get that behavior.

Synchronizing an audio file over network in Unet

I have a gameObject "plane" that isn't controlled by the clients. it gets spawned with an audio source that plays a clip when the host clicks a certain button. i would like the sound to be heard by the clients, i tried using rpc but i can't seem to be able to send them.
i keep getting the error: Found no behaviour for incoming [ClientRpc:InvokeRpcRpc_SendSoundIDToServer] on plane (UnityEngine.GameObject), the server and client should have the same NetworkBehaviour instances.
It's been driving me crazy for more than a day, i would really apreciate some help.
Here's my code:
using UnityEngine;
using UnityEngine.Networking;
[RequireComponent(typeof(AudioSource))]
[RequireComponent(typeof(NetworkIdentity))]
public class SpoolUp : NetworkBehaviour
{
private AudioSource source;
public AudioClip[] clips;
public bool start;
void Start()
{
clips = Resources.LoadAll("Audio");
source = GetComponent();
source.playOnAwake = false;
}
public void Spool()
{
start = true;
if (isServer)
PlaySound(0);
}
public void PlaySound(int id)
{
if (id >= 0 && id < clips.Length)
{
RpcPlaySound(id);
}
}
[ClientRpc]
void RpcPlaySound(int id)
{
source.PlayOneShot(clips[id]);
}
PS: I also get the following warning: ClientRpc [ClientRpc:InvokeRpcRpcPlaySound] handler not found [netId=4]

Android: "Application level" Pause and Resume [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I've been trying to get Application Level Pause and Resume similar to an activity's onPause and onResume. I know there's no API that has this functionality.
I try to follow this post: http://curioustechizen.blogspot.com/2012/12/android-application-level-pause-and.html
But I've had no luck so far.
Has anyone been able to achieve this? What paradigm did you use?
Let me know if you need me to paste some code into this question.
Thanks for the help
Another solution to the problem would be to just keep track of the count of onStart() and onStop() calls from every activity. Example:
First, create a class to hold the counts:
public class ActiveActivitiesTracker {
private static int sActiveActivities = 0;
public static void activityStarted()
{
if( sActiveActivities == 0 )
{
// TODO: Here is presumably "application level" resume
}
sActiveActivities++;
}
public static void activityStopped()
{
sActiveActivities--;
if( sActiveActivities == 0 )
{
// TODO: Here is presumably "application level" pause
}
}
}
Then in every activity, simply call the activityStarted() and activityStopped() methods:
#Override
public void onStart() {
super.onStart();
ActiveActivitiesTracker.activityStarted();
}
#Override
public void onStop() {
super.onStop();
ActiveActivitiesTracker.activityStopped();
}
I had the same problem. My aim was to lock the App, if the user abandons it. A simple aim, which i thought would be easy to implement. But all the solutions I found were way to complex. So I came to a simple solution: A time based lock.
Basically it works like this:
Start countdown to lock app in onPause
Stop countdown in onResume
If onResume is not called in time, change to locked
Therefor I created a small little class:
public class ApplicationLock {
private static final String TAG = ApplicationLock.class.getSimpleName();
private static final int LOCK_TIME = 1000; //lock after a second
private static boolean lock = true; //default is locked
private static Handler handler = new Handler();
private static Runnable runnable = new Runnable() {
#Override
public void run() {
lock = true;
Log.i("ActivityTracker", "App locked");
}
};
public static boolean activityStarted()
{
handler.removeCallbacks(runnable);
if(lock)
{
Log.i(TAG, "App resumed - LOCKED");
return true;
}else{
Log.i(TAG, "App resumed - NOT LOCKED");
return false;
}
}
public static void activityStopped()
{
handler.postDelayed(runnable, LOCK_TIME);
Log.i(TAG, "App paused - Starting countdown");
}
Just call activityStopped() in your activities onPause() and activityStarted() in onResume(). Check the result of activityStarted(). If it returns true, lock your app. If the orientation of the app is changed, onResume will be called very quickly after onPause, so the app will not lock.
This solution might not fit every scenario, but in my case it was the best solution. Additionally you can change the countdown, to increase the user experience (The user pressed a wrong button and returns to the app in a few seconds, no need to lock the app). Hope this is useful to someone else.
I have done something very similar to this in an app which used a service that provided GPS functions by several activities. The idea was to only have the service there when one of the activities that used it is visible, and not there when none are visible. In your case, every activity would hook into a service, and you will know when the entire application was paused or resumed by hooking into the service's onCreate() and onDestroy() methods.
Here is a stripped-down example:
Components needed (these could probably be placed into a utility class if you want to reuse them, or I just had them for each activity class):
private boolean mAppActiveServiceBound = false;
private AppActiveService mAppActiveService = null;
private ServiceConnection mAppActiveConnection = new ServiceConnection() {
public void onServiceConnected( ComponentName className, IBinder service ) {
mAppActiveService = ( (AppActiveService.AppActiveBinder) service ).getService();
}
public void onServiceDisconnected( ComponentName className ) {
mAppActiveService = null;
}
};
Then in your onStart() and onStop() methods for each activity:
#Override
public void onStart() {
super.onStart();
mAppActiveServiceBound = bindService( new Intent( this, AppActiveService.class ), mAppActiveConnection, Context.BIND_AUTO_CREATE );
}
#Override
public void onStop() {
super.onStop();
if( mAppActiveServiceBound ) {
unbindService( mAppActiveConnection );
mAppActiveServiceBound = false;
}
}
And finally, the service itself:
public class AppActiveService extends Service {
// Receives interactions from clients:
private final IBinder mBinder = new AppActiveBinder();
/**
* Provides a handle to the bound service.
*/
public class AppActiveBinder extends Binder {
AppActiveService getService() {
return AppActiveService.this;
}
}
#Override
public void onCreate(){
// TODO: Here is presumably "application level" resume
}
#Override
public void onDestroy(){
// TODO: Here is presumably "application level" pause
}
}

Ninject Transient Scope + Scope Disposal + Garbage Collection + Memory Leak

I am new at this (I'm still learning), I would appreciate very much if you Jedi masters out there can help me out with the question and concern that I have.
I want to use Ninject and I have the codes below, I would like to know whether my objects will get disposed properly and garbage collected.
For Ninject's default Transient Scope, I read that "Lifetime is not managed by the Kernel (the Scope object is null) and will never be Disposed."
If I would to use my codes in production, especially when I get lots of concurrent calls to my WebApi (POST), will it cause any problems like Memory Leak, etc?
What would be the best Ninject's Object scope to use for this situation?
By the way, if I don't specify the object scope like "kernel.Bind().To();", will it default to TransientScope?
public class VehicleClassRepository : IVehicleClassRepository
{
SomeDataContext context = new SomeDataContext();
public IQueryable<VehicleClass> All
{
get { return context.VehicleClasses; }
}
public IQueryable<VehicleClass> AllIncluding(params Expression<Func<VehicleClass, object>>[] includeProperties)
{
IQueryable<VehicleClass> query = context.VehicleClasses;
foreach (var includeProperty in includeProperties) {
query = query.Include(includeProperty);
}
return query;
}
public VehicleClass Find(int id)
{
return context.VehicleClasses.Find(id);
}
public void InsertOrUpdate(VehicleClass vehicleclass)
{
if (vehicleclass.VehicleClassId == default(int)) {
// New entity
context.VehicleClasses.Add(vehicleclass);
} else {
// Existing entity
context.Entry(vehicleclass).State = EntityState.Modified;
}
}
public void Delete(int id)
{
var vehicleclass = context.VehicleClasses.Find(id);
context.VehicleClasses.Remove(vehicleclass);
}
public void Save()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
public interface IVehicleClassRepository : IDisposable
{
IQueryable<VehicleClass> All { get; }
IQueryable<VehicleClass> AllIncluding(params Expression<Func<VehicleClass, object>>[] includeProperties);
VehicleClass Find(int id);
void InsertOrUpdate(VehicleClass vehicleclass);
void Delete(int id);
void Save();
}
In my NinjectWebCommon.cs:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IVehicleClassRepository>().To<VehicleClassRepository>();
}
In my WebApi's VehicleClassController.cs:
public HttpResponseMessage Post(VehicleClass value)
{
if (value == null)
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
else
{
vehicleclassRepository.InsertOrUpdate(value);
vehicleclassRepository.Save();
return new HttpResponseMessage(HttpStatusCode.Created);
}
}
Late answer (almost 2 years) but in case others read this...
Although it's true that the garbage collector will eventually dispose of your VehicleClassRepository instance, you'll very likely run into problems before then.
Your data context likely holds an open db connection until it's disposed. The db connection probably comes from a pool of db connections.
So long before the CLR ends up garbage collecting these (which would also dispose them), incoming requests end up blocking while trying to get a db connection but there are none available.
I've encountered this type of behavior and learned from it the hard way. So the VehicleClassRepository should be scoped in dependency scope so that you get one per call and more importantly, it'll get disposed immediately after the call is done.

Resources