I am using the Service Grid based on Apache Ignite .Net and I am seeking to implement the distributed tracing for requests spanning multiple Ignite services.
To implement that, I need to pass a request id (also known as correlation id) through the entire call chain. So I wonder if there is a way to transparently pass some context information from an Ignite service caller to the target Ignite service without wrapping the method arguments in some form of envelope? That would enable me to keep the method arguments clean.
I see that there is the void Execute(IServiceContext context) method that gives access to some context information on the receiving side. Is there a way to manipulate the context on the client side?
Thank you!
void Execute(IServiceContext context) method is invoked automatically whenever an instance of the service is deployed on a grid node, and ServiceContext instance is created inside the grid on service deployment, so it's not intended to be manipulated somehow from the client side.
In described case some kind of correlation id can be added to the service's methods signatures.
Related
Could please Give RealTime Example when we should use AddSingleTon and when AddScoped and When should use AddTransient.
As far as I know, the Singleton is normally used for a global single instance. For example, you will have an image store service you could have a service to load images from a given location and keeps them in memory for future use.
A scoped lifetime indicates that services are created once per client request. Normally we will use this for sql connection. It means it will create and dispose the sql connection per request.
A transient lifetime services are created each time they're requested from the service container. For example, during one request you use httpclient service to call other web api request multiple times, but the web api endpoint is different. At that time you will register the httpclient service as transient. That means each time when you call the httpclient service it will create a new httpclient to send the request not used the same one .
Transient — Services are created each time they are requested. It gets a new instance of the injected object, on each request of this object. For each time you inject this object is injected in the class, it will create a new instance.
Scoped — Services are created on each request (once per request). This is most recommended for WEB applications. So for example, if during a request you use the same dependency injection, in many places, you will use the same instance of that object, it will make reference to the same memory allocation.
Singleton — Services are created once for the lifetime of the application. It uses the same instance for the whole application.
I have a web service that will be consumed by some application (web site currently).
The calls are almost all specific to a certain client but still the same. So one call might be getAllFoo() but I would need some parameter to say from which client the Foo is.
It would become bothersome quickly if I just add a standard parameter to all calls so I was hoping to do it a little bit DRY and automatic. Something that would be included in all service calls.
Is IDispatchMessageInspector the right thing for me here? What kind of info could that include and can I access that info inside the methods?
Should I create some sort of attribute perhaps for the calls?
If anyone could point me towards a solution for this it would be great.
Edit
Another solution I'm thinking off.
Where the service call to a specific client happens on the consumer side, it will be known at instanceCreation so I could instance the ServiceClient with a known client.
Could I use this solution for the ClientBase<> extender somehow.
Let's say I'm serving Domain1 (let's call the client Domain to not confuse it with a serviceclient/consumer) I create a InformationProvider consumer side that has a ClientBase<IInformationService> field. I ensure that the DomainName (domain1) is set at construction so I could parhaps do the same thing when instancing the ClientBase<IInformationService> so It somehow let's the service know what domain I'm calling for.
I'm just still learning about WCF so I'm not sure how one would do this.
I can understand that you want to keep you solution simple and tidy, but ultimately - as you say yourself -
... I would need some parameter to say from which client...
The obvious and simplest solution is to include a client parameter on all your service calls where it is required. Surely there'll be service calls that don't require the client parameter, and in those cases you don't need to include the parameter.
You may be able to do something clever where a client identifier is passed discreetly under the covers, but beware of doing unnecessarily clever things. I would pass the client as a simple parameter because it is being used as a parameter. Two reasons come to mind:
if someone maintains your code they quickly understand what's going on.
if someone needs to use the service it is obvious how to use it.
A possible pattern:
Make sure you service instantiates per session. This means you'll have to use wsHttpBinding, netTcpBinding, or a custom binding as http does not support sessions.
Always call an initialization operation when each session is instantiated that sets the client id for that service.
Put this initialization operation inside a constructor for a proxy.
The steps involved would be something like this:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class MyService : IMyService
{
private int clientId;
public void StartUp(int clientId)
{
this.clientId = clientId;
and then client side, assuming you use the generated proxy, wrap the client inside another proxy.
public class ExtendedClient : MyServiceClient
{
public ExtendedClient(int clientid) : base()
{
this.StartUp(clientid);
}
Now you should instantiate the ExtendedClient, it will create the channel and prime the service by delivering the client id.
I would personally prefer to simply send the client id for each service call, but if you are able to use a session-able binding then this should work.
Just some information on WCF for you. If you have a stateless service, then you'll need to include the client as a parameter in every service call. This does not mean you need to include the client everywhere throughout your code - you could, for example, retrieve it inside the ClientBase constructor. But you will need to add it to every OperationContract and all the service implementations.
The alternative is to have a stateful service - the instance that you first use will remain for you to reuse (except for timeouts / exceptions). In this case you can potentially send the client just once, and then the service will know about the client for subsequent calls. This is the pattern described above. It means that you cannot use http binding. I believe that by doing this you're only increasing the potential for problems in your application (stateful services, having to ensure the initialization operation completes, more service calls being made).
Hopefully WCF has a reach instancing and concurrency management at service-side via Throttling.
My service client is an ASP.NET application. It consumes more than one WCF service so I create and parametrize WCF client at run-time (no configuration file is used).
Only the end point address is dynamic, and all the services (used by client) have the same method signatures (same contract).
For this reason I have referenced the service through Visual Studio and it has created my service proxy so I just take care of endpoint address at run-time:
class MyWcfClient
{
void DoSomething(string endpintAddress, int data)
{
// Create 'binding' and 'endpoint' ('endpoint' address is dynamic)
ServiceReference.ServiceClient serviceClient = new ServiceReference.ServiceClient(binding, endpoint);
// Parametrize 'serviceClient'
// Call WCF method (send 'data' to appropriate endpoint)
serviceClient.CLose();
}
}
Since the client is an asp.net application, each request runs on it's own worker thread (WCF method calls are very light and fast, so the thread would not block for a long time).
My question is about the instanciation and concurrency at the client-side.
Should MyWcfClient class be Singleton with one serviceClient instance or it be static class and a new serviceClient be created for each call ?
Should I create serviceClient (i.e, an array or list) based on the endpoints (there are 10-100 endpoints) ?
Note that my asp.net threads should not be blocked for a long time (i.e waiting in a queue for sending their related data via WCF)
There is no throttling on client side and it is not needed because you have client code under your control so you have control over number of requests executed. That is the difference to service where without throttling there is no control over number of incomming requests executed elsewhere (out of service control).
So if you want to control number of requests concurrently executed on client you must create object pool - there will be only limited number of MyWcfClient classes available and each class will always create new ServiceClient. Requests will wait in queue for free MyWcfClient instance.
If your only problem is how to create instances of ServiceClient then answer depends on type of binding.
Sessionful bindings like Net.Tcp, Net.Pipe or WsHttp with reliable session or security context: Create new instance for each communication relation. If your relation is just single call, create new instnace for each call. So you can use static class with static method and create new instance in that method.
Sessionless bindings like BasicHttp or WebHttp: You can reuse client for multiple calls but you can't close the client between subsequent calls. You can use array of prepared client instances. You will still need to handle some errors here.
Btw. also check asynchronous client calls and how to correctly close the service client.
From a little bit of reading around, it is my understanding that the only way to detect that a client has connected to my service is through writing my own code. I am using a Singleton service. I would like to display a message every time a client connects to my service that client x with ip xxx has connected. There is no built-in event that is generated? Am I correct?
No, I don't think there's any support in WCF for your requirement.
Not sure what you want to achieve with this, either. Your service class (in your case, just a single instance) really doesn't have any business putting up messages (on screen, I presume) - that really not it's job. The service class is used to handle a request and deliver a response - nothing more.
The ServiceHost class might be more of a candidate for this feature - but again, it's job really is to host the service, spin up the WCF runtime etc. - and it's really not a UI component, either.
What you could possibly do is this
have an Admin UI (a Winforms, console, or WPF app) running on your server alongside your service, providing an admin service to call
define a fast connection between the two services (using e.g. netNamedPipe binding which is perfect for intra-application messaging)
when your "real" service gets a call, the first thing it does is send out a message to the admin UI which can then pick up that message and handle it
That way, you could cleanly separate your real service and it's job (to provide that service) and the Admin UI stuff you want to do and build a cleanly separated system.
I have actually implemented my own connect, disconnect and ping service methods which I manually call from my client once the channel has been created. By using them as a kind of header section in all of my ServiceContract interface definitions (and their implementations, of course), they form an makeshift "base service definition" that only requires a bit of cut-n-paste.
The string-based parameters of connect and disconnect will be used to send client info to the server and return server info and (perhaps a unique connection id) to the client. In addition a set of timing reference points may make its way in also.
Note how SessionMode is required and the individual OperationContract properties IsInitiating and IsTerminating are explicitly specified for each method, the end result being what I would call a "single-session" service in that it defines connect and disconnect as the sole session bookends.
Note also that the ping command will be used as the target of a timer-based "heartbeat" call that tests the service connection state and defeats ALL connection timeouts without a single config file :-)
Note also that I haven't determined my fault-handling structure yet which may very well add a method or more and/or require other kinds of changes.
[ServiceContract( SessionMode = SessionMode.Required )]
public interface IRePropDalSvr {
[OperationContract( IsInitiating=true, IsTerminating=false )]
string connect (string pClientInfo);
[OperationContract( IsInitiating=false, IsTerminating=true, IsOneWay=true )]
void disconnect (string pClientInfo);
// ------------------------------------------------------------------------------------------
[OperationContract( IsInitiating=false, IsTerminating=false )]
string ping (string pInp);
// ------------------------------------------------------------------------------------------
// REST OF ServiceContract DEFINITION GOES HERE
One caveat: while I am currently using this code and its implemention in my service classes, I have not verified the code yet.
I am using wcf 4 and trying to transparently transfer context information between client and server.
I was looking at behaviors and was able to pass things around. My problem is how to flow the context received in the incoming headers to the other services that might be called by a service.
In the service behavior I intercept the the message and read the headers but don't know where to put that data to be accessible to the next service call that the current service might make.
What I am looking for is something like:
public void DoWork()
{
var someId = MyContext.SomeId;
//do something with it here and call another service
using(var proxy = GetProxy<IAnotherService>())
proxy.CallSomeOtherMethodThatShouldGetAccessTo_ MyContextualObject();
}
If I store the headers in thread local storage I might have problems due to thread agility(not sure this happens outside ASP.NET, aka custom service hosts). How would you implement the MyContext in the code above.
I chose the MyContext instead of accessing the headers directly because the initiator of the service call might not be a service in which case the MyContext is backed by HttpContext for example for storage.
In the service behavior I intercept
the the message and read the headers
but don't know where to put that data
to be accessible to the next service
call.
Typically, you don't have any state between calls. Each call is totally autonomous, each call gets a brand new instance of your service class created from scratch. That's the recommended best practice.
If you need to pass that piece of information (language, settings, whatever) to a second, third, fourth call, do so by passing it in their headers, too. Do not start to put state into the WCF server side! WCF services should always be totally autonomous and not retain any state, if at ever possible.
UPDATE: ok, after your comments: what might be of interest to you is the new RoutingService base class that will be shipped with WCF 4. It allows scenarios like you describe - getting a message from the outside and forwarding it to another service somewhere in the background. Google for "WCF4 RoutingService" - you should find a number of articles. I couldn't find antyhing in specific about headers, but I guess those would be transparently transported along.
There's also a two-part article series Building a WCF Router Part 1 (and part 2 here) in MSDN Magazine that accomplishes more or less the same in WCF 3.5 - again, not sure about headers, but maybe that could give you an idea.