Vamos lá... “Com saúde não se brinca. (português brasileiro)”, “Better safe than sorry. (inglês)”, “Mieux vaut prévenir que guérir. (francês)”, “Todo tiene solución, menos la muerte. (espanhol)”, este último é pesado (forte), não?
É... Chegou a hora dos testes. Sabemos que em muitas vezes, ela até já passou. Bom, e agora? Consigo reforçar a qualidade do meu desenvolvimento?
A resposta é: SIM. Sim, você consegue. A ferramenta Toolqa busca exatamente isto. É um facilitador. Qual é o seu objetivo? Garantir que as APIS atendam aos requisitos de negócio pré-estabelecidos, e também mantenha-se rígida com as <sarcasm> futuras tentativas frustradas </sarcasm> de acabar com a sua aplicação, site, App ou qualquer outro que utilize-se de sua API.
Agora deve estar se perguntando, mas como é que isto acontece? Onde está a mágica?
Assim como um nocaute, sem dar chances ao adversário, o Kubernetes, enquanto uma plataforma de código aberto, tem um universo de oportunidades devido à sua disponibilidade (isto é, a facilidade para encontrar suporte, serviços e ferramentas). Ele é uma plataforma que pode gerenciar os trabalhos e serviços em contêineres, o que simplifica e muito a configuração e automação destes processos.
Mas, vamos justificar a imagem título e dar o nome “correto” à ferramenta em questão: InterSystems Kubernetes Operator.
O princípio é básico, escolhem-se os serviços e
Ao contrário do filme, citado através da imagem (para quem não conhece, Matrix, 1999), a escolha entre Dynamic SQL e Embededd SQL, não é uma escolha entre a verdade e a fantasia, mas, mesmo assim é uma decisão a ser tomada. Abaixo, tentarei facilitar a escolha de vocês.
ObjectScript tem pelo menos três maneiras de lidar com erros (códigos de status, exceções, SQLCODE, etc.).A maior parte do código do sistema usa status, mas as exceções são mais fáceis de tratar por vários motivos.Trabalhando com código legado, você passa algum tempo traduzindo entre as diferentes técnicas.Eu uso muito esses trechos para referência.Esperançosamente, eles também são úteis para outras pessoas.
Neste artigo, vamos comparar as funções $Increment e $Sequence.
Em primeiro lugar, uma nota para os leitores que nunca ouviram falar de $Increment. $Increment é uma função Caché ObjectScript que realiza uma operação atômica para incrementar seu argumento em 1 e retornar o valor resultante. Você só pode passar um nó de variável global ou local como um parâmetro para $Increment, não uma expressão arbitrária. $Increment é muito usado ao atribuir IDs sequenciais. Em tais casos, o parâmetro de $Increment é geralmente um nó global. $Increment garante que cada processo que o utiliza obtenha um ID exclusivo.
` for i=1:1:10000 {
set Id = $Increment(^Person) ; new Id
set surname = ##class(%PopulateUtils).LastName() ; random last name
set name = ##class(%PopulateUtils).FirstName() ; random first name
set ^Person(Id) = $ListBuild(surname, name)
}`
O problema com $Increment é que se muitos processos estão adicionando linhas em paralelo, esses processos podem perder tempo esperando sua vez para alterar atomicamente o valor do nó global que contém o ID - ^ Person na amostra acima
[$ Sequence] (http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_fsequence) é uma nova função que foi projetada para lidar com esse problema. $ Sequence está disponível desde o Caché 2015.1. Assim como $ Increment, $ Sequence incrementa atomicamente o valor de seu parâmetro. Ao contrário de $ Increment, $ Sequence reservará alguns valores de contador subsequentes para o processo atual e, durante a próxima chamada no mesmo processo, simplesmente retornará o próximo valor do intervalo reservado. $ Sequence calcula automaticamente quantos valores reservar. Mais frequentemente, processar chamadas $ Sequence, mais valores $ Sequence reservas:
USER>kill ^myseq
USER>for i=1:1:15 {write "increment:",$Seq(^myseq)," allocated:",^myseq,! }
increment:1 allocated:1
increment:2 allocated:2
increment:3 allocated:4
increment:4 allocated:4
increment:5 allocated:8
increment:6 allocated:8
increment:7 allocated:8
increment:8 allocated:8
increment:9 allocated:16
increment:10 allocated:16
increment:11 allocated:16
increment:12 allocated:16
increment:13 allocated:16
increment:14 allocated:16
increment:15 allocated:16
Quando $Sequence (^ myseq) retornou 9, os próximos 8 valores (até 16) já estavam reservados para o processo atual. Se outro processo chamar $Sequence, ele obterá o valor 17, não 10.
$Sequence é projetado para processos que incrementam simultaneamente algum nó global. Como os valores de reserva de $Sequence, os IDs podem ter lacunas se o processo não usar todos os valores que foram reservados. O principal uso de $Sequence é a geração de IDs sequenciais. Comparado com $Sequence, $Increment é uma função mais genérica.
Vamos comparar a performance de $Increment e $Sequence:
Class DC.IncSeq.Test
{
ClassMethod filling()
{
lock +^P:"S"
set job = $job
for i=1:1:200000 {
set Id = $Increment(^Person)
set surname = ##class(%PopulateUtils).LastName()
set name = ##class(%PopulateUtils).FirstName()
set ^Person(Id) = $ListBuild(job, surname, name)
}
lock -^P:"S"
}
ClassMethod run()
{
kill ^Person
set z1 = $zhorolog
for i=1:1:10 {
job ..filling()
}
lock ^P
set z2 = $zhorolog - z1
lock
write "done:",z2,!
}
}
O método run jobs em 10 processos, cada um inserindo 200.000 registros em ^ Person global. Para esperar até que os processos filhos terminem. o método run tenta obter um bloqueio exclusivo em ^ P. Quando os processos filhos concluem seu trabalho e liberam o bloqueio compartilhado em ^ P, a execução adquirirá um bloqueio exclusivo em ^ P e continuará a execução. Em seguida, registramos o tempo da variável de sistema $zhorolog e calculamos quanto tempo levou para inserir esses registros. Meu notebook multi-core com HDD lento levou 40 segundos (para ciência, eu o executei várias vezes antes, então esta foi a 5ª execução):
USER>do ##class(DC.IncSeq.Test).run()
done:39.198488
É interessante detalhar esses 40 segundos. Ao executar [& # 94;% SYS.MONLBL] (http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_monlbl), podemos ver que um total de 100 segundos foram gastos obtendo ID. 100 segundos / 10 processos = cada processo gastou 10 segundos para adquirir um novo ID, 1,7 segundo para obter o nome e o sobrenome e 28,5 segundos para gravar dados nos dados globais.
A primeira coluna no relatório% SYS.MONLBL abaixo é o número da linha, a segunda é quantas vezes essa linha foi executada e a terceira é quantos segundos levou para executar esta linha.
; ** Source for Method 'filling' **
1 10 .001143 lock +^P:"S"
2 10 .000055 set job = $JOB
3 10 .000118 for i=1:1:200000 {
4 1998499 100.356554 set Id = $Increment(^Person)
5 1993866 10.409804 set surname = ##class(%PopulateUtils).LastName()
6 1990461 6.347832 set name = ##class(%PopulateUtils).FirstName()
7 1999762 285.54603 set ^Person(Id) = $ListBuild(job, surname, name)
8 1999825 3.393706 }
9 10 .000259 lock -^P:"S"
; ** End of source for Method 'filling' **
;
; ** Source for Method 'run' **
1 1 .005503 kill ^Person
2 1 .000002 set z1 = $zhorolog
3 1 .000002 for i=1:1:10 {
4 10 .201327 job ..filling()
5 0 0 }
6 1 43.472692 lock ^P
7 1 .00003 set z2 = $zhorolog - z1
8 1 .00001 lock
9 1 .000053 write "done:",z2,!
; ** End of source for Method 'run' **
O tempo total (43,47 segundos) é 4 segundos a mais do que durante a execução anterior devido ao perfil.
Vamos substituir algo em nosso código de teste, no método fill. Vamos mudar $ Increment (^Person) para $Sequence (^Person) e executar o teste novamente:
USER>do ##class(DC.IncSeq.Test).run()
done:5.135189
Este resultado é surpreendente. Ok, $Sequence diminuiu o tempo para obter a ID, mas para onde foram 28,5 segundos para armazenar dados no global? Vamos verificar ^% SYS.MONLBL:
; ** Source for Method 'filling' **
1 10 .001181 lock +^P:"S"
2 10 .000026 set job = $JOB
3 10 .000087 for i=1:1:200000 {
4 1802473 1.996279 set Id = $Sequence(^Person)
5 1784910 4.429576 set surname = ##class(%PopulateUtils).LastName()
6 1853508 3.829051 set name = ##class(%PopulateUtils).FirstName()
7 1838752 32.281624 set ^Person(Id) = $ListBuild(job, surname, name)
8 1951569 1.0243 }
9 10 .000219 lock -^P:"S"
; ** End of source for Method 'filling' **
;
; ** Source for Method 'run' **
1 1 .006514 kill ^Person
2 1 .000002 set z1 = $zhorolog
3 1 .000002 for i=1:1:10 {
4 10 .385055 job ..filling()
5 0 0 }
6 1 6.558119 lock ^P
7 1 .000011 set z2 = $zhorolog - z1
8 1 .000008 lock
9 1 .000025 write "done:",z2,!
; ** End of source for Method 'run' **
Agora, cada processo gasta 0,2 segundos em vez de 10 segundos para aquisição de ID. O que não está claro é por que o armazenamento de dados leva apenas 3,23 segundos por processo? O motivo é que os nós globais são armazenados em blocos de dados e, geralmente, cada bloco tem um tamanho de 8.192 bytes. Antes de alterar o valor do nó global (como set ^Person (Id) =…), o processo bloqueia todo o bloco. Se vários processos estiverem tentando alterar dados dentro de um mesmo bloco ao mesmo tempo, apenas um processo terá permissão para alterar o bloco e os outros terão que aguardar sua conclusão.
Vejamos o global criado usando $Increment para gerar novos IDs. Os registros sequenciais quase nunca teriam o mesmo ID do processo (lembre-se - armazenamos o ID do processo como o primeiro elemento da lista de dados):
1: ^Person(100000) = $lb("12950","Kelvin","Lydia")
2: ^Person(100001) = $lb("12943","Umansky","Agnes")
3: ^Person(100002) = $lb("12945","Frost","Natasha")
4: ^Person(100003) = $lb("12942","Loveluck","Terry")
5: ^Person(100004) = $lb("12951","Russell","Debra")
6: ^Person(100005) = $lb("12947","Wells","Chad")
7: ^Person(100006) = $lb("12946","Geoffrion","Susan")
8: ^Person(100007) = $lb("12945","Lennon","Roberta")
9: ^Person(100008) = $lb("12944","Beatty","Mark")
10: ^Person(100009) = $lb("12946","Kovalev","Nataliya")
11: ^Person(100010) = $lb("12947","Klingman","Olga")
12: ^Person(100011) = $lb("12942","Schultz","Alice")
13: ^Person(100012) = $lb("12949","Young","Filomena")
14: ^Person(100013) = $lb("12947","Klausner","James")
15: ^Person(100014) = $lb("12945","Ximines","Christine")
16: ^Person(100015) = $lb("12948","Quine","Mary")
17: ^Person(100016) = $lb("12948","Rogers","Sally")
18: ^Person(100017) = $lb("12950","Ueckert","Thelma")
19: ^Person(100018) = $lb("12944","Xander","Kim")
20: ^Person(100019) = $lb("12948","Ubertini","Juanita")
Os processos simultâneos estavam tentando gravar dados no mesmo bloco e gastando mais tempo esperando do que realmente alterando os dados. Usando $ Sequence, os IDs são gerados em blocos, portanto, processos diferentes provavelmente usariam blocos diferentes:
1: ^Person(100000) = $lb("12963","Yezek","Amanda")
// 351 records with process number 12963
353: ^Person(100352) = $lb("12963","Young","Lola")
354: ^Person(100353) = $lb("12967","Roentgen","Barb")
Se este exemplo parece algo que você está fazendo em seus projetos, considere o uso de $Sequence em vez de $Increment. Claro, consulte a [documentação] (http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_fsequence) antes de substituir cada ocorrência de $Increment por $Sequence.
E, claro, não acredite nos testes fornecidos aqui - verifique você mesmo.
A partir do Caché 2015.2, você pode configurar tabelas para usar $Sequence em vez de $Increment. Existe uma função de sistema [$system.Sequence.SetDDLUseSequence] (http://docs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25SYS&CLASSNAME=%25SYSTEM.SQL#METHOD_SetDDLUseSequence ) para isso, e a mesma opção está disponível em Configurações de SQL no Portal de gerenciamento.
Além disso, há um novo parâmetro de armazenamento na definição de classe - [IDFunction] (http://docs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25SYS&CLASSNAME=%25Dictionary.StorageDefinition #PROPERTY_IdFunction), que é definido como “incremento” por padrão, o que significa que $ Increment é usado para geração de Id. Você pode alterá-lo para "sequência" (Inspetor> Armazenamento> Padrão> IDFunction).
Bônus
Outro teste rápido que realizei no meu notebook: é uma pequena configuração ECP com DB Server localizado no sistema operacional host e Application Server na VM convidada no mesmo notebook. Mapeei ^ Pessoa para banco de dados remoto. É um teste básico, então não quero fazer generalizações com base nele. Existem [coisas a serem consideradas] (http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GDDM_develop#GDDM_develop_consider_increment) ao usar $ Increment e ECP. Dito isso, aqui estão os resultados:
### Com $Increment:
USER>do ##class(DC.IncSeq.Test).run()
done:163.781288
^%SYS.MONLBL:
; ** Source for Method 'filling' **
1 10 .000503 -- lock +^P:"S"
2 10 .000016 set job = $job
3 10 .000044 for i=1:1:200000 {
4 1843745 1546.57015 set Id = $Increment(^Person)
5 1880231 6.818051 set surname = ##class(%PopulateUtils).LastName()
6 1944594 3.520858 set name = ##class(%PopulateUtils).FirstName()
7 1816896 16.576452 set ^Person(Id) = $ListBuild(job, surname, name)
8 1933736 .895912 }
9 10 .000279 lock -^P:"S"
; ** End of source for Method 'filling' **
;
; ** Source for Method 'run' **
1 1 .000045 kill ^Person
2 1 .000001 set z1 = $zhorolog
3 1 .000007 for i=1:1:10 {
4 10 .059868 job ..filling()
5 0 0 }
6 1 170.342459 lock ^P
7 1 .000005 set z2 = $zhorolog - z1
8 1 .000013 lock
9 1 .000018 write "done:",z2,!
; ** End of source for Method 'run' **
### $Sequence:
USER>do ##class(DC.IncSeq.Test).run()
done:13.826716
^%SYS.MONLBL
; ** Source for Method 'filling' **
1 10 .000434 lock +^P:"S"
2 10 .000014 set job = $job
3 10 .000033 for i=1:1:200000 {
4 1838247 98.491738 set Id = $Sequence(^Person)
5 1712000 3.979588 set surname = ##class(%PopulateUtils).LastName()
6 1809643 3.522974 set name = ##class(%PopulateUtils).FirstName()
7 1787612 16.157567 set ^Person(Id) = $ListBuild(job, surname, name)
8 1862728 .825769 }
9 10 .000255 lock -^P:"S"
; ** End of source for Method 'filling' **
;
; ** Source for Method 'run' **
1 1 .000046 kill ^Person
2 1 .000002 set z1 = $zhorolog
3 1 .000004 for i=1:1:10 {
4 10 .037271 job ..filling()
5 0 0 }
6 1 14.620781 lock ^P
7 1 .000005 set z2 = $zhorolog - z1
8 1 .000013 lock
9 1 .000016 write "done:",z2,!
; ** End of source for Method 'run' **
Esta é uma visão bastante pessoal da história antes do Caché.
Não tem o objetivo de competir com os excelentes livros de Mike Kadow discutidos em um artigo anterior.
Temos uma história diferente e, portanto, isso visa criar uma perspectiva diferente do passado.
Toda a história começou em 1966 no MGH (Mass.General Hospital) em um PDP-7 Ser. # 103com 8 K de memória (palavras de 18 bits) [hoje = 18 K byte] como um sistema sobressalente.
"Número de série 103 - estava localizado no porão do agora demolido Edifício Thayer,atualmente [2014] o site do Cox Cancer Center no MGH. ""Neil Papparlardo e Curt Marble sob a orientação de Octo Barnett desenvolveram e lançaramo software inicial nesta máquina. "
Ao usar o Studio, ODBC ou uma conexão de terminal para Caché ou Ensemble, você deve estar se perguntando como proteger a conexão. Uma opção é adicionar TLS (também conhecido como SSL) à sua conexão. Os aplicativos cliente Caché - TELNET, ODBC e Studio - todos sabem como adicionar TLS à conexão. Eles só precisam ser configurados para fazer isso.
Configurar esses clientes é mais fácil em 2015.1 e posteriores. Vou discutir esse novo método. Se você já estiver usando o método antigo e legado, ele continuará funcionando, mas eu recomendo que você considere mudar para o novo.
Background
Esses aplicativos cliente podem ser instalados em uma máquina que não tenha o servidor instalado. Eles não podem depender de ter acesso aos locais normais para armazenar configurações, como o banco de dados CACHESYS ou o arquivo cpf. Em vez disso, suas configurações para os certificados ou protocolos a serem aceitos são armazenadas em um arquivo de texto. Muitas das configurações neste arquivo são semelhantes às configurações em uma configuração SSL / TLS no portal de gerenciamento.
Onde está o arquivo de configurações?
Você terá que criar seu próprio arquivo. O instalador do cliente não cria um para você.
Por padrão, o arquivo de configurações é chamado SSLDefs.ini e deve ser colocado no diretório InterSystems \ Cache sob o diretório para arquivos de programas comuns de 32 bits. Este diretório é encontrado na variável de ambiente do Windows * CommonProgramFiles (x86) * no Windows de 64 bits ou * CommonProgramFiles * no Windows de 32 bits.
Por exemplo, no Windows 8.1, o arquivo padrão seria:
C:\Program Files (x86)\Common Files\InterSystems\Cache\SSLdefs.ini
Se quiser mudar isso, você terá que dizer aos executáveis do cliente onde encontrar o arquivo de configurações. Você pode fazer isso definindo a variável de ambiente * ISC_SSLconfigurations * e configurando-a para todo o caminho e nome de arquivo do seu arquivo. Você pode precisar de permissões de administrador para fazer isso.
O que há no arquivo de configurações?
O arquivo possui dois tipos de seções. O primeiro tipo combina conexões com configurações TLS. Por exemplo, pode dizer ao Studio para usar a seção chamada "Configurações padrão" para encontrar seus parâmetros TLS ao se conectar a development.intersystems.com.
O segundo tipo define as configurações de TLS a serem usadas para a conexão. Por exemplo, eles definiriam por qual Autoridade de Certificação esperar que o certificado do servidor seja assinado. As configurações nestas seções são muito semelhantes às configurações em uma configuração SSL / TLS em um servidor Caché ou Ensemble.
O primeiro tipo de seção se parece com isto:
[Development Server]
Address=10.100.0.17
Port=1972
TelnetPort=23
SSLConfig=DefaultSettings
O nome entre colchetes pode ser o que você quiser. Ele está lá apenas para tornar mais fácil para você manter o controle de qual conexão é essa.
As configurações de Endereço, Porta e TelnetPort são usadas para decidir quais conexões devem corresponder a esta seção. Os endereços IP ou nomes DNS podem ser usados para o endereço em clientes 2016.1 ou posteriores. Tanto o endereço quanto a porta ou TelnetPort devem corresponder ao local onde o aplicativo cliente está se conectando para que a configuração seja usada.
O parâmetro final (SSLConfig) é o nome da configuração da qual obter as configurações de TLS. Ele precisa corresponder ao nome de uma das configurações no arquivo.
O segundo tipo de seção tem a seguinte aparência:
[DefaultSettings]
VerifyPeer=2
VerifyHost=1
CAfile=c:\InterSystems\certificates\CAcert.pem
CertFile=c:\InterSystems\certificates\ClientCert.pem
KeyFile=c:\InterSystems\certificates\ClientKey.key
Password=
KeyType=2
Protocols=24
CipherList=ALL:!aNULL:!eNULL:!EXP:!SSLv2
O nome da seção está listado na primeira linha: [DefaultSettings] e corresponde ao nome listado no parâmetro SSLConfig da primeira seção do exemplo acima. Portanto, esta configuração será usada para conexões com o servidor 10.100.0.17 na porta 1972 ou na porta 23.
Usar copiar e colar no exemplo acima geralmente causa caracteres não imprimíveis em seu arquivo de texto. Certifique-se de ter removido quaisquer caracteres extras, por exemplo, salvando o arquivo como somente texto e abrindo-o novamente.
Aqui está uma descrição do que os parâmetros significam:
- VerifyPeer
As opções para isso são 0 = nenhum, 1 = solicitação e 2 = exigir. Exigir é o valor recomendado. Se você não escolher nenhum, é possível que um servidor malicioso finja ser o servidor ao qual você pretende se conectar. Se você escolher requerer, precisará preencher uma Autoridade de certificação em que você confia para verificar os certificados para o valor CAFile. Isso é equivalente a "Verificação do certificado do servidor" no portal. (Observação: a solicitação não faz sentido para uma configuração de cliente, mas eu a incluí aqui para que você possa entender por que as opções são 0 e 2.)
- VerifyHost
As opções para isso são 0 = nenhum, 1 = obrigatório. Esta opção verifica se o certificado do servidor lista o nome do host ou IP ao qual você pediu para se conectar nos campos Nome comum do assunto ou subjectAlternativeName. Este campo não possui equivalente no portal, mas é o mesmo tipo de verificação da propriedade SSLCheckServerIdentity da classe% Net.HttpRequest. Só é configurável se o seu cliente estiver usando o Caché / Ensemble 2018.1 ou posterior, ou qualquer versão da InterSystems IRIS Data Platform.
- CAfile
O caminho para o arquivo de autoridade de certificação (CA) confiável. Deve ser a CA que assinou o certificado do * outro * lado (o servidor), não o seu próprio certificado. Isso deve ser preenchido se você escolheu um valor VerifyPeer de 2. Isso é o equivalente a "Arquivo contendo certificado (s) de autoridade de certificação confiável (s)" no portal. Os certificados devem estar no formato PEM.
- CertFile
O caminho para seu próprio certificado. Deve ficar em branco se o seu cliente não tiver um. Equivale a "Arquivo contendo o certificado deste cliente" no portal. Os certificados devem estar no formato PEM.
- KeyFile
O caminho para a chave privada correspondente para CertFile. Deve ser preenchido se você tiver um CertFile e em branco se não tiver. Isso é equivalente a "Arquivo contendo chave privada associada" no portal.
- Password
A senha necessária para descriptografar sua chave privada. Deve ficar em branco se você não estiver usando um certificado para este cliente ou se a chave privada do certificado não estiver criptografada no disco.
- KeyType
A sua chave privada é RSA (2) ou DSA (1)? O valor é relevante apenas para configurações que possuem CertFile e KeyFile definidos. Se você não tiver certeza de qual é, sua chave provavelmente é RSA.
- Protocols
Esta é uma representação decimal de valores de bits para as versões de SSL / TLS suportadas. As opções são: 1 = SSLv2, 2 = SSLv3, 4 = TLSv1, 8 = TLSv1.1, 16 = TLSv1.2. SSLv2 e SSLv3 têm problemas conhecidos e não são recomendados. Mais de uma versão pode ser especificada adicionando números. Por exemplo, 24 é TLSv1.1 e TLSv1.2. Isso equivale às caixas de seleção "Protocolos" do portal. (Observação: os 8 e 16 bits não estão em 2015.1. Se quiser usá-los, você precisa atualizar para 2015.2 ou superior.)
- CipherList
Isso é o equivalente a "ciphersuites ativados" no portal. Isso controla exatamente quais tipos de criptografia e hashing serão aceitáveis para este cliente. ** ALL:! ANULL:! ENULL:! EXP:! SSLv2 ** é o valor padrão para esta configuração no portal de gerenciamento. Se você está tendo problemas com sua conexão, provavelmente não é isso. Alterar isso pode tornar sua conexão menos segura, permitindo uma criptografia fraca. Você pode encontrar mais informações sobre este valor no site do openssl.
Final notes
Isso é tudo que você precisa fazer! Se você criar seu arquivo e colocá-lo no local conhecido, ele será usado automaticamente se o nome ou endereço IP e a porta que você está conectando corresponderem a uma das conexões listadas no arquivo.
Server setup
Este artigo é sobre como configurar o lado do cliente de sua conexão para usar SSL, mas não se esqueça de que o servidor ao qual você está se conectando também precisa entender como aceitar SSL. A documentação sobre como configurar o SuperServer para usar SSL pode ser encontrada aqui:
E a documentação de configuração do serviço Telnet está aqui:
O método $ SYSTEM.Security.Users.SetTelnetSSLSetting () permite controlar se o servidor Telnet permite ou exige o uso de SSL. Ele está disponível em 2016.1 e posteriores.
DSN configuration
Você não precisa alterar o DSN para uma conexão ODBC, contanto que tenha um endereço de conexão e uma porta correspondentes em seu arquivo de configurações. SSL será usado mesmo se a senha for selecionada para o método de autenticação no DSN. As opções Password with SSL / TLS e ** SSL / TLS server name ** eram para o estilo pré-2015.1 de configuração de SSL para ODBC.
Documentation link
A documentação sobre TLS para aplicativos cliente está agora disponível no site de documentos IRIS:
O InterSystems IRIS 2019.1 já foi lançado há algum tempo e gostaria de abordar algumas melhorias para lidar com JSON que podem ter passado despercebidas.Lidar com JSON como um formato de serialização é uma parte importante da construção de aplicativos modernos, especialmente ao interagir com terminais REST.
Recentemente, eu estava respondendo a algumas perguntas que alguém tinha sobre alguns bugs que surgem no Docker para Mac, e isso me lembrou o que Shakespeare escreveu em sua famosa tragédia sobre orquestração de software em grande escala, Kubelet: o Príncipe do Benchmark.
Esta postagem tem como objetivo guiá-lo através dos novos recursos JSON que introduzimos no Caché 2016.1.JSON surgiu para um formato de serialização usado em muitos lugares.A web começou, mas hoje é utilizada em todos os lugares.Temos muito o que abordar, então vamos começar.
Oi, pessoal,
Estamos nos conectando a um serviço da Web SOAP de terceiros.O wsdl se parece com o abaixo
Observe que o portType foi definido como / cvpService.
Então, quando estivermos tentando usar o SOAP Wizard para gerar um cliente para o serviço, encontraremos o seguinte erro que impediu a geração
Parece que '/ cvpService' não pode ser usado como um nome de classe válido (ou mesmo nome de método), portanto, a geração falhou.
Portanto, tenho 2 perguntas sobre a falha
Quando temos que prever o valor de um resultado categórico (ou discreto), usamos a regressão logística.Acredito que usamos a regressão linear para também prever o valor de um resultado, dados os valores de entrada.Então, qual é a diferença entre as duas metodologias?
Oi pessoal!Aqui está como concedo acesso SQL do usuário a uma determinada classe / tabela:
GRANT SELECT, UPDATE ON Packacge_X.Table_Y TO UserZComo posso conceder acesso SQL de um determinado usuário a um schema inteiro?
Deixe-me apresentar o suporte do InterSystems IRIS no IntelliJ IDEA.Este plugin adiciona suporte de realce de sintaxe para ObjectScript e importação e compilação automática no servidor após salvar um arquivo alterado.Ele usa LanguageServer escrito em Rust, onde foi adicionada a capacidade de importar e compilar código.
.png)
Além do IntelliJ IDEA, agora é possível configurar o SublimeText3 para poder compilar o código lá também.E o que você precisa é apenas do servidor de idioma que eu usei.

Nos bons velhos tempos (tm), determinar o tamanho dos dados, fluxos e índices para uma classe / tabela era fácil - você apenas executava %GSIZE e verificava as globais D, S e I respectivamente.
No entanto, hoje em dia a fragmentação, os nomes globais otimizados e os índices em globais separados produzem a saída% GSIZE parecida com esta:
A migração do Caché para o IRIS pode ser um grande desafio se o seu código crescer ao longo de muitos anos e provavelmente não tão estruturado como você pode gostar. Então você enfrenta a necessidade de verificar seu código migrado em relação a alguns dados de referência. Algumas amostras podem não ser um problema, mas podem ser algumas centenas de GB de dados para teste.Uma possível etapa seria ter seu código novo no IRIS, mas deixar seu enorme armazenamento de dados no Caché e conectar os dois ambientes via ECP. Eu criei um projeto demo que dá a você a oportunidade de experimentar com base
Dia 5: Desenvolvendo com Objetos InterSystems e SQL Finalizei minha participação no Desenvolvimento com InterSystems Objects e SQL com Joel Solon. O curso é muito legal e vou compartilhar com vocês algumas dicas que recebi durante o último dia de treinamento. Dicas apresentadas no dia 5: