Conteúdo


Melhorando o desempenho e a escalabilidade do IBM Sterling Order Management

Melhores práticas de design e codificação

Comments

Visão geral

O IBM Sterling Order Management é um aplicativo OLTP considerado escalável caso possa passar por um upgrade para processar mais transações adicionando novos processadores, dispositivos e armazenamento. O design ou código customizado tem um impacto significativo na escalabilidade de todo o aplicativo. Este aplicativo destaca as melhores práticas de design que podem ser adotadas para uma implementação do Sterling Order Management, para garantir a escalabilidade do aplicativo.

  1. Reduza o impacto da dependência de sistemas externos
  2. Defina o limite ideal de transações
  3. Elimine a sobrecarga da coleta de lixo (GC)
  4. Diminua a sobrecarga de E/S
  5. Reduza a sobrecarga da rede

Melhor prática de design nº 1 – Reduza a dependência de sistemas externos

O aplicativo IBM Sterling Selling and Fulfilment Suite® interage com vários aplicativos externos, como AVS (Sistema de Verificação de Endereços), sistema de pagamento e cálculo de imposto como parte do ciclo de preenchimento de pedidos. Essas interações são criadas a partir de transações da camada de aplicativo ou das transações da camada de agente. Uma transação da camada de aplicativos síncrona é iniciada por uma operação de solicitação ou resposta, e o resultado do processo é retornado para o responsável pela chamada imediatamente depois dessa operação. No entanto, a camada de agente que cria transações assíncronas é iniciada por uma operação unidirecional e os resultados são retornados iniciando outras operações unidirecionais. A interação com sistemas externos de forma síncrona gera uma forte dependência que afeta a experiência do usuário. Se o sistema externo não for responsivo, um aplicativo cliente como o COM ou SOM teria como resultado uma janela não responsiva para o usuário. A existência de várias chamadas dentro de um único limite de transformação impede a escalabilidade, já que o encadeamento de contêiner da web não será liberado para o conjunto comum a tempo de manipular outras solicitações. Isso causa escassez para o número ideal configurado de encadeamentos de contêiner da web. Um servidor de aplicativos tem configurações de tempo limite ajustáveis para garantir que o encadeamento não fique ocupado por um período indefinido. No entanto, é a camada de agente que pode representar essa ameaça, por não ter configurações de tempo limite de encadeamento. Portanto, é fundamental incluir uma implementação de tempo limite no lado do Sterling Selling and Fulfilment Suite ou no middleware (se houver) e emitir a mensagem adequada de tempo limite da resposta para a tela do usuário em caso de ausência de resposta do sistema externo.

Melhor prática de design nº 2 – Defina um limite de transação ideal

As transações são constituídas por uma unidade de trabalho realizada no modo de "tudo ou nada" que garante a atomicidade. A definição de um limite de transação ideal requer um entendimento claro da sequência de operações que está acontecendo dentro do limite de transação para garantir um aplicativo escalável que pode ser restaurado. O limite de transação é aplicável a transações síncronas e assíncronas. O tempo de resposta para o usuário ou rendimento e o mecanismo de bloqueio são os dois aspectos críticos a serem considerados ao determinar o limite ideal da transação. As APIs CreateOrder e ScheduleOrder combinadas em um único limite de transação para uma implementação podem não fornecer o rendimento ou o tempo de resposta para outra implementação. Todas as transações síncronas devem ser mais curtas e garantir o bloqueio exclusivo mínimo de linhas para obter um tempo de resposta melhor. A extensão incorreta dos modelos das APIs de base também pode causar bloqueios desnecessários.

Por exemplo, a chamada da API getShipmentDetails na V8.5 com o modelo padrão não coloca um bloqueio. Porém, se o modelo é estendido para conter os detalhes do pedido, ocorre o bloqueio exclusivo das linhas no registro do pedido. Cenários em que o bloqueio é inevitável, como changeOrder, manageOrganizationHierarchy: o designer deve definir um limite de transação mais curto, já que todos os bloqueios adquiridos por instruções dentro de uma transação são mantidos durante a transação. Quanto mais longo for o limite da transação, maior será a possibilidade da ocorrência de contenções de bloqueios de linha na camada do aplicativo e do agente, e isso acaba impedindo a escalabilidade.

O exemplo a seguir esclarece a questão do bloqueio. Supondo que as APIs getOrderDetails e getShipmentList sejam iniciadas uma após a outra em um único limite de transação. getOrderDetails adquire um bloqueio em um registro de pedido e não libera até que getShipmentList complete a execução. Todas as APIs List devem ser iniciadas com parâmetros de critérios rigorosos para garantir uma pesquisa limitada. Isso é ainda mais crítico no caso de APIs List expostas como um componente de serviço da web para um sistema externo. Se vários registros forem buscados a partir do banco de dados e a cláusula ORDER BY existe no SQL, toda a transação tem um tempo de execução muito mais longo devido à operação de classificação no lado do banco de dados. O banco de dados sempre tenta classificar no espaço de RAM dentro de sort_area_size e só vai para uma classificação de disco quando a memória RAM é esgotada. Se o número de registros não cabe na memória, a classificação ocorre no disco, tendo como resultados ciclos de CPU ainda mais altos. Essa cláusula ORDER BY pode ser eliminada com o acréscimo de um atributo IgnoreOrdering=Y no arquivo .xml de entrada.

Melhor prática de design nº 3 – Elimine a sobrecarga da coleta de lixo (GC)

As camadas de aplicativo e de agente usam a JVM™ para a alocação de memória dinâmica. À medida que mais objetos são criados a partir de um código customizado ineficiente, há pouco espaço para novos objetos na área de heap, e a JVM™ realiza o trabalho extra, tendo como resultado uma coleta de lixo (GC) frequente. A GC identifica objetos de dados que não são mais referenciados e, em seguida, recupera a memória ocupada por esses objetos. A criação de objetos é uma das operações de custo mais alto em termos de utilização da memória e impacto no desempenho. Portanto, é recomendável criar ou inicializar objetos somente quando isso for necessário no código. É necessário evitar a criação de objetos temporários dentro de métodos chamados frequentemente. É melhor criar os objetos no início e mantê-los até que sejam necessários. Programas Java™ passam bastante tempo em um loop. Portanto, nunca crie objetos temporários dentro do loop. Em vez disso, otimize o loop para obter um desempenho melhor. O exemplo a seguir apresenta uma amostra de loop for :

Lista 1. Inicial para o código de amostra do loop for
public loop control 1()
{
  String str = "Sudhanshu";
  for (int j = 0; j < str.length(); j++)
  {
    // code doesn’t change the length of the string.
  }
}

public loop control 2()
{
  String str = "Sudhanshu";
  int len = str.length();
  for (int j = 0; j < len; j++)
  {
    // code doesn’t change the length of the string.
  }
}

O loop control2 pode ser melhorado ainda mais por meio da modificação do loop para contar de trás para frente. A JVM™ é otimizada para comparar com inteiros entre -1 e +5. Portanto, modificar um loop para que ele compare com 0 produz loops mais fáceis. O loop na Lista 1 pode ser alterado para usar o seguinte na instrução do loop:

Lista 2. Código de amostra do loop for modificado
for (int j = len-1; j >= 0; j-)

A concatenação de cadeia de caracteres com o operador "+" cria muitos objetos temporários, aumenta a coleta de lixo e tem um desempenho muito mais lento que o de StringBuffer. Os métodos que operam em uma cadeia de caracteres retornam uma nova cadeia de caracteres, não uma cópia atualizada da antiga.

Lista 3. Código de amostra da concatenação de cadeia de caracteres
String abc = "<OrderLineList>" +
		" <OrderLine DeliveryMethod="  "
		ItemGroupCode="  "
		OrderLineKey="  "
		OrderedQty="  " +
		" PrimeLineNo=" "
		SubLineNo="/>" + 
		" >) ";

O uso de coleções inadequadas cria uma sobrecarga significativa de GC. Por exemplo, um ArrayList cria espaço e copia todas as suas referências durante uma inserção e seu custo aumenta à medida que o ArrayList aumenta. Também é importante lembrar que um TreeMap é mais lento que um HashMap.

Melhor prática de design nº 4 – Imponha a extensão de banco de dados adequada

É inevitável que as extensões para as tabelas do banco de dados OOB mantenham colunas customizadas como parte da customização. No entanto, é necessário ter a devida diligência para escolher o tipo de dados adequado para a coluna customizada. Por exemplo, é necessário escolher entre CHAR e VARCHAR2.

  • CHAR é usado para armazenar sequência de caracteres de comprimento fixo. Os valores da cadeia de caracteres são preenchidos com espaços em branco antes de serem armazenados no disco. Se esse tipo é usado para armazenar as cadeias de caracteres de comprimento variável, ele desperdiça espaços em disco.
  • VARCHAR2 , por outro lado, é usado para armazenar sequências de caracteres de comprimento variável. O comprimento do valor da cadeia de caracteres é armazenado no disco com o valor em si, tendo como resultado o uso ineficiente do espaço em disco.

Portanto, CHAR é um número alto e, por causa disso, no Sterling Selling and Fulfilment Suite V9.1, todas as colunas CHAR do OOB estão sendo substituídas por VARCHAR2. As transações OLTP do Sterling Selling and Fulfilment Suite passam por inserções e atualizações frequentes nos dados da transação. Essas atualizações aumentam a probabilidade de que o problema de encadeamento e migração de linhas se manifeste caso tipos de dados inadequados sejam incluídos como colunas estendidas.

  • Migração de linhas - o banco de dados Oracle® move toda a linha para um novo bloco de dados, caso a linha caiba nesse bloco. A linha original de uma linha migrada contém um ponteiro ou "endereço de encaminhamento" para o novo bloco que contém a linha migrada.
  • Encadeamento de linhas - O banco de dados Oracle® armazena os dados da linha em uma cadeia de um bloco de dados ou mais, reservado para o segmento. O encadeamento de linhas ocorre com mais frequência em linhas grandes.

Se o banco de dados realiza uma E/S para ler um índice e uma E/S para ler a tabela referente a uma linha não migrada, o banco de dados precisa de uma E/S adicional para obter os dados de linha reais, referentes à linha migrada ou encadeada. A extensão de uma tabela OOB que contém muitas colunas como YFS_ITEM – 152 colunas, YFS_ORDER_LINE – 179 colunas, YFS_SHIPMENT – 156 colunas para conter o tipo de dados CLOB teria como resultado a migração de linhas no caso de atualizações frequentes. Se o total de colunas de uma tabela for superior a 255, haverá encadeamento de linhas. Portanto, qualquer extensão nessas tabelas no Sterling Selling and Fulfilment Suite deve ser realizada com critério. Sempre avalie a opção de manter uma entidade separada com relacionamento de chave estrangeira com essas entidades para incluir colunas customizadas para os tipos de dados CLOB ou VARCHAR (tamanho da coluna > 1000). Além disso, a implementação da poda do modelo é essencial no código customizado para controlar os dados que são buscados somente na tabela primária, e não nas tabelas primária e secundária, para reduzir o número de IOPS.

Melhor prática de design nº 5 - Diminua a sobrecarga de rede e E/S

Uma solicitação de dados da camada de agente do aplicativo para a camada de banco de dados passa pela rede; o banco de dados, por sua vez, realiza uma operação de E/S para buscar dados no disco como resposta. Com a quantidade ideal de dados passando pela camada de rede, o banco de dados realiza uma operação de E/S no período de tempo esperado, e o aplicativo atinge o rendimento e o tempo de resposta esperados. Se um design ou código inadequado apresenta sobrecargas, o aplicativo deixa de ser escalável. A manipulação de exceções é um dos recursos que, caso seja implementado inadequadamente, induz sobrecargas significativas na rede.

Por exemplo, se houver uma exceção durante a operação do usuário e a lógica customizada lançar todo o rastreio da pilha de erro para um usuário de COM ou SOM, consequentemente ocorre uma congestão da rede, já que dados desnecessários devem passar pela rede para serem exibidos para o usuário. Os dados exibidos são pouco relevantes para o usuário. O recurso do código de erro de OOB é usado para exibir a mensagem de erro correspondente.

Lista 4. Codificação inadequada
yfsUserExitException.setErrorDescription(e.getMessage());
yfsUserExitException.setStackTrace(e.getStackTrace());

A presença da instrução System.out.println dentro do código Java™ personalizado consome um espaço em disco que é alocado para a instância do servidor de aplicativos e tem como resultado a contenção do espaço em disco. Além disso, apresenta latência na gravação de logs, tendo como resultado a lentidão no rendimento ou no tempo de resposta, já que a criação de log de JVM está sincronizado. A criação de log padrão é INFO e ERROR a partir do aplicativo Sterling Selling and Fulfilment Suite. Portanto, o Log4j deve ser usado para criar o log, em vez de System.out.println. O banco de dados apresentaria sobrecarga de E/S devido à grande quantidade de colunas estendidas com tipos de dados como CLOB ou VARCHAR2 (tamanho > 2000) nas tabelas.

Por exemplo, internamente o produto executa a consulta selecionada com ‘*’ em YFS_ITEM.

Lista 5. SELECT QUERY
SELECT  /*YANTRA*/ YFS_ITEM.* FROM YFS_ITEM YFS_ITEM WHERE (YFS_ITEM.ITEM_KEY = 'XYZ')

A consulta na Lista 5 busca um único registro do banco de dados, já que Item_KEY , sendo a chave primária, é usada na cláusula WHERE . No entanto, a operação de E/S apresenta um gargalo de desempenho por causa do grande número de colunas que incluem colunas estendidas de CLOB ou VARCHAR2 presentes na entidade YFS_ITEM . Portanto, é necessário garantir que os dados buscados sejam estritamente controlados pelo modelo.

Conclusão

A escalabilidade está estreitamente relacionada ao desempenho. O aplicativo não consegue ajustar a escala na presença de gargalos de desempenho críticos introduzidos pelo design e desenvolvimento inadequados. Essas cinco práticas de design devem ser implementadas durante a fase de design e desenvolvimento de uma implementação para garantir a escalabilidade.


Recursos para download


Temas relacionados


Comentários

Acesse ou registre-se para adicionar e acompanhar os comentários.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java
ArticleID=982557
ArticleTitle=Melhorando o desempenho e a escalabilidade do IBM Sterling Order Management
publish-date=09052014