Auto Scaling の仕組みを改善する前にまずは API 側のコードを修正することで対応を行いました。
こういう細かい処理のロジックを見直すことで最適化、高速化することももちろん効果的ですが、ピーキーなアクセスで最も効果的なのは短期キャッシュです。
キャッシュは適切に使わないと思わぬトラブルを生むことが多く、出来れば使用は避けたいものです。
しかし短期キャッシュであれば情報の更新頻度次第ではあまり問題にならない場合があります。
そして今回のケースにおいてはライブ配信の時間は事前に決定し変更はされない、レシピ情報も事前に確定することがほとんです。
その為、短期キャッシュを入れる事でキャッシュのデメリット無くアプリケーションのスループットを上げることが出来ると判断しました。
想定外のユーザ数が来た時に一番問題になったのは cookpadTV の更に先にある別の Micro Service(サービス B) への API リクエストでした。
サービス B は Auto Scaling 設定が入っておらず、大量にアクセスが流れてレスポンスタイムが悪化、cookpadTV API の unicorn worker が詰まって Nginx がエラーを返し始めるという状況でした。
ここの部分の API コールを短期キャッシュすることでスループットを大幅に上げることが出来ました。
同時アクセスが大量に来るのは push 通知によっても発生することがあります。その為、今後は remote push 通知を送信する前に送信件数をベースに Auto Scaling する仕組みを導入していく想定です。
補足
Micro Services でサービスを開発していると、他チームの Service に依存して、自分達の Service だけ Auto Scaling してもサービス全体としては成り立たないことがあります。
その為その境界線を意識し、自分達の開発しているサービス内でカバーできるような設計にしていく必要があります。
キャッシュやリトライ戦略は各 Service が個別に開発するというよりはサービスメッシュ*2によって統合管理が達成出来るのではと考えています。
最後に
イベント型サービス向けの Auto Scaling が必要になってから、突貫で作った形ではありますがクックパッドの既存の基盤のおかげでなんとか運用が回る Auto Scaling 環境が出来ました。
この辺りの基盤がしっかりしている事は今回非常に助かりました。
$ slips -c config.yml deploy
2018-04-13 14:40:07.379 INFO [cli.py:466] Bulding stack: log-counter
2018-04-13 14:40:07.379 INFO [cli.py:154] no package file is given, building
2018-04-13 14:40:07.736 INFO [cli.py:470] package file: /var/folders/3_/nv_wpjw173vgvd3ct4vzjp2r0000gp/T/tmpem2eyhgf.zip
2018-04-13 14:40:07.736 INFO [cli.py:474] no SAM template file is given, building
2018-04-13 14:40:07.763 INFO [cli.py:481] SAM template file: /var/folders/3_/nv_wpjw173vgvd3ct4vzjp2r0000gp/T/tmp1bahl7dn.yml
2018-04-13 14:40:07.763 INFO [cli.py:418] package command: aws cloudformation package --template-file /var/folders/3_/nv_wpjw173vgvd3ct4vzjp2r0000gp/T/tmp1bahl7dn.yml --s3-bucket home-network.mgmt --output-template-file /var/folders/3_/nv_wpjw173vgvd3ct4vzjp2r0000gp/T/tmpa1r9z4e7.yml
2018-04-13 14:40:08.652 INFO [cli.py:431] generated SAM file: /var/folders/3_/nv_wpjw173vgvd3ct4vzjp2r0000gp/T/tmpa1r9z4e7.yml
2018-04-13 14:42:11.138 INFO [cli.py:461] Completed (Applied)
2018-04-13 14:42:11.138 INFO [cli.py:559] exit
クックパッドでは、毎年恒例になっているサマーインターンシップを今年も開催いたします!今年のインターンシップは、サービス開発エンジニア向けに 10 Day Tech インターンシップ、リサーチエンジニア向けに 5 Day R&D インターンシップ、デザイナー向けに 5 Day Design インターンシップを行なうというかたちになっています。
10 Day Tech インターンシップでは、モバイルアプリケーションからサーバーサイド、インフラストラクチャーまで、フルスタックエンジニアとして必要な技術をぎゅっと前半の講義・課題パートに詰め込んでいます。後半では、クックパッドの現場に配属されて研修を行なうOJTコースと、前半で学んだ内容をチームで実践するPBLコースに分かれてインターンシップを行ないます。
5 Day R&D インターンシップは、機械学習や自然言語処理を専攻とする修士課程・博士課程の方を対象に実施します。クックパッドの膨大なデータという大学の研究では経験することが難しい生のデータに触れることのできる、貴重な機会です。
また、5 Day Designは、参加者同士でチームを組み、料理に関する課題を解決するサービスを発想し形にします。メンターからサポートを受けながら、ユーザーが抱える課題をインタビューを通して理解し、その解決策のデザイン・プロトタイピングを行ないます。実践と平行して、クックパッドが持つサービスデザイン手法やノウハウを講義形式で学びます。
# Sync certificates and Provisioning Profiles via git repository
match(
app_identifier: ["com.cookpad.awesome-app-for-inhouse", "com.cookpad.awesome-app-for-inhouse.NotificationService"],
git_branch: 'enterprise',
team_id: enterprise_team_id,
type: 'enterprise',
readonly: true,
)
# Build iOS app with the profiles
build_ios_app
運用してみての問題点
一見便利なmatchですが、今回大規模に運用してみて、下記のような問題に直面しました。
1ライセンス当たり同時に1つの証明書しか扱えない問題
matchの一番の問題点は、同時に管理できる証明書が1つに制限されてしまうという問題です。
Apple Developer Centerでは、1ライセンス当たり同時に2つの証明書を作成することができますが、matchでは、新しく証明書を作成したい場合は、match nukeと呼ばれる機能を使い、既存の証明書と、それを利用しているProvisioning Profileを全てrevokeする必要があります。
この仕組みでは画像へのリクエストに応じてその場で画像変換を行うので、サービスの運営において様々なバリエーションの画像が必要な場合であってもそれらを予め用意しておく必要がなく、画像を変換する為のサーバも必要としません。S3 に画像ファイルさえ置けばよいのでサーバサイドのアプリケーションの種類や言語を問わず、たとえ静的な WEB サイトであったとしても様々なバリエーションの画像を提供することができます。
16:40-17:20 桑原仁雄(@pocke):A parser based syntax highlighter @pockeが作成したIroというgemについてお話します。このgemは、Rubyのシンタックスハイライターです。今回はその特徴と実装についてを紹介します。
17:30-18:30 ライトニングトーク
Sangyong Sim(@riseshia):Find out potential dead codes from diff
Rubyで静的に未使用コードを探す時に間違って検出してしまうのを減らす方法について紹介します。
2日目 6月1日(金)
10:50-11:30 Kirk Haines(@wyhaines):It's Rubies All The Way Down 通常、Webアプリケーションスタックでは、アプリケーションそのものの処理にRubyを使用し、それ以外のレイヤーはRuby以外の言語で書かれているものをつかいます。発表では、その他のレイヤーについても、Rubyにしてみたらどうなるかを見ていきます。
15:20-15:50 午後休憩: Cookpad live coding by @hokaccha @hokacchaがクックパッドのサイトを変更・デプロイする様子をブースでライブコーディングします。
2日目 6月1日(金)
12:00-13:00 ランチ休憩:Q&A タイム by @pockeこの時間は、クックパッドブースに@pockeがおりますので、1日目 5月31日(木)16:40-17:20 A parser based syntax highlighter に関するご質問がある方は、ぜひこの時間にブースにて、本人に聞いてみてください。
15:20-15:50 Global Office Hoursクックパッドは、海外事業の全てを統括する第二本社をイギリス・ブリストルに開設しサービス展開を進め、展開国数は現在68カ国となりました。本時間には海外勤務経験のある社員がブースにおります。海外で働くことに興味がある方は、ぜひお気軽に話しを聞いてみてください!
3日目 6月2日(土)
12:00-13:00 ランチ休憩:Q&A タイム by@wyhainesこの時間は、クックパッドブースに@wyhainesがおりますので、2日目 6月1日(金)10:50-11:30 It's Rubies All The Way Down に関するご質問がある方は、ぜひこの時間にブースにて、本人に聞いてみてください。
15:20-15:50 午後休憩:Ruby interpreter development live @ko1と @mameによるRuby インタプリタのライブコーディングです。登壇時の発表内容に関してご質問がある方も、この時間にお声がけください。
Drink Up
Cookpad X RubyKaigi 2018: Day 2 Party
Cookpad international HQ team is hosting a party in the evening on Day 2 of RubyKaigi 2018. Come along to network, meet other Rubyists and perhaps a Ruby committer or special guest or two. How exciting!
もともと Railsは Web 画面から DB 構造までをあえて密に結合させることで、簡単なサービスを高速に開発するフレームワークとしてデビューしました。と同時に、 Web アプリケーションフレームワークとしての使い勝手の良さや時流も手伝って、そう単純でないサービスを作るのにも使われるようになりました。
G SuiteではReports APIが用意されており、これを使ってAdmin activity, Google Drive activity, Login activity, Mobile activity, Authorization Token activityを取得することができます。これらAPIにLambdaで定期的にアクセスし、ログデータとしてS3に保存しています。
Azure AD
Azure Active Directory (AD) は Single Sign On のサービスとして利用しており様々な外部サービスを利用する際の認証のハブになっています。こちらも何か問題があった場合にどの端末からどのサービスへのアクセスがあったかを辿ることができます。
例えば、GuardDutyから「あるユーザが普段と異なるネットワークからAPIを操作している」というアラートが発報されたとします。その時、Graylog で該当ユーザ名とその前後の時間帯を検索すると例として G Suite でサービスにログインしたログ、そのユーザ名についてメールでやりとりされたログ、AWSで他のAPIを発行したログを一気通貫で見ることができます。これによって、そのユーザがその時間帯にどのような活動をどのネットワークからしていたのかがワンストップで確認できるようになり、それが正規のユーザの活動だったのか、それとも外部の悪意あるユーザがなりすましていたのかを容易に判断できるようになります。
defprofile_app_load_timeBenchmark.measure do
system("./bin/rails r '1;'") orraise"error"endend# Warming disk cache, ...
puts profile_app_load_time
3.times do
result = profile_app_load_time
puts result
influx.write_point("cookpad_ci_app_load_time", tags: { app: app }, values: { load_time: result.real })
end
This ariticle is a translation of the original article which was published at the beginning of May. To make up for the backgroud of this article, Cookpad is mid-size technology company having 200+ product developes, 10+ teams, 90 million monthly average users. https://info.cookpad.com/en
Hello, this is Taiki from developer productivity team. For this time, I would like to introduce about the knowledge obtained by building and using a service mesh at Cookpad.
For the service mesh itself, I think that you will have full experience with the following articles, announcements and tutorials:
We introduced a service mesh mainly to solve operational problems such as troubleshooting, capacity planning, and keeping system reliability. In particular:
As for the first one, there was a problem that it became difficult to grasp as to which service and which service was communicating, where the failure of a certain service propagated, as the scale expanded. I think that this problem should be solved by centrally managing information on where and where they are connected.
For the second one, we further digged the first one, which was a problem that we do not know the status of communication between one service and another service easily. For example, RPS, response time, number of success / failure status, timeout, status of circuit breaker, etc. In the case where two or more services refer to a certain backend service, resolution of metrics from the proxy or load balancer of the backend service was insufficient because they were not tagged by request origin services.
For the third one, it was an issue that "fault isolation configuration has not been successfully set". At that time, using the library in each application, setting of timeout, retry, circuit breaker were done. But to know what kind of setting, it is necessary to see application code separately. There is no listing and situation grasp and it was difficult to improve those settings continuously. Also, because the settings related to Fault Isolation should be improved continuously, it was better to be testable, and we wanted such a platform.
In order to solve more advanced problems, we also construct functions such as gRPC infrastructure construction, delegation of processing around distribution tracing, diversification of deployment method by traffic control, authentication authorization gateway, etc. in scope. This area will be discussed later.
Current status
The service mesh in the Cookpad uses Envoy as the data-plane and created our own control-plane. Although we initially considered installing Istio which is already implemented as a service mesh, nearly all applications in the Cookpad are operating on a container management service called AWS ECS, so the merit of cooperation with Kubernetes is limited. In consideration of what we wanted to realize and the complexity of Istio's software itself, we chose the path of our own control-plane which can be started small.
The control-plane part of the service mesh implemented this time consists of several components. I will explain the roles and action flow of each component:
A repository that centrally manages the configuration of the service mesh.
Place the generated response JSON on Amazon S3 and use it as an xDS API from Envoy
The reason why the setting is managed in the central repository is that,
we'd like to keep track of change history with reason and keep track of it later
we would like to be able to review changes in settings across organizations such as SRE team
Regarding load balancing, initally, I designed it by Internal ELB, but the infrastructure for gRPC application went also in the the requirement *3, we've prepared client-side load balancing by using SDS (Service Discovery Service) API *4. We are deploying a side-car container in the ECS task that performs health check for app container and registers connection destination information in SDS API.
Image may be NSFW. Clik here to view.
The configuration around the metrics is as follows:
Store all metrics to Prometheus
Send tagged metrics to statsd_exporter running on the ECS container host instance using dog_statsd sink*5
All metrics include application id via fixed-string tags to identify each node*6
In case the application process runs directly on the EC2 instance without using ECS or Docker, the Envoy process is running as a daemon directly in the instance, but the architecture is almost the same. There is a reason for not setting pull directly from Prometheus to Envoy, because we still can not extract histogram metrics from Envoy's Prometheus compatible endpoint*7. As this will be improved in the future, we plan to eliminate stasd_exporter at that time.
Image may be NSFW. Clik here to view.
On Grafana, dashboards and Envoy's entire dashboard are prepared for each service, such as upstream RPS and timeout occurrence. We will also prepare a dashboard of the service x service dimension.
Per service dashboard:
Image may be NSFW. Clik here to view.
For example, circuit breaker related metrics when the upstream is down:
Image may be NSFW. Clik here to view.
Dashboard for envoys:
Image may be NSFW. Clik here to view.
The service configuration is visualized using Vizceral developed by Netflix. For implementation, we developed fork of promviz and promviz-front*8. As we are introducing it only for some services yet, the number of nodes currently displayed is small, but we provide the following dashboards.
Service configuration diagram for each region, RPS, error rate:
Image may be NSFW. Clik here to view.
Downstream / upstream of a specific service:
Image may be NSFW. Clik here to view.
As a subsystem of the service mesh, we deploy a gateway for accessing the gRPC server application in the staging environment from the developer machine in our offices*9. It is constructed by combining SDS API and Envoy with software that manages internal application called hako-console.
Gateway app (Envoy) sends xDS API request to gateway controller
The Gateway controller obtains the list of gRPC applications in the staging environment from hako-console and returns the Route Discovery Service / Cluster Discovery Service API response based on it
The Gateway app gets the actual connection destination from the SDS API based on the response
From the hand of the developer, the AWS ELB Network Load Balancer is referred to and the gateway app performs routing
Image may be NSFW. Clik here to view.
Results
The most remarkable in the introduction of service mesh was that it was able to suppress the influence of temporary disability. There are multiple cooperation parts between services with many traffic, and up to now, 200+ network-related trivial errors*10 have been constantly occurring in an hour*11, it decreased to about whether it could come out in one week or not with the proper retry setting by the service mesh.
Various metrics have come to be seen from the viewpoint of monitoring, but since we are introducing it only for some services and we have not reached full-scale utilization due to the introduction day, we expect to use it in the future. In terms of management, it became very easy to understand our system when the connection between services became visible, so we would like to prevent overlooking and missing consideration by introducing it to all services.
Future plan
Migrate to v2 API, transition to Istio
The xDS API has been using v1 because of its initial design situation and the requirement to use S3 as a delivery back end, but since the v1 API is deprecated, we plan to move this to v2. At the same time we are considering moving control-plane to Istio. Also, if we are going to make our own control-plane, we plane to build LDS/RDS/CDS/EDS API*12 using go-control-plane.
Replacing Reverse proxy
Up to now, Cookpad uses NGINX as reverse proxy, but considering replacing reverse proxy and edge proxy from NGINX to Envoy considering the difference in knowledge of internal implementation, gRPC correspondence, and acquisition metrics.
Traffic Control
As we move to client-side load balancing and replace reverse proxy, we will be able to freely change traffic by operating Envoy, so we will be able to realize canary deployment, traffic shifting and request shadowing.
Fault injection
It is a mechanism that deliberately injects delays and failures in a properly managed environment and tests whether the actual service group works properly. Envoy has various functions *13.
Perform distributed tracing on the data-plane layer
In Cookpad, AWS X-Ray is used as a distributed tracing system*14. Currently we implement the distributed tracing function as a library, but we are planning to move this to data-plane and realize it at the service mesh layer.
Authentication Authorization Gateway
This is to authenticate and authorize processing only at the front-most server receiving user's request, and the subsequent servers will use the results around. Previously, it was incompletely implemented as a library, but by shifting to data-plane, we can recieve the advantages of out of process model.
Wrapping up
We have introduced the current state and future plan of service mesh in Cookpad. Many functions can be easily realized already, and as more things can be done by the layer of service mesh in the future, it is highly recommended for every microservices system.
*3:Our gRPC applications already use this mechanism in a production environment
*4:Server-side load balancing which simply use Internal ELB (NLB or TCP mode CLB) has disadvantages in terms of performance due to unbalanced balancing and also it is not enough in terms of metrics that can be obtained
クックパッドでは、テックリードや新卒、インターン、バイトといった肩書きに関係なく、誰もがレビュワー・レビュイーになります。
チームやプロダクトによって開発ルールは少しずつ異なりますが、私の所属する会員事業部では、PR を出したときに GHE やチャットで部内のエンジニアにメンションして、その時にレビューできる人がレビューするという形を取っています。