WCF service not behaving concurrently - wcf

I have a service code like:
[ServiceContract]
public interface IService1
{
[OperationContract]
void MyOperation1();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,ConcurrencyMode=ConcurrencyMode.Multiple)]
public class service1 : IService1
{
public service1()
{
Console.WriteLine("creating instance");
}
public void MyOperation1()
{
Console.WriteLine("starting..");
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Console.WriteLine("Ending..");
}
}
My Client code looks like:
static void Main(string[] args)
{
Thread[] t = new Thread[10];
NetTcpBinding myBinding = new NetTcpBinding();
EndpointAddress myEndpoint = new EndpointAddress("net.tcp://localhost:8000/MyService");
ChannelFactory<IService1> myChannelFactory = new ChannelFactory<IService1>(myBinding, myEndpoint);
IService1 instance = myChannelFactory.CreateChannel();
for (int i = 0; i < 10; i++)
{
t[i] = new Thread(new ThreadStart(delegate()
{
instance.MyOperation1();
}));
}
for (int i = 0; i < 10; i++)
{
t[i].Start();
}
}
I am getting an output (where the calls are executed one by one):
creating instance
starting..
3
Ending..
starting..
3
Ending..
starting..
12
Ending..
starting..
3
Ending..
starting..
12
Ending..
starting..
3
Ending..
starting..
12
Ending..
starting..
3
Ending..
starting..
12
Ending..
starting..
3
Ending..
I am expecting all the calls to start parallely like this:
creating instance
starting..
starting..
starting..
starting..
3
Ending..
4
6
Ending..

It is probably due to you using a single client (channel) instance.
The new threads that you create must wait for the previous thread to release the channel before it can use it.

Related

How to simulate an error to setBatchErrorHandler() in kafka consumer container?

I've a kafka consumer application that uses ConcurrentKafkaListenerContainerFactory and I read that setBatchErrorHandler is used to handle errors when there is an error during batch listening. Below is my codes for configuring the factory and receiving function. May I know how can I simulate the error to use BatchErrorHandler?
#Bean(name = "xxxconsumer")
public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory(ConsumerFactory<String, String> consumerFactory) {
final ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory);
factory.setConcurrency(14);
factory.setBatchListener(true);
factory.setBatchErrorHandler(new BatchLoggingErrorHandler());
return factory;
}
#KafkaListener(
topics = "filler.name.1",
containerFactory = "xxxconsumer"
)
public void receive(#Payload List<String> messages) {
for (int i = 0; i < messages.size(); i++) {
log.info("Received message='{}' ", messages.get(i));
transform(messages.get(i));
}
log.info("All batch messages received");
}
I'm using spring-kafka v2.3.7.
You can throw a RuntimeException in the listener to simulate an error and see the BatchLoggingErrorHandler kicking in.
Consider this application:
#SpringBootApplication
public class SO71276422 {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SO71276422.class, args);
try {
Thread.sleep(10000);
}
catch (InterruptedException e) {
Thread.interrupted();
throw new RuntimeException("Interrupted");
}
KafkaOperations kafkaTemplate = context.getBean("kafkaTemplate", KafkaOperations.class);
for (int i = 0; i < 10; i++) {
kafkaTemplate.send("filler.name.1", "My message " + i);
}
}
Logger log = LoggerFactory.getLogger(this.getClass());
#KafkaListener(
topics = "filler.name.1",
containerFactory = "xxxconsumer"
)
public void receive(#Payload List<String> messages) {
log.info("Received messages: " + messages);
for (int i = 0; i < messages.size(); i++) {
log.info("Received message='{}' ", messages.get(i));
transform(messages.get(i));
}
throw new RuntimeException("Test exception");
}
private void transform(String s) {
log.info("Transforming message " + s);
}
#Configuration
static class MyConfiguration {
#Bean
public ConsumerFactory<String, String> consumerFactory() {
Map<String, Object> config = new HashMap<>();
config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
config.put(ConsumerConfig.GROUP_ID_CONFIG, "grp_STRING");
return new DefaultKafkaConsumerFactory<>(config);
//inject consumer factory to kafka listener consumer factory
}
#Bean(name = "xxxconsumer")
public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory(ConsumerFactory<String, String> consumerFactory) {
final ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory);
factory.setConcurrency(14);
factory.setBatchListener(true);
factory.setBatchErrorHandler(new BatchLoggingErrorHandler());
return factory;
}
}
}
Will produce this logs:
2022-02-28 15:22:54.795 INFO 19058 --- [ntainer#0-0-C-1] 1276422$$EnhancerBySpringCGLIB$$7449d5be : Received messages: [My message 0, My message 1, My message 2, My message 3, My message 4, My message 5, My message 6, My message 7, My message 8, My message 9]
...
2022-02-28 15:22:54.796 INFO 19058 --- [ntainer#0-0-C-1] 1276422$$EnhancerBySpringCGLIB$$7449d5be : Transforming message My message 9
2022-02-28 15:22:54.799 ERROR 19058 --- [ntainer#0-0-C-1] o.s.k.listener.BatchLoggingErrorHandler : Error while processing:
filler.name.1-0#40
filler.name.1-0#41
filler.name.1-0#42
filler.name.1-0#43
filler.name.1-0#44
filler.name.1-0#45
filler.name.1-0#46
filler.name.1-0#47
filler.name.1-0#48
filler.name.1-0#49

addlast()method null pointer exception

public class Node {
private String element;
private Node next;
public void setNext(Node newNext) {
next = newNext;
}
public class SLinkedList {
protected Node head;
protected Node tail;
protected long size;
public void addLast(Node newNode) {
newNode.setNext(null);
tail.setNext(newNode);
tail = newNode;
size = size + 1;
}
public class TestLinkedList {
public static void main(String args[]) {
SLinkedList myList = new SLinkedList();
//create 3 node
Node m = new Node("Tom1", null);
Node n = new Node("Tom2", null);
Node p = new Node("Tom3", null);
//add 1 node at the end
myList.addLast(m);
//print
System.out.println(myList);
System.out.println("Size=\t"+myList.getSize());
}
when executed "myList.addLast(m); it shows nullpointerexception at "tail.setNext(newNode);"
I just wanna know what happen?
In your code,
tail.setNext(newNode); // tail isn't initialized yet
tail = newNode;
Instead do,
tail = newNode;
tail.setNext(newNode);

akka fails silently while serializing TypedActor proxies and ActorRef across 32 bit and 64 bit JVMs

What configuration is required to fix the following problem?
Akka Actor on 64 bit jvm(machine1) CANNOT use TypedActor proxies on the 32 bit jvm(machine2) (CASE1)
but WORKS vice versa (CASE2).
Is there some configuration setting for serialization I'm missing out?
I'm using akka-2.2.1 from java.
I've a small test code which replicates this problem always.
There are no logs which report "ERRORS", despite enabling even remote-lifecycle events.
It just times out when calling registerListener() on CASE1.
I'm clueless, any help/clue is greatly appreciated.
server.java
public class Server implements ServerActor {
public static final String serverActorName = "server";
public static final String serverIP = "192.168.11.112";
public static final int serverPort = 9999;
public static void main(String[] args) {
new Server();
}
ActorSystem serverSystem;
public Server() {
String network = String
.format("akka.actor.provider = \"akka.remote.RemoteActorRefProvider\" \n"
+ "akka.remote.enabled-transports = [\"akka.remote.netty.tcp\"] \n"
+ "akka.remote.netty.tcp.hostname = \"%s\" \n"
+ "akka.remote.netty.tcp.port = %d", Server.serverIP,
Server.serverPort);
Config config = ConfigFactory.parseString("akka.loglevel = DEBUG \n"
+ "akka.actor.debug.lifecycle = on \n" + network);
serverSystem = ActorSystem.create("sys", config);
RemoteActorRefProvider ref = (RemoteActorRefProvider) serverSystem
.provider();
Address addr = ref.transport().defaultAddress();
String port = addr.port().get().toString();
System.out.printf("Server Akka IP=%s PORT=%s\n", addr, port);
final Server server = this;
// start server service
#SuppressWarnings("unused")
ServerActor proxy = TypedActor.get(serverSystem).typedActorOf(
new TypedProps<Server>(ServerActor.class,
new Creator<Server>() {
private static final long serialVersionUID = 6301999771454618282L;
#Override
public Server create() {
return server;
}
}), Server.serverActorName);
}
#Override
public boolean registerListener(ITestListener listener) {
listener.update(10);
return true;
}
}
And client.java
public class Client implements ITestListener {
public static final String clientActorName = "client";
public static final String clientIP = "192.168.11.111";
public static void main(String[] args) {
new Client();
}
ActorSystem clientSystem;
private ITestListener clientListener = null;
public Client() {
String network = String
.format("akka.actor.provider = \"akka.remote.RemoteActorRefProvider\" \n"
+ "akka.remote.enabled-transports = [\"akka.remote.netty.tcp\"] \n"
+ "akka.remote.netty.tcp.hostname = \"%s\" \n"
+ "akka.remote.netty.tcp.port = 0", Client.clientIP);
Config config = ConfigFactory.parseString("akka.loglevel = DEBUG \n"
+ "akka.actor.debug.lifecycle = on \n" + network);
clientSystem = ActorSystem.create("sys", config);
RemoteActorRefProvider ref = (RemoteActorRefProvider) clientSystem
.provider();
Address addr = ref.transport().defaultAddress();
String port = addr.port().get().toString();
System.out.printf("Client Akka IP=%s PORT=%s\n", addr, port);
final Client client = this;
// start server service
clientListener = TypedActor.get(clientSystem).typedActorOf(
new TypedProps<Client>(ITestListener.class,
new Creator<Client>() {
private static final long serialVersionUID = 2034444366744329184L;
#Override
public Client create() {
return client;
}
}), Client.clientActorName);
connect();
}
private void connect() {
// Connect to remote actor system
String remotePath = String.format("akka.tcp://sys#%s:%d/user/%s",
Server.serverIP, Server.serverPort, Server.serverActorName);
// get remote server proxy object
// TypedActor.context().setReceiveTimeout(Duration.create("3 second"));
ActorRef remoteRef = clientSystem.actorFor(remotePath);
if (remoteRef == null)
throw new RuntimeException("Cannot get remote akka actor");
final ServerActor server = TypedActor.get(clientSystem).typedActorOf(
new TypedProps<ServerActor>(ServerActor.class), remoteRef);
server.registerListener(clientListener);
}
#Override
public void update(int a) {
System.out.printf("*********** Server Sent %d ************\n", a);
}
}

WCF REST Service: InstanceContextMode.PerCall not working

I have implemented a REST service for WCF. The service offers one function that can be called by many clients and this function takes more than 1 minute to complete. So what I wanted is that for each client, a new object is used, so that many clients can be handled at a time.
My interface looks like this:
[ServiceContract]
public interface ISimulatorControlServices
{
[WebGet]
[OperationContract]
string DoSomething(string xml);
}
And the (test) implementation of it:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall]
public class SimulatorControlService : SimulatorServiceInterfaces.ISimulatorControlServices
{
public SimulatorControlService()
{
Console.WriteLine("SimulatorControlService started.");
}
public string DoSomething(string xml)
{
System.Threading.Thread.Sleep(2000);
return "blub";
}
}
The problem now is: if I use a client that creates 10 (or whatever number) threads, each of it calling the service, they dont run concurrently. This means, the calls are being handled one after each other. Does anybody have an idea why this happens?
Added: client-side code
Spawning threads:
for (int i = 0; i < 5; i++)
{
Thread thread = new Thread(new ThreadStart(DoSomethingTest));
thread.Start();
}
Method:
private static void DoSomethingTest()
{
try
{
using (ChannelFactory<ISimulatorControlServices> cf = new ChannelFactory<ISimulatorControlServices>(new WebHttpBinding(), "http://localhost:9002/bla/SimulatorControlService"))
{
cf.Endpoint.Behaviors.Add(new WebHttpBehavior());
ISimulatorControlServices channel = cf.CreateChannel();
string s;
int threadID = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("Thread {0} calling DoSomething()...", threadID);
string testXml = "test";
s = channel.StartPressureMapping(testXml);
Console.WriteLine("Thread {0} finished with reponse: {1}", threadID, s);
}
}
catch (CommunicationException cex)
{
Console.WriteLine("A communication exception occurred: {0}", cex.Message);
}
}
Thanks in advance!
Since the service is controlled by a GUI, the "UseSynchronizationContext" attribute was needed to solve the problem:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode=ConcurrencyMode.Multiple, UseSynchronizationContext=false)]

My test indicates .NET Remoting is faster than WCF 4 by a factor of 1.5

In order to tell whether my project should migrate from .net remoting to WCF, I extracted its network communication part and implemented it by WCF. I run the remoting version and wcf version and eventually find remoting is faster than wcf by a factor of 1.5, which greatly differs from the msdn article.
Test configuration
WCF and .NET Remoting both use tcp channel without encryption, no app.config file. Compiled in release mode, no optimization.
Operations
What my program does is this.
You can download the two solutions here.
WCF test
Service Host
ServiceHost host = new ServiceHost(typeof(Server), new Uri(string.Format("net.tcp://{0}:{1}/{2}", args[0], args[1], args[2])));
var binding = new NetTcpBinding();
binding.MaxReceivedMessageSize = 614400;
binding.ReaderQuotas.MaxArrayLength = 512000;//a max picture of 500KB
binding.Security.Mode = SecurityMode.None;
host.AddServiceEndpoint(typeof(IServer), binding, string.Empty);
host.Open();
Server
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single
//, IncludeExceptionDetailInFaults = true
, ConcurrencyMode = ConcurrencyMode.Reentrant
)]
public class Server : IServer
{
public EntryRequirement GetEntryRequirement()
{
return new EntryRequirement(new[] { "fuck", "sex" }, false);
}
public void AddClient()
{
var client = OperationContext.Current.GetCallbackChannel<IServerCallback>();
var p = client.Profile;
var x = client.Password;
System.Diagnostics.Debug.WriteLine(p);
System.Diagnostics.Debug.WriteLine(x);
}
}
Client side
Player player = new Player();
player.Password = "12423";
player.Profile = new Contracts.PlayerProfile
{
Description = "I'm a man.",
HeadImage = imageData,
Name = "Loveright"
};
var binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 20; i++)
{
ServerProxy server = new ServerProxy(player, binding,
new EndpointAddress(string.Format("net.tcp://{0}:{1}/{2}", args[0], args[1], args[2])));
server.GetEntryRequirement();
server.AddClient();
}
watch.Stop();
HeadImage is a picture of size 139KB.
Player class
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
class Player : IServerCallback
{
public PlayerProfile Profile { get; set; }
public string Password { get; set; }
public void ClientCollectionChangedEventHandler(object sender, ControllersChangedEventArgs e)
{
}
public void ClientUpdatedEventHandler(object sender, ClientUpdatedEventArgs e)
{
}
}
.NET Remoting test
Host
var serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
var clientProv = new BinaryClientFormatterSinkProvider();
IDictionary props = new Hashtable();
props["port"] = args[1];
props["name"] = "tcp server";
var channel = new TcpChannel(props, clientProv, serverProv);
ChannelServices.RegisterChannel(channel, false);
System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownServiceType(typeof(Server),
args[2], System.Runtime.Remoting.WellKnownObjectMode.Singleton);
Client
var serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
var clientProv = new BinaryClientFormatterSinkProvider();
IDictionary props = new Hashtable();
props["name"] = "tcp client " + Guid.NewGuid();
props["port"] = 0;
var channel = new TcpChannel(props, clientProv, serverProv);
ChannelServices.RegisterChannel(channel, false);
FileStream stream = new FileStream(#"logotz6.png", FileMode.Open);
byte[] imageData = new byte[stream.Length];
stream.Read(imageData, 0, imageData.Length);
stream.Close();
Player player = new Player();
player.Password = "12423";
player.Profile = new PlayerProfile
{
Description = "I'm a man.",
HeadImage = imageData,
Name = "Loveright"
};
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 20; i++)
{
var serverProxy = (IServer)Activator.GetObject(typeof(IServer), string.Format("tcp://{0}:{1}/{2}", args[0], args[1], args[2]));
serverProxy.GetEntryRequirement();
serverProxy.AddClient(player);
}
watch.Stop();
You can download the two solutions here.
Result
So do I make the test somewhere unfair to WCF?
Should it be the message encoding king ?
Have you used binaryMessageEncoding instead of textMessageEncoding or soapMessageEncoding ?
You can create a custom binding to do this :
internal sealed class MyBinding : CustomBinding
{
private static readonly BindingElementCollection elementCollection;
static MyBinding()
{
MessageEncodingBindingElement encoding = new BinaryMessageEncodingBindingElement();
TcpTransportBindingElement transport = new TcpTransportBindingElement();
elementCollection = new BindingElementCollection();
elementCollection.Add(encoding);
elementCollection.Add(transport);
}
internal MyBinding(string bindingName, string bindingNamespace)
: base()
{
base.Namespace = bindingNamespace;
base.Name = bindingName;
}
public override BindingElementCollection CreateBindingElements()
{
return elementCollection;
}
}