VMware {code} Community
pshterev
VMware Employee
VMware Employee

How to correctly use VimPortType for vCenter server VMODL API communication

Hello. I'm working on a vSphere client plugin using the HTML SDK and I checked the vsphere-wssdk-service project included in the SDK as one of the examples where VimService and VimPortType classes are used to get ServiceContent for a VC and then it's used to work with VC VMODL API. In that project VimPortType instance is statically initialized because it takes several seconds. I made some tests and indeed it takes about 5-6 seconds to create VimPortType instance and since it takes so much time I'm trying to figure out how to effectively reuse that instance so my questions are:

1. Can we reuse VimPortType across multiple requests ? - it is obviously done in wssdk example in the SDK but is that part of the code production ready ?

2. Can we reuse VimPortType across multiple request handlers/dataProviders ? - so that we can initialize it statically on only one place in the server code and reuse it across different request handlers or dataProviders

3. Is VimPortType thread safe so that one instance can be safely used from multiple threads without external synchronization ? - again this is done in wssdk

4. Should we externally handle synchronization for this code from wssdk example (com.vmware.samples.vspherewssdk.DataProviderImpl) (not done in the example) :

      Map<String, Object> reqContext = ((BindingProvider)_vimPort).getRequestContext();

      reqContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, serviceUrl);

      reqContext.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true);

      reqContext.put(MessageContext.HTTP_REQUEST_HEADERS, reqHeadrs);

      ServiceContent serviceContent = null;

      try {

         serviceContent = _vimPort.retrieveServiceContent(svcInstanceRef);

      } catch (RuntimeFaultFaultMsg e) {

         _logger.error("getServiceContent error: " + e);

      }

I checked that multiple threads work with a single instance of the data provider with a single instance of the VimPortType (_vimPort reference in the example above). Since _vimPort.requestContext is first modified with the selected VC and user session and then _vimPort.retrieveServiceContent is invoked then the whole block should be synchronized for _vimPort reference. Am I right in my guess or the whole DataProviderImpl.getProperties() is somehow externally synchronized and guaranteed that no simultaneous request are being handled which means in that case that we should not care for synchronization ?

5. And to partially reiterate my previous question - is there any external synchronization performed by vSphere client when handling server request to plugin services ?

3 Replies
laurentsd
VMware Employee
VMware Employee

This API belongs to the vSphere Management SDK, not the Web Client SDK per so, but those are valid questions that we are interested in documenting better for plugin developers. It will take some research to get the correct information, thanks.

Reply
0 Kudos
pshterev
VMware Employee
VMware Employee

Hi Laurent. Is there any updates on this topic? Probably someone I can contact with this question?

Reply
0 Kudos
Plam_Dimitrov
VMware Employee
VMware Employee

Hello,

As per the JAX-WS specification (see section 4.2.3 - Proxies, page 76) the Port objects for a Service are not guaranteed to be thread-safe. This means that the wssdk sample is, indeed, not a good example of how to use the VIM25 API in a multi-threaded environment.

To answer each of the questions individually:

1. Can we reuse VimPortType across multiple requests ? - yes, if the VimPort objectis not used concurrently

2. Can we reuse VimPortType across multiple request handlers/dataProviders ? - yes, if the VimPort objectis not used concurrently

3. Is VimPortType thread safe so that one instance can be safely used from multiple threads without external synchronization ? - no

4. Should we externally handle synchronization for this code (...) from wssdk example (com.vmware.samples.vspherewssdk.DataProviderImpl) (not done in the example)  - yes, some sort of synchronization is needed here

5. And to partially reiterate my previous question - is there any external synchronization performed by vSphere client when handling server request to plugin services ? - no, the vSphere Client doesn't do any external synchronization to plugin service - if such is needed it must be implemented within the plugin service itself.

Also note a couple of things:

1) Only the first invocation of getPort()  is taking a lot of time - subsequent calls are instantaneous (around 20-30ms)

2) The first call to getPort() does the loading of the WSDL definitions and as such amounts to a 20-30MB heap increase - subsequent calls take much less

We still do not have a definitive solution to the multi-threaded use case of the vim25 API but here are some proposals which you may experiment with and see if they fit your needs:

1) If your plugin service is not supposed to handle a large number of simultaneous requests and is not performance critical then the simplest thing to do is to synchronize the access to the _vimPort object

2) If you need to handle a larger amount of requests then try the following - Instead of having a static VimPortType (_vimPort) object which serves all requests, have a static VimService object. On every request do a "getPort()" and do the operation through that port-  this is certainly thread-safe. There are a couple of drawbacks/issues here:

   - The first request to do getPort() will be very slow - in order to avoid this, make a dummy call to "getPort()" in the static initializer of the class so that real requests will be fast later on.

   - Each getPort() call seems to create a certain amount of non-garbage-collectable objects that are from the JAX-WS implementation (SEIStub). The reason this happens is that the threads that execute the getPort() are part of the data-service pool and the default JAX-WS implementation uses ThreadLocals. This leak can probably be avoided by doing the VImPort operations in a separate thread that will actually be garbage collected once it's done.

3) A third option that will both restrict the JAX-WS leak and allow for concurrency is to implement a pool of VimPorts of a reasonable for the service size.