{"id":1399,"date":"2017-11-02T17:46:18","date_gmt":"2017-11-02T09:46:18","guid":{"rendered":"https:\/\/yanjingang.com\/blog\/?p=1399"},"modified":"2017-11-02T17:46:48","modified_gmt":"2017-11-02T09:46:48","slug":"kafka%e5%88%86%e5%8c%ba%e5%88%86%e9%85%8d%e7%ad%96%e7%95%a5partition-assignment-strategy","status":"publish","type":"post","link":"https:\/\/yanjingang.com\/blog\/?p=1399","title":{"rendered":"Kafka\u5206\u533a\u5206\u914d\u7b56\u7565(Partition Assignment Strategy)"},"content":{"rendered":"<div id=\"toc_container\" class=\"no_bullets\">\n<p class=\"toc_title\">\u76ee\u5f55<\/p>\n<ul class=\"toc_list\">\n<li><span class=\"toc_number toc_depth_1\">1<\/span>\u00a0\u95ee\u9898<\/li>\n<li><span class=\"toc_number toc_depth_1\">2<\/span>\u00a0Range strategy<\/li>\n<li><span class=\"toc_number toc_depth_1\">3<\/span>\u00a0RoundRobin strategy<\/li>\n<\/ul>\n<\/div>\n<h2 id=\"problem\"><span id=\"i\">\u95ee\u9898<\/span><\/h2>\n<p>\u7528\u8fc7\u00a0<span class=\"wp_keywordlink_affiliate\">Kafka<\/span>\u00a0\u7684\u540c\u5b66\u5e94\u8be5\u90fd\u77e5\u9053\uff0c\u6bcf\u4e2a Topic \u4e00\u822c\u4f1a\u6709\u5f88\u591a\u4e2a partitions\u3002\u4e3a\u4e86\u4f7f\u5f97\u6211\u4eec\u80fd\u591f\u53ca\u65f6\u6d88\u8d39\u6d88\u606f\uff0c\u6211\u4eec\u4e5f\u53ef\u80fd\u4f1a\u542f\u52a8\u591a\u4e2a Consumer \u53bb\u6d88\u8d39\uff0c\u800c\u6bcf\u4e2a Consumer \u53c8\u4f1a\u542f\u52a8\u4e00\u4e2a\u6216\u591a\u4e2astreams\u53bb\u5206\u522b\u6d88\u8d39 Topic \u5bf9\u5e94\u5206\u533a\u4e2d\u7684\u6570\u636e\u3002\u6211\u4eec\u53c8\u77e5\u9053\uff0c<span class=\"wp_keywordlink_affiliate\">Kafka<\/span>\u00a0\u5b58\u5728 Consumer Group \u7684\u6982\u5ff5\uff0c\u4e5f\u5c31\u662f\u00a0<code>group.id<\/code>\u00a0\u4e00\u6837\u7684 Consumer\uff0c\u8fd9\u4e9b Consumer \u5c5e\u4e8e\u540c\u4e00\u4e2aConsumer Group\uff0c\u7ec4\u5185\u7684\u6240\u6709\u6d88\u8d39\u8005\u534f\u8c03\u5728\u4e00\u8d77\u6765\u6d88\u8d39\u8ba2\u9605\u4e3b\u9898(subscribed topics)\u7684\u6240\u6709\u5206\u533a(partition)\u3002\u5f53\u7136\uff0c\u6bcf\u4e2a\u5206\u533a\u53ea\u80fd\u7531\u540c\u4e00\u4e2a\u6d88\u8d39\u7ec4\u5185\u7684\u4e00\u4e2aconsumer\u6765\u6d88\u8d39\u3002\u90a3\u4e48\u95ee\u9898\u6765\u4e86\uff0c\u540c\u4e00\u4e2a Consumer Group \u91cc\u9762\u7684 Consumer \u662f\u5982\u4f55\u77e5\u9053\u8be5\u6d88\u8d39\u54ea\u4e9b\u5206\u533a\u91cc\u9762\u7684\u6570\u636e\u5462\uff1f<\/p>\n<div class=\"wp-caption aligncenter\"><a href=\"https:\/\/yanjingang.com\/blog\/?attachment_id=1400\" rel=\"attachment wp-att-1400\"><img loading=\"lazy\" class=\"alignnone size-full wp-image-1400\" src=\"https:\/\/yanjingang.com\/blog\/wp-content\/uploads\/2017\/11\/kafka.png\" alt=\"\" width=\"519\" height=\"354\" srcset=\"https:\/\/yanjingang.com\/blog\/wp-content\/uploads\/2017\/11\/kafka.png 519w, https:\/\/yanjingang.com\/blog\/wp-content\/uploads\/2017\/11\/kafka-300x205.png 300w\" sizes=\"(max-width: 519px) 100vw, 519px\" \/><\/a><\/div>\n<p>\u5982\u4e0a\u56fe\uff0cConsumer1 \u4e3a\u5565\u6d88\u8d39\u7684\u662f Partition0 \u548c Partition2\uff0c\u800c\u4e0d\u662f Partition0 \u548c Partition3\uff1f\u8fd9\u5c31\u6d89\u53ca\u5230\u00a0<span class=\"wp_keywordlink_affiliate\">Kafka<\/span>\u00a0\u5185\u90e8\u5206\u533a\u5206\u914d\u7b56\u7565\uff08Partition Assignment Strategy\uff09\u4e86\u3002<\/p>\n<p>\u5728 Kafka \u5185\u90e8\u5b58\u5728\u4e24\u79cd\u9ed8\u8ba4\u7684\u5206\u533a\u5206\u914d\u7b56\u7565\uff1aRange \u548c RoundRobin\u3002\u5f53\u4ee5\u4e0b\u4e8b\u4ef6\u53d1\u751f\u65f6\uff0cKafka \u5c06\u4f1a\u8fdb\u884c\u4e00\u6b21\u5206\u533a\u5206\u914d\uff1a<\/p>\n<ul>\n<li>\u540c\u4e00\u4e2a Consumer Group \u5185\u65b0\u589e\u6d88\u8d39\u8005<\/li>\n<li>\u6d88\u8d39\u8005\u79bb\u5f00\u5f53\u524d\u6240\u5c5e\u7684Consumer Group\uff0c\u5305\u62ecshuts down \u6216 crashes<\/li>\n<li>\u8ba2\u9605\u7684\u4e3b\u9898\u65b0\u589e\u5206\u533a<\/li>\n<\/ul>\n<p>\u5c06\u5206\u533a\u7684\u6240\u6709\u6743\u4ece\u4e00\u4e2a\u6d88\u8d39\u8005\u79fb\u5230\u53e6\u4e00\u4e2a\u6d88\u8d39\u8005\u79f0\u4e3a\u91cd\u65b0\u5e73\u8861\uff08rebalance\uff09\uff0c\u5982\u4f55rebalance\u5c31\u6d89\u53ca\u5230\u672c\u6587\u63d0\u5230\u7684\u5206\u533a\u5206\u914d\u7b56\u7565\u3002\u4e0b\u9762\u6211\u4eec\u5c06\u8be6\u7ec6\u4ecb\u7ecd Kafka \u5185\u7f6e\u7684\u4e24\u79cd\u5206\u533a\u5206\u914d\u7b56\u7565\u3002\u672c\u6587\u5047\u8bbe\u6211\u4eec\u6709\u4e2a\u540d\u4e3a T1 \u7684\u4e3b\u9898\uff0c\u5176\u5305\u542b\u4e8610\u4e2a\u5206\u533a\uff0c\u7136\u540e\u6211\u4eec\u6709\u4e24\u4e2a\u6d88\u8d39\u8005\uff08C1\uff0cC2\uff09\u6765\u6d88\u8d39\u8fd910\u4e2a\u5206\u533a\u91cc\u9762\u7684\u6570\u636e\uff0c\u800c\u4e14 C1 \u7684 num.streams = 1\uff0cC2 \u7684 num.streams = 2\u3002<\/p>\n<h2 id=\"Range strategy\"><span id=\"Range_strategy\">Range strategy<\/span><\/h2>\n<p>Range\u7b56\u7565\u662f\u5bf9\u6bcf\u4e2a\u4e3b\u9898\u800c\u8a00\u7684\uff0c\u9996\u5148\u5bf9\u540c\u4e00\u4e2a\u4e3b\u9898\u91cc\u9762\u7684\u5206\u533a\u6309\u7167\u5e8f\u53f7\u8fdb\u884c\u6392\u5e8f\uff0c\u5e76\u5bf9\u6d88\u8d39\u8005\u6309\u7167\u5b57\u6bcd\u987a\u5e8f\u8fdb\u884c\u6392\u5e8f\u3002\u5728\u6211\u4eec\u7684\u4f8b\u5b50\u91cc\u9762\uff0c\u6392\u5b8c\u5e8f\u7684\u5206\u533a\u5c06\u4f1a\u662f0, 1, 2, 3, 4, 5, 6, 7, 8, 9\uff1b\u6d88\u8d39\u8005\u7ebf\u7a0b\u6392\u5b8c\u5e8f\u5c06\u4f1a\u662fC1-0, C2-0, C2-1\u3002\u7136\u540e\u5c06partitions\u7684\u4e2a\u6570\u9664\u4e8e\u6d88\u8d39\u8005\u7ebf\u7a0b\u7684\u603b\u6570\u6765\u51b3\u5b9a\u6bcf\u4e2a\u6d88\u8d39\u8005\u7ebf\u7a0b\u6d88\u8d39\u51e0\u4e2a\u5206\u533a\u3002\u5982\u679c\u9664\u4e0d\u5c3d\uff0c\u90a3\u4e48\u524d\u9762\u51e0\u4e2a\u6d88\u8d39\u8005\u7ebf\u7a0b\u5c06\u4f1a\u591a\u6d88\u8d39\u4e00\u4e2a\u5206\u533a\u3002\u5728\u6211\u4eec\u7684\u4f8b\u5b50\u91cc\u9762\uff0c\u6211\u4eec\u670910\u4e2a\u5206\u533a\uff0c3\u4e2a\u6d88\u8d39\u8005\u7ebf\u7a0b\uff0c 10 \/ 3 = 3\uff0c\u800c\u4e14\u9664\u4e0d\u5c3d\uff0c\u90a3\u4e48\u6d88\u8d39\u8005\u7ebf\u7a0b C1-0 \u5c06\u4f1a\u591a\u6d88\u8d39\u4e00\u4e2a\u5206\u533a\uff0c\u6240\u4ee5\u6700\u540e\u5206\u533a\u5206\u914d\u7684\u7ed3\u679c\u770b\u8d77\u6765\u662f\u8fd9\u6837\u7684\uff1a<\/p>\n<p>C1-0 \u5c06\u6d88\u8d39 0, 1, 2, 3 \u5206\u533a<br \/>\nC2-0 \u5c06\u6d88\u8d39 4, 5, 6 \u5206\u533a<br \/>\nC2-1 \u5c06\u6d88\u8d39 7, 8, 9 \u5206\u533a<\/p>\n<p>\u5047\u5982\u6211\u4eec\u670911\u4e2a\u5206\u533a\uff0c\u90a3\u4e48\u6700\u540e\u5206\u533a\u5206\u914d\u7684\u7ed3\u679c\u770b\u8d77\u6765\u662f\u8fd9\u6837\u7684\uff1a<\/p>\n<p>C1-0 \u5c06\u6d88\u8d39 0, 1, 2, 3 \u5206\u533a<br \/>\nC2-0 \u5c06\u6d88\u8d39 4, 5, 6, 7 \u5206\u533a<br \/>\nC2-1 \u5c06\u6d88\u8d39 8, 9, 10 \u5206\u533a<\/p>\n<p>\u5047\u5982\u6211\u4eec\u67092\u4e2a\u4e3b\u9898(T1\u548cT2)\uff0c\u5206\u522b\u670910\u4e2a\u5206\u533a\uff0c\u90a3\u4e48\u6700\u540e\u5206\u533a\u5206\u914d\u7684\u7ed3\u679c\u770b\u8d77\u6765\u662f\u8fd9\u6837\u7684\uff1a<\/p>\n<p>C1-0 \u5c06\u6d88\u8d39 T1\u4e3b\u9898\u7684 0, 1, 2, 3 \u5206\u533a\u4ee5\u53ca T2\u4e3b\u9898\u7684 0, 1, 2, 3\u5206\u533a<br \/>\nC2-0 \u5c06\u6d88\u8d39 T1\u4e3b\u9898\u7684 4, 5, 6 \u5206\u533a\u4ee5\u53ca T2\u4e3b\u9898\u7684 4, 5, 6\u5206\u533a<br \/>\nC2-1 \u5c06\u6d88\u8d39 T1\u4e3b\u9898\u7684 7, 8, 9 \u5206\u533a\u4ee5\u53ca T2\u4e3b\u9898\u7684 7, 8, 9\u5206\u533a<\/p>\n<p>\u53ef\u4ee5\u770b\u51fa\uff0cC1-0 \u6d88\u8d39\u8005\u7ebf\u7a0b\u6bd4\u5176\u4ed6\u6d88\u8d39\u8005\u7ebf\u7a0b\u591a\u6d88\u8d39\u4e862\u4e2a\u5206\u533a\uff0c\u8fd9\u5c31\u662fRange strategy\u7684\u4e00\u4e2a\u5f88\u660e\u663e\u7684\u5f0a\u7aef\u3002<\/p>\n<h2 id=\"RoundRobin strategy\"><span id=\"RoundRobin_strategy\">RoundRobin strategy<\/span><\/h2>\n<p>\u4f7f\u7528RoundRobin\u7b56\u7565\u6709\u4e24\u4e2a\u524d\u63d0\u6761\u4ef6\u5fc5\u987b\u6ee1\u8db3\uff1a<\/p>\n<ul>\n<li>\u540c\u4e00\u4e2aConsumer Group\u91cc\u9762\u7684\u6240\u6709\u6d88\u8d39\u8005\u7684num.streams\u5fc5\u987b\u76f8\u7b49\uff1b<\/li>\n<li>\u6bcf\u4e2a\u6d88\u8d39\u8005\u8ba2\u9605\u7684\u4e3b\u9898\u5fc5\u987b\u76f8\u540c\u3002<\/li>\n<\/ul>\n<p>\u6240\u4ee5\u8fd9\u91cc\u5047\u8bbe\u524d\u9762\u63d0\u5230\u76842\u4e2a\u6d88\u8d39\u8005\u7684num.streams = 2\u3002RoundRobin\u7b56\u7565\u7684\u5de5\u4f5c\u539f\u7406\uff1a\u5c06\u6240\u6709\u4e3b\u9898\u7684\u5206\u533a\u7ec4\u6210 TopicAndPartition \u5217\u8868\uff0c\u7136\u540e\u5bf9 TopicAndPartition \u5217\u8868\u6309\u7167 hashCode \u8fdb\u884c\u6392\u5e8f\uff0c\u8fd9\u91cc\u6587\u5b57\u53ef\u80fd\u8bf4\u4e0d\u6e05\uff0c\u770b\u4e0b\u9762\u7684\u4ee3\u7801\u5e94\u8be5\u4f1a\u660e\u767d\uff1a<\/p>\n<div>\n<div id=\"highlighter_588259\" class=\"syntaxhighlighter nogutter scala\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"scala keyword\">val<\/code> <code class=\"scala plain\">allTopicPartitions <\/code><code class=\"scala keyword\">=<\/code> <code class=\"scala plain\">ctx.partitionsForTopic.flatMap { <\/code><code class=\"scala keyword\">case<\/code><code class=\"scala plain\">(topic, partitions) <\/code><code class=\"scala keyword\">=<\/code><code class=\"scala plain\">&gt;<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"scala spaces\">\u00a0\u00a0<\/code><code class=\"scala plain\">info(<\/code><code class=\"scala string\">\"Consumer %s rebalancing the following partitions for topic %s: %s\"<\/code><\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"scala spaces\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/code><code class=\"scala plain\">.format(ctx.consumerId, topic, partitions))<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"scala spaces\">\u00a0\u00a0<\/code><code class=\"scala plain\">partitions.map(partition <\/code><code class=\"scala keyword\">=<\/code><code class=\"scala plain\">&gt; {<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"scala spaces\">\u00a0\u00a0\u00a0\u00a0<\/code><code class=\"scala plain\">TopicAndPartition(topic, partition)<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"scala spaces\">\u00a0\u00a0<\/code><code class=\"scala plain\">})<\/code><\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"scala plain\">}.toSeq.sortWith((topicPartition<\/code><code class=\"scala value\">1<\/code><code class=\"scala plain\">, topicPartition<\/code><code class=\"scala value\">2<\/code><code class=\"scala plain\">) <\/code><code class=\"scala keyword\">=<\/code><code class=\"scala plain\">&gt; {<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"scala spaces\">\u00a0\u00a0<\/code><code class=\"scala comments\">\/*<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"scala spaces\">\u00a0\u00a0\u00a0<\/code><code class=\"scala comments\">* Randomize the order by taking the hashcode to reduce the likelihood of all partitions of a given topic ending<\/code><\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"scala spaces\">\u00a0\u00a0\u00a0<\/code><code class=\"scala comments\">* up on one consumer (if it has a high enough stream count).<\/code><\/div>\n<div class=\"line number11 index10 alt2\"><code class=\"scala spaces\">\u00a0\u00a0\u00a0<\/code><code class=\"scala comments\">*\/<\/code><\/div>\n<div class=\"line number12 index11 alt1\"><code class=\"scala spaces\">\u00a0\u00a0<\/code><code class=\"scala plain\">topicPartition<\/code><code class=\"scala value\">1<\/code><code class=\"scala plain\">.toString.hashCode &lt; topicPartition<\/code><code class=\"scala value\">2<\/code><code class=\"scala plain\">.toString.hashCode<\/code><\/div>\n<div class=\"line number13 index12 alt2\"><code class=\"scala plain\">})<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u6700\u540e\u6309\u7167round-robin\u98ce\u683c\u5c06\u5206\u533a\u5206\u522b\u5206\u914d\u7ed9\u4e0d\u540c\u7684\u6d88\u8d39\u8005\u7ebf\u7a0b\u3002<\/p>\n<p>\u5728\u6211\u4eec\u7684\u4f8b\u5b50\u91cc\u9762\uff0c\u5047\u5982\u6309\u7167 hashCode \u6392\u5e8f\u5b8c\u7684topic-partitions\u7ec4\u4f9d\u6b21\u4e3aT1-5, T1-3, T1-0, T1-8, T1-2, T1-1, T1-4, T1-7, T1-6, T1-9\uff0c\u6211\u4eec\u7684\u6d88\u8d39\u8005\u7ebf\u7a0b\u6392\u5e8f\u4e3aC1-0, C1-1, C2-0, C2-1\uff0c\u6700\u540e\u5206\u533a\u5206\u914d\u7684\u7ed3\u679c\u4e3a\uff1a<\/p>\n<p>C1-0 \u5c06\u6d88\u8d39 T1-5, T1-2, T1-6 \u5206\u533a\uff1b<br \/>\nC1-1 \u5c06\u6d88\u8d39 T1-3, T1-1, T1-9 \u5206\u533a\uff1b<br \/>\nC2-0 \u5c06\u6d88\u8d39 T1-0, T1-4 \u5206\u533a\uff1b<br \/>\nC2-1 \u5c06\u6d88\u8d39 T1-8, T1-7 \u5206\u533a\uff1b<\/p>\n<p>\u591a\u4e2a\u4e3b\u9898\u7684\u5206\u533a\u5206\u914d\u548c\u5355\u4e2a\u4e3b\u9898\u7c7b\u4f3c\uff0c\u8fd9\u91cc\u5c31\u4e0d\u5728\u4ecb\u7ecd\u4e86\u3002<\/p>\n<p>\u6839\u636e\u4e0a\u9762\u7684\u8be6\u7ec6\u4ecb\u7ecd\u76f8\u4fe1\u5927\u5bb6\u5df2\u7ecf\u5bf9Kafka\u7684\u5206\u533a\u5206\u914d\u7b56\u7565\u539f\u7406\u5f88\u6e05\u695a\u4e86\u3002\u4e0d\u8fc7\u9057\u61be\u7684\u662f\uff0c\u76ee\u524d\u6211\u4eec\u8fd8\u4e0d\u80fd\u81ea\u5b9a\u4e49\u5206\u533a\u5206\u914d\u7b56\u7565\uff0c\u53ea\u80fd\u901a\u8fc7<code>partition.assignment.strategy<\/code>\u53c2\u6570\u9009\u62e9 range \u6216 roundrobin\u3002<code>partition.assignment.strategy<\/code>\u53c2\u6570\u9ed8\u8ba4\u7684\u503c\u662frange\u3002<\/p>\n<div class=\"note\">\n<p>\u4e0a\u9762\u7684\u6587\u5b57\u53ef\u80fd\u6709\u63cf\u8ff0\u4e0d\u51c6\u786e\u6216\u4e0d\u6e05\u695a\u7684\u5730\u65b9\uff0c\u8fd9\u91cc\u5217\u51fa\u4e86\u5b98\u65b9\u5bf9\u7740\u4e24\u79cd\u7b56\u7565\u7684\u89e3\u91ca\uff1a<\/p>\n<ul>\n<li>RoundRobin\uff1a<br \/>\nThe round-robin partition assignor lays out all the available partitions and all the available consumer threads. It then proceeds to do a round-robin assignment from partition to consumer thread. If the subscriptions of all consumer instances are identical, then the partitions will be uniformly distributed. (i.e., the partition ownership counts will be within a delta of exactly one across all consumer threads.)(For simplicity of implementation) the assignor is allowed to assign a given topic-partition to any consumer instance and thread-id within that instance. Therefore, round-robin assignment is allowed only if:<br \/>\na) Every topic has the same number of streams within a consumer instance<br \/>\nb) The set of subscribed topics is identical for every consumer instance within the group.<\/li>\n<li>Range:<br \/>\nRange partitioning works on a per-topic basis. For each topic, we lay out the available partitions in numeric order and the consumer threads in lexicographic order. We then divide the number of partitions by the total number of consumer streams (threads) to determine the number of partitions to assign to each consumer. If it does not evenly divide, then the first few consumers will have one extra partition. For example, suppose there are two consumers C1 and C2 with two streams each, and there are five available partitions (p0, p1, p2, p3, p4). So each consumer thread will get at least one partition and the first consumer thread will get one extra partition. So the assignment will be: p0 -&gt; C1-0, p1 -&gt; C1-0, p2 -&gt; C1-1, p3 -&gt; C2-0, p4 -&gt; C2-1<\/li>\n<\/ul>\n<p><span style=\"color: #999999;\">\u6458\u81ea\uff1ahttps:\/\/www.iteblog.com\/archives\/2209.html<\/span><\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u76ee\u5f55 1\u00a0\u95ee\u9898 2\u00a0Range strategy 3\u00a0RoundRobin strategy \u95ee\u9898 \u7528\u8fc7\u00a0Ka [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[509],"tags":[521,510,520],"_links":{"self":[{"href":"https:\/\/yanjingang.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1399"}],"collection":[{"href":"https:\/\/yanjingang.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yanjingang.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yanjingang.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/yanjingang.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1399"}],"version-history":[{"count":0,"href":"https:\/\/yanjingang.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1399\/revisions"}],"wp:attachment":[{"href":"https:\/\/yanjingang.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1399"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yanjingang.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1399"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yanjingang.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1399"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}