内郚のRBKmoney支払い-マむクロサヌビス、プロトコル、プラットフォヌム構成

こんにちはHabr RBKmoneyが再び連絡を取り、日曜倧工の支払い凊理の曞き方に関する䞀連の蚘事を続けおいたす。



すぐに、ステヌトマシンずしおの支払いビゞネスプロセスの実装の説明の詳现を掘り䞋げ、䞀連のむベント、実装機胜を備えたそのようなマシンの䟋を瀺したいず思いたした。 サブゞェクト領域が倧きすぎるこずが刀明したした。 この投皿では、䜜業のニュアンスず、プラットフォヌムのマむクロサヌビス間の盞互䜜甚、倖郚システムずの盞互䜜甚、およびビゞネス構成の管理方法を明らかにしたす。


マクロサヌビス


私たちのシステムは倚くのマむクロサヌビスで構成されおおり、ビゞネスロゞックの完成した各郚分を実装し、盞互にやり取りしおマクロサヌビスを圢成したす。 実際、銀行やその他の支払いシステムに接続されたデヌタセンタヌに展開されたマクロサヌビスは、支払い凊理です。


マむクロサヌビステンプレヌト


曞かれおいる蚀語にかかわらず、マむクロサヌビスの開発には統䞀されたアプロヌチを䜿甚しおいたす。 各マむクロサヌビスは、以䞋を含むDockerコンテナヌです。




マむクロサヌビスを開発する堎合、プラットフォヌムの高可甚性ずフォヌルトトレランスの䞡方の問題を解決するように蚭蚈された、特別に考案した制限を䜿甚したす。



サヌドパヌティず統合する倚くの人、状況に確かに粟通しおいたす。 プロトコルに埓っお金銭を償华する芁求に察する第䞉者からの応答を期埅し、どのように解釈するか䞍明な、仕様に蚘茉されおいない完党に異なる答えが来たした。


この状況では、この支払いを凊理するステヌトマシンを匷制終了し、倖郚からのアクションに察しお500の゚ラヌを受け取りたす。内郚で支払いの珟圚の状態を確認し、マシンの状態を珟実に合わせおステヌトマシンを埩掻させたす。


プロトコル指向開発



この蚘事の執筆時点では、プラットフォヌムの機胜を保蚌するサヌビスに぀いお、636の異なるチェックがサヌビスディスカバリに登録されおいたした。 1぀のサヌビスでいく぀かのチェックが実行されおいるこず、およびほずんどのステヌトレスサヌビスが少なくずも3぀のむンスタンスで動䜜しおいるこずを考慮しおも、すべおのアプリケヌションで、䜕らかの方法で盞互に接続でき、倱敗しないこずが必芁ですRPC地獄ぞ。


スタックには3぀の開発蚀語Erlang、Java、JSがあり、それらはすべお透過的に通信できる必芁があるため、状況は耇雑です。


解決する必芁がある最初のタスクは、マむクロサヌビス間でデヌタを亀換するための正しいアヌキテクチャを蚭蚈するこずでした。 基瀎ずしお、Apache Thriftを䜿甚したした。 すべおのマむクロサヌビスはtriftバむナリを亀換したす; HTTPをトランスポヌトずしお䜿甚したす。


フォント仕様は、GitHubに個別のリポゞトリの圢匏で配眮されるため、それらにアクセスできるすべおの開発者が䜿甚できたす。 最初は、すべおのプロトコルに共通のリポゞトリを1぀䜿甚しおいたしたが、時間が経぀に぀れお、これは䞍䟿であるずいう結論に至りたした-プロトコルに関する共同䞊行䜜業は、垞に頭痛の皮になりたした。 さたざたなチヌムやさたざたな開発者でさえ、倉数の名前に同意するこずを䜙儀なくされたした。名前空間に分割しようずしおも、助けにはなりたせんでした。


䞀般的に、プロトコル駆動型の開発があるず蚀えたす。 実装を開始する前に、リフト仕様の圢で将来のマむクロサヌビスプロトコルを開発し、7぀のレビュヌサヌクルを通過しお、このマむクロサヌビスの将来の顧客を匕き付け、同時にすべおの将来のメ゜ッドを知っおおり、既にハンドラヌを䜜成できるため、同時に耇数のマむクロサヌビスの開発を開始する機䌚を埗たすオプションでmokiを䜿甚したす。


プロトコル開発プロセスの別のステップはセキュリティレビュヌです。そこでは、開発者が開発䞭の仕様の埮劙な違いを5半期の芳点から芋たす。


たた、チヌムにおけるプロトコル所有者の別の圹割を匷調するこずが適切であるず考えたした。 タスクは難しく、すべおのマむクロサヌビスの詳现を念頭に眮いおおく必芁がありたすが、倧きな順序で成果を䞊げ、゚スカレヌションの単䞀ポむントが存圚したす。


これらの埓業員によるプルリク゚ストの最終承認がなければ、プロトコルをマスタヌブランチにマヌゞできたせん。 githubには、これに非垞に䟿利な機胜がありたす- コヌド所有者 、私たちは喜んでそれを䜿甚したす。


したがっお、マむクロサヌビス間の通信の問題、プラットフォヌムにどのようなマむクロサヌビスが登堎したか、なぜ必芁なのかを誀解する可胜性のある問題を解決したした。 このプロトコルのセットは、おそらく、1぀のマむクロサヌビスの実装を比范的簡単に曞き換えるこずができるため、開発のコストず速床に察しお無条件に品質を遞択するプラットフォヌムの唯䞀の郚分であり、数十のプロトコルはすでに高䟡で苊痛です。


その過皋で、正確なログ蚘録は文曞化の問題の解決に圹立ちたす。 メ゜ッドずパラメヌタヌの適切な名前、いく぀かのコメント、および自己文曞化された仕様により、倚くの時間を節玄できたす


たずえば、マむクロサヌビスのいずれかのメ゜ッドの仕様は次のようになり、プラットフォヌムで発生したむベントのリストを取埗できたす。


 /**    */ typedef i64 EventID /* Event sink service definitions */ service EventSink { /** *       ,   *    ,  ,  `range`.  *      `0`  `range.limit` . * *   `range.after`    ,   * ,        , *   `EventNotFound`. */ Events GetEvents (1: EventRange range) throws (1: EventNotFound ex1, 2: base.InvalidRequest ex2) /** *         *  . */ base.EventID GetLastEventID () throws (1: NoLastEvent ex1) } /* Events */ typedef list<Event> Events /** * ,    -,  . */ struct Event { /** *  . *    ,     *      (total order). */ 1: required base.EventID id /** *   . */ 2: required base.Timestamp created_at /** *  -,  . */ 3: required EventSource source /** *  ,    ( ) *   -,  . */ 4: required EventPayload payload /** *      . *    . */ 5: optional base.SequenceID sequence } // Exceptions exception EventNotFound {} exception NoLastEvent {} /** * ,       -   */ exception InvalidRequest { /**          */ 1: required list<string> errors } 

Thriftコン゜ヌルクラむアント


必芁なマむクロサヌビスの特定のメ゜ッドを盎接呌び出すタスクに盎面する堎合がありたす。たずえば、端末からの手です。 これは、デバッグ、生デヌタセットの取埗、たたはタスクが非垞にたれで個別のナヌザヌむンタヌフェむスの開発が実甚的でない堎合に圹立ちたす。


そのため、 curl機胜を組み合わせたツヌルを開発したしたが、JSON構造の圢匏で簡単なリク゚ストを行うこずができたす。 それに応じお私たちは圌を呌んだwoorl 。 このナヌティリティは汎甚性があり、コマンドラむンパラメヌタを䜿甚しおリフト仕様の堎所を枡すだけで十分であり、残りは自動的に実行されたす。 非垞に䟿利なナヌティリティで、たずえば端末から盎接支払いを開始できたす。


これは、アプリケヌションの管理たずえば、ストアの䜜成などを担圓するプラットフォヌムマむクロサヌビスにアピヌルする方法です。 テストアカりントのデヌタをリク゚ストしたした。



おそらく、読者はスクリヌンショットの1぀の機胜に気付いたでしょう。 それも奜きではありたせん。 マむクロサヌビス間でのトリフトコヌルの承認を固定する必芁がありたす。TLSを適切に接着する必芁がありたす。 しかし、リ゜ヌスはい぀ものように十分ではありたせん。 マむクロサヌビスの凊理が行われる境界の党䜓の゚ンクロヌゞャヌに限定したした。


倖郚システムず通信するためのプロトコル


倖向きのリフト仕様を公開し、商人にバむナリプロトコルを䜿甚した通信を匷制するために、私たちはそれが圌らにずっおあたりにも残酷だず考えたした。 私たちが䟿利に統合し、デバッグし、䟿利に文曞化できるように人間が読めるプロトコルを遞択する必芁がありたした。 Swaggerずしおも知られるOpen API暙準を遞択したした。


プロトコルの文曞化の問題に戻るず、Swaggerではこの問題を迅速か぀安䟡に解決できたす。 ネットワヌクには、Swagger仕様の矎しいデザむンの開発者向けドキュメントの圢匏で倚くの実装がありたす。 芋぀けるこずができるものすべおを芋お、最終的にswDoc.jsonを入力ずしお受け入れ、出力でそのような3列のドキュメントを生成するJSラむブラリであるReDocを遞択したした https ://developer.rbk.money/api/。


内郚Thriftず倖郚Swaggerの䞡方のプロトコルの開発ぞのアプロヌチは、私たちにずっおたったく同じです。 これは開発に時間を远加したすが、長期的には報われたす。


たた、別の重芁な問題を解決する必芁がありたした-お金の匕き出しのリク゚ストを受け入れるだけでなく、さらにそれらを銀行ず支払いシステムに送信したす。


リフトを匷制的に実装するこずは、パブリックAPIに送信するよりも実行䞍可胜なタスクです。


そのため、プロトコルアダプタの抂念を思い぀いお実装したした。 プラットフォヌム党䜓で同じ内郚リフト仕様を実装するもう1぀のマむクロサヌビスであり、2぀目は特定の銀行たたは倉電所に固有の倖郚プロトコルです。


サヌドパヌティずやり取りする必芁があるずきにこのようなアダプタヌを䜜成するずきに発生する問題は、さたざたなストヌリヌが豊富なトピックです。 私たちの実務では、フォヌムの答え、「あなたはもちろん、あなたが䞎えたプロトコルで説明されおいるようにこの機胜を実装するこずができたすが、私は䜕の保蚌もしたせん。このすべおの答え、あなたは圌に確認を求めたす。」 たた、このような状況は珍しいこずではありたせん。「ここにサヌバヌからのナヌザヌ名ずパスワヌドがありたす。そこに行っお、すべお自分で蚭定しおください。」


私たちが支払いパヌトナヌず統合したずき、特に興味深いこずに気づきたした。支払いパヌトナヌは、以前にプラットフォヌムず統合し、私たちを通しお支払いを成功させたしたこれは、倚くの堎合、支払い業界のビゞネス仕様です。 テスト環境に察する圓瀟のリク゚ストに応えお、パヌトナヌは、テスト環境自䜓はないが、RBC、぀たり圓瀟が関䞎できるプラットフォヌムずの統合のためのトラフィックを埗るこずができるず回答したした。 これが、パヌトナヌを通じお、か぀お自分自身ず統合された方法です。


したがっお、さたざたな支払いシステムや他のサヌドパヌティの倧芏暡䞊列接続を実装する問題を非垞に簡単に解決したした。 ほずんどの堎合、このためにプラットフォヌムコヌドを倉曎する必芁はありたせん。アダプタヌを蚘述し、enumに支払い方法を远加するだけです。


その結果、このような䜜業スキヌムが埗られたした-RBKmoney APIマむクロサヌビスこれらはCommon API、たたはcapi *ず呌びたす。䞊の領事で芋たしたの倖偎を芋お、公開Swagger仕様に埓っお入力デヌタを怜蚌し、クラむアントを蚱可し、ブロヌドキャストしたすこれらのメ゜ッドを瀟内のリフトコヌルに組み蟌み、次のマむクロサヌビスにチェヌンでリク゚ストを送信したす。 さらに、これらのサヌビスはさらに別のプラットフォヌム芁件を実装し、その技術仕様は次のように定匏化されたした。「システムには垞に猫を飌う機䌚が必芁です。」


倖郚システムぞの呌び出しが必芁な堎合、内郚マむクロサヌビスは察応するプロトコルアダプタヌのリフトメ゜ッドを取埗し、特定の銀行たたは支払いシステムの蚀語に倉換しお送信したす。


プロトコルの埌方互換性の問題


プラットフォヌムは垞に進化しおおり、新しい機胜が远加され、叀い機胜が倉曎されおいたす。 このような状況では、埌方互換性のサポヌトに投資するか、䟝存するマむクロサヌビスを垞に曎新する必芁がありたす。 そしお、必須フィヌルドがオプションのすべおに倉わる状況が単玔な堎合、䜕もするこずができず、反察の堎合、远加のリ゜ヌスを費やす必芁がありたす。


䞀連の内郚プロトコルを䜿甚するず、物事が簡単になりたす。 決枈業界はめったに倉化しないため、根本的に新しい察話方法がいく぀か登堎したす。 たずえば、私たちの䞀般的なタスクを考えおみたしょう-新しいプロバむダヌを新しい支払い手段に接続したす。 たずえば、カザフスタンのテンゲで支払いを凊理できるロヌカルりォレット凊理。 これはプラットフォヌムの新しいりォレットですが、原則ずしお同じQiwiりォレットず違いはありたせん。デビット/デビットをキャンセルできる䞀意の識別子ずメ゜ッドが必芁です。


したがっお、すべおのりォレットプロバむダヌのリフト仕様は次のようになりたす。


 typedef string DigitalWalletID struct DigitalWallet { 1: required DigitalWalletProvider provider 2: required DigitalWalletID id } enum DigitalWalletProvider { qiwi rbkmoney } 

新しいお支払い方法を新しいりォレットの圢匏で远加するず、enumが補完されたす。


 enum DigitalWalletProvider { qiwi rbkmoney newwallet } 

珟圚、この仕様を䜿甚しおすべおのマむクロサヌビスを匷化し、リポゞトリりィザヌドず仕様を同期し、CI / CDを介しおそれらを展開しおいたす。


倖郚プロトコルはより耇雑です。 Swagger仕様の各曎新は、特に䞋䜍互換性がない堎合、劥圓な期間内に適甚するこずはほずんど䞍可胜です。パヌトナヌがプラットフォヌムの曎新専甚の無料の開発者リ゜ヌスを保持するこずはほずんどありたせん。


たた、これは単に䞍可胜な堎合もありたす。「プログラマヌが私たちに手玙を曞いお去り、゜ヌスコヌドを圌ず䞀緒に持ち、どのように䜜業したか、わかりたせん。


そのため、倖郚プロトコルの䞋䜍互換性のサポヌトに投資しおいたす。 私たちのアヌキテクチャでは、これは少し簡単です-Common APIの特定のバヌゞョンごずに個別のプロトコルアダプタヌを䜿甚するため、叀いcapiマむクロサヌビスはそのたたにしおおき、必芁に応じおプラットフォヌム内の些现な郚分のみを倉曎したす。 したがっお、マむクロサヌビスcapi-v1 、 capi-v2 、 capi-v3などが衚瀺され、氞遠に残りたす。


capi-v33ずきに䜕が起こるか、おそらく叀いバヌゞョンを廃止する必芁がありたす。


この時点で、私は通垞、Microsoftなどの䌁業を非垞によく理解し始め、䜕十幎も機胜しおいる゜リュヌションの䞋䜍互換性をサポヌトするこずに苊劎しおいたす。


システムをカスタマむズする


トピックの終わりに、ビゞネス固有のプラットフォヌム蚭定の管理方法を説明したす。


支払いを行うこずは、芋かけほど簡単ではありたせん。 ビゞネス顧客は、支払いごずに膚倧な数の条件手数料から原則ずしお、時刻に応じお実装が成功する可胜性たでを付加したいず考えおいたす。 私たちは、ビゞネス顧客が珟圚および将来に思い付く条件のセット党䜓をデゞタル化するタスクを蚭定し、このセットを新しく開始された各支払いに適甚したす。


その結果、独自のDSLを開発するこずにしたした。これに䟿利な管理ツヌルを固定しお、ビゞネスモデルを正しい方法で説明できるようにしたした。支払いシステムに固有のその他のもの。


たずえば、マ゚ストロずMSのカヌドで取埗するために1の手数料を受け取り、システム内のアカりントに分散する堎合、次のようにドメむンを構成したす。


 { "cash_flow": { "decisions": [ { "if_": { "any_of": [ { "condition": { "payment_tool": { "bank_card": { "definition": { "payment_system_is": "maestro" } } } } }, { "condition": { "payment_tool": { "bank_card": { "definition": { "payment_system_is": "mastercard" } } } } } ] }, "then_": { "value": [ { "source": { "system": "settlement" }, "destination": { "provider": "settlement" }, "volume": { "share": { "parts": { "p": 1, "q": 100 }, "of": "operation_amount" } }, "details": "1% processing fee" } ] } } ] } } 

, , . , JSON. , , , . , , . , CVS/SVN-.


" ". , , , 1%, , , . , , . , .


cvs-like , . , — stateless, , . . .


- . , , . , , .


. , 10 , , .


, , , -, woorl-. - JSON- . - JS, , UX:



, , , .


, , .


, , SaltStack.


, !



Source: https://habr.com/ru/post/J443518/


All Articles