{"id":51659,"date":"2022-06-23T09:41:18","date_gmt":"2022-06-23T01:41:18","guid":{"rendered":"https:\/\/version-2.com\/?p=51659"},"modified":"2022-07-08T17:37:02","modified_gmt":"2022-07-08T09:37:02","slug":"surely-nobody-would-write-a-web-service-in-c","status":"publish","type":"post","link":"https:\/\/version-2.com\/zh\/2022\/06\/surely-nobody-would-write-a-web-service-in-c\/","title":{"rendered":"Surely nobody would write a web service in C++"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"51659\" class=\"elementor elementor-51659\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-35fe5dd post-content elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"35fe5dd\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;jet_parallax_layout_list&quot;:[{&quot;jet_parallax_layout_image&quot;:{&quot;url&quot;:&quot;&quot;,&quot;id&quot;:&quot;&quot;,&quot;size&quot;:&quot;&quot;},&quot;_id&quot;:&quot;cef08c3&quot;,&quot;jet_parallax_layout_image_tablet&quot;:{&quot;url&quot;:&quot;&quot;,&quot;id&quot;:&quot;&quot;,&quot;size&quot;:&quot;&quot;},&quot;jet_parallax_layout_image_mobile&quot;:{&quot;url&quot;:&quot;&quot;,&quot;id&quot;:&quot;&quot;,&quot;size&quot;:&quot;&quot;},&quot;jet_parallax_layout_speed&quot;:{&quot;unit&quot;:&quot;%&quot;,&quot;size&quot;:50,&quot;sizes&quot;:[]},&quot;jet_parallax_layout_type&quot;:&quot;scroll&quot;,&quot;jet_parallax_layout_direction&quot;:&quot;1&quot;,&quot;jet_parallax_layout_fx_direction&quot;:null,&quot;jet_parallax_layout_z_index&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_x&quot;:50,&quot;jet_parallax_layout_bg_x_tablet&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_x_mobile&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_y&quot;:50,&quot;jet_parallax_layout_bg_y_tablet&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_y_mobile&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_size&quot;:&quot;auto&quot;,&quot;jet_parallax_layout_bg_size_tablet&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_size_mobile&quot;:&quot;&quot;,&quot;jet_parallax_layout_animation_prop&quot;:&quot;transform&quot;,&quot;jet_parallax_layout_on&quot;:[&quot;desktop&quot;,&quot;tablet&quot;]}]}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-409a2e9a\" data-id=\"409a2e9a\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-5a8be8f elementor-widget elementor-widget-text-editor\" data-id=\"5a8be8f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p align=\"center\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/images.prismic.io\/keepit\/0f95be5e-6033-4099-b070-6ecef643d2f5_why-c%2B%2B-web-service+.png?w=958&amp;ssl=1\" alt=\"\" height=\"757\" width=\"757\"><\/p>\n\n<p>A while back, one of my colleagues was hanging out in an online developer forum and some people there were starting up a good old-fashioned language war (the type of exchange where one person familiar with language A will announce its superiority over language B, with which the other person isn\u2019t familiar \u2013 not really a productive use of time when you think about it, but a popular pastime nonetheless).<\/p>\n<p>During this debate, one developer confidently proclaims that \u2018surely nobody would ever write a web service in C++,\u2019 to which my colleague responds, \u2018well that\u2019s exactly what we did here at Keepit.\u2019 This prompted some questions, and this piece is an attempt to explain why we did what we did and to explain how this choice has been working out for us, given that this code base started life about 10 years ago. <\/p>\n<p>To put things into perspective, it will be necessary to start with some minimal background information about this service we set out to build.<\/p>\n<h4>What is Keepit?<\/h4>\n<p>Keepit is a backup service in the cloud. We will store backup copies of your (cloud) data so that if\u2014or when\u2014your primary data is compromised for one reason or another (but most likely because of ransomware or account takeover via phishing), then you will still have complete daily copies of your data going back as many years as you want. <\/p>\n<p>Years of data. This should make you think. <\/p>\n<p>Several years ago, <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/office365itpros.com\/2022\/04\/28\/office-365-number-of-users\/\">Microsoft claimed having 350 million seats<\/a> on their 365 platform, which is one of the cloud platforms that we protect. Let\u2019s say we get just 10% of that market (we should get much more because we are by far the best solution out there, but let\u2019s be conservative for the sake of argument), that means we need to store all data for 35 million people (and that\u2019s just on one of these platforms \u2013 we protect several other platforms as well). <\/p><p> <\/p><p>It doesn\u2019t end there: being backup, we copy all your changes, and we hold your old data, and that means when you clean up your primary storage and delete old documents, we keep the copy. Many customers want a year or three of retention, but we have customers who pay for 100 years of retention. <\/p>\n<p>One hundred years. That means our great grandchildren will be fixing the bugs we put in our code today. This should make you think too. <\/p>\n<p>Knowing the very high-level goals of our service, let\u2019s talk about requirements for such a thing. <\/p>\n<h4>Core system: storage<\/h4>\n<p>We knew from the get-go that we would be implementing a storage solution which would need to store a very large amount of data (as everything is moving to the cloud, let\u2019s say a few percent of all the world\u2019s data) for a very long period of time (say a hundred years). <\/p>\n<p>Now everyone in the storage business will talk about SSDs, NVMe, and other high-performance data storage technologies. None of this is relevant for large scale, affordable storage, however. Spinning disks is the name of the game and probably will be for at least another decade. <\/p><p> <\/p><p>SSDs are getting the density, sure, but they are still not close to viable from a cost perspective. This means we will be writing all data to rotating magnetic media. When you write data to magnetic media, over the years, your media will demagnetize. That means, if we store a backup on a hard drive today, we probably can\u2019t read it back just ten years from now. <\/p><p> <\/p><p>That means we need to regularly move all this data from system to system to keep the data \u2018fresh.\u2019 Talking about performance, large capacity hard drives today rotate at 7200rpm, exactly the same speed as back in 1992. Access time is dominated by the rotational latency, which means that this is really an aspect of computers that has been almost at a standstill for 30 years while everything else has become faster in every way. We knew we had to deal with this. <\/p>\n<p>I should probably note here that yes, we are talking about running our software on actual physical computers \u2013 no public cloud for us. If you want to go big, don\u2019t do what the big players say you should do, do what the big players do. If public cloud was so great, Microsoft wouldn\u2019t have built their own to run 365 \u2013 they would have run it on AWS which was very well established long before Microsoft thought about building 365. This doesn\u2019t mean you can\u2019t prototype on public cloud of course. <\/p>\n<p>To solve our core storage need, we designed a filesystem\u2014basically, an object storage system optimized for storing very large-scale backup data. Clearly, we expect the implementation of this storage system to have a significant lifespan.  <\/p><p> <\/p><p>We may want to create a better implementation one day in the future when hardware has evolved far beyond what we can imagine today, but it is worth pointing out that the storage systems we use today are very similar in architecture to what they would look like 30 years ago, and I would assume in 30 years from today. Clearly, the core code that manages all of your data is not something you want to re-write every few weeks. <\/p><p> <\/p><p>So, to implement this system, we went out looking for which new experimental languages had been invented in the six months leading up to implementation start. No wait, we didn\u2019t. <\/p>\n<h4>What we need from a language<\/h4>\n<p>There are really two types of languages: <\/p>\n<p>1: Systems programming languages \u2013 those that have practically no runtime, where you can look at the code and have a high degree of confidence in understanding exactly what that leads to on your processor, the type of language you would write an operating system kernel in. This would be languages like C, C++, and who knows \u2013 maybe Rust or something else. <\/p>\n<p>2: The higher-level languages, which often have significant runtimes. The good ones of these offer benefits that you cannot get in a language without a significant runtime. This would be a language like Common Lisp, but people more commonly talk about C# and Java even though I will argue they only do so because nobody taught them Lisp.  <\/p>\n<p>And then you have the other languages that fit various niche use cases. This could be Python, Haskell, JavaScript, and so forth. I don\u2019t mean to talk them down, but they are not reasonable languages for software development of the type we are talking about here; and since what we\u2019re talking about here isn\u2019t actually so special, you could take my argument to mean that they are just not very reasonable languages for software development outside of niche uses, and that would be a fair interpretation of my opinion. <\/p>\n<p>So, to be a little more concrete, what it is that we really need from a language is: <\/p>\n<p>1: It must support the efficient implementation of algorithms and data structures; meaning we must have tight control over memory when we need it, our language must support the actual hardware data types like 64-bit integers on modern processors, etc.  So, this rules out Python (not compiled), Ruby (not compiled) and JavaScript (JIT but doesn\u2019t have integers or arrays). <\/p>\n<p>2: When we write code today, the tool chain in 20 years\u2019 time must still support our code with little or no changes. Because we simply can\u2019t rewrite our code every few years. We will get nowhere if that\u2019s what we do. That\u2019s why large, important software systems today are still often written in C \u2013 because they started out life in the 80s or 90s and they are still the most significant operating system kernels or database management systems that exist to this day. <\/p><p> <\/p><p>Steady evolution is the recipe, not rewrite from scratch every three years. This basically rules out any language that hasn\u2019t been standardized and widely used for at least 10 years before we start the project. Meaning, since we started in 2012, that rules out any language that came out after 2002, so Go, Rust, and many other languages would have been out of the picture. C and C++ would work though. <\/p>\n<p>3: We run on Linux. If you do anything significant with computers on a network, you probably run on Linux, too. We don\u2019t want a language that is \u2018ported\u2019 to Linux as a curiosity \u2013 like C#. We need a language that is native on Linux with a significant and mature toolchain that is certain to receive significant investment for decades to come. Again, that\u2019s really C and C++. <\/p>\n<p>4: You need to design for failure. Everything from writing to a disk, to allocating the smallest piece of memory, can and will eventually fail. Relying on the developer to check error codes or return values at every single call to a nontrivial function (and too many trivial functions too) is rough. Yes, it can be done and there are impressive examples of this. <\/p>\n<p>I am humbled by software such as the Postgres database or the Linux kernel which are very reliable pieces of software written in C which require such tedious checking. C++, in my experience, with RAII and exceptions, offers a much safer alternative. It is not free, of course \u2013 it avoids one set of problems and introduces another. In my experience however, it is less difficult to write reliable software using RAII and exceptions than to rely on developers not missing a single potential error return and correct recovery and cleanup. For this reason, I will prefer C++ over C and over both Rust and Go.  <\/p>\n<p>5: Obviously the language must offer sufficiently powerful functionality to make the implementation of a larger application bearable and maybe even enjoyable. In reality, however, if your language has functions, you can accomplish a lot; Fortran got functions in 1958 and since then most languages have had them. <\/p>\n<p>Yes, generic programming is nice in C++. A real programmable language like Common Lisp would be preferable of course. Any other modern programming language will surely have some other feature which was added because it is potentially nice and potentially justifies the existence of the language. <\/p>\n<p>But in reality, the hard part is getting your data structures right. Getting your algorithms right. Knowing what you\u2019re trying to build and then building exactly that, nothing more and nothing less. <\/p>\n<p>If we are honest, most languages would work. However, C++ is a nice compromise: it has some generic programming, the STL is incredibly useful, it offers basic OO concepts, and RAII (and structured error handling). <\/p>\n<p>If we look at the criteria here, there really aren\u2019t that many candidate languages to choose from, even if we compromise a bit here and there. Therefore, the question really isn\u2019t \u2018why\u2019 we would write a web service in C++, the question really is \u2018why wouldn\u2019t we\u2019 write a web service in C++. Realistically, what else would you use, given the scope of what we\u2019re solving here? <\/p>\n<h4> Versatility<\/h4>\n<p>Performance matters. Don\u2019t let anyone tell you otherwise. Anyone who says that \u2018memory is cheap\u2019 and uses that as an excuse should not be building your large-scale storage systems (or application servers or anything else that does interesting work on large amounts of data). <\/p>\n<p>Donald Knuth said, \u2018Premature optimization is the root of all evil\u2019 and I absolutely believe that. However, \u2018no optimization and elastic scaling is the root of all public cloud revenue\u2019 is probably also true. Don\u2019t go to extremes \u2013 don\u2019t put yourself in a situation where you cannot, at the appropriate time, optimize your solution to be frugal with its resource use. When your solution is \u2018elastically scaling\u2019 for you in some public cloud on a credit card subscription, it is very hard to go back and fix your unit economics. Chances are you never will. <\/p>\n<p>The typical computer configuration for a storage server in Keepit is 168 18 TB hard drives attached to a single-socket 32-core 3.4GHz 64-bit processor and 1TiB of RAM. It\u2019s really important to note here that we use only one TiB of RAM for three PiB of raw disk: this is a 3000:1 ratio \u2013 it is not uncommon to see general purpose storage systems recommend a 30:1 ratio of disk to RAM (which would require us to run with 100TiB of RAM at which point memory most certainly isn\u2019t cheap anymore). Through the magic of our storage software, this gives us about 2PiB of customer-usable storage in only 11U of rack space. This means we can provide a total of 8PiB of usable storage in a single 44U rack of systems, consuming less than 10kW of power. This matters. <\/p>\n<p>If you run a business, you want to be able to make a profit. Your customers will want you to make a profit, especially if they bet on you having their data 100 years from now. If you want to grow your business with investments, your investors will think this matters. In Keepit, we have amazing unit economics \u2013 we got the largest series A round of investment for an IT company in the history of Denmark ever \u2013 and part of the reason for that was because of our unit economics. Basically, our storage technology, not least the implementation of it, enabled this. <\/p>\n<p>The choice of C++ has allowed us to implement a CPU- and memory-efficient storage system reliably that uses the available hardware resources to their fullest extent. This ranges from careful layout of data structures in memory to an efficient HTTP stack that exposes the functionality and moves more than a GiB of data per second per server over a friendly RESTful HTTP API on the network. C++ enables and supports every layer of this software, and that is quite a feat. <\/p>\n<p>Let me briefly digress with another note on versatility. I have this personal hobby project where I am developing a lab power supply for my basement lab (because every basement needs a lab). In order to adjust current and voltage limits, I want to use rotary encoders rather than potentiometers. <\/p>\n<p>A rotary encoder is basically an axle that activates two small switches in a specific sequence and by looking at the sequence you can detect if the user is turning the axle in one direction or the other. The encoder signal gets fed to a 1MHz 8-bit processor with 1 kB of RAM and 8 kB of flash for my code.  <\/p>\n<p>To implement the code that detects the turning of these encoders, it makes sense to use a textbook, object-oriented approach. Create a class for an encoder. Define a couple of methods for reading the switches and for reading out the final turn data. Declare a bit of local state. Beautifully encapsulated in pure OO style. The main logic can then instantiate the two encoders and call the methods on these objects. I am implementing the software for this project in C++ as well \u2013 try to think about that for a moment: The same language that allows us to efficiently and fully utilize a 32-core 3.4GHz 64-bit processor with 1TiB of RAM and 3PiB of raw disk works \u2018just as well\u2019 on a 1-core 1MHz 8-bit processor with 1kiB of RAM and 8kiB of flash storage \u2013 and the code looks basically the same.<\/p>\n<p>There are not many languages that can stretch this wide and not show the slightest sign of being close to its limit. This is truly something to behold.<\/p>\n<h4> The rest of the stack<\/h4>\n<p>The storage service exposes a simple RESTful API over HTTP using an HTTP stack we implemented from scratch in C++. Instantiating a web server in C++ is a single line of code \u2013 processing requests is as trivial as one could wish for. <\/p>\n<p>I\u2019ve heard plenty of arguments that doing HTTP or XML or other \u2018web\u2019 technology work would be simpler in Java or C# or other newer languages, but really, if you write your code well, why would this be difficult? Why would you spend more than a line of code to instantiate a web server?  Why would parsing an XML document be difficult?  <\/p>\n<p>For XML, we implemented a validating parser using C++ metaprogramming; I have to be honest and say this was not fun all the way through and I couldn\u2019t sit down and write another today without reading up on this significantly first. C++ metaprogramming is nothing like a proper macro system \u2013 but it can absolutely solve a lot of problems, including giving us an RNC-like schema syntax for declaring a validating XML parser and generating efficient code for exactly that parser. <\/p>\n<p>This also means when we parse an XML document and we declare that one of the elements is an integer, then either it parses an integer successfully or it throws. If we declare a string, we get the string properly decoded so that we always work on the native data \u2013 we cannot ever forget to validate a value and we cannot ever forget to escape or un-escape data. By creating a proper XML parser using the language well, we have not only made our life simpler, we have also made it safer. <\/p>\n<p>The entire software ecosystem at Keepit may revolve around our storage systems, but we have several other supporting systems that use our shared components for the HTTP and XML stack.   <\/p>\n<p>One other notable C++ system is our search engine. Like so many other companies, we found ourselves needing a search engine to assist us with providing an amazing end user experience when browsing their datasets. And like so many others we fired up a cluster of Elasticsearch servers and went to work. <\/p>\n<p>Very quickly we got hit by this basic fact that Elastic is great at queries and not very good at updates \u2013 and we have many more updates than we have queries. We simply couldn\u2019t get this to scale like we\u2019re used to. What to do? <\/p>\n<p>While struggling with Elastic, we started the \u2018Plan-B\u2019 project to create a simple search engine from scratch \u2013 this engine has been our only search engine for years now and to this day, the process is still called \u2018bsearch.\u2019  <\/p>\n<p>Our search engine offers a google-like matching so that you can find your documents even if you misspell them, and it is a piece of technology that we are quite actively developing both to improve matching capabilities across languages and to allow for more efficient processing of much larger datasets, which will open up for other uses in the future.  <\/p>\n<p>Of our backend code base, about 81% of our code is C++. Another 16% is Common Lisp. The remaining 3% is Java. <\/p>\n<p>We use Common Lisp in two major areas: For \u2018general purpose\u2019 business functions such as messaging, resource accounting, billing, statistical data processing, etc. And we use it for backup dataset processing. These are two very different uses.  <\/p>\n<p>The first is a more classical application of the language where performance is maybe less of a concern but where the unparalleled power of the language allows for beautiful implementations of otherwise tedious programs. <\/p>\n<p>The second use is a less traditional use case where enormous datasets are processed and where the majority of the memory is actually allocated and managed outside of the garbage collector \u2013 it is truly a high-performance Lisp system where we benefit from the power of the language to do interesting and efficient extractions of certain key data from the hundreds of petabytes of customer data that pass through our systems. <\/p>\n<p>Many people don\u2019t know Common Lisp and may propose that \u2018Surely nobody would write a web service in Common Lisp.\u2019 Well, as with all other languages you need to understand the language to offer useful criticism; and the really groundbreaking feature of Common Lisp is its macro system. It is what makes Common Lisp by far the most powerful language in existence by a large margin. <\/p>\n<p>This is nothing like C pre-processor macros; the Common Lisp macro system allows you to use the full power of the language to generate code for the compiler. Effectively, this means the language is fully programmable. This is not something that is simple to understand since there is no meaningful way to do this using C-like language syntax, which is also why the Lisp dialects have a syntax that is fundamentally different from other languages. <\/p>\n<p>In other words, if you do not understand the Lisp syntax, you are not equipped to comprehend what the macro system allows. This is not simple to wrap your head around, but, for example, I can mention that Common Lisp was the first general purpose programming language to get Object Orientation added to it, and this was done not with a change to the language and the compiler, but with a library that contained some macros. Imagine that. <\/p>\n<p>Fortran allows you to implicitly declare the type of variables by using certain letters in the first character of the variable name \u2013 just for fun, I implemented that with a macro for Common Lisp. If I wanted to do that with C or C++ or any other language, I would need to extend the compiler. <\/p>\n<p>The idea of using the first character in the name of the variable to implicitly declare its type is of course ridiculous, but there are many little syntactical shortcuts or constructs that can help you in daily life that you may wish was present in your language of choice which you can only hope the language steering committee may one day add to the standard. <\/p>\n<p>With Common Lisp, this is everyday stuff \u2013 no need to wait. If you want a new type of control structure or declaration mechanism, just go ahead and build it. The power of this cannot be overstated. C++ metaprogramming (and go generics and everything else) pales in comparison, useful as it is. <\/p>\n<h4>Lessons learned<\/h4>\n<p>First of all, it really sucks to have multiple languages; you can\u2019t expect everyone to be an expert in all, so by having more than one language, you decimate the effective size of your team. However, we picked Common Lisp to replace a sprawling forest of little scripts done in more languages than I could shake a stick at\u2014meaning we are fortunate to have only two languages on our backend. <\/p>\n<p>C++ and Common Lisp are so different that they complement each other well. Yes, we could have done everything in C++, but there are problems we solve in Common Lisp which would have been much less enjoyable to solve in C++. Now on the downside, we have two HTTP stacks, two XML stacks, two database libraries, two connection pools, and so on and so forth. There is no simple perfect solution here; the compromise we have arrived at is indeed working out very well for us. <\/p>\n<p>We\u2019ve been told many times that recruiting for C++ is hard because recruiting for \u2018web technologies\u2019 is so much simpler. Well guess what, finding good JavaScript developers is just as hard as finding good C++ developers in my experience. With Common Lisp it\u2019s different again: it\u2019s harder to find people, but the percentage of the candidates that are actually qualified is higher, so all in all, it\u2019s actually fine. Recruitment is difficult across languages, period. <\/p>\n<p>The best you can do is go to a conference, talk about your tech, and hope that some developers show up at your booth to talk about employment. <\/p>\n<h4> Old grumpy man\u2019s advice for youngsters considering a career in software engineering<\/h4>\n<p>First of all, seriously consider a computer science education. There exist amazingly qualified people who do not have this and some of them work for us, but in my experience most really good developers have this. It certainly helps to get a foundation of mathematics, logic, and basic computer science. Knowing why things work will make learning new things infinitely simpler. <\/p>\n<p>Learn multiple, properly different programming languages and write actual code in them. You need to experience (by failing) how functions are useful as abstractions and how terrible it is to work with ill-designed abstractions. You need to fail and spend serious time failing. <\/p>\n<p>Make sure one of those languages is a compiled language with little or no runtime: C, C++, Rust, or even Fortran for that matter (not sure Fortran has much long-term perspective left in it though \u2013 it\u2019s probably time to say goodbye).  Now challenge yourself to write the most efficient implementation of some simple problem \u2013 maybe a matrix multiplication for example. <\/p>\n<p>Disassemble the code and look at it. At least get some understanding of the processor instructions and why they are generated from the code you wrote. Learn how cache lines matter. Time your code and find out why your solution isn\u2019t faster than it is. Then make it faster until you can prove to yourself that your instructions pipeline as much as they can, your cache misses are minimal, you don\u2019t wait on register write delays and so on and so forth. <\/p>\n<p>Also, make sure that one of those languages is Common Lisp. It should be a criminal offence for a university to not teach Common Lisp in their computer science curriculum. Read \u2018The Structure and Interpretation of Computer Programs \u2013 SICP\u2019 too. Even if you will never use Lisp again, knowing it will make you a better developer in any other language. <\/p>\n<p>And finally, as much as I dislike JavaScript, you should learn that, too. The most beautiful backend code will too easily be ignored if you cannot beautifully present its results \u2013 and today this means doing something with JavaScript.<\/p>\n<p>Aside from my previous criticisms, you can make working with JavaScript more bearable, for example, by creating your own framework rather than relying on the constantly changing megabyte sized atrocities that your common web projects rely on. However, this is probably a topic for future discussion. <\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2004c86 elementor-widget elementor-widget-shortcode\" data-id=\"2004c86\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\">\t\t<div data-elementor-type=\"page\" data-elementor-id=\"18103\" class=\"elementor elementor-18103\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-748947f elementor-section-full_width elementor-section-height-default elementor-section-height-default\" data-id=\"748947f\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;jet_parallax_layout_list&quot;:[{&quot;jet_parallax_layout_image&quot;:{&quot;url&quot;:&quot;&quot;,&quot;id&quot;:&quot;&quot;,&quot;size&quot;:&quot;&quot;},&quot;_id&quot;:&quot;c4f773e&quot;,&quot;jet_parallax_layout_image_tablet&quot;:{&quot;url&quot;:&quot;&quot;,&quot;id&quot;:&quot;&quot;,&quot;size&quot;:&quot;&quot;},&quot;jet_parallax_layout_image_mobile&quot;:{&quot;url&quot;:&quot;&quot;,&quot;id&quot;:&quot;&quot;,&quot;size&quot;:&quot;&quot;},&quot;jet_parallax_layout_speed&quot;:{&quot;unit&quot;:&quot;%&quot;,&quot;size&quot;:50,&quot;sizes&quot;:[]},&quot;jet_parallax_layout_type&quot;:&quot;scroll&quot;,&quot;jet_parallax_layout_direction&quot;:&quot;1&quot;,&quot;jet_parallax_layout_fx_direction&quot;:null,&quot;jet_parallax_layout_z_index&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_x&quot;:50,&quot;jet_parallax_layout_bg_x_tablet&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_x_mobile&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_y&quot;:50,&quot;jet_parallax_layout_bg_y_tablet&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_y_mobile&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_size&quot;:&quot;auto&quot;,&quot;jet_parallax_layout_bg_size_tablet&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_size_mobile&quot;:&quot;&quot;,&quot;jet_parallax_layout_animation_prop&quot;:&quot;transform&quot;,&quot;jet_parallax_layout_on&quot;:[&quot;desktop&quot;,&quot;tablet&quot;]}]}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7995c19\" data-id=\"7995c19\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-a437045 elementor-widget elementor-widget-image-box\" data-id=\"a437045\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image-box.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-image-box-wrapper\"><div class=\"elementor-image-box-content\"><h3 class=\"elementor-image-box-title\">About Version 2 Digital<\/h3><p class=\"elementor-image-box-description\">Version 2 Digital is one of the most dynamic IT companies in Asia. The company distributes a wide range of IT products across various areas including cyber security, cloud, data protection, end points, infrastructures, system monitoring, storage, networking, business productivity and communication products.\n<br><br>\nThrough an extensive network of channels, point of sales, resellers, and partnership companies, Version 2 offers quality products and services which are highly acclaimed in the market. Its customers cover a wide spectrum which include Global 1000 enterprises, regional listed companies, different vertical industries, public utilities, Government, a vast number of successful SMEs, and consumers in various Asian cities.<\/p><\/div><\/div>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t\n\t\t<div data-elementor-type=\"page\" data-elementor-id=\"50842\" class=\"elementor elementor-50842\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c1043a3 elementor-section-full_width elementor-section-height-default elementor-section-height-default\" data-id=\"c1043a3\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;jet_parallax_layout_list&quot;:[{&quot;_id&quot;:&quot;c4f773e&quot;,&quot;jet_parallax_layout_image&quot;:{&quot;url&quot;:&quot;&quot;,&quot;id&quot;:&quot;&quot;,&quot;size&quot;:&quot;&quot;},&quot;jet_parallax_layout_image_tablet&quot;:{&quot;url&quot;:&quot;&quot;,&quot;id&quot;:&quot;&quot;,&quot;size&quot;:&quot;&quot;},&quot;jet_parallax_layout_image_mobile&quot;:{&quot;url&quot;:&quot;&quot;,&quot;id&quot;:&quot;&quot;,&quot;size&quot;:&quot;&quot;},&quot;jet_parallax_layout_speed&quot;:{&quot;unit&quot;:&quot;%&quot;,&quot;size&quot;:50,&quot;sizes&quot;:[]},&quot;jet_parallax_layout_type&quot;:&quot;scroll&quot;,&quot;jet_parallax_layout_direction&quot;:&quot;1&quot;,&quot;jet_parallax_layout_fx_direction&quot;:null,&quot;jet_parallax_layout_z_index&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_x&quot;:50,&quot;jet_parallax_layout_bg_x_tablet&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_x_mobile&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_y&quot;:50,&quot;jet_parallax_layout_bg_y_tablet&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_y_mobile&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_size&quot;:&quot;auto&quot;,&quot;jet_parallax_layout_bg_size_tablet&quot;:&quot;&quot;,&quot;jet_parallax_layout_bg_size_mobile&quot;:&quot;&quot;,&quot;jet_parallax_layout_animation_prop&quot;:&quot;transform&quot;,&quot;jet_parallax_layout_on&quot;:[&quot;desktop&quot;,&quot;tablet&quot;]}]}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c911d7d\" data-id=\"c911d7d\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-026fa41 elementor-widget elementor-widget-text-editor\" data-id=\"026fa41\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p><strong>About Keepit<\/strong><br \/>At Keepit, we believe in a digital future where all software is delivered as a service. Keepit\u2019s mission is to protect data in the cloud Keepit is a software company specializing in Cloud-to-Cloud data backup and recovery. Deriving from +20 year experience in building best-in-class data protection and hosting services, Keepit is pioneering the way to secure and protect cloud data at scale.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>A while back, one of my colleagues was hanging out in a [&hellip;]<\/p>\n","protected":false},"author":143524195,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[488,853,61],"tags":[489,854],"class_list":["post-51659","post","type-post","status-publish","format-standard","hentry","category-488","category-keepit","category-press-release","tag-489","tag-keepit"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Surely nobody would write a web service in C++ - Version 2<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/\" \/>\n<meta property=\"og:locale\" content=\"zh_HK\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Surely nobody would write a web service in C++ - Version 2\" \/>\n<meta property=\"og:description\" content=\"A while back, one of my colleagues was hanging out in a [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/\" \/>\n<meta property=\"og:site_name\" content=\"Version 2\" \/>\n<meta property=\"article:published_time\" content=\"2022-06-23T01:41:18+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-07-08T09:37:02+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/images.prismic.io\/keepit\/0f95be5e-6033-4099-b070-6ecef643d2f5_why-c%2B%2B-web-service+.png?w=958&amp;ssl=1\" \/>\n<meta name=\"author\" content=\"version2hk\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"version2hk\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9810\u8a08\u95b1\u8b80\u6642\u9593\" \/>\n\t<meta name=\"twitter:data2\" content=\"21 \u5206\u9418\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.keepit.com\\\/blog\\\/why-web-service-written-in-c-plus-plus\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/version-2.com\\\/2022\\\/06\\\/surely-nobody-would-write-a-web-service-in-c\\\/\"},\"author\":{\"name\":\"version2hk\",\"@id\":\"https:\\\/\\\/version-2.com\\\/zh\\\/#\\\/schema\\\/person\\\/d14d2d3cd77ffdb618b9f1330fe084db\"},\"headline\":\"Surely nobody would write a web service in C++\",\"datePublished\":\"2022-06-23T01:41:18+00:00\",\"dateModified\":\"2022-07-08T09:37:02+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/version-2.com\\\/2022\\\/06\\\/surely-nobody-would-write-a-web-service-in-c\\\/\"},\"wordCount\":4315,\"publisher\":{\"@id\":\"https:\\\/\\\/version-2.com\\\/zh\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.keepit.com\\\/blog\\\/why-web-service-written-in-c-plus-plus\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/images.prismic.io\\\/keepit\\\/0f95be5e-6033-4099-b070-6ecef643d2f5_why-c%2B%2B-web-service+.png?w=958&amp;ssl=1\",\"keywords\":[\"2022\",\"Keepit\"],\"articleSection\":[\"2022\",\"Keepit\",\"Press Release\"],\"inLanguage\":\"zh-HK\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/version-2.com\\\/2022\\\/06\\\/surely-nobody-would-write-a-web-service-in-c\\\/\",\"url\":\"https:\\\/\\\/www.keepit.com\\\/blog\\\/why-web-service-written-in-c-plus-plus\\\/\",\"name\":\"Surely nobody would write a web service in C++ - Version 2\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/version-2.com\\\/zh\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.keepit.com\\\/blog\\\/why-web-service-written-in-c-plus-plus\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.keepit.com\\\/blog\\\/why-web-service-written-in-c-plus-plus\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/images.prismic.io\\\/keepit\\\/0f95be5e-6033-4099-b070-6ecef643d2f5_why-c%2B%2B-web-service+.png?w=958&amp;ssl=1\",\"datePublished\":\"2022-06-23T01:41:18+00:00\",\"dateModified\":\"2022-07-08T09:37:02+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.keepit.com\\\/blog\\\/why-web-service-written-in-c-plus-plus\\\/#breadcrumb\"},\"inLanguage\":\"zh-HK\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.keepit.com\\\/blog\\\/why-web-service-written-in-c-plus-plus\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-HK\",\"@id\":\"https:\\\/\\\/www.keepit.com\\\/blog\\\/why-web-service-written-in-c-plus-plus\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/images.prismic.io\\\/keepit\\\/0f95be5e-6033-4099-b070-6ecef643d2f5_why-c%2B%2B-web-service+.png?w=958&amp;ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/images.prismic.io\\\/keepit\\\/0f95be5e-6033-4099-b070-6ecef643d2f5_why-c%2B%2B-web-service+.png?w=958&amp;ssl=1\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.keepit.com\\\/blog\\\/why-web-service-written-in-c-plus-plus\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9801\",\"item\":\"https:\\\/\\\/version-2.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Surely nobody would write a web service in C++\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/version-2.com\\\/zh\\\/#website\",\"url\":\"https:\\\/\\\/version-2.com\\\/zh\\\/\",\"name\":\"Version 2\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/version-2.com\\\/zh\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/version-2.com\\\/zh\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"zh-HK\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/version-2.com\\\/zh\\\/#organization\",\"name\":\"Version 2\",\"url\":\"https:\\\/\\\/version-2.com\\\/zh\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-HK\",\"@id\":\"https:\\\/\\\/version-2.com\\\/zh\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/version-2.com\\\/wp-content\\\/uploads\\\/2020\\\/08\\\/v2-hk-hor-4.png?fit=1795%2C335&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/version-2.com\\\/wp-content\\\/uploads\\\/2020\\\/08\\\/v2-hk-hor-4.png?fit=1795%2C335&ssl=1\",\"width\":1795,\"height\":335,\"caption\":\"Version 2\"},\"image\":{\"@id\":\"https:\\\/\\\/version-2.com\\\/zh\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/version-2.com\\\/zh\\\/#\\\/schema\\\/person\\\/d14d2d3cd77ffdb618b9f1330fe084db\",\"name\":\"version2hk\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-HK\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d280627252b42d7489de74dd88aa04043a495f25e258575000dc767e287bf94c?s=96&d=identicon&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d280627252b42d7489de74dd88aa04043a495f25e258575000dc767e287bf94c?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d280627252b42d7489de74dd88aa04043a495f25e258575000dc767e287bf94c?s=96&d=identicon&r=g\",\"caption\":\"version2hk\"},\"sameAs\":[\"http:\\\/\\\/version2xfortcom.wordpress.com\"],\"url\":\"https:\\\/\\\/version-2.com\\\/zh\\\/author\\\/version2hk\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Surely nobody would write a web service in C++ - Version 2","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/","og_locale":"zh_HK","og_type":"article","og_title":"Surely nobody would write a web service in C++ - Version 2","og_description":"A while back, one of my colleagues was hanging out in a [&hellip;]","og_url":"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/","og_site_name":"Version 2","article_published_time":"2022-06-23T01:41:18+00:00","article_modified_time":"2022-07-08T09:37:02+00:00","og_image":[{"url":"https:\/\/i0.wp.com\/images.prismic.io\/keepit\/0f95be5e-6033-4099-b070-6ecef643d2f5_why-c%2B%2B-web-service+.png?w=958&amp;ssl=1","type":"","width":"","height":""}],"author":"version2hk","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"version2hk","\u9810\u8a08\u95b1\u8b80\u6642\u9593":"21 \u5206\u9418"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/#article","isPartOf":{"@id":"https:\/\/version-2.com\/2022\/06\/surely-nobody-would-write-a-web-service-in-c\/"},"author":{"name":"version2hk","@id":"https:\/\/version-2.com\/zh\/#\/schema\/person\/d14d2d3cd77ffdb618b9f1330fe084db"},"headline":"Surely nobody would write a web service in C++","datePublished":"2022-06-23T01:41:18+00:00","dateModified":"2022-07-08T09:37:02+00:00","mainEntityOfPage":{"@id":"https:\/\/version-2.com\/2022\/06\/surely-nobody-would-write-a-web-service-in-c\/"},"wordCount":4315,"publisher":{"@id":"https:\/\/version-2.com\/zh\/#organization"},"image":{"@id":"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/images.prismic.io\/keepit\/0f95be5e-6033-4099-b070-6ecef643d2f5_why-c%2B%2B-web-service+.png?w=958&amp;ssl=1","keywords":["2022","Keepit"],"articleSection":["2022","Keepit","Press Release"],"inLanguage":"zh-HK"},{"@type":"WebPage","@id":"https:\/\/version-2.com\/2022\/06\/surely-nobody-would-write-a-web-service-in-c\/","url":"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/","name":"Surely nobody would write a web service in C++ - Version 2","isPartOf":{"@id":"https:\/\/version-2.com\/zh\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/#primaryimage"},"image":{"@id":"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/images.prismic.io\/keepit\/0f95be5e-6033-4099-b070-6ecef643d2f5_why-c%2B%2B-web-service+.png?w=958&amp;ssl=1","datePublished":"2022-06-23T01:41:18+00:00","dateModified":"2022-07-08T09:37:02+00:00","breadcrumb":{"@id":"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/#breadcrumb"},"inLanguage":"zh-HK","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/"]}]},{"@type":"ImageObject","inLanguage":"zh-HK","@id":"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/#primaryimage","url":"https:\/\/i0.wp.com\/images.prismic.io\/keepit\/0f95be5e-6033-4099-b070-6ecef643d2f5_why-c%2B%2B-web-service+.png?w=958&amp;ssl=1","contentUrl":"https:\/\/i0.wp.com\/images.prismic.io\/keepit\/0f95be5e-6033-4099-b070-6ecef643d2f5_why-c%2B%2B-web-service+.png?w=958&amp;ssl=1"},{"@type":"BreadcrumbList","@id":"https:\/\/www.keepit.com\/blog\/why-web-service-written-in-c-plus-plus\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9801","item":"https:\/\/version-2.com\/"},{"@type":"ListItem","position":2,"name":"Surely nobody would write a web service in C++"}]},{"@type":"WebSite","@id":"https:\/\/version-2.com\/zh\/#website","url":"https:\/\/version-2.com\/zh\/","name":"Version 2","description":"","publisher":{"@id":"https:\/\/version-2.com\/zh\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/version-2.com\/zh\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"zh-HK"},{"@type":"Organization","@id":"https:\/\/version-2.com\/zh\/#organization","name":"Version 2","url":"https:\/\/version-2.com\/zh\/","logo":{"@type":"ImageObject","inLanguage":"zh-HK","@id":"https:\/\/version-2.com\/zh\/#\/schema\/logo\/image\/","url":"https:\/\/i0.wp.com\/version-2.com\/wp-content\/uploads\/2020\/08\/v2-hk-hor-4.png?fit=1795%2C335&ssl=1","contentUrl":"https:\/\/i0.wp.com\/version-2.com\/wp-content\/uploads\/2020\/08\/v2-hk-hor-4.png?fit=1795%2C335&ssl=1","width":1795,"height":335,"caption":"Version 2"},"image":{"@id":"https:\/\/version-2.com\/zh\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/version-2.com\/zh\/#\/schema\/person\/d14d2d3cd77ffdb618b9f1330fe084db","name":"version2hk","image":{"@type":"ImageObject","inLanguage":"zh-HK","@id":"https:\/\/secure.gravatar.com\/avatar\/d280627252b42d7489de74dd88aa04043a495f25e258575000dc767e287bf94c?s=96&d=identicon&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/d280627252b42d7489de74dd88aa04043a495f25e258575000dc767e287bf94c?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d280627252b42d7489de74dd88aa04043a495f25e258575000dc767e287bf94c?s=96&d=identicon&r=g","caption":"version2hk"},"sameAs":["http:\/\/version2xfortcom.wordpress.com"],"url":"https:\/\/version-2.com\/zh\/author\/version2hk\/"}]}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pbQRKm-drd","post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/version-2.com\/zh\/wp-json\/wp\/v2\/posts\/51659","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/version-2.com\/zh\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/version-2.com\/zh\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/version-2.com\/zh\/wp-json\/wp\/v2\/users\/143524195"}],"replies":[{"embeddable":true,"href":"https:\/\/version-2.com\/zh\/wp-json\/wp\/v2\/comments?post=51659"}],"version-history":[{"count":4,"href":"https:\/\/version-2.com\/zh\/wp-json\/wp\/v2\/posts\/51659\/revisions"}],"predecessor-version":[{"id":51663,"href":"https:\/\/version-2.com\/zh\/wp-json\/wp\/v2\/posts\/51659\/revisions\/51663"}],"wp:attachment":[{"href":"https:\/\/version-2.com\/zh\/wp-json\/wp\/v2\/media?parent=51659"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/version-2.com\/zh\/wp-json\/wp\/v2\/categories?post=51659"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/version-2.com\/zh\/wp-json\/wp\/v2\/tags?post=51659"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}