---
# System prepended metadata

title: Anser Service Discovery 實作問題
tags: [Anser]

---

# Anser Service Discovery 實作問題
###### tags: `Anser`
[TOC]

## URI scheme 問題 (已解)

Service Setting時需帶入isHttp，判斷是否為HTTPS Request，但Consul api取得Service info時無法取得關於scheme的訊息。

### 解決辦法1
透過Consul設定中的scheme欄位，為所有服務發現的服務填充scheme，但可能衍生另一個問題，如果服務發現中的service無法用Https訪問時，會造成Action請求錯誤，硬解的話，目前想到一個辦法，先打開發人員在Consul設定的scheme，假設是HTTPS，如果無效，再打Http，如果再無效就註銷服務，並通知該服務不可用。

### 解決辦法2 - 目前解法
:::success
於服務註冊時，於Tag標記使用的scheme，後續Service Setting時直接取用即可。
一開始於Tag標註HTTP或HTTPS，如果都沒標註則預設使用HTTPS。
:::


### 解決辦法3
從根本解決，服務註冊的同時，使用KV儲存服務資訊，後續直接對KV List取用。

<hr>

## 服務對接 (未解)

Q : Anser取得服務位置後，可能出現同個服務多個IP的狀況，例如product service有127.0.0.1:8080、127.0.0.1:8081 ....位置。
如此一來，Anser的服務請求該導向哪邊?


### 解法1
搭配Fabio，順便做服務的負載均衡，有極大限度可讓開發人員自行定義服務走向。

![](https://i.imgur.com/E0hSmXh.jpg)

Fabio會自動向Consul-server獲取健康的服務，並於Fabio本地紀錄路由表
例如打這組請求 ```curl -s http://140.127.74.171:9998/api/routes | jq '.'```
fabio會回傳所有健康路由表，ANSER只需拿到Fabio暴露出來的service名稱就可以開始打API了。
```
[
  {
    "service": "product_service",
    "host": "",
    "path": "/product_service",
    "src": "/product_service",
    "dst": "http://140.127.74.162:8081/",
    "opts": "strip=/product_service",
    "weight": 0.5,
    "tags": [
      "HTTP",
      "rails"
    ],
    "cmd": "route add",
    "rate1": 0,
    "pct99": 0
  },
  {
    "service": "product_service",
    "host": "",
    "path": "/product_service",
    "src": "/product_service",
    "dst": "http://140.127.74.137:80/",
    "opts": "strip=/product_service",
    "weight": 0.5,
    "tags": [
      "HTTP",
      "rails"
    ],
    "cmd": "route add",
    "rate1": 0,
    "pct99": 0
  },
]
```

![](https://i.imgur.com/MWXTP8g.png)

:::info
如有相同服務名稱註冊進consul的話，fabio會自動認為他們是一樣的服務，進而分配訪問權重，訪問方式fabio提供兩個分別是 RR(輪詢)、RND(微秒級別的random調度)，以上皆為fabio內部實現，也可透過參數細調。
:::

:::success
優點: 
* 這麼做的好處是，ANSER不必透過consul取得服務列表，再進一步對微服務訪問，只在乎fabio服務是否活著即可。
* 不用管服務多寡，統一用fabio進行服務存取，做到服務的負載均衡，以及反向代理。
* 解決了一開始同個服務多個IP的狀況。
* fabio目前可負荷每秒2W5個請求流量。
:::

:::danger
缺點:
* 微服務集成為cluster後，如果微服務叢集只對外暴露一個接口(叢集內部又做了一次負載均衡+反向代理)的話，fabio就顯得多餘了。
* 維運團隊如何顧好fabio的運行狀況。
* 如fabio遭遇意外關機，維運團隊重啟後，ANSER需即時獲得fabio的對外port，這個port fabio並不會向consul註冊，就算註冊了也會出現服務不健康的標誌。
:::


## ANSER GATEWAY實現單服務多節點選擇功能

### 作法
:::success
1.當客戶端對某個服務發起請求時，anser先到consul撈出該服務對應的健康IP
2.透過輪詢演算法找出某個訪問IP
3.對該IP發起訪問
4.回傳結果
:::

### 需面臨的問題
:::danger
1.服務請求發起時，本地列表的搜尋優先度是否要高於consul搜尋。
2.如果每次請求發起時，都對consul進行服務列表取得的動作，是否會耗費多於資源。
3.承2.，可以改為anser gateway於背景執行服務列表的更新，這樣就可以將服務統一儲存於本地服務列表進行存取。
4.服務節點的演算法
:::

## Service Discovery實現

###  
