More Related Content
Similar to Usage Experience of Spring Cloud Eureka & OpenFeign (20)
Usage Experience of Spring Cloud Eureka & OpenFeign
- 11. Too young, too simple
1. 考量到不買K8S這類平台的用戶
2. 開發的技術比佈署的技術早決定
3. Swarm與K8S在當時還在競爭
設計微服務架構當時
並沒有以K8S為運行考量
- 18. 狀況一、Get 參數的傳遞
@GetMapping(“/foo”)
public void composite(Bar bar) {
client.bar(bar);
}
@Getter
@Setter
public class Bar {
private long id;
private String name;
}
呼叫: /foo?id=1&name=aaa
@FeignClient("foo")
public interface FooClient {
@GetMapping("/bar")
public DemoObject composite(Bar bar);
}
Controller FeignClient
- 19. 狀況一、Get 參數的傳遞
@GetMapping(“/foo”)
public void composite(Bar bar) {
client.bar(bar);
}
@Getter
@Setter
public class Bar {
private long id;
private String name;
}
呼叫: /foo?id=1&name=aaa
@FeignClient("foo")
public interface FooClient {
@GetMapping("/bar")
public DemoObject composite(Bar bar);
}
Controller FeignClient
feign.FeignException$MethodNotAllowed:
status 405 reading FooClient#bar(Bar)
- 20. 狀況一、Get 參數的傳遞
FeignClient的參數預設都會被視為Body
然而 Get 無法擁有 MessageBody
因此被轉成 Post 所導致
@FeignClient("foo")
public interface FooClient {
@GetMapping("/bar")
public DemoObject composite(Bar bar);
}
feign.FeignException$MethodNotAllowed:
status 405 reading FooClient#bar(Bar)
- 23. 狀況一、Get 參數的傳遞
因此如果你像我們一樣,只能用1.x.x
@Bean
public FeignObjectEncoder feignObjectEncoder(
ObjectFactory<HttpMessageConverters> messageConverters, ObjectMapper objectMapper) {
return new FeignObjectEncoder(new SpringEncoder(messageConverters), objectMapper);
}
那就得土砲一系列的 FeignObjectEncoder
public class FeignObjectEncoder implements feign.codec.Encoder
1. 維持處理原本的邏輯, 2. Object to QueryString, 3. Body清空
- 26. 狀況二、錯誤訊息傳遞
A B C
{
"timestamp": "2019-10-02T09:43:07.872+0000",
"status": 500,
"error": "Internal Server Error",
"message": "status 500 reading B#foo(Bar)",
"path": "/foo"
}
三個Service 透過FeignClient連續呼叫
- 27. 狀況二、錯誤訊息傳遞
A B C
三個Service 透過FeignClient連續呼叫
{
"timestamp": "2019-10-02T09:43:07.872+0000",
"status": 500,
"error": "Internal Server Error",
"message": "status 500 reading A#foo(Bar)",
"path": "/foo"
}
- 28. 狀況二、錯誤訊息傳遞
A B C
三個Service 透過FeignClient連續呼叫
{
"timestamp": "2019-10-02T09:43:07.872+0000",
"status": 500,
"error": "Internal Server Error",
"message": "status 500 reading A#foo(Bar)",
"path": "/foo"
}
- 30. 狀況二、錯誤訊息傳遞
{
"timestamp": "2019-10-02T09:43:07.872+0000",
"status": 500,
"error": "Internal Server Error",
"message": "status 500 reading B#foo(Bar)",
"path": "/foo"
}
protected FeignException(int status, String message, Throwable cause, byte[] content) {
super(message, cause);
this.status = status;
this.content = content;
}
實際上針對所有類型的呼叫錯誤都會被包裝成FeignException
原本的message會被塞到content
新的message只會是 "status %s reading %s"
並且SpringMVC會很好心的幫你只把Message傳出去
- 45. 狀況三、本機流程測試
解決方法:客製 ZonePreferenceServerListFilter
public class CustomZoneFilter extends ZonePreferenceServerListFilter {
@Override
public List<Server> getFilteredListOfServers(List<Server> servers) {
final List<Server> filteredServers = super.getFilteredListOfServers(servers);
// 從filteredServers中以自訂的邏輯篩選出可以呼叫的Server
return callableServers;
}
}
@Bean
public ServerListFilter<Server> onlyMyZoneFilter() {
return new CustomZoneFilter();
}
Editor's Notes
- 說明微服務與傳統單一架構1. Java 包檔方式的差異
2. 佈署方式的差異
- 微服務如何用Java實作
**下一張有梗
- 開發面:Service之間的溝通 method > protocol
管理面:佈署方式的差異(這麼多的App怎麼管理?)
設計面:Service的職責(Gateway, Composit, Base…)
設計面:Domain方面的切分
- 公司目前的作法
SpringBoot撰寫專案透過JIB包成Image
Run在Docker上
用K8S管理叢集
**下一張講但書
- 開發第一步首先遇到的問題,Service間的呼叫
(此處已假定為是以同步方式透過Restful呼叫)
然而剛剛有說是佈在K8S上,所以…
- K8S內有Service層作為LoadBalance可直接以service name呼叫
口述一下K8S關於Service>Pod>Container的東西
然而這在當時行不通…
- 1. 考量到不買K8S這類平台的用戶2. 開發的技術比佈署的技術早決定3. Swarm與K8S在當時還在競爭
- 將話題導引到SpringCloud上
** 下一張換章節
- 我們所使用的SpringCloud有哪些部分
Services, ConfigServer, ServiceDiscovery
描述一下各個存在的職責與目的
- 同步呼叫的執行過程,帶出Eureka與Feign的存在,職責
下一張再講他們各自的操作
- Eureka:服務的註冊(server),與發現(client),會配合Ribbon使用
Feign:RestfulAPI包裝
** 下一張換章節
- 整個微服務專案建置的過程中發生了很多狀況
這次針對幾個代表性的狀況描述一下
- 主要是Feign的問題
傳遞Get參數時,若沒有指定annotation,會被塞入
- @SpringQueryMap於底層會透過QueryMapEncode對參數進行序列化
- 2015年建置底層
然而這些功能2018年12月才加進來
- 所以當時我們的作法是自己實作 FeignObjectEncoder
實作內容
非Get仍走原本的行
Get時將參數處理成QueryString
且要清空Body,否則還是會被轉為Post
- 小結一下
- Service透過Fiegn連續呼叫
- 只會知道A的Feign報錯了
** 下一頁有梗
- ** 下一頁有梗
- 回頭描述一下有Log的樣子而且這實際上不算是問題,因為每個Service理應都只專注在自己的事情上
- FeignException的建構子
其中message就是"status %s reading %s"
而真正的ExceptionMessage則在content
- 以發生順序的方式講解訊息被包掉的原因
一個原因是FeignException的結構
另一個原因是SpringMVC處理Exception的方式
- 只要讓MVC包Exception訊息時,碰到FeignException就多處理content的資訊
- 小結一下
- 開發時需要流程測試,但是服務切太多了,一台電腦根本跑不動
- 我司解法,在一個叢及環境上開出這些服務
- 這些服務全部都能夠對外獨立呼叫
- 實際上這是透過Eureka做到的
- 講一下Zone的作用方式** 下一張有梗
- FOO開了BC
BAR開了DA由於BAR沒有開C,所以這C理應要呼叫公司的叢集環境,但…
** 下一張有梗
- 會打所有已知的Service
Eureka的所有已知,包含了公司叢集、BAR、理所當然也包含FOO
** 下一張有梗
- 說明一下Eureka跟Ribbon的機制
- 白話:自製Zone選擇Service的規則,然後註冊為SpringBean
下一張才講實作內容
- 實作內容
- 小結一下
- 總結,同時說明SpringCloud與K8S元生解決方案的對應
- 公司招生中