過去2つの会社で、私は [〜#〜] rest [〜#〜] webappを介してデータをクエリするためのAPIが存在します。つまり、webappに代わりに [ 〜#〜] sql [〜#〜] 直接REST APIを呼び出し、SQLを実行して結果を返します。
私の質問は-なぜこれが行われるのですか?
サードパーティに公開されるとしたら、理解できました。完全なDBよりも限定されたREST APIを公開する方が良いです。しかし、これらの会社の両方ではそうではありません。
これらのREST APIによって [〜#〜] dbm [〜#〜] Sを簡単に切り替えることができるようになっています。しかし、それがデータベース抽象化レイヤーのポイントではありませんか( [〜#〜] dbal [〜#〜] )?たぶん [〜#〜] orm [〜#〜] をDBALとして使用するか、生のSQLを記述して、必要に応じてDBALにDB固有のものを翻訳させることができます(例:翻訳 [〜#〜] limit [〜#〜] for MySQL to [〜#〜] top [〜#〜] for [〜 #〜] mssql [〜#〜] )。
どちらにせよ、私には不必要に思えます。また、問題の診断も難しくなると思います。 webappのレポートが間違った数値を示している場合、SQLクエリを単にダンプすることはできません-REST URLをダンプしてから、REST APIとして機能しているプロジェクトに移動し、それからSQLを引き出します。つまり、診断プロセスの速度を低下させる間接層が追加されます。
クライアントがデータベースに直接アクセスすることを許可する場合-データベースアブストラクションレイヤーを使用した場合でも、次のようになります。
つまり、RESTの部分についてはまったく触れていません。APIの背後でデータベースを分離することは、データベースを管理するチームとそれを使用するチームがそうでない場合、より賢明な選択です。これらのパーツを自分のペースで進化させることができるので、同期しています。
そうです、Webアプリケーションとデータベースの間にREST APIレイヤーを導入する明確な利点はなく、複雑さとパフォーマンスのオーバーヘッドにコストがかかります。
矛盾する答えが得られるのは、アーキテクチャの「クライアント」が何であるかについての混乱です。
あなたのアーキテクチャでは(私がそれを正しく理解している場合)、ブラウザが単一のWebアプリと対話していて、それがデータベースと対話しています。 REST Webアプリとデータベースの間にAPIレイヤーを導入してもメリットはありません。記載されているすべてのメリット(キャッシュ、データベースの分離など)は、コード内のデータアクセスレイヤーで実現できます。
しかし、REST APIが理にかなっているいくつかのotherアーキテクチャがあります:
データベースにアクセスするクライアントが複数ある場合-つまり、単一のWebアプリではなく、同じデータベースにアクセスする複数の独立したWebアプリ。共通のRESTインターフェースを作成して、データモデルの共有やキャッシングなどを可能にすることには利点があるかもしれません。同じDALライブラリを共有することでいくつかの利点を得ることができますが、アプリはさまざまな言語とプラットフォームで開発されていますが、これはエンタープライズシステムでは一般的です。
データベースに直接アクセスする複数のデスクトップアプリがある場合。これは、古典的な「2層」アーキテクチャーであり、Webアプリと比較すると支持されなくなっています。 RESTレイヤーを導入すると、データアクセスロジックを集中化できます。特に、同じデータベースに複数の分散クライアントに直接アクセスするのは危険なので、セキュリティをより厳密に制御できます。
サーバーから直接データをフェッチするJavaScriptコードがある場合は、REST APIなど)が必要です。
警告:大きな投稿、いくつかの意見、漠然とした「あなたに最適な方法を実行する」結論
一般的に、これはデータベースの周りに「六角形のアーキテクチャ」を実装する手段として行われます。 Webアプリケーション、モバイルアプリケーション、デスクトップアプリケーション、バルクインポーター、バックグラウンド処理のすべてで、データベースを統一された方法で使用できます。確かに、データベースにアクセスするための豊富なライブラリを作成し、すべてのプロセスでそのライブラリを使用することにより、ある程度同じことを達成できます。実際、非常にシンプルなシステムを備えた小さなお店にいる場合は、実際にはそれがおそらくより良い方法です。これはより単純なアプローチであり、より複雑なシステムの高度な機能が必要ない場合は、なぜその複雑さの代償を払うのでしょうか。ただし、大規模でデータベースと対話する必要がある大規模で洗練されたシステムのセットを使用している場合、アプリケーションとデータの間にWebサービスを配置することには多くの利点があります。
プラットフォームの独立性とメンテナンス
データベースがあり、Pythonライブラリを作成してそのデータベースとやり取りする場合、誰もがそのライブラリをプルしてデータベースとやり取りすることは素晴らしいことです。しかし、突然、モバイルアプリ、そのモバイルアプリもデータベースと通信する必要があります。iOSエンジニアはPythonを使用せず、AndroidエンジニアはPythonを使用しません。おそらくiOSみんながAppleの言語を使いたがっていて、AndroidエンジニアはJavaを使いたがっています。そうすると、データアクセスライブラリを3つの異なる言語で作成して維持するのが困難になります。おそらくiOSとAndroid開発者は、共有できるコードを最大化するためにXamarinのようなものを使用することを決定します。データアクセスライブラリを.NETに移植する必要がある場合を除いて、完璧です。そして、あなたの会社は、 Webアプリケーションは異なるが関連する製品であり、企業は会社のプラットフォームのデータの一部を新しいプラットフォームに統合したいと考えています。子会社のプラットフォームを買収。問題が1つだけあります。子会社は新興企業であり、アプリケーションの大部分をDartで作成することにしました。さらに、Xamarinのパイロットを行っていたモバイルチームは、何らかの理由(おそらくあなたの制御が及ばない理由)のために、それは彼らのためではなく、彼らが開発するモバイルデバイスに固有のツールと言語を使用することに決めました。しかし、あなたがそのフェーズにいる間、チームはすでに.NETでデータアクセスライブラリの大部分を提供しており、社内の別のチームがいくつかのクレイジーなSalesforce統合を書いていて、そこからすべてを.NETで行うことにしました。はすでに.NETのデータアクセスライブラリでしたが、モバイルも当初.NETを使用することを計画していたため、これは良いアイデアのように思われました。
つまり、非常に現実的なイベントの発生により、Python、.NET、Swift、Java、およびDartで記述されたデータアクセスライブラリができました。彼らもあなたが望むほど素敵ではありません。 ORMを希望するほど効果的に使用することはできません。言語ごとに異なるORMツールがあるため、必要以上に多くのコードを記述する必要がありました。また、5つあるため、各インカネーションに必要な時間を費やすことができませんでした。ライブラリのDartバージョンは特に扱いにくいものです。ライブラリとサポートが実際には存在しなかったため、一部のライブラリは独自のトランザクションのものをロールバックする必要があったためです。このため、Dartアプリケーションにはデータベースに対して読み取り専用の機能しかなかったはずですが、企業はすでに、計画しているすべての機能に追加の労力を費やす価値があると考えていました。そして、データアクセスライブラリのこれらすべての化身に存在する検証ロジックの一部にバグがあることがわかりました。次に、これらのすべてのライブラリでこのバグを修正するためのテストとコードを記述し、これらすべてのライブラリへの変更のコードレビューを取得し、これらすべてのライブラリでQAを取得し、すべてを使用してすべてのシステムへの変更をリリースする必要があります。これらのライブラリ。その間、あなたの顧客は不満を抱き、ツイッターを利用して、あなたの会社の主力製品をターゲットにすることはもちろんのこと、想像もしなかったであろう下品さの組み合わせをつなぎ合わせました。そして、製品の所有者は、状況についてまったく理解しないことを決定します。
一部の環境では、上記の例は不自然なものであることを理解してください。また、この一連のイベントは数年の間に展開する可能性があることを考慮してください。一般に、アーキテクトやビジネスパーソンがデータベースに他のシステムを接続することについて話し始めるところまで来たら、「REST APIを前に置くことを望むでしょう。このデータベースがいくつかのシステムで共有され始めることが明らかになったら、Webサービス/ REST APIがその前に置かれたかどうかを検討してください。検証のバグを修正すると、 5回ではなく1回実行するので、はるかに迅速かつ簡単になります。修正をリリースすることは、変更を他のシステムにリリースするためにリリースする他のいくつかのシステムに依存しないため、調整がはるかに簡単になります。
TLDR;データにアクセスする必要がある各アプリケーションにデータアクセスロジックを分散させるよりも、データアクセスロジックを一元化して非常にシンHTTPクライアントを維持する方が簡単です。実際、HTTPクライアントはメタデータから生成されることもあります。大規模なシステムでは、REST APIにより、維持するコードが少なくなります
パフォーマンスとスケーラビリティ
一部の人々は、最初にWebサービスを経由するのではなく、データベースと直接対話する方が速いと信じているかもしれません。アプリケーションが1つしかない場合、それは確かに当てはまります。しかし、より大きなシステムでは、私はその感情に同意しません。最終的に、ある程度の規模では、データベースの前にある種のキャッシュを配置することが非常に有益になります。たぶん、あなたはHibernateを使用していて、InfinispanグリッドをL2キャッシュとしてインストールしたいと考えています。アプリケーションとは別にWebサービスをホストする4台のサーバーのクラスターがある場合は、同期レプリケーションがオンになっている組み込みトポロジを使用できます。 30台のアプリケーションサーバーのクラスターに配置しようとすると、そのセットアップでレプリケーションを有効にするオーバーヘッドが多すぎるため、Infinispanを分散モードまたは何らかの専用トポロジで実行する必要があります。突然、Hibernateはキャッシュから読み取るためにネットワークを経由する必要があります。さらに、InfinispanはJavaでのみ機能します。他の言語を使用している場合は、他のキャッシュソリューションが必要になります。データベースに到達する前にアプリケーションからWebサービスに移動しなければならないというネットワークオーバーヘッドは、通常は独自のオーバーヘッドを伴うはるかに複雑なキャッシュソリューションを使用する必要があるため、すぐに相殺されます。
さらに、そのREST APIのHTTPレイヤーは、別の貴重なキャッシュメカニズムを提供します。REST APIのサーバーは、応答にキャッシュヘッダーを置くことができ、これらの応答非常に拡張性の高いネットワークレイヤーでキャッシュできます。1台または2台のサーバーを使用する小規模な設定では、データベースと通信するときにアプリケーションのメモリ内キャッシュを使用することをお勧めしますが、大規模なプラットフォームでは多くのアプリケーションが多くのサーバーで実行されている場合、ネットワークを活用してキャッシュを処理する必要があります。これは、squid、varnish、nginxなどを適切に構成すると、比較的小さなハードウェアで異常なレベルにスケールアウトできるためです。1秒あたり数十万または数百万のリクエストスループットの向上は、HTTPキャッシュから行う方が、アプリケーションサーバーやデータベースから行うよりもはるかに安価です。
その上、大量のクライアントをすべてデータベースに向けるのではなく、いくつかのサーバーに向けるのではなく、データベースに向けるのではなく、データベースと接続プールのチューニングを非常に難しくすることができます。一般に、アプリケーションサーバー上の実際のワークロードのほとんどはアプリケーションに関するものです。データベースからデータが返ってくるのを待つことは、多くの場合時間がかかりますが、一般に計算コストはそれほど高くありません。アプリケーションのワークロードを処理するために40台のサーバーが必要になる場合がありますが、データベースからデータをフェッチするために40台のサーバーは必要ありません。そのタスクをWebサービス専用にすると、Webサービスは他のアプリケーションよりもはるかに少ないサーバーで実行されます。つまり、データベースへの接続がはるかに少なくて済みます。データベースが大量の同時接続にサービスを提供している場合、データベースは一般的に同様に機能しないため、これは重要です。
TLDR;さまざまな言語やテクノロジーを使用して多くの異なるアプリケーションで発生する場合よりも、単一の専用Webサービス内で発生する場合の方が、データアクセスを調整、スケーリング、キャッシュする方が簡単です
最終的な考え
この考え方から離れないでください「ああ、いつもRESTデータを取得するためのAPIを使用する必要があります」または "このばかは、私たちのWebアプリがデータベースと直接通信するので、私たちが間違っていると言っていますが、私たちのものは正常に動作します!"私がしようとしている主要なポイントはシステムやビジネスによって要件は異なります。多くの場合、データベースの前にREST APIを置くことは実際には意味がありません。正当化を必要とするより複雑なアーキテクチャです。その複雑さ。しかし、複雑さが正当化される場合、REST APIを使用することには多くの利点があります。さまざまな懸念を比較検討し、システムに適切なアプローチを選択できることは、エンジニア。
さらに、REST APIがデバッグの邪魔をしている場合は、その図に何か問題があるか欠落している可能性があります。その抽象化レイヤーを追加すると、本質的にデバッグが困難になるとは思いません。私は大規模なn層システムで作業し、分散ログコンテキストがあることを確認します。おそらく、ユーザーがリクエストを開始したときに、そのリクエストに対してGUIDを生成し、ユーザー名をログに記録しますそのユーザーとそのユーザーが行った要求。次に、アプリケーションが他のシステムと通信するときにGUID onを渡します。適切なログの集計とインデックス付けを使用すると、問題を報告しているユーザーについてプラットフォーム全体をクエリできます。 、すべてのアクションを可視化し、システム全体を細かく調整して、問題が発生した場所をすばやく特定します。繰り返しますが、これはより複雑なアーキテクチャであるため、そのアーキテクチャのサポートを容易にするために、より複雑なインフラストラクチャを用意する必要があります。
ソース: http://alistair.cockburn.us/Hexagonal+architecturehttps://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
私が正しく理解している場合 DBALとは の場合、答えは、RESTインターフェースで任意の言語を使用できるということですクライアント用ですが、DBALはクライアントに単一言語を使用できるライブラリです。
これは、開発チームが多く、すべてが同じ言語に熟達しているわけではない会社にとっては、利点となります。彼らのソフトウェアがDBに直接クエリできるようにすることは機能的には同等ですが、「限定されたREST APIを完全なDBよりも公開する方が良い」と言います。
より抽象的な言葉で言えば、あなた自身が質問に答えています:
ですから、診断プロセスを遅くする追加の間接層です。
...これがあるので 有名な格言 は、「コンピュータサイエンスのすべての問題は別のレベルの間接参照で解決できる」と述べています。 :)
同じ会社内にいるからといって、すべての人にすべてを公開する必要があるわけではありません。 REST APIは、明確な契約により、企業内のチーム間の限定的な消費者/プロバイダー関係を定義する方法です。Amazonは、この形式の組織において パイオニア でした。
APIは抽象化のレイヤーも提供し、特定のイディオムのセットを使用できるようにします。必ずしも、データベースで使用されているのと同じ用語でコンシューマーと話したいとは限りません。また、必ずしも同じ方法で各消費者と話したいとは思わないでしょう。
RESTはデータベースクエリ用であり、そうではないことを考えています。RESTは、現在の状態を表しています。REST表現を変更または取得しますが、それがすべてです。その状態がデータベースによって利用可能になった場合、その表現がどのようにして行われるかはREST =どちらもデータベースクエリではありません。
DBALはデータへのアクセスのみを考慮しますが、ほとんどのアプリケーションでは、データへのアクセスだけでなく、操作のすべての副作用の実行も考慮します。
たとえば、eコマースシステム。注文がシステムに入ってきたら、顧客に領収書をメールで送りたい、会計システムに接続して貸借対照表を更新したい、支払い処理業者に接続してクレジットカードを処理する場合、注文の詳細を不正検出サービスに送信して、カードの支払いがチャージバックになる可能性があるかどうかを確認します(不正な注文ではよくあることです)。注文を発送するために倉庫システムに接続する必要があります。 、供給が少なくなったときに自分のサプライヤーに接続してより多くの在庫を注文したい、機械学習アルゴリズムを実行してクロスセル製品の推奨を提供したい、CRMに接続して失敗した注文についてフラグを立てます。レポートやアラートなどのために、分析サービスに注文を記録します。
これらの操作のほとんどは、信頼できるシステム、つまりサーバー上で行う必要があり、これらの副次的な操作はデータベースに関連しておらず、DBALレイヤーで開発するには複雑すぎることがよくあります。