Vou te contar como fazer um serviço de retransmissão simples para o frontend (um exemplo será em php), bem como como é fácil projetar uma API analógica na base e registrá-la para retransmissão para o frontend.
PS: um exemplo de backend e frontend será em PHP, banco de dados firebird. Mas isso não é necessário, você pode usar qualquer linguagem de programação e qualquer banco de dados.
PS: Peço que não jogue o chapéu. Eu sei que agora não é popular, por certos motivos sociais, existem mais especialistas em PHP ou Python no mercado do que programadores SQL, eles são mais baratos, todo mundo adora ORM. Acredita-se que ao estabelecer a lógica no banco de dados, é mais difícil organizar uma arquitetura de microsserviço. Mais difícil de gerenciar o controle de versão. Go compila e deve ser executado mais rápido do que um banco de dados. É popular estabelecer lógica de negócios em estruturas de php, etc.
As razões são muitas e todos têm argumentos de um lado e do outro, e cada um pode ser discutido profundamente.
Mas este artigo é para aqueles que desejam definir a lógica de negócios no banco de dados . Não há nenhum propósito aqui para promover tal método. Por favor, esteja correto nos comentários.
Em geral, o método é muito simples e irritante em termos de velocidade. Se você escrever uma retransmissão de microsserviço competente e usar ativamente tabelas de serviço no banco de dados, o registro de novas APIs requer apenas uma tabela de serviço no formato:
CREATE TABLE DFM_PROC (
ID INTEGER NOT NULL,
NAME VARCHAR(70) NOT NULL,
DISCRIPTION VARCHAR(1000)
);
Por exemplo:
O esquema é o seguinte:
Aqui consideraremos como organizar o trabalho do microsserviço "Serviço para interface". Vou dar um
exemplo de um frontend em php
function ser1($proc_id,$json)
{
//
$post='hash='.$_SESSION['sess_id'].'&user_id='.$_SESSION['id_user'].'&proc_id='.$proc_id.'&json='.base64_encode($json);
//
$url = 'http://192.168.128.1/ser.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST , true);
curl_setopt($ch, CURLOPT_POSTFIELDS ,$post);
$result = curl_exec($ch);
$arr_res=json_decode($result,true);
curl_close($ch);
return $arr_res;
}
//
//
// 4 -
if (isset($_POST['go_new_prof']))
{
unset($arr);
$arr['0']=$_SESSION['id_user'];
$arr['1']=(int)$_GET['tp'];
$arr['2']=(int)$_POST['lang_list'];
$arr_prof=ser1(4,json_encode($arr));
}
Um exemplo de um procedimento chamado em SQL
create or alter procedure DFM_PROF_ADD (
USER_ID smallint,
TYPE_ varchar(10),
LANG smallint)
as
begin
INSERT INTO DFM_PROFILES (USER_ID, TYPE_, LANG)
VALUES (:USER_ID, :TYPE_, :LANG);
suspend;
end
Agora entendemos como um relé de microsserviço entenderá que é necessário realizar esse procedimento específico, como entenderá quais parâmetros ele possui, como o puxará. Vou dar um exemplo de código, detalhes nos comentários do código
<?php
$proc_id=(int)$_POST['proc_id'];
$json= base64_decode($_POST['json']);
$arr_json = json_decode($json,true);
// JSON
switch (json_last_error()) {
case JSON_ERROR_NONE:
$err = null;
break;
case JSON_ERROR_DEPTH:
$err = ' ';
break;
case JSON_ERROR_STATE_MISMATCH:
$err = ' ';
break;
case JSON_ERROR_CTRL_CHAR:
$err = ' ';
break;
case JSON_ERROR_SYNTAX:
$err = ' , JSON';
break;
case JSON_ERROR_UTF8:
$err = ' UTF-8, ';
break;
default:
$err = ' ';
break;
}
// JSON
if ($err==null)
{
// ID
$user_id=1;
// ID
$sql_proc = "select p.name from DFM_PROC p where p.id=".$proc_id;
$res_proc = ibase_query($dbh, $sql_proc);
$prom_proc = ibase_fetch_row($res_proc);
//
$sql_in='select ';
// ,
// RDB$PROCEDURE_PARAMETERS
$sql = 'select pp.rdb$parameter_number, pp.rdb$parameter_name from DFM_PROC p
left join RDB$PROCEDURE_PARAMETERS pp on pp.rdb$procedure_name=UPPER(p.name)
where p.id='.$proc_id.' and pp.rdb$parameter_type=1 --
order by pp.rdb$parameter_number';
$res = ibase_query($dbh, $sql);
$i_cou_out=0;
while($prom = ibase_fetch_row($res))
{
//p. -
$i_cou_out++;
if ($prom[0]>0) $sql_in.=',';
$sql_in.='p.'.$prom[1];
$name_out[$prom[0]]=$prom[1];
}
// -
$sql_in.=' from '.$prom_proc[0];
// , , execute procedure
if ($i_cou_out==0) $sql_in='execute procedure '.$prom_proc[0];
//
$sql = 'select
pp.rdb$parameter_number,
pp.rdb$parameter_name,
case
when f.rdb$field_type=7 then 1 --smalint
when f.rdb$field_type=8 then 2 --integer
when f.rdb$field_type=16 and f.rdb$field_scale=0 then 3 --bigint
when f.rdb$field_type=16 and f.rdb$field_scale<0 then 4 --frloat
when f.rdb$field_type=12 then 5 --date
when f.rdb$field_type=13 then 6 --time
when f.rdb$field_type=35 then 7 --timestamp
when f.rdb$field_type=37 then 8 --varcahr
end,
f.rdb$field_type, --
f.rdb$character_length, --
f.rdb$field_precision, --
f.rdb$field_scale --
from DFM_PROC p
left join RDB$PROCEDURE_PARAMETERS pp on pp.rdb$procedure_name=UPPER(p.name)
left join RDB$FIELDS f on f.rdb$field_name=pp.rdb$field_source
where p.id='.$proc_id.' and pp.rdb$parameter_type=0 --
order by pp.rdb$parameter_number';
$res = ibase_query($dbh, $sql);
$i_cou=0;
while($prom = ibase_fetch_row($res))
{
$i_cou++;
if ($prom[0]>0) $sql_in.=','; else $sql_in.='(';
if (($prom[2]==5)or($prom[2]==6)or($prom[2]==7)or($prom[2]==8))
//
// null
if ($arr_json[$prom[0]]=='')
$sql_in.="null";
else
$sql_in.="'".($arr_json[$prom[0]])."'";
else
//
if ($arr_json[$prom[0]]=='')
$sql_in.="null";
else
$sql_in.=($arr_json[$prom[0]]);
}
//
if ($i_cou_out==0)
{if ($i_cou>0) $sql_in.=')';}
else
{if ($i_cou>0) $sql_in.=') p'; else $sql_in.=' p';}
// p.
//
$res_in = ibase_query($dbh, $sql_in);
if ($i_cou_out==0)
{
// execute procedure
$json_out='{
"error_json":"",
"error_code_json":"",
"result":" execute procedure",
"result_code":0
}';
}
else
{
// json
$i_json=0;
$json_out='{';
while($prom_in = ibase_fetch_row($res_in))
{
if ($i_json>0) $json_out.=',';
$json_out.='"'.$i_json.'":{';
foreach($prom_in as $k => $v)
{
if ($k>0) $json_out.=',
';
$json_out.='"'.trim($name_out[$k]).'":"'.$v.'"';
}
$json_out.='}';
$i_json++;
}
$json_out.='}';
}
// - , ,
if (ibase_errmsg()=='')
{
//
echo $json_out;
}
else
{
//
$err_json='{
"error_json":"'.$err.'",
"error_code_json":'.json_last_error().',
"result":"'.str_replace('"','\'',ibase_errmsg()).'",
"result_code":2,
"sql_err":"'.$sql_in.'"}';
echo $err_json;
}
}
else
{
// JSON
$err_json='{
"error_json":"'.$err.'",
"error_code_json":'.json_last_error().',
"result":" json",
"result_code":3
}';
echo $err_json;
}
?>
O que obtemos no final.
1) Escrevemos um relé de microsserviço 1 vez. Todo o resto do design da arquitetura de backend ocorre no banco de dados. Em PHP (ou Go, Python, qual será o microsserviço), não escalamos mais.
Por exemplo, um novo recurso era necessário no site - um frontend está sendo feito, um procedimento está sendo feito. O procedimento é registrado na placa e o frontend por seu número de registro chama a API de microsserviço. TUDO.
Eu recomendo escrever um relé de microsserviço em Go conforme compilado e muito mais rápido. A vantagem é que só precisa ser escrito uma vez e o programa não é complicado. Além disso, será um elemento altamente carregado, para o qual ocorrem chamadas intensivas.
Biblioteca para conectar firebird a goland: https://github.com/nakagami/firebirdsql .
2) Todo o processamento vai para procedimentos - obtemos elementos compilados que processam tudo no nível do banco de dados e produzem um RESULTADO. Essa. se a operação consiste em vários selecionar, inserir, atualizar, etc. não direcionamos dados pela rede para o back-end, mas os processamos imediatamente no banco de dados.
Além disso, um procedimento é um elemento compilado com um plano de consulta gerado. Nenhum recurso é gasto nisso também.
3) Microsserviço-relé, para formar o procedimento, refere-se ao banco de dados 4 vezes.
1. Obtenha seu nome
2. Obtenha seus parâmetros de saída
3. Obtenha seus parâmetros de entrada
4. Execute o procedimento
4 vezes, porque consideramos um método universal. Isso pode ser reduzido para uma vez.
Como:
1. Pode ser armazenado localmente em um editor de texto em um servidor web, por exemplo. Periodicamente, apenas puxando esta tabela e atualizando quando uma nova é adicionada.
2.3. Da mesma forma, você pode armazená-lo localmente puxando-o por completo quando algo for atualizado.
4) Nem todo backend pode ser feito no banco de dados! Esta é uma parte essencial de tudo, mas devemos nos guiar por considerações de conveniência .
Por exemplo, alguns chats, mailings, etc. aspectos da vida de um serviço da web, é claro, devem ser feitos como microsserviços separados na linguagem de programação mais conveniente para isso. Não é necessário transferir toda a lógica do serviço web para a base a qualquer custo! Você precisa transferir apenas a parte que for conveniente para isso!