I am developing an Service-Oriented based application for Hotel Reservation System using WCF architecture. It has following 3 three components:
1. WCF Service that has Service and Data contracts for invoking moudules of room reservation.
2. WCF Host that keeps log of service access by client
3. WCF client that has UI for Hotel Reservation.
I am looking for guidelines to implement concurrency in my application having following features:
1. Only one request shall be entertained at the time.
2. If more than one requests are received, then these should be synchronized using locks/mutex/semaphores.
Coding guidelines shall be helpful.
I think this is the allocation issue of the external resources, such as the database access, the I/O for on the single file. WCF supports transaction and transmitting it on the client-side. We are capable of locking the access to the database by using transaction when another client attempt to access it.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/transactions-overview
Moreover, we can also use the shared lock which locks the service instance, occupying all the resource lest the other instance access the service, please refer to the below code.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple)]
class MyService : IMyContract
{
public void MyMethod()
{
lock(typeof(MyService))
{
...
MyResource.DoWork();
...
}
}
}
static class MyResource
{
public static void DoWork()
{
lock(typeof(MyService))
{
...
}
}
}
Please refer to the below link, Chaper8(concurrency management), resources and services, deadlock avoidance.
https://ashishmit99.files.wordpress.com/2013/01/oreilly-programming-wcf-services-3rd-edition-aug-2010.pdf
Here is an official document relates to Concurrency mode, aiming to solve access conflict from the multiple users.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/sessions-instancing-and-concurrency
Related
Sorry about the vague title, it's rather hard to explain. I have the following setup:
I'm running a .NET Core 2.2 Web API hosted in Service Fabric.
Part of this API's responsibilities is to monitor an external FTP storage for new incoming files.
Each file will trigger a Mediator Command to be invoked with processing logic.
I've implemented a hybrid solution based on https://learn.microsoft.com/en-us/dotnet/architecture/microservices/multi-container-microservice-net-applications/background-tasks-with-ihostedservice and https://blog.maartenballiauw.be/post/2017/08/01/building-a-scheduled-cache-updater-in-aspnet-core-2.html. In essence this is an IHostedService implementation that is registered in the Startup.cs of this API. Its basically a background service running in-process.
As for the problem. The solution above works fine on a 1-node cluster, but causes "duplicates" to be processed when running on a 5-node cluster. The problem lies in the fact that on a 5-node cluster, there are ofcourse 5 identical ScheduledTasks running and will all access the same file on the FTP at the same time.
I've realised this is caused somewhat by improper separation of concerns - aka the API shouldn't be responsible for this, rather a completely separate process should handle this.
This brings me to the different services supported on Service fabric (Stateful, Stateless, Actors and Hosted Guest Exe's). The Actor seems to be the only one that runs single-threaded, even on a 5-node cluster. Additionally, an Actor doesn't seem to be well suited for this kind of scenario, as it needs to be triggered. In my case, I basically need a daemon that runs all the time on a schedule. If I'm not mistaken, the other stateful/stateless services will run with 5 "clones" as well and just cause the same issue as I currently have.
I guess my question is: how can I do efficient background processing with Service Fabric and avoid these multi-threaded/duplicate issues? Thanks in advance for any input.
In service farbic you have 2 options with actors:
Reliable actor timers
Reliable actor reminders
You can use the state to determine if the actor has processed your ftp file.
Have a look at this blog post, to see how they used a reminder to run every 30 seconds.
It's important that the code in your actor allows reantrancy.
Basically because the actors are reliable, your code might get executed multiple times and be canceled in the middle of an execution.
Instead of doing this:
public void Method()
{
_ftpService.Process(file);
}
Consider doing this:
public void Method(int fileId)
{
if (_ftpService.IsNotProcessed(fileId))
{
_ftpService.Process(file);
_ftpService.SetProcessed(fileId);
}
}
If your actor has trouble disposing, you might want to check if you are handling cancelationtokens in your code. I never had this issue, but we are using autofac, with Autofac.ServiceFabric to register our actors with RegisterActor<T>() and we have cancelationtokens in most of our logic. Also the documentation of CancellationTokenSource can help you.
Example
public Ctor()
{
_cancelationTokenSource = new CancellationTokenSource();
_cancellationToken= _cancelationTokenSource.Token;
}
public async Task SomeMethod()
{
while(/*condition*/)
{
_cancellationToken.ThrowIfCancellationRequested();
/*Other code*/
}
}
protected override async Task OnDeactivateAsync()
{
_cancelationTokenSource.Cancel();
}
This is about my solution to that question
It is been a long time since my last c# coding, and it is my first time to write a Web Service...
Previous Question:
I need to use a DLL on an Ubuntu with Python. Final solution is using a web service for that propose...
My problem is, the API is used for a kind of payment. There are three basic function of the DLL to be used in the webservice... First one is used for connection to the server, second one is asking available payments, third one is selecting one and making the payment...
Since my system is using Python, I wish to keep the logic that selects the payment method on python, not on the web service.
And my problem is, when I make a connection, webservice must create a connection object, and do the following two steps using that connection. That it may dispose that connection object and create a new one for the next connection and payment.
So, my Python code will do something like that...
Use web service and create a connection
Get a list of available payments from web service (these two functions can be used as a single function in the web service)
Do some calculation and select the proper payment in python...
Send payment method info to web service...
All these steps must be done with the connection object from the first step.
As I said before, I do not have much knowledge about web services and using them on python... So I'm confused whether I may use the same connection object for steps 2 and 4. If I create the connection object as a global in my web service on the connection step, then my following function calls use that object? In OOP that's the way it must be, but I can not be sure if it will be same in web services?
Some code snippet :
namespace paymentType{
public class x : System.Web.Services.WebService{
ConnectionObj conn;
ConnResult result;
[WebMethod]
public void ConnectToServer(String deviceId){
conn = new ConnectionObj();
result = baglanti.Connect(deviceId);
}
[WebMethod]
public List<int> GetCompanyList(){
List<int> kurumlar = new List<int>();
if (sonuc.CRCStatus){
if (baglanti.CompanyList != null) { blah blah blah...}
Since conn is a global, can i set it in the function call ConnectToServer and use the baglanti object for the other functions...
UPDATE: Let me try to get it more clear...
When I connect to remote server (via function in the DLL), remote server accepts my connection and give me a somewhat unique id for that connection. Then I ask for available payments for a customer. Server sends all available ones with a transaction id belong to that transaction. And in the final step, I use the transaction id that I want for doing the payment. Problem is, each transaction id is usable within the connection that it was created. So, I must request for transaction id and confirm the one I want in the same connection...
But as far as I see, best solution is using a single function call and do all the job on the web service since API provider considers removing the connection-transactionId lock might cause some security vulnerabilities...
But on the other hand, I do not want to handle it on the web service...
One more question... On the connection step, creating the connection and using set/get functions or returning the connection object and pass it back to the web service for each following step might work?
If you're communicating using a web service, it should preferrably be stateless – that is, you should always send any context information the service implementation needs in the request. While technologies that let you implement stateful web services exist, they'd likely make things more complicated, not less.
I'm not clear from your description on why you need the connection object to be created in Step 1, or why you can't just create a different connection object for steps 2 and 4 – which is how I'd implement this.
My project was standalone application then I decided to split it as client & server because I need powerful CPU usage and portability at the same time. Now multiple clients can connect to one server.
It was easy when 1 by 1 processing did the job. Now I need to call the same function & scope area again & again at the same time -via client requests-
Please can anyone give me some clue how should I handle these operations, I need to know how can I isolate clients' processes from each other at the server side? My communication is asynchronous, server receives a request and starts a new thread. I think I pass a parameter which one carries the client information, and another parameter as job id -to help client back, client may ask for multiple jobs and some jobs finish quicker than others-
Should I instantiate the class Process on each call? Can I use a static method, etc, any explanation will be of great help!
Below is the part of my code to need modification
class static readonly Data
{
public variable listOfValues[]
}
class Process
{
local variable bestValue
function findBestValue(from, to)
{
...
if(processResult > bestValue) bestValue = processResult
...
}
...
for(i=0;i<10;i++) startThread(findBestValue(i*1000,i*1000+999));
...
}
EDIT: I think I have to instantiate a
new Process class and call the
function for each client and ignore
the same client for same job since job is already running.
Not getting into your application design, since you didn't talk much about it, I think that your problem is ideal for using WCF WebServices. You get client isolation by design because every request will start in it's own thread. You can create WCF host as standalone application/windows service.
You can wrap your communication with WCF service and configure it to be PerCall service (meaning each request will be processed separately from others).
So you'll clean up your buisness logic from syncronization stuff. That's the best way, because managing and creating threads is not difficult to implement, but it is difficult to implement correctly and optimized for resources consumption.
My scenerio is like this:
On the server there is an application which exposes a COM object allowing to interact with this application programaticaly. However I can connect only once through COM due to licence restrictions. So, after initialization a COM object will return me a more specified ConnectionObject.
I need an advice what management model I schould chose for my service which will be interacting with the ConnectionObject:
Per-Call Service:
I have two options here:
I can log through COM, perform operation and Logout releasing the connection. But this logging process is somewhat time consuming.
I could create some sort of
singleton class which could keep
reference to the ConnectionObject.
The problem is that I do not know
how to share the same instance of
object through different instances
of the service? Is it possible?
Singleton Service:
The problem of sharing ConnectionObject does not exists. Object will be created at the begining of life of the service and freed when service will be shut down. However I've read that using this kind of service is not recommended.
Thanks for any advices.
Given your requirements with the COM object, and the time consuming log in and out process - I would go with the singleton service. We use our WCF services like this all the time (also talking to legagy COM objects).
You can add the following attribute to the class definition of your WCF service to get the behaviour:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyService : IMyServiceContract
{
[OperationBehavior]
public void MyServiceCall ()
I would like to know in how the Session locking mechanism work and how I can lock a variable and its respective child objects for multiple reads/exclusive write in a server farm environment.
Scenario
The web farm will use 3 Windows 2003 servers, each server as its own app domain for the Web application. The sesion object is saved on SQL Server 2005.
The object to use in my web app is at follows:
MySampleClass = class
{
public string Id;
public Dictionary<string, CustomClass1> Data;
public List<string> Commands;
public CustomClass2 MoreData;
}
where customClass 1 and 2 are business classes that are part of the application.
now in one of the web pages, code will look like:
Session["myObj"] = new MySampleClass();
in other pages:
MySampleClass = (MySampleClass)Session["myObj"];
//Is Session["myObj"] accessed in a multiple reader/exclusive writer mode? if so is it locking just the variable or the whole contents?
MySampleClass.Commands.Add("sample string");
MySampleClass.Commands.RemoveAt(0);
//More CRUD changes
//Are these changes available to other pages as soon as I finish the CRUD changes?
let me know if you need more details
Have a look here under Locking Session-Store Data. Basically, unless your page says it wants read-only session access, the session is locked on the DB and other callers for that session will poll at 1/2sec interval until it is unlocked.
There is also a detailed explanation on "Session State Providers" on msdn.
It covers the algorithm and rules used when using out-of-process session state providers in ASP.NET.