マイクロサービスに関する簡単なブログを準備し、PHPでマイクロフレームワークを記述し、Dockerですべての例を実行します

しかし、新製品がマイクロサービスアーキテクチャ上ですぐに書き始められ、モノリスの切断に対処することはできないと言ったらどうでしょうか。 これは一般的に正常ですか? 便利ですか? 答えを知りたいですか?







タスク:フレームワークを使用せずに、週末(時間は10〜15時間に制限されます)にPHPでマイクロサービスに関する球状のブログを書く必要があります。 常識を使用できます。 また、フロントエンドについても忘れ、仮想化なしでは生きていけないことを忘れないでください。 Dockerを選択します。 面白い? 猫に転送します。







画像



マイクロサービス



マイクロサービスのアプローチに興味があるが、どこから始めればよいかわからない場合は、Sam Newmanの著書 『Building Microservices』から始めてください。 このアプローチの主なポイントを少し説明しようと思いますが、追加があればコメントに書いてください。 一般に、何らかの理由で、私は、特にあなたの特定のケースで、以下に説明するアプローチのいずれかに当てはまるふりをしません。







前述のブログの例ですべてを検討します。 もちろん、これはタスクのためのタスクですが、このバージョンでも動作し、正常に動作することに注意してください(迅速かつ問題なく)。







マイクロサービスの本質は、モノリシックアーキテクチャと比較して理解しやすいです。 通常のブログエンジンはどのように見えますか? 大まかに言って、これは1つのアプリケーションにすぎません。 記事、コメント、ページ、ユーザー、およびその他の機能ユニットの操作は、決して共有されない単一のソースコードパッケージに含まれています。









コンポーネント間のすべての接続がコード内の呼び出しである場合、クラス、パターンなどの間の何らかの関係 または、互いに分離することが不可能な場合は、単にgovnokodでさえもです。







ブログはどのように表示されますか? はい、ほぼ同じ、正直に言うと。









唯一の違いは、コンポーネントのあるボックスが1つのアプリケーションのコードに囲まれたコンポーネントではなくなり、矢印がこのコード内のクラスのシステムコールではなくなったことです。 現在、これらは個別のコンポーネントであり、矢印は通常のhttp要求です。







なぜこれが必要なのですか? おそらく誰もがこれを必要としているわけではないとすぐに判断します。 これは、かなり大きな会社で、各サービスに開発チームを割り当てることができる場合に非常に便利です。 中規模の会社であっても、各サービスに人を割り当てるといいと思います。 ただし、会社全体で自分が1人であっても、マイクロサービスには興味深いものがあります。







サービスの大きさはどれくらいですか? 境界線を引くのは困難です。間違いは多大な費用がかかりますが、要するに、サービスはシステムの特定の単位であり、短時間で完全に書き換えることができます。 経験的に、あなたまたはあなたのチームに1週間でサービスに対応させてください。 ここでの主なアイデアは、サービスを小さくすることです。 彼らはモノリスの束になってはいけません。







だから、私が自分のために選べる肯定的なことは、一般に、すべて同じ傾向にあります:開発のための信じられないほどの使いやすさ:









私たちのアプリケーションは何ができるはずですか? それほど多くはありません。

4ページ:









機能は簡単です:









Docker





これで、理論についてはもう話さず、アプリケーションをカットしましょう。 ドッキングウィンドウに配置します。 このような分散アプリケーションを仮想化なしで1台のマシンで開発することはほとんど不可能です。 Dockerの説明は、この記事の範囲を超えているため、フラグメントで表示されます。 あなたは彼について何かを知っていると仮定されます。







ところで、ここにブログをダウンロードして実行できるカブへのリンクがあります。以下のコードを使用して何かを参照してください。 https://github.com/gregory-vc/blog







私たちの最も単純なブログにはいくつのコンテナがありますか? ちなみに、コンテナは、本質的には、ネットワークを介して他のコンテナと通信する別のサーバーの仮想化です。ただし、厳密な類似のcontainer = serverを使用する場合、一部のコンテナは放棄する必要があります。 マイクロサービスに関するブログの最も簡単な実装では、24個のコンテナーをカウントしました。 見てみましょう。









一部のサービスのコピーが2つあるのはなぜですか? なぜならそれは面白くなく、はっきりしないからです。







1つのコマンドですべてをデプロイするdocker-composeファイルは次のようになります。

https://github.com/gregory-vc/blog/blob/master/host/docker-compose.yml

最も興味深いものから、ゲートウェイコンテナのphp設定を検討します。







'php_gate': image: 'tattoor/blog_php' container_name: 'php_gate' volumes_from: ['source_gate'] volumes: ['./logs/php/gate/:/var/log/dev_php'] links: - nginx_post_1:post1.blog - nginx_post_2:post2.blog - nginx_comment_1:comment1.blog - nginx_comment_2:comment2.blog - nginx_auth_1:auth1.blog - nginx_auth_2:auth2.blog - redis environment: - POST_1_HOST=post1.blog - POST_1_PORT=80 - POST_2_HOST=post2.blog - POST_2_PORT=80 - COMMENT_1_HOST=comment1.blog - COMMENT_1_PORT=80 - COMMENT_2_HOST=comment2.blog - COMMENT_2_PORT=80 - AUTH_1_HOST=auth1.blog - AUTH_1_PORT=80 - AUTH_2_HOST=auth2.blog - AUTH_2_PORT=80
      
      





リンクコンテナの説明セクション。これは基本的に/ etc / hosts /







 docker exec php_gate cat /etc/hosts 172.17.0.36 auth1.blog 86b8b266477d nginx_auth_1 172.17.0.36 nginx_auth_1 86b8b266477d 172.17.0.21 comment1.blog 836bacb42e78 nginx_comment_1 172.17.0.19 comment2.blog c554a8888801 nginx_comment_2 172.17.0.20 post2.blog 37f81921419c nginx_post_2 172.17.0.7 redis a1932016be87 172.17.0.37 auth2.blog 5715045a213b nginx_auth_2 172.17.0.37 nginx_auth_2 5715045a213b 172.17.0.21 nginx_comment_1 836bacb42e78 172.17.0.19 nginx_comment_2 c554a8888801 172.17.0.22 nginx_post_1 1cc1ef5ab896 172.17.0.22 post1.blog 1cc1ef5ab896 nginx_post_1 172.17.0.20 nginx_post_2 37f81921419c 172.17.0.23 fafe93f31a67
      
      





指定されたホストで、Dockerの内部ネットワークを介して別のコンテナにアクセスするだけです。







また、環境セクションは、getenv()を介してアプリケーション内で取得できる変数の指定にすぎません。 docker-composeファイルがアプリケーション全体を設定するための単一のエントリポイントになるように作成されます。







サービスの構造は、ディレクトリが近くにあるように見えますが、









しかし、実際には、ホストのドッカーを起動すると、これらの各ディレクトリは個別の分離された対応するコンテナ内に表示されます。 それは何らかの形で行われます:







 'source_post_1': volumes: ['../Services/Post:/home/gregory/source/']
      
      





つまり、それらはもうすぐ近くにありますが、起動時には、あるサービスなどから別のサービスのクラスを含める機会はありません。 近くにあるのは利便性のためだけであり、実際にはお互いにまったく触れずに、それぞれがリポジトリ内にある必要があります。







ゲートサービス





このサービスは、ブログへのエントリポイントとなり、テンプレートをレンダリングし、結果を表示し、必要なサービスを引き出します。 ところで、さまざまなアプローチがあります。たとえば、単一のエントリポイントを拒否し、すべてをフロントエンドに実装できます。 つまり、ブラウザ自体が必要なサービスにアクセスし、ブラウザで結果を直接収集します。 私が言えることは、それはすべてあなたの特定のケースに依存し、そこにはプラスとマイナスがあります。







だから、私たちはPHPを持っています。 とはいえ、少なくとも作曲家を連れて行きましょう。 さらに2つのディレクトリを作成してみましょう。1つはマイクロフレームワーク用で、これはこれから作成します。2つ目はパブリックスクリプト、js、およびその他のリソース用です。







次のようになります。









コンポーザーでは、単純にオートロードを実装する場所を指定するため、これに煩わされることはなく、生成されたオートロードをpublic / index.phpに接続します。







だから、私たちはすでに何かを持っています、私たちがまだ必要なものを決定しましょう









悪くない、他に何?









このようなオブジェクトのリポジトリを作成して、どこにも作成しないようにします。ただし、必要な依存関係をすべて備えたアプリケーションの任意の時点で既に作成されたアプリケーションにアクセス(インジェクト)できるようにします。 Reflectionやその他の興味深いことを楽しむことはありません。時間は厳しく制限されています。







  Storage::set('Request', new Request()); Storage::set('Router', new Router()); Storage::set('Redirect', new Redirect()); Storage::set('App', new App());
      
      





Diでは、このリポジトリを使用して、必要なオブジェクトをすべて追加します。

公開では、Diを起動し、ルーターを取得し、便利なすべてのURLを登録し、アプリケーションを受け取って起動します。







  $router->get('/logout/', 'AuthController@logout'); $router->get('/404', 'SystemController@notFound'); $router->post('/post/add_request/', 'PostController@add')
      
      





アプリケーションでは、要求を取得し、この要求に対する既存のコントローラーの既存のアクションをルーターにマッピングすると同時に、受信したすべてのポスト変数または取得変数を要求に書き込みます。







コントローラーメソッドを実行し、応答を取得し、応答をレンダリングして、作業の結果を表示するだけです。







  $current_request = $this->router->getCurrent(); $controller = new $current_request->controller; $response = $controller->{$current_request->method}(); $response->render();
      
      





フレームワークがあり、サービスを操作し、サービスを含むディレクトリを作成し、各サービスのクラスを作成し、各サービスのアクセスポイントを記述する必要があります。 クエリオプションを実装するサービスのメインクラスからそれらを継承します。







https://github.com/gregory-vc/blog/blob/master/Services/Gate/My/Engine/Service.php







  static public function get($method, $params = []) { $service = new static; return $service->executeGet($method, $params); } static public function post($method, $params = []) { $service = new static; return $service->executePost($method, $params); }
      
      





そこで、リクエスト内で、サービスによって提供されるコネクタからランダムなコネクタを選択します。







  $rand_connector = rand(0, $count_connector) % $count_connector;
      
      





コントローラからリクエストを作成し、次のようにレンダリングします。







  $posts = Post::get('all'); return $this->response->html('posts', $posts);
      
      





レンダリングする必要がありますが、どうやって? テンプレートエンジンはありません。 自分で書きますか? いえいえ phpを使用してください。







  ob_start(); require_once($layout_template); $contents = ob_get_contents(); ob_end_clean(); $this->content = $contents;
      
      





4行のサイズの非常に強力なテンプレートエンジン。







投稿およびコメントサービス



次は? これで、リクエストを作成して結果を表示できるようになりました。次に、答えを提供するサービスを作成する必要があります。 新しいエンジンを他のサービスにコピーし、URLを変更し、リモートサービスの代わりにモデルとデータベースで作業を記述します。







デフォルトではfindAll、findBy、add、saveのモデルで作業を実装します:

https://github.com/gregory-vc/blog/blob/master/Services/Auth/My/Engine/Model.php







それで何? 正直に言うと、承認を除けば、それだけで十分です。

他のサービスから他のサービスまで、あらゆるサービスのゲートリクエストを行うことができます。







認可サービス

スキームは単純です。ユーザーとそのアクセス権が承認サーバーにあり、ゲートウェイから承認リクエストを作成し、トークンを生成し、それをゲートウェイと別のユーザーに返し、ユーザーとトークンをセッションに入れます。 投稿を追加するリクエストと一緒にトークンを送信することを忘れられない、何のため? そうです、郵便サービスは承認サービスに行き、このトークンが良いかどうかを尋ねますか? 結果に応じて、ジェネレーターの実行は異なります。







  public function login($user, $password) { $hash = hash('sha256', $password); $user = User::findBy([ 'login' => $user, 'password' => $hash ]); if (!empty($user) && is_array($user)) { $user = current($user); $user['token'] = bin2hex(random_bytes(30)); User::save($user); return [ 'login' => $user['login'], 'token' => $user['token'] ]; } else { throw new \Exception('Not found user'); } }
      
      





結果



一般に、1つのコマンドでダウンロードしてデプロイできます。リポジトリを思い出させます: https : //github.com/gregory-vc/blog







意味のどこに収まるか-明確にするために、この特定のノードまたはこのブロックが生成されたノードを推測しました。







また、ページが生成された時間にも感銘を受けました。 これは、投稿といくつかのコメント(!)があるページの場合、5〜9ミリ秒です。 はい、これはすべて偏っています、はい、これらはすべてオウムです、はい、マイクロサービスはそれとは何の関係もありません、はい、比較するものに依存します。 しかし。 同じキャラメルがそのページを生成します。一般に、リクエストとデータはなく、自分のマシン上で90ミリ秒間、あいさつだけです。 これは10〜20倍長くなります。







比較するのではなく、さらに多くのことが行われていることを理解していますが、それでも、別の分離されたマイクロサービスのこの特定の現在のタスクでは、これはすべて必要ではありません。 コメントサービスについては、ネットワーク経由でサービスを扱うクラスを廃止しました。 ゲートウェイサービスの場合、基本クラスを破棄しました。 特定のサービスごとに、彼が必要とするものだけを収集しました。 そして、適切なサービスはほんの少し必要です:)







そして最も重要なことは、これはこのブログを信じられないほどのワークロードに拡大するための信じられないほどの可能性です。 たとえば、誰も干渉せず、Goのコメントサービスを使用して書き換えます。







問題



ネットワークオーバーヘッド

別のサービスがどのように機能するかわからない場合、ひどく機能せず、すべてを損なう状況になる可能性があります。また、サービスを使用します(!)結果を提供します。







すべてを試す方法を思い出させてください







 Clone git clone https://github.com/gregory-vc/blog.git . Install Docker: wget -qO- https://get.docker.com/ | sh sudo usermod -aG docker user sudo apt-get install python-pip sudo pip install docker-compose Compile chmod 744 compile ./compile chmod 744 upload_db ./upload_db Run http://gate.blog:30001/ admin admin
      
      






All Articles