{"id":52113,"date":"2019-11-01T00:00:00","date_gmt":"2019-10-31T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/bioyino-raspredelyonnyj-masshtabiruemyj-agregator-metrik"},"modified":"2020-02-18T13:59:47","modified_gmt":"2020-02-18T10:59:47","slug":"bioyino-raspredelyonnyj-masshtabiruemyj-agregator-metrik","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/bioyino-raspredelyonnyj-masshtabiruemyj-agregator-metrik","title":{"rendered":"Bioyino \u2014 a distributed, scalable metrics aggregator","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>So, you are collecting metrics. Just like us. We are also collecting metrics. Of course, the ones needed for business. Today we will talk about the very first link in our monitoring system \u2014 a statsd-compatible aggregation server. <noindex><a rel=\"nofollow\" href=\"http:\/\/bit.ly\/2Noxg1M\">bioyino<\/a><\/noindex>, why we wrote it and why we moved away from brubeck. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bioyino \u2014 a distributed, scalable metrics aggregator\" src=\"\/wp-content\/uploads\/2019\/11\/312c9a706828acc65f638a6a8abfc5b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>From our previous articles (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/avito\/blog\/335410\/\">1<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/avito\/blog\/343928\/\">2<\/a><\/noindex>) you can learn that for some time we collected tags using <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/github\/brubeck\">brubeck.<\/a><\/noindex>It's written in C. From a coding perspective \u2014 it's as simple as a cork (this is important when you want to contribute) and, most importantly, it handles our volumes of 2 million metrics per second (MPS) at peak without any significant issues. The documentation claims support for 4 million MPS with asterisks. This means you will achieve the stated figure if you configure the network correctly on Linux. (We do not know how many MPS can be obtained if the network is left as is). Despite these advantages, we had several serious complaints about brubeck.<\/p>\n<p><\/p>\n<p><em>Complaint 1.<\/em> Github \u2014 the project's developer \u2014 stopped supporting it: publishing patches and fixes, accepting our and (not just our) PRs. Activity resumed in the last few months (around February-March 2018), but there was almost 2 years of complete silence before that. Additionally, the project is developed <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/github\/brubeck\/pull\/31#issuecomment-325907734\">for Github's internal needs<\/a><\/noindex>, which can become a serious obstacle to implementing new features.<\/p>\n<p><\/p>\n<p><em>Complaint 2.<\/em> Accuracy of calculations. Brubeck aggregates only 65536 values. In our case, for some metrics during the aggregation period (30 seconds), there can be much more values (1,527,392 at peak). As a result of such sampling, the maximum and minimum values appear useless. For example, like this: <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bioyino \u2014 a distributed, scalable metrics aggregator\" src=\"\/wp-content\/uploads\/2019\/11\/4222a1a7d1e127137220595241f5276c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em>How it was<\/em><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bioyino \u2014 a distributed, scalable metrics aggregator\" src=\"\/wp-content\/uploads\/2019\/11\/c8f0025c61f708584328ea30aacf7bc0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em>How it should have been<\/em><\/p>\n<p><\/p>\n<p>For the same reason, sums are calculated incorrectly. Add to this the bug with the overflow of a 32-bit float, which sends the server into a segfault upon receiving what seems to be an innocuous metric, and it gets even better. The bug, by the way, still hasn\u2019t been fixed.<\/p>\n<p><\/p>\n<p>And finally, <em>Complaint X<\/em>At the time of this writing, we are ready to present it to all 14 more or less functional implementations of statsd that we could find. Let's imagine that some particular infrastructure has grown to the point where handling 4 million MPS is no longer sufficient. Or perhaps it hasn't grown yet, but metrics are already important enough for you that even short, 2-3 minute outages on the graphs can become critical and trigger bouts of unbearable depression among managers. Since treating depression is a thankless task, technical solutions are necessary.<\/p>\n<p><\/p>\n<p>Firstly, fault tolerance, so that a sudden issue on the server doesn't cause a psychiatric zombie apocalypse in the office. Secondly, scalability, to be able to handle more than 4 million MPS while not delving into the depths of the Linux networking stack and comfortably growing 'horizontally' to the required sizes.<\/p>\n<p><\/p>\n<p>Since we had headroom in scaling, we decided to start with fault tolerance. 'Oh! Fault tolerance! This is simple, we can do this,' we thought and launched 2 servers, deploying a copy of brubeck on each. To accomplish this, we had to duplicate the traffic with metrics to both servers and even write a little utility for that. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Albibek\/udpdup\">utility<\/a><\/noindex>. We solved the fault tolerance issue with this approach, but\u2026 not very well. At first, everything seemed to be working fine: each brubeck collects its own aggregation variant, writes data to Graphite every 30 seconds, overwriting the old interval (this is done on the Graphite side). If one server fails, we always have the second with its own copy of aggregated data. However, the problem is that if a server fails, a 'sawtooth' pattern appears on the graphs. This is related to the fact that the 30-second intervals on brubeck are not synchronized, and at the moment of failure, one of them does not get overwritten. The same happens when the second server starts. It\u2019s quite bearable, but we want better! The scalability issue hasn\u2019t gone away either. All metrics are still 'flying' to a single server, so we are still constrained by the same 2-4 million MPS depending on the network upgrade.<\/p>\n<p><\/p>\n<p>If you think a little about the problem and simultaneously dig through the snow with a shovel, an obvious idea might come to mind: we need a statsd that can operate in distributed mode. That is, one where synchronization between nodes is implemented based on time and metrics. \"Of course, such a solution must already exist,\" we said and went Googling... and found nothing. After sifting through documentation on various statsd (<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/etsy\/statsd\/wiki#server-implementations\">https:\/\/github.com\/etsy\/statsd\/wiki#server-implementations<\/a><\/noindex> as of 11.12.2017), we found absolutely nothing. Apparently, neither developers nor users of these solutions have faced such an abundance of metrics yet, otherwise they would have certainly come up with something.<\/p>\n<p><\/p>\n<p>And then we remembered the \"toy\" statsd \u2014 bioyino, which we wrote at a hackathon just for fun (the project name was generated by a script before the hackathon started) and realized that we urgently needed our own statsd. Why?<\/p>\n<p><\/p>\n<ul>\n<li>because there are too few clones of statsd in the world,<\/li>\n<li>because we can ensure the desired or close to desired fault tolerance and scalability (including synchronizing aggregated metrics between servers and solving the problem of conflicts during submission),<\/li>\n<li>because we can calculate metrics more accurately than brubeck does,<\/li>\n<li>because we can collect more detailed statistics that brubeck practically did not provide us,<\/li>\n<li>because we were given a chance to program our own hyper-performance distributed scalablapplication that will not completely replicate the architecture of another similar hyperfor... nupone. <\/li>\n<\/ul>\n<p><\/p>\n<p>What to write on? Of course, Rust. Why?<\/p>\n<p><\/p>\n<ul>\n<li>because there was already a prototype solution,<\/li>\n<li>because the author of the article already knew Rust at that time and was eager to write something for production in it with the possibility of releasing it as open-source,<\/li>\n<li>because languages with GC do not suit us due to the nature of the traffic we receive (practically realtime) and GC pauses are practically unacceptable, <\/li>\n<li>because maximum performance is needed, comparable to C<\/li>\n<li>because Rust provides us with fearless concurrency, and starting to write this in C\/C++, we would have encountered even more vulnerabilities, buffer overflows, race conditions, and other scary words than brubeck did.<\/li>\n<\/ul>\n<p><\/p>\n<p>There was also an argument against Rust. The company lacked experience in creating projects using Rust, and we do not plan to use it in our main project either. Therefore, there were serious concerns that it wouldn't work, but we decided to take the risk and give it a try.<\/p>\n<p><\/p>\n<p>Time passed\u2026<\/p>\n<p><\/p>\n<p>Finally, after several unsuccessful attempts, the first working version was ready. What did we get? Here it is.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bioyino \u2014 a distributed, scalable metrics aggregator\" src=\"\/wp-content\/uploads\/2019\/11\/322c4136ed033b80b31a89d7b5f63af8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Each node receives its own set of metrics and stores them locally, without aggregating metrics for those types where the full set is required for final aggregation. The nodes are interconnected by a distributed locking protocol, which allows selecting the one (this is where we cried) that is worthy of sending metrics to the Great One. Currently, this issue is being addressed using <noindex><a rel=\"nofollow\" href=\"https:\/\/www.consul.io\/docs\/guides\/leader-election.html\">Consul<\/a><\/noindex>, but in the future, the author's ambitions extend to <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Albibek\/raft-consensus\">own<\/a><\/noindex> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Albibek\/raft-tokio\">implementations<\/a><\/noindex> Raft, where the worthy one will undoubtedly be the consensus leader node. In addition to consensus, nodes frequently (by default, once per second) send their neighbors the parts of pre-aggregated metrics that they managed to gather during that second. This means that scalability and fault tolerance are preserved \u2014 each of the nodes still holds the complete set of metrics, but the metrics are now sent in an aggregated form, over TCP and encoded in a binary protocol, significantly reducing duplication costs compared to UDP. Despite the considerable number of incoming metrics, accumulation requires very little memory and even less CPU. For our highly compressible metrics, this is just a few dozen megabytes of data. An additional bonus is the absence of unnecessary data rewrites in Graphite, as was the case with burbeck.<\/p>\n<p><\/p>\n<p>UDP packets with metrics are balanced across nodes on the network hardware using a simple Round Robin method. Naturally, the network device does not analyze the contents of the packets and can therefore handle significantly more than 4M packets per second, not to mention the metrics it knows nothing about. Considering that metrics do not arrive one by one in each packet, we do not anticipate performance issues here. In case of a server failure, the network device quickly (within 1-2 seconds) detects this fact and removes the failed server from the rotation. As a result, passive nodes (i.e., those that are not leaders) can be turned on and off with hardly any noticeable dips on the graphs. The most we lose is a portion of the metrics that arrived during the last second. A sudden loss\/off switching of the leader will still show a minor anomaly (the 30-second interval remains out of sync), but if there is communication between the nodes, we can minimize these issues, for example, by sending synchronization packets.<\/p>\n<p><\/p>\n<p>A bit about the internal structure. The application is, of course, multithreaded, but the thread architecture differs from that used in brubeck. Threads in brubeck are uniform \u2014 each one is responsible for both collecting information and aggregation at the same time. In bioyino, worker threads are divided into two groups: those responsible for networking and those responsible for aggregation. This division allows for more flexible application management depending on the type of metrics: where intensive aggregation is required, we can increase the number of aggregators; where there is a lot of network traffic \u2014 increase the number of networking threads. At present, on our servers, we operate with 8 networking and 4 aggregating threads.<\/p>\n<p><\/p>\n<p>The counting (aggregation-relevant) part is quite mundane. Buffers filled by networking threads are distributed among the counting threads, where they are subsequently parsed and aggregated. Upon request, metrics are sent for transmission to other nodes. All this, including data transfer between nodes and interaction with Consul, is done asynchronously and operates on the framework <noindex><a rel=\"nofollow\" href=\"https:\/\/tokio.rs\">tokio<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>The network component responsible for receiving metrics posed far more challenges during development. The main task of isolating network streams into separate entities was to reduce the time the stream spends <em>do not<\/em> reading data from the socket. Options that utilized asynchronous UDP and the standard recvmsg quickly fell through: the former consumes too much user-space CPU for event handling, while the latter involves too many context switches. Therefore, we currently use <noindex><a rel=\"nofollow\" href=\"https:\/\/linux.die.net\/man\/2\/recvmmsg\">recvmmsg<\/a><\/noindex> with large buffers (and buffers, ladies and gentlemen, are no trivial matter!). Support for standard UDP has been retained for less demanding cases where recvmmsg is not necessary. In multimessage mode, the main goal is achieved: the overwhelming majority of the network stream's time is spent clearing the OS queue \u2014 reading data from the socket and relocating it to the userspace buffer, only occasionally switching to deliver the filled buffer to aggregators. The queue in the socket practically does not accumulate, and the number of dropped packets hardly increases. <\/p>\n<p>\n<b class=\"spoiler_title\">Note<\/b><\/p>\n<p>By default, the buffer size is set quite large. If you decide to try the server yourself, you may encounter the issue that after sending a small number of metrics, they will not arrive in Graphite, remaining in the network stream's buffer. For working with a small amount of metrics, you need to set smaller values for bufsize and task-queue-size in the config.<\/p>\n<p><\/p>\n<p>Finally \u2014 a few graphs for the chart enthusiasts.<\/p>\n<p><\/p>\n<p>Statistics on the number of incoming metrics per server: over 2 million MPS.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bioyino \u2014 a distributed, scalable metrics aggregator\" src=\"\/wp-content\/uploads\/2019\/11\/c6cb1a36c267657d55ec22df518f8d03.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Disabling one of the nodes and redistributing incoming metrics.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bioyino \u2014 a distributed, scalable metrics aggregator\" src=\"\/wp-content\/uploads\/2019\/11\/106af265a6bc2a8b31fe34df69e9c200.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Statistics on outgoing metrics: only one node sends \u2014 the raid boss.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bioyino \u2014 a distributed, scalable metrics aggregator\" src=\"\/wp-content\/uploads\/2019\/11\/582730b501a42bb3a371a84bf2e2394b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Statistics on the performance of each node, taking into account errors in various system modules.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bioyino \u2014 a distributed, scalable metrics aggregator\" src=\"\/wp-content\/uploads\/2019\/11\/101377281c3add8c598c6439ca25d271.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Detailing of incoming metrics (metric names are hidden).<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Bioyino \u2014 a distributed, scalable metrics aggregator\" src=\"\/wp-content\/uploads\/2019\/11\/6cf0b61b454b0414799460c482e03242.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>What do we plan to do with all of this next? Of course, write code, blah\u2026! The project was originally intended to be open-source and will remain so for its entire lifespan. Our immediate plans include transitioning to our own version of Raft, switching the peer protocol to a more portable one, adding internal statistics, new types of metrics, fixing bugs, and other improvements. <\/p>\n<p><\/p>\n<p>Of course, we welcome anyone willing to help develop the project: create PRs, Issues, and we will respond and refine as much as possible.<\/p>\n<p><\/p>\n<p>And that, as they say, that's all folks, buy our elephants!<\/p>\n<p>\n<center><div class=\"youtube-placeholder\" data-id=\"siCiIyg4ZZY\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/siCiIyg4ZZY\/hqdefault.jpg\" alt=\"Play video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\n<br \/>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/avito\/blog\/354714\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0418\u0442\u0430\u043a, \u0432\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438. \u041a\u0430\u043a \u0438 \u043c\u044b. \u041c\u044b \u0442\u043e\u0436\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043c\u0435\u0442\u0440\u0438\u043a\u0438. \u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u043c \u043e \u0441\u0430\u043c\u043e\u043c \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u0432\u0435\u043d\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043d\u0430\u0448\u0435\u0433\u043e \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430 \u2014 statsd-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u0438 bioyino, \u0437\u0430\u0447\u0435\u043c \u043c\u044b \u0435\u0433\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u043e\u0442\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u043e\u0442 brubeck. \u0418\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u043d\u0430\u0448\u0438\u0445 \u0441\u0442\u0430\u0442\u0435\u0439 (1, 2) \u043c\u043e\u0436\u043d\u043e \u0443\u0437\u043d\u0430\u0442\u044c, \u0447\u0442\u043e \u0434\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043c\u0435\u0442\u043a\u0438 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u043b\u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-52113","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0418\u0442\u0430\u043a, \u0432\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438. \u041a\u0430\u043a \u0438 \u043c\u044b. \u041c\u044b \u0442\u043e\u0436\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043c\u0435\u0442\u0440\u0438\u043a\u0438. \u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/bioyino-raspredelyonnyj-masshtabiruemyj-agregator-metrik\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47Bioyino \u2014 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043e\u0440 \u043c\u0435\u0442\u0440\u0438\u043a | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0418\u0442\u0430\u043a, \u0432\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438. \u041a\u0430\u043a \u0438 \u043c\u044b. \u041c\u044b \u0442\u043e\u0436\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043c\u0435\u0442\u0440\u0438\u043a\u0438. \u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/bioyino-raspredelyonnyj-masshtabiruemyj-agregator-metrik\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T10:59:47+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Bioyino \u2014 a distributed, scalable metrics aggregator | ProHoster","description":"So, you\u2019re collecting metrics. Just like us. We are also collecting metrics. Naturally, they are essential for business.","canonical_url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/bioyino-raspredelyonnyj-masshtabiruemyj-agregator-metrik","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47Bioyino \u2014 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043e\u0440 \u043c\u0435\u0442\u0440\u0438\u043a | ProHoster","og:description":"\u0418\u0442\u0430\u043a, \u0432\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438. \u041a\u0430\u043a \u0438 \u043c\u044b. \u041c\u044b \u0442\u043e\u0436\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043c\u0435\u0442\u0440\u0438\u043a\u0438. \u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430.","og:url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/bioyino-raspredelyonnyj-masshtabiruemyj-agregator-metrik","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T21:00:00+00:00","article:modified_time":"2020-02-18T10:59:47+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52113","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 02:30:22","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:49:49","updated":"2026-01-24 02:30:22","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/52113","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=52113"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/52113\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=52113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=52113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=52113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}