Backend du service Web dans la base de données. Comment créer une logique métier et créer un relais de microservice pour l'API frontend

Cet article vous montrera comment organiser la conception simple de la logique métier du service Web dans une base de données PL-SQL intégrée.



Je vais vous dire comment créer un service de relais simple pour le frontend (un exemple sera en php), ainsi que comment il est facile de concevoir une API analogique dans la base et de l'enregistrer pour le relayer vers le frontend.



PS: un exemple de backend et frontend sera en PHP, base de données firebird. Mais ce n'est pas nécessaire, vous pouvez utiliser n'importe quel langage de programmation et n'importe quelle base de données.


PS: Je vous demande de ne pas jeter vos chapeaux. Je sais que maintenant ce n'est pas populaire, pour certaines raisons sociales, il y a plus de spécialistes PHP ou Python sur le marché que de programmeurs SQL, ils sont moins chers, tout le monde aime l'ORM. On pense que lors de la définition de la logique dans la base de données, il est plus difficile d'organiser une architecture de microservice. Plus difficile à gérer le contrÎle de version. Go compile et devrait fonctionner plus rapidement qu'une base de données. Il est courant de poser la logique métier dans les frameworks php, etc.

Les raisons sont multiples et chacun a des arguments d'un cĂŽtĂ© et de l'autre, et chacun peut ĂȘtre profondĂ©ment argumentĂ©.



Mais cet article s'adresse Ă  ceux qui souhaitent dĂ©finir une logique mĂ©tier dans la base de donnĂ©es . Il n'y a aucun but ici de promouvoir une telle mĂ©thode. Veuillez ĂȘtre correct dans les commentaires.


En gĂ©nĂ©ral, la mĂ©thode est trĂšs simple et gĂȘnante en termes de vitesse. Si vous Ă©crivez un relais de microservice compĂ©tent et utilisez activement des tables de service dans la base de donnĂ©es, l'enregistrement de nouvelles API ne nĂ©cessite qu'une seule table de service du formulaire:



CREATE TABLE DFM_PROC (
    ID           INTEGER NOT NULL,
    NAME         VARCHAR(70) NOT NULL,
    DISCRIPTION  VARCHAR(1000)
);
      
      





Par exemple:



image



Le schéma est le suivant:



image



Nous examinerons ici comment organiser le travail du microservice «Service pour interface». Je vais donner un



exemple de frontend en 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));
}

      
      





Un exemple de procédure appelée en 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
      
      





Nous comprenons maintenant comment un microservice-relais comprendra qu'il est nécessaire d'effectuer cette procédure particuliÚre, comment il comprendra les paramÚtres dont il dispose, comment il le tirera. Je vais donner un exemple de code, des détails dans les commentaires dans le code




<?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;   
   
}

?>

      
      





Ce que nous obtenons Ă  la fin.



1) Nous écrivons un relais de microservice 1 fois. Tout le reste de la conception de l'architecture backend se déroule dans la base de données. En PHP (ou Go, Python, quel sera le microservice) on ne grimpe plus.



Par exemple, une nouvelle fonctionnalité était nécessaire sur le site - une interface est en cours de réalisation, une procédure est en cours. La procédure est enregistrée dans la plaque et le frontend par son numéro d'enregistrement appelle l'API du microservice. TOUT.



Je recommande d'Ă©crire un relais de microservice dans Go comme compilĂ© et beaucoup plus rapide. L'avantage est qu'il ne doit ĂȘtre Ă©crit qu'une seule fois et que le programme n'est pas compliquĂ©. De plus, ce sera un Ă©lĂ©ment trĂšs chargĂ©, auquel des appels intensifs se produiront.



BibliothĂšque pour connecter Firebird au goland: https://github.com/nakagami/firebirdsql .



2) Tout le traitement entre dans des procĂ©dures - nous obtenons des Ă©lĂ©ments compilĂ©s qui traitent tout au niveau de la base de donnĂ©es et produisent un RÉSULTAT. Ceux. si l'opĂ©ration consiste en plusieurs sĂ©lection, insertion, mise Ă  jour, etc. nous ne conduisons pas les donnĂ©es sur le rĂ©seau vers le backend, mais les traitons immĂ©diatement dans la base de donnĂ©es.



De plus, une procĂ©dure est un Ă©lĂ©ment compilĂ© avec un plan de requĂȘte gĂ©nĂ©rĂ©. Aucune ressource n'est dĂ©pensĂ©e pour cela non plus.



3) Microservice-relais, pour former la procédure, se réfÚre à la base de données 4 fois.



1. Obtenez son nom

2. Obtenez ses paramĂštres sortants

3. Obtenez ses paramĂštres entrants

4. Exécutez la procédure

4 fois, car nous avons considĂ©rĂ© une mĂ©thode universelle. Cela peut ĂȘtre rĂ©duit Ă  une fois.



Comment:



1. Il peut ĂȘtre stockĂ© localement dans un Ă©diteur de texte sur un serveur Web par exemple. PĂ©riodiquement, il suffit de tirer ce tableau et de le mettre Ă  jour lorsqu'un nouveau est ajoutĂ©.

2.3. De mĂȘme, vous pouvez le stocker localement en le tirant partout lorsque quelque chose est mis Ă  jour.



4) Tout le backend ne peut pas ĂȘtre fait sur la base de donnĂ©es! C'est une partie essentielle de tout, mais il faut ĂȘtre guidĂ© par des considĂ©rations d'opportunitĂ© .



Par exemple, certains chats, mailings, etc. les aspects de la vie d'un service Web, bien sĂ»r, doivent ĂȘtre rĂ©alisĂ©s en tant que microservices sĂ©parĂ©s dans le langage de programmation le plus pratique pour cela. Il n'est pas nĂ©cessaire de transfĂ©rer Ă  tout prix toute la logique du web service vers la base! Vous n'avez besoin de transfĂ©rer que la partie qui vous convient!



All Articles