By Joe Di Pol-Oracle on Oct 27, 2015
If you are not familiar with WebLogic Server multi-tenancy support, you should read Tim Quinn's blog: Domain Partitions for Multi-tenancy in WebLogic Server. It gives a nice overview of the partition feature in WLS 12.2.1 and covers concepts that are used in this article.
As you learned in Tim's blog, a domain partition (partition for short) is an administrative and runtime slice of a WebLogic domain that contains a collection of application and resources. Those applications and resources need to run somewhere in your domain: on a cluster, on a specific managed server, or on the admin server itself.
In 12.1.3 and before you target applications and resources individually -- typically directly to a managed server or cluster. In a partition this is a bit different:
- In a partition resources and applications are grouped into resource groups, and it is the resource group that is targeted. When a target is set on a resource group it applies to all of the resources and applications inside of the resource group (you don't target them individually).
- Resource groups inside partitions are targeted to virtual targets – not directly to managed servers or clusters
So what are virtual targets? If you are familiar with virtual hosts in WLS (or the general concept of virtual hosts in web servers), then you can think of virtual targets as similar to virtual hosts. A virtual target accomplishes three things:
- It provides a physical
target (cluster or server). The virtual target is deployed to the physical target, and any
resources deployed to the virtual target are deployed to the physical
target that the virtual target wraps.
- It provides a separate HTTP server. So any web application deployed to the virtual target runs in its HTTP server (and not the default HTTP server).
- It provides a mapping of incoming requests (in the form of a URL) to a specific virtual target and therefore to a specific partition
Let's look at each of these a bit closer.
You can specify a managed server or a cluster as a physical target for a virtual target (using the set or addTarget methods on VirtualTargetMBean). Note that even though the VirtualTargetMBean methods support multiple physical targets, there is currently validation in place to prevent setting more than one physical target on a VirtualTarget.
The physical target accomplishes two things:
- It is the target that the virtual target is deployed to (and therefore where the virtual HTTP server will run)
- It is the target that is used when resources and apps are deployed to the virtual target
Each Virtual Target has its own HTTP server that is lazily initialized on the managed server (or cluster of managed servers) where the virtual target is running (targeted). Any web application or resource that is deployed to the virtual target will run in this HTTP server. This avoids context path clashes with applications running in other virtual targets (or in the default HTTP Server).
When a request enters a WLS instance two key things need to occur:
- The partition that the URL "belongs to" needs to be identified
- For HTTP requests, the VirtualTarget needs to be located so that the proper HTTP server can be used.
This means that the virtual target needs information to match against incoming URLs to see if they "match" the virtual target
A Virtual Target has three attributes that can be set to accomplish this matching:
- Virtual hostnames: one or more virtual hostnames
- uriPrefix: a single URI prefix path
- port: a port number
A Virtual Target can have zero or more virtual hostnames. These hostnames are matched against the hostname used by the client
(with HTTP this is provided by the Host: field introduced in HTTP 1.1). The matching is a literal string comparisons, but you can specify more than
one hostname. This is handy for aliasing all possible hostnames that might be
used in requests (myserver, myserver.us.com, etc). Also, the virtual hostname is not required. So if you want to use uriPrefix only (or port number only) that's fine.
In addition to matching on the hostname, you can match on the URI of the incoming request, so that all requests that start with a specific URI path match that virtual target. For example "/partition1".
Port number based routing is provided primarily for backwards compatibility with older clients where changing the URL is not an option. You can specify an explicit port number on a virtual target, or a port offset. If a port offset is used then the offset is applied to the default channel of the server, or to a specific base channel if you specify a base channel name on the Virtual Target.
If you specify a port number on a Virtual Target, then WLS will automatically
create channels for the virtual target at runtime. You don't need to
create these channels yourself. Any requests that come in on that
channel (port number) will go to the virtual target. In this regard the port number trumps both uri prefix and virtual hostname.
Here are some examples to illustrate how the matching works. This assumes the server's default port number is 7001.
|Hostnames||uriPrefix||Port Num||Matching URLs||Non-matching URLs||Notes|
The host name must be an exact string match.
|http://red.com/red/myapp||Both hostname and uriPrefix must match|
||7277||http://anyhost.com:7277/myapp||http://anyhost.com:7001/myapp||Any request coming to 7277 will match, otherwise no match.|
|-||/red||-||http://anyhost.com:7001/red/myapp||http://colors.com:7001/blue/myapp||No hostname specified. In that case the hostname is essentially a wildcard.|
Pick a scheme and stay with it and don't get fancy probing strange combinations. Typically you'll want to use one of these patterns:
- Differentiate by virtual hostname only: red.com, blue.com, green.com
- Differentiate by uriPrefix only: colors.com:7001/red, colors.com:7001/blue, colors.com:7001/green
- Differentiate by port number only: colors.com:7277, colors.com:7278, colors.com:7279
- Only differentiate by port number when you have to for backwards compatibility with existing clients.
Also, keep in mind that VirtualTargets do not have anything to do with how a request gets to a specific server/port. So if you use virtual hostnames you have to handle this, typically by creating the appropriate hostname entries in DNS, or by using a load balancer.
If you are not familiar with the general concept of HTTP virtual servers (aka virtual hosts) it is probably worth reading up on that topic.
As mentioned in the introduction resources/apps in a partition are grouped into resource groups, and it is the resource groups that are targeted. There are a couple important concepts:
- Partition's available targets (PartitionMBean availableTargets): this is a list of virtual targets that can be used within the partition to target resource groups. Typically a WLS admin will create a number of virtual targets in the domain, and then assign a subset of them to a specific partition. Resource groups within the partition can only be targeted to one of these available targets.
- Partition's default target (PartitionMBean defaultTargets):
a partition can also have zero or more default targets.
Resource groups in the partition can be explicitly targeted (by using
the methods on ResourceGroupMBean to add or set targets).
But if no explicit targets are set on a resource group, then by default
it picks up the partition's default targets.
- Note that there is a boolean attribute on ResourceGroupMBean: useDefaultTargets. If this is true (and by default it is) then the resource group will use the partition's default targets for targeting if no explicit target is set. If this is false then the resource group will not use the partition's defaults and you must set the targets on the resource group explicitly. Also, if you explicitly set targets on a resource group then this flag is flipped to "false" with the anticipation that you never want to pick up the partition's defaults.
- Partition's effective targets: the (sub)set of available targets that are in use at any given time by resource groups in the partition.
So a common sequence for setting up partition targeting is:
- WLS admin creates some virtual targets at the domain level for use by partitions
- WLS admin creates partitions, and sets the available targets on the partitions to the set of virtual targets they want each partition to use
(or Partition) admin creates resource groups in the partition and sets
the resource group targets based on the available targets for the
partition (or use the partition default)
Note that in the simplest case you just assign one virtual target to a partition (as an available target) and make it the partition's default target. Then all resource groups in the partition will use that one target.
Some things to watch out for:
- Hogging virtual targets: if you define a virtual target with no hostname and a uriPrefix of "/", then that virtual target would hog all requests coming into the domain. You never want that. Things will break. WLS configuration validation tries to prevent the creation of such virtual targets, but it can't catch all cases. So be mindful that you want the virtual target to only match requests specifically intended for it.
- Restrictions: in 12.2.1 there are some targeting restrictins. Some examples:
- A virtual target can not be shared by more than one partition
- A virtual target can have only one (server or cluster) set on it as a target
- A resource group can be targeted to more than one virtual target
- Unless the resource group contains one or more of: JMSServer, MessagingBridge, PathService, JMSBridgeDestination, FileStore, JDBCStore, JMSSystemResource
Here is a simple example using WLST that creates a partition named "Acme" with a single resource group and virtual target. An application is deployed to that resource group. The virtual target has "myserver" (the admin server) as its physical target and uses a uriPrefix of "/acme" -- so to access the application you must prefix the URL with "/acme". Finally, the partition is started, since partitions are not running by default.
import os,sys,urllib,time # Change this to the location of a simple web application. APP_PATH='/scratch/tmp/counter.war' # Change these to your admin login credentials and connection URL USER='admin' PASSWORD='admin123' T3_URL='t3://localhost:7001' # Change this to be the name of the server you want to deploy the app to SERVER='myserver' print "Connecting to " + T3_URL connect(USER,PASSWORD,T3_URL) edit() domain=getMBean('/') tgt=getMBean('/Servers/' + SERVER) # Create "Acme" virtual target # We set a uriPrefix only (no virtual host names) startEdit() acmevt=domain.createVirtualTarget('AcmeVT') acmevt.addTarget(tgt) acmevt.setUriPrefix('/acme') # The VT contains a virtual HTTP server. We can configure it acmevt.getWebServer().getWebServerLog().setBufferSizeKB(0) activate() # Create Acme partition and ResourceGroup startEdit() acmepart=domain.createPartition('Acme') acmepart.addAvailableTarget(acmevt) acmerg=acmepart.createResourceGroup('SimpleRG') acmerg.addTarget(acmevt) activate() # Deploy the application to SimpleRG in partition Acme startEdit() progress=deploy(appName='sampleapp', path=APP_PATH, partition=acmepart.getName(), resourceGroup=acmerg.getName(), deploymentOrder=10,securityModel='DDOnly') activate() while not (progress.isCompleted() or progress.isFailed()) : os.time.sleep(2) progress.printStatus() # You must start the partition to get the stuff in it running # This is a convenience command to start the partition and # wait for it to come up startPartitionWait(acmepart) # Now hit the webapp at (for example) http://localhost:7001/acme/webapp/webapp.jsp