Cassandra exception while live schema change - cassandra

For our project we need live schema changes. For these purposes we created test. It adds and deletes tables in cassandra. I'm using 10 threads with datastax driver. But I am getting this Exception in some threads.
Exception in thread "Thread-7"
com.datastax.driver.core.exceptions.NoHostAvailableException: All
host(s) tried for query failed (tried: localhost/127.0.0.1
(com.datastax.driver.core.exceptions.DriverException: Timeout during
read))
Cassandra is alive. I can still execute queries throw cqlsh.
Threads does'n fail. Thread can add tables, then suddenly log this exception and again add tables. Exception can appear several times in one thread.
Each thread has its own session.
Looking to the cassandra.yaml:
concurrent_writes and reads = 32
increasing of MAX_HEAP_SIZE and HEAP_NEWSIZE in cassandra-env.sh doesn't help me.
Cassandra version 2.0.7
Could someone suggest how to deal with it?
public class AddTableThread extends Thread {
private Cluster cluster;
private Session session;
private final String KEYSPACE = "cas";
private final String HOST = "localhost";
private final int PORT = 9042;
private boolean isRunning = true;
// counter for the added tables
private int i = 0;
// Number of the tables that thread has to add
private int fin = -2;
public AddTableThread() {
connect();
}
public AddTableThread setTablesCount(int f) {
this.fin = f;
System.out.println(this.getName() + " : must add " + fin + " tables");
return this;
}
#Override
public void run() {
System.out.println(this.getName() + " : starting thread \n");
while (isRunning) {
String name = createName();
try {
session.execute(createTableQuery(name));
System.out.println(this.getName() + " : table is created "
+ name);
i++;
} catch (com.datastax.driver.core.exceptions.NoHostAvailableException e) {
System.out
.println("\n\n" + this.getName() + "!!!!FAILED!!!!!!");
System.out.println(this.getName() + " : added " + i + " tables");
System.out.println(this.getName() + " : table " + name
+ " wasn't added");
}
try {
Thread.sleep((new Random().nextInt(5000)));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (i == fin) {
isRunning = false;
}
}
close();
log();
}
// creates query that creates table in keyspace with name tableName
private String createTableQuery(String tableName) {
return "CREATE TABLE cas." + tableName
+ "(id timeuuid PRIMARY KEY, text varchar, value int);";
}
public void finish() {
isRunning = false;
}
private void log() {
System.out.println("\n" + this.getName() + " : finish");
System.out.println(this.getName() + " : added " + i + " tables");
System.out.println("_____________________\n");
}
// generates unique table name
private String createName() {
return "cf_" + UUIDGen.getTimeUUID().toString().replace("-", "_");
}
private void connect() {
SocketOptions so = new SocketOptions();
so.setConnectTimeoutMillis(20000);
so.setReadTimeoutMillis(20000);
cluster = Cluster.builder().withSocketOptions(so).addContactPoint(HOST)
.withPort(PORT).build();
session = cluster.connect(KEYSPACE);
}
private void close() {
session.close();
cluster.close();
}
}

Creating takes time. So try to increment:
read_request_timeout_in_ms: 5000
and
request_timeout_in_ms: 10000
And try to uncomment
rpc_max_threads: 2048
Experiment with these parameters.

Related

Spark streaming how to get context inside foreachRDD

How can I use "ssc.sparkContext()" in foreachRDD of spark streaming?
If I use "ssc.sparkContext()" as it is in foreachRDD (JAVA) (basically, something like ssc.sparkContext().broadcast(map)), then I get "Task not serializable" error.
If I use "(new JavaSparkContext(rdd.context())).broadcast(map)" then there is no problem.
So, basically is "ssc.sparkContext()" equivalent to "(new JavaSparkContext(rdd.context()))"?
And if I use "(new JavaSparkContext(rdd.context())).broadcast(map)" will the broadcast variable i.e. associated "map" get distributed to all executors in SparkContext.
Code is given below:
Here, "bcv.broadcastVar = (new JavaSparkContext(rdd.context())).broadcast(map);" works but "bcv.broadcastVar = ssc.sparkContext.broadcast(map);" does not work
words.foreachRDD(new Function<JavaRDD<String>, Void>() {
#Override
public Void call(JavaRDD<String> rdd) throws Exception {
if (rdd != null) {
System.out.println("Hello World - words - SSC !!!"); // Gets printed on Driver
if (stat.data_changed == 1) {
stat.data_changed = 0;
bcv.broadcastVar.unpersist(); // Unpersist BC variable
bcv.broadcastVar = (new JavaSparkContext(rdd.context())).broadcast(map); // Re-broadcast same BC variable with NEW data
}
}
rdd.foreachPartition(new VoidFunction<Iterator<String>>() {
#Override
public void call(Iterator<String> items) throws Exception {
System.out.println("words.foreachRDD.foreachPartition: CALLED ..."); // Gets called on Worker/Executor
Integer index = 1;
String lastKey = "";
Integer lastValue = 0;
while (true) {
String key = "A" + Long.toString(index);
Integer value = bcv.broadcastVar.value().get(key); // Executor Consumes map
if (value == null) break;
lastKey = key;
lastValue = value;
index++;
}
System.out.println("Executor BC: key/value: " + lastKey + " = " + lastValue);
return;
}
});
return null;
}
});

Problems in using SwingWorker class for reading a file and implementing a JProgressBar

Note: This question may look like a repetition of several question posted on the forum, but I am really stuck on this problem from quite some time and I am not able to solve this issue using the solutions posted for similar questions. I have posted my code here and need help to proceed further
So, here is my issue:
I am writing a Java GUI application which loads a file before performing any processing. There is a waiting time on an average of about 10-15 seconds during which the file is parsed. After this waiting time, what I get see on the GUI is,
The parsed file in the form of individual leaves in the JTree in a Jpanel
Some header information (example: data range) in two individual JTextField
A heat map generated after parsing the data in a different JPanel on the GUI.
The program connects to R to parse the file and read the header information.
Now, I want to use swing worker to put the file reading process on a different thread so that it does not block the EDT. I am not sure how I can build my SwingWorker class so that the process is done in the background and the results for the 3 components are displayed when the process is complete. And, during this file reading process I want to display a JProgressBar.
Here is the code which does the whole process, starting from selection of the file selection menu item. This is in the main GUI method.
JScrollPane spectralFilesScrollPane;
if ((e.getSource() == OpenImagingFileButton) || (e.getSource() == loadRawSpectraMenuItem)) {
int returnVal = fcImg.showOpenDialog(GUIMain.this);
// File chooser
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = fcImg.getSelectedFile();
//JTree and treenode creation
DefaultMutableTreeNode root = new DefaultMutableTreeNode(file);
rawSpectraTree = new JTree(root);
DefaultTreeModel model = (DefaultTreeModel) rawSpectraTree.getModel();
try {
// R connection
rc = new RConnection();
final String inputFileDirectory = file.getParent();
System.out.println("Current path: " + currentPath);
rc.assign("importImagingFile", currentPath.concat("/importImagingFile.R"));
rc.eval("source(importImagingFile)");
rc.assign("currentWorkingDirectory", currentPath);
rc.assign("inputFileDirectory", inputFileDirectory);
rawSpectrumObjects = rc.eval("importImagingFile(inputFileDirectory,currentWorkingDirectory)");
rc.assign("plotAverageSpectra", currentPath.concat("/plotAverageSpectra.R"));
rc.eval("source(plotAverageSpectra)");
rc.assign("rawSpectrumObjects", rawSpectrumObjects);
REXP averageSpectraObject = rc.eval("plotAverageSpectra(rawSpectrumObjects)");
rc.assign("AverageMassSpecObjectToSpectra", currentPath.concat("/AverageMassSpecObjectToSpectra.R"));
rc.eval("source(AverageMassSpecObjectToSpectra)");
rc.assign("averageSpectraObject", averageSpectraObject);
REXP averageSpectra = rc.eval("AverageMassSpecObjectToSpectra(averageSpectraObject)");
averageSpectraMatrix = averageSpectra.asDoubleMatrix();
String[] spectrumName = new String[rawSpectrumObjects.asList().size()];
for (int i = 0; i < rawSpectrumObjects.asList().size(); i++) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode("Spectrum_" + (i + 1));
model.insertNodeInto(node, root, i);
}
// Expand all the nodes of the JTree
for(int i=0;i< model.getChildCount(root);++i){
rawSpectraTree.expandRow(i);
}
DefaultMutableTreeNode firstLeaf = ((DefaultMutableTreeNode)rawSpectraTree.getModel().getRoot()).getFirstLeaf();
rawSpectraTree.setSelectionPath(new TreePath(firstLeaf.getPath()));
updateSpectralTableandChartRAW(firstLeaf);
// List the min and the max m/z of in the respective data fields
rc.assign("dataMassRange", currentPath.concat("/dataMassRange.R"));
rc.eval("source(dataMassRange)");
rc.assign("rawSpectrumObjects", rawSpectrumObjects);
REXP massRange = rc.eval("dataMassRange(rawSpectrumObjects)");
double[] massRangeValues = massRange.asDoubles();
minMzValue = (float)massRangeValues[0];
maxMzValue = (float)massRangeValues[1];
GlobalMinMz = minMzValue;
GlobalMaxMz = maxMzValue;
// Adds the range values to the jTextField
minMz.setText(Float.toString(minMzValue));
minMz.validate();
minMz.repaint();
maxMz.setText(Float.toString(maxMzValue));
maxMz.validate();
maxMz.repaint();
// Update status bar with the uploaded data details
statusLabel.setText("File name: " + file.getName() + " | " + "Total spectra: " + rawSpectrumObjects.asList().size() + " | " + "Mass range: " + GlobalMinMz + "-" + GlobalMaxMz);
// Generates a heatmap
rawIntensityMap = gim.generateIntensityMap(rawSpectrumObjects, currentPath, minMzValue, maxMzValue, Gradient.GRADIENT_Rainbow, "RAW");
rawIntensityMap.addMouseListener(this);
rawIntensityMap.addMouseMotionListener(this);
imagePanel.add(rawIntensityMap, BorderLayout.CENTER);
coordinates = new JLabel();
coordinates.setBounds(31, 31, rawIntensityMap.getWidth() - 31, rawIntensityMap.getHeight() - 31);
panelRefresh(imagePanel);
tabbedSpectralFiles.setEnabledAt(1, false);
rawSpectraTree.addTreeSelectionListener(new TreeSelectionListener() {
#Override
public void valueChanged(TreeSelectionEvent e) {
try {
DefaultMutableTreeNode selectedNode =
(DefaultMutableTreeNode) rawSpectraTree.getLastSelectedPathComponent();
int rowCount = listTableModel.getRowCount();
for (int l = 0; l < rowCount; l++) {
listTableModel.removeRow(0);
}
updateSpectralTableandChartRAW(selectedNode);
} catch (RserveException e2) {
e2.printStackTrace();
} catch (REXPMismatchException e1) {
e1.printStackTrace();
}
}
});
spectralFilesScrollPane = new JScrollPane();
spectralFilesScrollPane.setViewportView(rawSpectraTree);
spectralFilesScrollPane.setPreferredSize(rawFilesPanel.getSize());
rawFilesPanel.add(spectralFilesScrollPane);
tabbedSpectralFiles.validate();
tabbedSpectralFiles.repaint();
rawImage.setEnabled(true);
peakPickedImage.setEnabled(false);
loadPeakListMenuItem.setEnabled(true); //active now
loadPeaklistsButton.setEnabled(true); //active now
propertiesMenuItem.setEnabled(true); // active now
propertiesButton.setEnabled(true); //active now
} catch (RserveException e1) {
JOptionPane.showMessageDialog(this,
"There was an error in the R connection. Please try again!", "Error",
JOptionPane.ERROR_MESSAGE);
} catch (REXPMismatchException e1) {
JOptionPane.showMessageDialog(this,
"Operation requested is not supported by the given R object type. Please try again!", "Error",
JOptionPane.ERROR_MESSAGE);
}
// hideProgress();
}
}
I tried creating a SwingWorker class, but I am totally confused how I can get all the three outputs on the GUI, plus have a progress bar. It is not complete, but I don't know how to proceed further.
public class FileReadWorker extends SwingWorker<REXP, String>{
private static void failIfInterrupted() throws InterruptedException {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException("Interrupted while loading imaging file!");
}
}
// The file that is being read
private final File fileName;
private JTree rawSpectraTree;
private RConnection rc;
private REXP rawSpectrumObjects;
private double[][] averageSpectraMatrix;
private Path currentRelativePath = Paths.get("");
private final String currentPath = currentRelativePath.toAbsolutePath().toString();
final JProgressBar progressBar = new JProgressBar();
// public FileReadWorker(File fileName)
// {
// this.fileName = fileName;
// System.out.println("I am here");
// }
public FileReadWorker(final JProgressBar progressBar, File fileName) {
this.fileName = fileName;
addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
progressBar.setValue((Integer) evt.getNewValue());
}
}
});
progressBar.setVisible(true);
progressBar.setStringPainted(true);
progressBar.setValue(0);
setProgress(0);
}
#Override
protected REXP doInBackground() throws Exception {
System.out.println("I am here... in background");
DefaultMutableTreeNode root = new DefaultMutableTreeNode(fileName);
rawSpectraTree = new JTree(root);
DefaultTreeModel model = (DefaultTreeModel) rawSpectraTree.getModel();
rc = new RConnection();
final String inputFileDirectory = fileName.getParent();
rc.assign("importImagingFile", currentPath.concat("/importImagingFile.R"));
rc.eval("source(importImagingFile)");
rc.assign("currentWorkingDirectory", currentPath);
rc.assign("inputFileDirectory", inputFileDirectory);
rawSpectrumObjects = rc.eval("importImagingFile(inputFileDirectory,currentWorkingDirectory)");
rc.assign("plotAverageSpectra", currentPath.concat("/plotAverageSpectra.R"));
rc.eval("source(plotAverageSpectra)");
rc.assign("rawSpectrumObjects", rawSpectrumObjects);
REXP averageSpectraObject = rc.eval("plotAverageSpectra(rawSpectrumObjects)");
rc.assign("AverageMassSpecObjectToSpectra", currentPath.concat("/AverageMassSpecObjectToSpectra.R"));
rc.eval("source(AverageMassSpecObjectToSpectra)");
rc.assign("averageSpectraObject", averageSpectraObject);
REXP averageSpectra = rc.eval("AverageMassSpecObjectToSpectra(averageSpectraObject)");
averageSpectraMatrix = averageSpectra.asDoubleMatrix();
for (int i = 0; i < rawSpectrumObjects.asList().size(); i++) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode("Spectrum_" + (i + 1));
model.insertNodeInto(node, root, i);
}
// Expand all the nodes of the JTree
for(int i=0;i< model.getChildCount(root);++i){
rawSpectraTree.expandRow(i);
}
return averageSpectra;
}
#Override
public void done() {
setProgress(100);
progressBar.setValue(100);
progressBar.setStringPainted(false);
progressBar.setVisible(false);
}
}
Any help would be very much appreciated.

Error while adding entity object to DBContext object called from Parallel.Foreach loop

Error :
If the event originated on another computer, the display information had to be saved with the event.
The following information was included with the event:
Object reference not set to an instance of an object. at
System.Data.Objects.ObjectStateManager.DetectConflicts(IList1
entries) at System.Data.Objects.ObjectStateManager.DetectChanges()
at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean
force) at
System.Data.Entity.Internal.Linq.InternalSet1.ActOnSet(Action action,
EntityState newState, Object entity, String methodName) at
System.Data.Entity.Internal.Linq.InternalSet1.Add(Object entity)
at System.Data.Entity.DbSet1.Add(TEntity entity) at
ESHealthCheckService.BusinessFacade.BusinessOperationsLayer.AddErrorToDbObject(Exception
ex, Server serverObj, Service windowsServiceObj)
the message resource is present but the message is not found in the string/message table
public void CheckForServerHealth()
{
businessLayerObj.SetStartTimeWindowsService();
List<ServerMonitor> serverMonitorList = new List<ServerMonitor>();
serverList = businessLayerObj.GetServerList();
Parallel.ForEach(
serverList,
() => new List<ServerMonitor>(),
(server, loop, localState) =>
{
localState.Add(serverStatus(server, new ServerMonitor()));
return localState;
},
localState =>
{
lock (serverMonitorList)
{
foreach (ServerMonitor serverMonitor in localState)
{
serverMonitorList.Add(serverMonitor);
}
}
});
businessLayerObj.SaveServerHealth(serverMonitorList);
}
public ServerMonitor serverStatus(Server serverObj, ServerMonitor serverMonitorObj)
{
if (new Ping().Send(serverObj.ServerName, 30).Status == IPStatus.Success)
{
serverMonitorObj.Status = true;
try
{
PerformanceCounter cpu = new PerformanceCounter("Processor", "% Processor Time", "_Total", serverObj.ServerName);
serverMonitorObj.CPUUtlilization = (cpu.NextValue());
}
catch (Exception ex)
{
businessLayerObj.AddErrorObjectToStaticList(ex, serverObj);
}
serverMonitorObj.ServerID = serverObj.ServerID;
try
{
string[] diskArray = serverObj.DriveMonitor.ToString().Split(':');
if (diskArray != null && diskArray.Contains("NA"))
{
serverMonitorObj.DiskSpace = "NA";
}
else
{
serverMonitorObj.DiskSpace = ReadFreeSpaceOnNetworkDrives(serverObj.ServerName, diskArray);
}
}
catch (Exception ex)
{
businessLayerObj.AddErrorObjectToStaticList(ex, serverObj);
}
serverMonitorObj.CreatedDateTime = DateTime.Now;
}
else
{
serverMonitorObj.Status = false;
serverMonitorObj.ServerID = serverObj.ServerID;
//return serverMonitorObj;
}
return serverMonitorObj;
}
public void AddErrorObjectToStaticList(Exception ex, Server serverObj = null, Service windowsServiceObj = null)
{
EShelathLoging esLogger = new EShelathLoging();
esLogger.CreateDatetime = DateTime.Now;
if (ex.InnerException != null)
{
esLogger.Message = (windowsServiceObj == null ? ex.InnerException.Message : ("Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.InnerException.Message));
//esLogger.Message = "Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.InnerException.Message;
esLogger.StackTrace = (ex.InnerException.StackTrace == null ? "" : ex.InnerException.StackTrace);
}
else
{
esLogger.Message = (windowsServiceObj == null ? ex.Message : ("Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.Message));
//esLogger.Message = "Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.Message;
esLogger.StackTrace = ex.StackTrace;
}
if (serverObj != null)
{
esLogger.ServerName = serverObj.ServerName;
}
try
{
lock (lockObject)
{
esHealthCheckLoggingList.Add(esLogger);
}
}
catch (Exception exe)
{
string logEntry = "Application";
if (EventLog.SourceExists(logEntry) == false)
{
EventLog.CreateEventSource(logEntry, "Windows and IIS health check Log");
}
EventLog eventLog = new EventLog();
eventLog.Source = logEntry;
eventLog.WriteEntry(exe.Message + " " + exe.StackTrace, EventLogEntryType.Error);
}
}
And then the below function is called to add objects from static list to the db object.
public void AddErrorToDbObject()
{
try
{
foreach (EShelathLoging eslogObject in esHealthCheckLoggingList)
{
lock (lockObject)
{
dbObject.EShelathLogings.Add(eslogObject);
}
}
}
catch (DbEntityValidationException exp)
{
string logEntry = "Application";
if (EventLog.SourceExists(logEntry) == false)
{
EventLog.CreateEventSource(logEntry, "Windows and IIS health check Log");
}
EventLog eventLog = new EventLog();
eventLog.Source = logEntry;
eventLog.WriteEntry(exp.Message + " " + exp.StackTrace, EventLogEntryType.Error);
}
catch (Exception exe)
{
string logEntry = "Application";
if (EventLog.SourceExists(logEntry) == false)
{
EventLog.CreateEventSource(logEntry, "Windows and IIS health check Log");
}
EventLog eventLog = new EventLog();
eventLog.Source = logEntry;
eventLog.WriteEntry(exe.Message + " " + exe.StackTrace, EventLogEntryType.Error);
}`enter code here`
}
DbSet<T> is not thread-safe, so you can't use it from multiple threads at the same time. It seems you're trying to fix that by using a lock, but you're doing that incorrectly. For this to work, all threads have to share a single lock object. Having separate lock object for each thread, like you do now, won't do anything.
Please note that I received the same exception with the application I was working on, and determined that the best way to resolve the issue was to add an AsyncLock, because of what #svick mentioned about how DbSet is not threadsafe. Thank you, #svick!
I'm guessing that your DbContext is inside your businessLayerObj, so here is what I recommend, using Stephen Cleary's excellent Nito.AsyncEx (see https://www.nuget.org/packages/Nito.AsyncEx/):
using Nito.AsyncEx;
// ...
private readonly AsyncLock _dbContextMutex = new AsyncLock();
public void CheckForServerHealth()
{
using (await _dbContextMutex.LockAsync().ConfigureAwait(false))
{
await MyDbContextOperations(businessLayerObj).ConfigureAwait(false);
}
}
private async Task MyDbContextOperations(BusinessLayerClass businessLayerObj)
{
await Task.Run(() =>
{
// operations with businessLayerObj/dbcontext here...
});
}

Cassandra slowed down with more nodes

I set up a Cassandra cluster on AWS. What I want to get is increased I/O throughput (number of reads/writes per second) as more nodes are added (as advertised). However, I got exactly the opposite. The performance is reduced as new nodes are added.
Do you know any typical issues that prevents it from scaling?
Here is some details:
I am adding a text file (15MB) to the column family. Each line is a record. There are 150000 records. When there is 1 node, it takes about 90 seconds to write. But when there are 2 nodes, it takes 120 seconds. I can see the data is spread to 2 nodes. However, there is no increase in throughput.
The source code is below:
public class WordGenCAS {
static final String KEYSPACE = "text_ks";
static final String COLUMN_FAMILY = "text_table";
static final String COLUMN_NAME = "text_col";
public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.out.println("Usage: WordGenCAS <input file> <host1,host2,...>");
System.exit(-1);
}
String[] contactPts = args[1].split(",");
Cluster cluster = Cluster.builder()
.addContactPoints(contactPts)
.build();
Session session = cluster.connect(KEYSPACE);
InputStream fis = new FileInputStream(args[0]);
InputStreamReader in = new InputStreamReader(fis, "UTF-8");
BufferedReader br = new BufferedReader(in);
String line;
int lineCount = 0;
while ( (line = br.readLine()) != null) {
line = line.replaceAll("'", " ");
line = line.trim();
if (line.isEmpty())
continue;
System.out.println("[" + line + "]");
String cqlStatement2 = String.format("insert into %s (id, %s) values (%d, '%s');",
COLUMN_FAMILY,
COLUMN_NAME,
lineCount,
line);
session.execute(cqlStatement2);
lineCount++;
}
System.out.println("Total lines written: " + lineCount);
}
}
The DB schema is the following:
CREATE KEYSPACE text_ks WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 2 };
USE text_ks;
CREATE TABLE text_table (
id int,
text_col text,
primary key (id)
) WITH COMPACT STORAGE;
Thanks!
Even if this an old post, I think it's worth posting a solution for these (common) kind of problems.
As you've already discovered, loading data with a serial procedure is slow. What you've been suggested is the right thing to do.
However, issuing a lot of queries without applying some sort of back pressure is likely looking for troubles, and you'll gonna lose data due to excessive overload on the server (and on the driver to some extent).
This solution will load data with async calls, and will try to apply some back pressure on the client to avoid data loss.
public class WordGenCAS {
static final String KEYSPACE = "text_ks";
static final String COLUMN_FAMILY = "text_table";
static final String COLUMN_NAME = "text_col";
public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.out.println("Usage: WordGenCAS <input file> <host1,host2,...>");
System.exit(-1);
}
String[] contactPts = args[1].split(",");
Cluster cluster = Cluster.builder()
.addContactPoints(contactPts)
.build();
Session session = cluster.connect(KEYSPACE);
InputStream fis = new FileInputStream(args[0]);
InputStreamReader in = new InputStreamReader(fis, "UTF-8");
BufferedReader br = new BufferedReader(in);
String line;
int lineCount = 0;
// This is the futures list of our queries
List<Future<ResultSet>> futures = new ArrayList<>();
// Loop
while ( (line = br.readLine()) != null) {
line = line.replaceAll("'", " ");
line = line.trim();
if (line.isEmpty())
continue;
System.out.println("[" + line + "]");
String cqlStatement2 = String.format("insert into %s (id, %s) values (%d, '%s');",
COLUMN_FAMILY,
COLUMN_NAME,
lineCount,
line);
lineCount++;
// Add the "future" returned by async method the to the list
futures.add(session.executeAsync(cqlStatement2));
// Apply some backpressure if we issued more than X query.
// Change X to another value suitable for your cluster
while (futures.size() > 1000) {
Future<ResultSet> future = futures.remove(0);
try {
future.get();
} catch (Exception e) {
e.printStackTrace();
}
}
}
System.out.println("Total lines written: " + lineCount);
System.out.println("Waiting for writes to complete...");
// Wait until all writes are done.
while (futures.size() > 0) {
Future<ResultSet> future = futures.remove(0);
try {
future.get();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Done!");
}
}

What is the correct way to implement concurrency in wcf service?

I am trying understand concurrency in wcf and downloaded a sample code from here and done some changes for testing two way calls. To my surprise I could not see the effect of concurrency for two way calls (Although I can see concurrency for one way calls).
Is it the way WCF concurrency model works? (or)
Am I doing something terribly wrong?
This is the service code.
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract(IsOneWay=true)]
void Call(string ClientName);
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class HelloWorldService : IHelloWorldService
{
public static int counter;
public HelloWorldService()
{
counter++;
}
public void Call(string ClientName)
{
Console.WriteLine("Instance:" + counter.ToString() + " Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + " Time:" + DateTime.Now.ToString() + "\n\n");
Thread.Sleep(5000);
}
public string GetData(int value)
{
Console.WriteLine("Instance:" + counter.ToString() + " Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + " Time:" + DateTime.Now.ToString() + "\n\n");
Thread.Sleep(5000);
return value.ToString();
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
Console.WriteLine("Instance:" + counter.ToString() + " Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + " Time:" + DateTime.Now.ToString() + "\n\n");
Thread.Sleep(5000);
return composite;
}
}
This is the service hosting code.
class Program
{
static void Main(string[] args)
{
//Create a URI to serve as the base address
//Uri httpUrl = new Uri("net.tcp://localhost:8001/HelloWorld");
Uri httpUrl = new Uri("http://localhost:8010/MyService/HelloWorld");
//Create ServiceHost
ServiceHost host
= new ServiceHost(typeof(ClassLibrary1.HelloWorldService), httpUrl);
//Add a service endpoint
host.AddServiceEndpoint(typeof(ClassLibrary1.IHelloWorldService)
, new WSHttpBinding(), "");
//Enable metadata exchange
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
host.Description.Behaviors.Add(smb);
ServiceThrottlingBehavior stb = new ServiceThrottlingBehavior();
stb.MaxConcurrentCalls = 100;
stb.MaxConcurrentInstances = 100;
stb.MaxConcurrentSessions = 100;
host.Description.Behaviors.Add(stb);
//Start the Service
host.Open();
Console.WriteLine("Service is host at " + DateTime.Now.ToString());
Console.WriteLine("Host is running... Press <Enter> key to stop");
Console.ReadLine();
}
}
This is the client code.
class Program
{
static int m_NumberOfWorkers = 10;
static readonly object m_Locker = new object();
static bool flag_GO = false;
static Stopwatch m_OverAllStopwatch = new Stopwatch();
static ConcurrentBag<Stopwatch> m_bagIndividualStopwatch = new ConcurrentBag<Stopwatch>();
static int m_CompletedWorkers = 0;
static ServiceReference1.HelloWorldServiceClient m_objProxy;
static int m_KindOfMethod;
static void Main(string[] args)
{
while(true)
{
try
{
flag_GO = false;
Console.WriteLine("Enter number of concurrent clients:");
m_NumberOfWorkers = Int32.Parse(Console.ReadLine());
Console.WriteLine("Kind of method (1: One way, 2: Two way 3: Two way using data contract):");
m_KindOfMethod = Int32.Parse(Console.ReadLine());
// Create Workers
List<Thread> lstThreads = new List<Thread>();
for (int i = 0; i < m_NumberOfWorkers; ++i)
{
lstThreads.Add(new Thread(WaitOnPulse));
}
// Start Workers
for (int i = 0; i < lstThreads.Count; ++i)
{
lstThreads[i].Start();
}
m_objProxy = new ServiceReference1.HelloWorldServiceClient();
m_OverAllStopwatch.Restart();
// Signal all workers
lock (m_Locker)
{
flag_GO = true;
Monitor.PulseAll(m_Locker);
}
// Wait all workers to finish
for (int i = 0; i < lstThreads.Count; ++i)
{
lstThreads[i].Join();
}
m_objProxy.Close();
m_objProxy = null;
}
catch
{
return;
}
}
}
private static void WaitOnPulse()
{
lock (m_Locker)
{
while (!flag_GO) Monitor.Wait(m_Locker);
}
TestWhatEverYouWant();
IamDone();
}
private static void TestWhatEverYouWant()
{
Stopwatch stopWatch = Stopwatch.StartNew();
//Thread.Sleep(1000);
switch (m_KindOfMethod)
{
case 1:
m_objProxy.Call(m_NumberOfWorkers.ToString() + "Client Calls");
break;
case 2:
m_objProxy.GetData(m_NumberOfWorkers);
break;
case 3:
ServiceReference1.CompositeType objData = new ServiceReference1.CompositeType();
m_objProxy.GetDataUsingDataContract(objData);
break;
}
stopWatch.Stop();
m_bagIndividualStopwatch.Add(stopWatch);
}
private static void IamDone()
{
Interlocked.Increment(ref m_CompletedWorkers);
// Summarize results if all workers are done
if (Interlocked.CompareExchange(ref m_CompletedWorkers, 0, m_NumberOfWorkers) == m_NumberOfWorkers)
{
m_OverAllStopwatch.Stop();
Console.WriteLine("OverAll Elapsed Time: {0}", m_OverAllStopwatch.ElapsedMilliseconds);
Stopwatch stopWatch;
while (m_bagIndividualStopwatch.TryTake(out stopWatch))
//foreach (Stopwatch stopWatch in m_bagIndividualStopwatch)
{
Console.WriteLine("Individual Elapsed Time: {0}", stopWatch.ElapsedMilliseconds);
}
}
}
}
This is the Cleint trace:
Enter number of concurrent clients:
8
Kind of method (1: One way, 2: Two way 3: Two way using data contract):
2
OverAll Elapsed Time: 42022
Individual Elapsed Time: 42021
Individual Elapsed Time: 37013
Individual Elapsed Time: 32008
Individual Elapsed Time: 26987
Individual Elapsed Time: 21981
Individual Elapsed Time: 16980
Individual Elapsed Time: 11968
Individual Elapsed Time: 6985
This is the server trace:
Instance:1 Thread:6 Time:12/17/2012 8:09:29 PM
Instance:1 Thread:5 Time:12/17/2012 8:09:34 PM
Instance:1 Thread:7 Time:12/17/2012 8:09:39 PM
Instance:1 Thread:7 Time:12/17/2012 8:09:44 PM
Instance:1 Thread:5 Time:12/17/2012 8:09:49 PM
Instance:1 Thread:7 Time:12/17/2012 8:09:54 PM
Instance:1 Thread:5 Time:12/17/2012 8:09:59 PM
Instance:1 Thread:7 Time:12/17/2012 8:10:04 PM
For these results you can clearly see that the requests were processed sequentially. Ideally I was expecting all the 8 concurrent requrest would finish in 5 sec. But it took around 42 sec to finish.
The problem in my code is the way the proxy is used. I have created just one proxy for all concurrent clients and all calls to the service were made through this proxy only. So, all these calls were getting queued in the channel. Creating one proxy for each client, the way one should simulate wcf load test, solved the problem.
I still think the problem is with settings; proxy and number of threads originating from each proxy, the link explains it well.
Also have a look at following link; may be test client can have a problem.
Seeking WCF Duplex "TwoWay" Subscribe+Callback Example

Resources