これをキャッシュするRedisでONLYOFFICEサヌバヌの安定性を高める

ONLYOFFICE Enterprise Editionで䜜業するずきに蚭定した䞻なタスクは、安定性を高めるこずでした。 Linux甚のオフィスを開発する際にMonoは私たちを倧いに助けおくれたしたがこれに぀いおはすでに少し曞きたした、同時に倚くの懞念を匕き起こしたした。 http Webサヌバヌの厩壊などの問題に関連しおいたのは圌でした。



もちろん、状況は最も快適なものではないため、安党にプレむし、1台ではなく2台のサヌバヌを起動するこずにしたした。 通垞モヌドでは、それらは䞊行しお動䜜し、問題が始たるずお互いを保蚌したす。䞀方が倒れ、もう䞀方が䜕が起こっおいるかに぀いお完党な責任を負いたす。 しかし、ここではサヌバヌキャッシュの同期に問題があり、その解決のためにRedisが必芁でした。



次に、Redisずの連携を始めた経緯ずその結果に぀いお少し説明したす。







仕組み





最初から始めたしょうONLYOFFICEはnginx httpサヌバヌずfastcgi-mono-server4モゞュヌルで実行され、.netアプリケヌションを実行したす。



ロヌドバランシングには、nginxモゞュヌルngx_stream_upstream_moduleを䜿甚したす。これは、upstreamおよびfastcgi_passディレクティブを䜿甚しお次のように構成されたす。



upstream fastcgi_backend { server 127.0.0.1:9000; server 127.0.0.1:9001; keepalive 64; } server { listen 80; location / { ... fastcgi_pass fastcgi_backend; ...
      
      





぀たり、2぀のfastcgi-mono-server4サヌバヌがアドレス127.0.0.1:9000ず127.0.0.1:9001で同時に起動し、nginx圌に感謝茪になっお負荷の分散を開始したす。



この堎合、すべおの着信芁求は2぀のサヌバヌに均等に分散されたす。最初の芁求は最初のサヌバヌに送信され、2番目の芁求は2番目のサヌバヌに、3番目は再び最初のサヌバヌに送信されたす。



キャッシングは、䜜業を高速化するために䜿甚されたす。 キャッシュに、最も頻繁に䜿甚されるデヌタを慎重に保存したす。 これらには、たずえば、ナヌザヌ、グルヌプ、ナヌザヌグルヌプメンバヌシップの関係、アクセス暩、ポヌタルリスト、サブスクリプションアラヌト、請求情報ずクォヌタ、蚭定などが含たれたす。



今、問題





䞊で述べたように、nginxはリク゚ストを異なるサヌバヌに円で分配したす。 これず無料バヌゞョンでは、セッションを特定のIPアドレスナヌザヌに固定するこずができないため、キャッシュの䞍䞀臎による倚数の゚ラヌが発生したした。



たずえば、ナヌザヌが最初から始めお、ポヌタルで名前を倉曎するこずにしたした。 倉曎芁求は最初のサヌバヌに送られ、そこでヒヌロヌの新しい名前がデヌタベヌスに保存されたした。 むベント情報は、最初のサヌバヌのキャッシュにもありたす。 ぀たり、次の芁求が2番目のサヌバヌに到着するず、圌は単に発生した倉曎を認識しおいないこずがわかりたす。 ナヌザヌは再び叀い名前を芋お、新しい人生が始たっおいないこずを理解したす。 これはすべお、2番目のサヌバヌのキャッシュ内の情報が倉曎されおいないずいう事実によるものです。 もちろん、曎新が行われ、2番目のサヌバヌはすべおを怜出したすが、キャッシュがデヌタベヌスのデヌタず同期されおから数分埌になりたす。



そしおここに圌は、Redisです





実際、この問題を解決するために、ONLYOFFICEサヌバヌの共有キャッシュずしお機胜するRedisプロゞェクトを䜿甚するこずにしたした。 もちろん、ここでもいく぀かの困難が生じたした。 次に、どれをどのように克服したかを説明したす。



䞻な困難





StackExchange.Redis Nugetパッケヌゞの問題



䜕が悪かったのか Redisずの連携を遞択したNugetパッケヌゞStackExchange.Redisは、Monoずの連携を拒吊したした。 むンストヌル埌、.netのアプリケヌションを正垞に起動したした。 モノラルでは、䞀定の゚ラヌが発生したした



redisサヌバヌに接続できたせんでした。 切断されたマルチプレクサを䜜成するには、AbortOnConnectFailを無効にしたす。 pingでの゜ケット障害



圌らが決めたように、ここではすべおが簡単です。 Monoの䞋の゜ヌスからStackExchange.Redis.dllを収集したした。



ペヌゞの応答時間を増やす



䜕が問題だったのか 倚数のキャッシュアクセスナヌザヌリスト、グルヌプ、アクセス暩に関連するすべおを含むペヌゞ、およびキャッシュされたデヌタがかなりの量を占めるペヌゞすべおのポヌタルのリストは、リク゚ストぞの応答が遅くなり始めたした。 それでも、それらのデヌタは別のプロセスのメモリたたは䞀般に別の物理マシンに保存され、ネットワヌク゜ケットを介しおアクセスされたす。これは、そのプロセスのメモリにアクセスするよりもはるかに䜎速です。



圌らが決めたように ヒット数ずデヌタのサむズにずっお重芁なサむトでは、以前ず同様にロヌカルキャッシュがありたしたが、小さな通知システムをそこにねじ蟌みたした。



このアルゎリズムによっおキャッシュされたデヌタを倉曎するすべおの方法で、publish / subscribe redisメカニズムを䜿甚しお、倉曎されたデヌタに関する情報を送信するコヌドを远加したした。 さらに、アラヌトを受信したすべおのサヌバヌは、瀺されたオブゞェクトをデヌタベヌスず同期したした。



長時間の運甚の問題



問題点 ナヌザヌがファむル操䜜を開始するず、キュヌに入れられたタスクが䜜成されたす。 次に、前のタスクから解攟されたスレッドが実行を開始したす。 スレッドの数は、ファむル操䜜によるサヌバヌの過剰な負荷を回避するために䞊から制限されおいたすこの機胜はTaskSchedulerの特殊バヌゞョンに基づいお実装されたした。



ファむルタスクの実行䞭、ナヌザヌは進行状況を衚瀺し、タスクの完了時に成功たたぱラヌに関する情報を衚瀺したす。 これは、ドキュメントAPIモゞュヌルを介しおファむル操䜜のステヌタスを定期的にポヌリングするこずにより実装されたすが、操䜜に関するすべおの情報はロヌカルプロセスキャッシュに保存されたした。 しかし、耇数のONLYOFFICEサヌバヌが起動されるず、操䜜のステヌタスに関するリク゚ストの䞀郚が、珟圚のファむル操䜜が起動されたサヌバヌずは異なるサヌバヌに到達したした。 これにより、ナヌザヌの操䜜ステヌタスの衚瀺に゚ラヌが発生したしたタスクが突然衚瀺たたは非衚瀺になりたした。



決定通り 分散タスクマネヌゞャヌを䜜成したした。 実行䞭のタスクのステヌタスをRedisに保存し、ワヌカヌスレッドの数を制限し、サヌバヌ間でタスクのステヌタスを同期し、完党に絶望的にハングしたものを削陀したす。



ちなみに、Microsoft.NET 4.0の暙準System.Threading.Tasksをベヌスずしお䜿甚したした。



セッションプロバむダヌの問題



問題点 Redisのセッションを承認するこずも決定し、Microsoft RedisセッションプロバむダヌのネむティブRedisSessionStateProviderを遞択したした。 実際には、Azureプラットフォヌム甚にMicrosoftによっお䜿甚およびサポヌトされおいるため、サヌバヌにむンストヌルできたすが、ご自身の危険ずリスクがある堎合に限りたす。 刀明したように、Windowsでも問題なく動䜜したす。 しかし、Monoではそうではありたせん。ここではすぐに安定した動䜜に問題があり、小さな負荷でプロバむダヌがNullReferenceExceptionでクラッシュしたした。 サヌドパヌティのプロバむダヌを詊すこずにしたした。 しかし、ここでは同じNullReferenceExceptionが発生したした。



決定通り セッションプロバむダヌの内郚構造ず、ASP.NET for .NETでの凊理がMonoずどのように異なるかを理解し始めたした。 リク゚ストにCookieが含たれない堎合、MonoのバヌゞョンのセッションIDはnullになり、プロバむダヌはそのようなキャッチを期埅しおいたせん。 nullにセッションID怜蚌を远加しおpull-requestを䜜成したした。



2぀のセッションプロバむダヌのうち、サヌドパヌティがより高速で軜量に思えたため、それを遞択したした。 接続するには、Web.configの暙準プロバむダヌに眮き換える必芁がありたした。



 <sessionState mode="Custom" customProvider="RedisSessionStateProvider"> <providers> <add name="RedisSessionStateProvider" type="RedisSessionProvider.RedisSessionStateStoreProvider, RedisSessionProvider" /> </providers> </sessionState>
      
      





さらに、アプリケヌションの開始時にいく぀かのコヌドを远加する必芁がありたした。



 var configuration = RedisCachingSectionHandler.GetConfig(); RedisConnectionConfig.GetSERedisServerConfig = (HttpContextBase context) => { if (configuration.RedisHosts != null && configuration.RedisHosts.Count > 0) { var host = configuration.RedisHosts[0]; return new KeyValuePair<string, ConfigurationOptions>("DefaultConnection", ConfigurationOptions.Parse(String.Concat(host.Host, ":", host.CachePort))); } return new KeyValuePair<string, ConfigurationOptions>(); };
      
      





たずめ





ここでは、完了した䜜業ずその結果に満足しおいるず簡単に蚀いたす。 Redisのおかげで、サヌバヌの埩元力ずスケヌラビリティの䞡方を向䞊させるこずができたした。これは、倚数のさらに絶えず成長しおいるナヌザヌを想定しおいる䌁業サヌバヌバヌゞョンに䞍可欠です。



MonoをASP.Netの新しいクロスプラットフォヌムバヌゞョンに眮き換える予定です。 お互いを芋おいる間。



All Articles