Search in sources :

Example 1 with ClusteringFault

use of org.apache.axis2.clustering.ClusteringFault in project carbon-apimgt by wso2.

the class TenantLoadMessageSenderTest method testSendTenantRegistryLoadMessage.

@Test
public void testSendTenantRegistryLoadMessage() throws ClusteringFault {
    ClusteringAgent clusteringAgent = PowerMockito.mock(ClusteringAgent.class);
    ClusteringMessage request = new TenantLoadMessage(1, "a.com");
    ClusteringCommand command = PowerMockito.mock(ClusteringCommand.class);
    List<ClusteringCommand> commandList = new ArrayList<ClusteringCommand>();
    commandList.add(command);
    PowerMockito.when(clusteringAgent.sendMessage(request, true)).thenReturn(commandList);
    tenantLoadMessageSender.sendTenantLoadMessage(clusteringAgent, 1, "a.com", 1);
}
Also used : ClusteringCommand(org.apache.axis2.clustering.ClusteringCommand) ClusteringMessage(org.apache.axis2.clustering.ClusteringMessage) ArrayList(java.util.ArrayList) ClusteringAgent(org.apache.axis2.clustering.ClusteringAgent) TenantLoadMessage(org.wso2.carbon.apimgt.impl.message.clustering.TenantLoadMessage) Test(org.junit.Test) PrepareForTest(org.powermock.core.classloader.annotations.PrepareForTest)

Example 2 with ClusteringFault

use of org.apache.axis2.clustering.ClusteringFault in project carbon-apimgt by wso2.

the class APIThrottleHandler method doRoleBasedAccessThrottling.

private boolean doRoleBasedAccessThrottling(MessageContext synCtx, ConfigurationContext cc) {
    boolean canAccess = true;
    ThrottleDataHolder dataHolder = (ThrottleDataHolder) cc.getPropertyNonReplicable(ThrottleConstants.THROTTLE_INFO_KEY);
    if (throttle.getThrottleContext(ThrottleConstants.ROLE_BASED_THROTTLE_KEY) == null) {
        // skip role base throttling
        return true;
    }
    ConcurrentAccessController cac = null;
    if (isClusteringEnable) {
        // for clustered  env.,gets it from axis configuration context
        cac = (ConcurrentAccessController) cc.getProperty(key);
    }
    if (!synCtx.isResponse()) {
        // gets the remote caller role name
        AuthenticationContext authContext = APISecurityUtils.getAuthenticationContext(synCtx);
        String accessToken;
        String consumerKey;
        String authorizedUser;
        String roleID;
        String applicationId;
        String applicationTier;
        if (authContext != null) {
            // Although the method says getApiKey, what is actually returned is the Bearer header (accessToken)
            accessToken = authContext.getApiKey();
            consumerKey = authContext.getConsumerKey();
            authorizedUser = authContext.getUsername();
            roleID = authContext.getTier();
            applicationTier = authContext.getApplicationTier();
            applicationId = authContext.getApplicationId();
            if (accessToken == null || roleID == null) {
                log.warn("No consumer key or role information found on the request - " + "Throttling not applied");
                return true;
            }
        } else {
            log.warn("No authentication context information found on the request - " + "Throttling not applied");
            return true;
        }
        // Domain name based throttling
        // check whether a configuration has been defined for this role name or not
        // loads the ThrottleContext
        ThrottleContext resourceContext = throttle.getThrottleContext(RESOURCE_THROTTLE_KEY);
        if (resourceContext == null) {
            log.warn("Unable to load throttle context");
            return true;
        }
        // Loads the ThrottleConfiguration
        ThrottleConfiguration config = resourceContext.getThrottleConfiguration();
        if (config != null) {
            String applicationRoleId = null;
            // If an application level tier has been specified and it is not 'Unlimited'
            if (applicationTier != null && !APIConstants.UNLIMITED_TIER.equals(applicationTier)) {
                // Get the configuration role of the application
                // applicationRoleId = config.getConfigurationKeyOfCaller(applicationTier);
                applicationRoleId = applicationTier;
            }
            AccessInformation info = null;
            // If application level throttling is applied
            if (applicationRoleId != null) {
                ThrottleContext applicationThrottleContext = getApplicationThrottleContext(synCtx, dataHolder, applicationId);
                if (isClusteringEnable) {
                    applicationThrottleContext.setConfigurationContext(cc);
                    applicationThrottleContext.setThrottleId(id);
                }
                // First throttle by application
                try {
                    info = applicationRoleBasedAccessController.canAccess(applicationThrottleContext, applicationId, applicationRoleId);
                    if (log.isDebugEnabled()) {
                        log.debug("Throttle by Application " + applicationId);
                        log.debug("Allowed = " + (info != null ? info.isAccessAllowed() : "false"));
                    }
                } catch (ThrottleException e) {
                    log.warn("Exception occurred while performing role " + "based throttling", e);
                    synCtx.setProperty(APIThrottleConstants.THROTTLED_OUT_REASON, APIThrottleConstants.APPLICATION_LIMIT_EXCEEDED);
                    return false;
                }
                // check for the permission for access
                if (info != null && !info.isAccessAllowed()) {
                    log.info("Exceeded the allocated quota in Application level.");
                    // if the access has denied by rate based throttling
                    if (cac != null) {
                        cac.incrementAndGet();
                        // set back if this is a clustered env
                        if (isClusteringEnable) {
                            cc.setProperty(key, cac);
                            resourceContext.setConfigurationContext(cc);
                            // replicate the current state of ConcurrentAccessController
                            try {
                                Replicator.replicate(cc, new String[] { key });
                            } catch (ClusteringFault clusteringFault) {
                                log.error("Error during replicating states", clusteringFault);
                            }
                        }
                    }
                    synCtx.setProperty(APIThrottleConstants.THROTTLED_OUT_REASON, APIThrottleConstants.APPLICATION_LIMIT_EXCEEDED);
                    return false;
                }
            }
            // ---------------End of application level throttling------------
            // ==============================Start of Resource level throttling======================================
            // get throttling information for given request with resource path and http verb
            // VerbInfoDTO verbInfoDTO = null;
            // verbInfoDTO = validator.getVerbInfoDTOFromAPIData(apiContext, apiVersion, requestPath, httpMethod);
            VerbInfoDTO verbInfoDTO = (VerbInfoDTO) synCtx.getProperty(APIConstants.VERB_INFO_DTO);
            String resourceLevelRoleId = null;
            // no data related to verb information data
            if (verbInfoDTO == null) {
                log.warn("Error while getting throttling information for resource and http verb");
                return false;
            } else {
                // Not only we can proceed
                String resourceAndHTTPVerbThrottlingTier = verbInfoDTO.getThrottling();
                // If there no any tier then we need to set it as unlimited
                if (resourceAndHTTPVerbThrottlingTier == null) {
                    log.warn("Unable to find throttling information for resource and http verb. Throttling will " + "not apply");
                } else {
                    resourceLevelRoleId = resourceAndHTTPVerbThrottlingTier;
                }
                // adding consumerKey and authz_user combination instead of access token to resourceAndHTTPVerbKey
                // This avoids sending more than the permitted number of requests in a unit time by
                // regenerating the access token
                String resourceAndHTTPVerbKey = verbInfoDTO.getRequestKey() + '-' + consumerKey + ':' + authorizedUser;
                // if request not null then only we proceed
                if (resourceLevelRoleId != null) {
                    try {
                        // if application level throttling has passed
                        if (!APIConstants.UNLIMITED_TIER.equals(resourceLevelRoleId) && (info == null || info.isAccessAllowed())) {
                            // If this is a clustered env.
                            if (isClusteringEnable) {
                                resourceContext.setConfigurationContext(cc);
                                resourceContext.setThrottleId(id + "resource");
                            }
                            info = roleBasedAccessController.canAccess(resourceContext, resourceAndHTTPVerbKey, resourceAndHTTPVerbThrottlingTier);
                        }
                    } catch (ThrottleException e) {
                        log.warn("Exception occurred while performing resource" + "based throttling", e);
                        synCtx.setProperty(APIThrottleConstants.THROTTLED_OUT_REASON, APIThrottleConstants.RESOURCE_LIMIT_EXCEEDED);
                        return false;
                    }
                    // check for the permission for access
                    if (info != null && !info.isAccessAllowed()) {
                        log.info("Exceeded the allocated quota in Resource level.");
                        // if the access has denied by rate based throttling
                        if (cac != null) {
                            cac.incrementAndGet();
                            // set back if this is a clustered env
                            if (isClusteringEnable) {
                                cc.setProperty(key, cac);
                                // replicate the current state of ConcurrentAccessController
                                try {
                                    Replicator.replicate(cc, new String[] { key });
                                } catch (ClusteringFault clusteringFault) {
                                    log.error("Error during replicating states", clusteringFault);
                                }
                            }
                        }
                        if (isContinueOnThrottleReached(resourceAndHTTPVerbThrottlingTier)) {
                            // limit has reached.
                            if (synCtx.getProperty(APIConstants.API_USAGE_THROTTLE_OUT_PROPERTY_KEY) == null) {
                                synCtx.setProperty(APIConstants.API_USAGE_THROTTLE_OUT_PROPERTY_KEY, Boolean.TRUE);
                            }
                        } else {
                            synCtx.setProperty(APIThrottleConstants.THROTTLED_OUT_REASON, APIThrottleConstants.RESOURCE_LIMIT_EXCEEDED);
                            return false;
                        }
                    }
                } else {
                    log.warn("Unable to find the throttle policy for role.");
                }
            }
            // ==============================End of Resource level throttling=======================================
            // ---------------Start of API level throttling------------------
            // Domain name based throttling
            // check whether a configuration has been defined for this role name or not
            // loads the ThrottleContext
            ThrottleContext context = throttle.getThrottleContext(ThrottleConstants.ROLE_BASED_THROTTLE_KEY);
            String apiKey;
            if (context == null) {
                log.warn("Unable to load throttle context");
                return true;
            }
            // If this is a clustered env.
            // check for configuration role of the caller
            config = context.getThrottleConfiguration();
            String consumerRoleID = config.getConfigurationKeyOfCaller(roleID);
            if (isClusteringEnable) {
                context.setConfigurationContext(cc);
                context.setThrottleId(id);
            }
            try {
                String apiContext = (String) synCtx.getProperty(RESTConstants.REST_API_CONTEXT);
                String apiVersion = (String) synCtx.getProperty(RESTConstants.SYNAPSE_REST_API_VERSION);
                apiContext = apiContext != null ? apiContext : "";
                apiVersion = apiVersion != null ? apiVersion : "";
                // adding consumerKey and authz_user combination instead of access token to apiKey
                // This avoids sending more than the permitted number of requests in a unit time by
                // regenerating the access token
                apiKey = apiContext + ':' + apiVersion + ':' + consumerKey + ':' + authorizedUser;
                // if application level throttling has passed
                if (!APIConstants.UNLIMITED_TIER.equals(roleID) && (info == null || info.isAccessAllowed())) {
                    // Throttle by access token
                    info = roleBasedAccessController.canAccess(context, apiKey, consumerRoleID);
                }
            } catch (ThrottleException e) {
                log.warn("Exception occurred while performing role " + "based throttling", e);
                synCtx.setProperty(APIThrottleConstants.THROTTLED_OUT_REASON, APIThrottleConstants.API_LIMIT_EXCEEDED);
                return false;
            }
            // check for the permission for access
            if (info != null && !info.isAccessAllowed()) {
                log.info("Exceeded the allocated quota in API level.");
                // if the access has denied by rate based throttling
                if (cac != null) {
                    cac.incrementAndGet();
                    // set back if this is a clustered env
                    if (isClusteringEnable) {
                        cc.setProperty(key, cac);
                        // replicate the current state of ConcurrentAccessController
                        try {
                            Replicator.replicate(cc, new String[] { key });
                        } catch (ClusteringFault clusteringFault) {
                            log.error("Error during replicating states", clusteringFault);
                        }
                    }
                }
                if (isContinueOnThrottleReached(consumerRoleID)) {
                    // limit has reached.
                    if (synCtx.getProperty(APIConstants.API_USAGE_THROTTLE_OUT_PROPERTY_KEY) == null) {
                        synCtx.setProperty(APIConstants.API_USAGE_THROTTLE_OUT_PROPERTY_KEY, Boolean.TRUE);
                    }
                    if (log.isDebugEnabled()) {
                        log.debug("Request throttled at API level for throttle key" + apiKey + ". But role " + consumerRoleID + "allows to continue to serve requests");
                    }
                } else {
                    synCtx.setProperty(APIThrottleConstants.THROTTLED_OUT_REASON, APIThrottleConstants.API_LIMIT_EXCEEDED);
                    return false;
                }
            }
        }
    }
    // ---------------End of API level throttling------------------
    // ---------------Start of Hard throttling------------------
    ThrottleContext hardThrottleContext = throttle.getThrottleContext(APIThrottleConstants.HARD_THROTTLING_CONFIGURATION);
    try {
        String apiContext = (String) synCtx.getProperty(RESTConstants.REST_API_CONTEXT);
        String apiVersion = (String) synCtx.getProperty(RESTConstants.SYNAPSE_REST_API_VERSION);
        apiContext = apiContext != null ? apiContext : "";
        apiVersion = apiVersion != null ? apiVersion : "";
        AuthenticationContext authContext = APISecurityUtils.getAuthenticationContext(synCtx);
        if (hardThrottleContext != null && authContext.getKeyType() != null) {
            String throttleKey = apiContext + ':' + apiVersion + ':' + authContext.getKeyType();
            AccessInformation info = null;
            if (isClusteringEnable) {
                hardThrottleContext.setConfigurationContext(cc);
            }
            if (APIConstants.API_KEY_TYPE_PRODUCTION.equals(authContext.getKeyType())) {
                hardThrottleContext.setThrottleId(id + APIThrottleConstants.PRODUCTION_HARD_LIMIT);
                info = roleBasedAccessController.canAccess(hardThrottleContext, throttleKey, APIThrottleConstants.PRODUCTION_HARD_LIMIT);
            } else if (APIConstants.API_KEY_TYPE_SANDBOX.equals(authContext.getKeyType())) {
                hardThrottleContext.setThrottleId(id + APIThrottleConstants.SANDBOX_HARD_LIMIT);
                info = roleBasedAccessController.canAccess(hardThrottleContext, throttleKey, APIThrottleConstants.SANDBOX_HARD_LIMIT);
            }
            if (log.isDebugEnabled()) {
                log.debug("Throttle by hard limit " + throttleKey);
                log.debug("Allowed = " + (info != null ? info.isAccessAllowed() : "false"));
            }
            if (info != null && !info.isAccessAllowed()) {
                synCtx.setProperty(APIThrottleConstants.THROTTLED_OUT_REASON, APIThrottleConstants.HARD_LIMIT_EXCEEDED);
                log.info("Hard Throttling limit exceeded.");
                return false;
            }
        }
    } catch (ThrottleException e) {
        log.warn("Exception occurred while performing role based throttling", e);
        synCtx.setProperty(APIThrottleConstants.THROTTLED_OUT_REASON, APIThrottleConstants.HARD_LIMIT_EXCEEDED);
        return false;
    }
    return canAccess;
}
Also used : ThrottleContext(org.apache.synapse.commons.throttle.core.ThrottleContext) ThrottleDataHolder(org.apache.synapse.commons.throttle.core.ThrottleDataHolder) AuthenticationContext(org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationContext) VerbInfoDTO(org.wso2.carbon.apimgt.impl.dto.VerbInfoDTO) AccessInformation(org.apache.synapse.commons.throttle.core.AccessInformation) ThrottleException(org.apache.synapse.commons.throttle.core.ThrottleException) ThrottleConfiguration(org.apache.synapse.commons.throttle.core.ThrottleConfiguration) ConcurrentAccessController(org.apache.synapse.commons.throttle.core.ConcurrentAccessController) ClusteringFault(org.apache.axis2.clustering.ClusteringFault)

Example 3 with ClusteringFault

use of org.apache.axis2.clustering.ClusteringFault in project carbon-apimgt by wso2.

the class APIThrottleHandler method doThrottle.

private boolean doThrottle(MessageContext messageContext) {
    boolean isResponse = messageContext.isResponse();
    org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext).getAxis2MessageContext();
    ConfigurationContext cc = axis2MC.getConfigurationContext();
    ThrottleDataHolder dataHolder = null;
    if (cc == null) {
        handleException("Error while retrieving ConfigurationContext from messageContext");
    }
    synchronized (cc) {
        dataHolder = (ThrottleDataHolder) cc.getProperty(ThrottleConstants.THROTTLE_INFO_KEY);
        if (dataHolder == null) {
            dataHolder = new ThrottleDataHolder();
            cc.setNonReplicableProperty(ThrottleConstants.THROTTLE_INFO_KEY, dataHolder);
        }
    }
    if ((throttle == null && !isResponse) || (isResponse && concurrentAccessController == null)) {
        isClusteringEnable = isClusteringEnabled();
    }
    if (!isResponse) {
        // if this is a clustered environment
        if (isClusteringEnable) {
            concurrentAccessController = (ConcurrentAccessController) cc.getProperty(key);
        }
        initThrottle(messageContext, cc);
    } else {
        // if the message flow path is OUT , then must lookup from ConfigurationContext -
        // never create ,just get the existing one
        concurrentAccessController = (ConcurrentAccessController) cc.getProperty(key);
    }
    // perform concurrency throttling
    boolean canAccess = doThrottleByConcurrency(isResponse);
    // then do access rate based throttling
    if (canAccess && !isResponse && throttle != null) {
        canAccess = throttleByAccessRate(axis2MC, cc) && doRoleBasedAccessThrottling(messageContext, cc);
    }
    // Just replicate the current state of ConcurrentAccessController
    if (isClusteringEnable && concurrentAccessController != null) {
        try {
            Replicator.replicate(cc);
        } catch (ClusteringFault clusteringFault) {
            handleException("Error during the replicating  states ", clusteringFault);
        }
    }
    if (!canAccess) {
        handleThrottleOut(messageContext);
        return false;
    }
    return true;
}
Also used : ConfigurationContext(org.apache.axis2.context.ConfigurationContext) ThrottleDataHolder(org.apache.synapse.commons.throttle.core.ThrottleDataHolder) Axis2MessageContext(org.apache.synapse.core.axis2.Axis2MessageContext) ClusteringFault(org.apache.axis2.clustering.ClusteringFault)

Example 4 with ClusteringFault

use of org.apache.axis2.clustering.ClusteringFault in project carbon-apimgt by wso2.

the class TenantLoadMessageSender method sendTenantLoadMessage.

/**
 * Send the {@link TenantLoadMessage} message
 *
 * @param clusteringAgent {@link ClusteringAgent} object
 * @param tenantId        tenant id
 * @param tenantDomain    tenant domain
 * @param retryCount      retry count if cluster message sending fails
 * @throws ClusteringFault id cluster message sending fails
 */
void sendTenantLoadMessage(ClusteringAgent clusteringAgent, int tenantId, String tenantDomain, int retryCount) throws ClusteringFault {
    // need to re-try if the initial message fails.
    int numberOfRetries = 0;
    ClusteringMessage request = new TenantLoadMessage(tenantId, tenantDomain);
    while (numberOfRetries < retryCount) {
        try {
            clusteringAgent.sendMessage(request, true);
            log.info("Sent [" + request.toString() + "]");
            break;
        } catch (ClusteringFault e) {
            numberOfRetries++;
            if (numberOfRetries < retryCount) {
                log.warn("Could not send TenantRegistryLoadMessage for tenant " + tenantId + ". Retry will be attempted in 2s. Request: " + request, e);
            } else {
                // cluster message sending failed, throw
                throw e;
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ignored) {
            }
        }
    }
}
Also used : ClusteringMessage(org.apache.axis2.clustering.ClusteringMessage) TenantLoadMessage(org.wso2.carbon.apimgt.impl.message.clustering.TenantLoadMessage) ClusteringFault(org.apache.axis2.clustering.ClusteringFault)

Example 5 with ClusteringFault

use of org.apache.axis2.clustering.ClusteringFault in project carbon-apimgt by wso2.

the class TenantLoadMessageSender method notifyTenantLoad.

@Override
public void notifyTenantLoad() {
    ClusteringAgent clusteringAgent = getClusteringAgent();
    // if clustering is not enabled, the clusteringAgent should be null
    if (clusteringAgent != null) {
        int tenantId = getTenantId();
        String tenantDomain = getTenantDomain();
        try {
            sendTenantLoadMessage(clusteringAgent, tenantId, tenantDomain, 60);
        } catch (ClusteringFault e) {
            log.error("Could not send TenantLoadMessage for tenant domain: " + tenantDomain + ", tenant " + "id: " + tenantId + ". Several retries failed.", e);
        }
    }
}
Also used : ClusteringAgent(org.apache.axis2.clustering.ClusteringAgent) ClusteringFault(org.apache.axis2.clustering.ClusteringFault)

Aggregations

ClusteringFault (org.apache.axis2.clustering.ClusteringFault)5 Test (org.junit.Test)4 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)4 ClusteringAgent (org.apache.axis2.clustering.ClusteringAgent)3 ConfigurationContext (org.apache.axis2.context.ConfigurationContext)3 TenantLoadMessage (org.wso2.carbon.apimgt.impl.message.clustering.TenantLoadMessage)3 ArrayList (java.util.ArrayList)2 ClusteringCommand (org.apache.axis2.clustering.ClusteringCommand)2 ClusteringMessage (org.apache.axis2.clustering.ClusteringMessage)2 AxisConfiguration (org.apache.axis2.engine.AxisConfiguration)2 ThrottleDataHolder (org.apache.synapse.commons.throttle.core.ThrottleDataHolder)2 AccessInformation (org.apache.synapse.commons.throttle.core.AccessInformation)1 ConcurrentAccessController (org.apache.synapse.commons.throttle.core.ConcurrentAccessController)1 ThrottleConfiguration (org.apache.synapse.commons.throttle.core.ThrottleConfiguration)1 ThrottleContext (org.apache.synapse.commons.throttle.core.ThrottleContext)1 ThrottleException (org.apache.synapse.commons.throttle.core.ThrottleException)1 Axis2MessageContext (org.apache.synapse.core.axis2.Axis2MessageContext)1 AuthenticationContext (org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationContext)1 VerbInfoDTO (org.wso2.carbon.apimgt.impl.dto.VerbInfoDTO)1