基于spring boot 2.0的IoT應用集成和使用servicecomb實踐(基于springboot的畢設)
目錄
- 集成步驟
- 集成效果
- 運行時變化
- 開發方式變化
- 周邊工具變化
- 開啟metrics監控
- 常見問題
- 三方件沖突
- SpringMVC數據類型支持
- 依賴于Spring MVC特定機制的業務邏輯
本文通過一個IoT的應用展現在Spring Boot 2.0中集成和使用servicecomb。IoT應用原來使用Spring Boot 2.0開發,然后通過少量的步驟集成servicecomb。本文說明集成servicecomb以后給應用帶來了哪些新特性,中間存在的一些變化和改造過程中碰到的問題。本文檔根據servicecomb 2.0.1版本刷新,詳細的版本介紹請參考SDK配套關系說明。
集成步驟
在Spring Boot中集成servicecomb的基本原理,可以參考在spring boot中使用java chassis的描述。將一個現有 Spring Boot的應用改造為servciecomb,一般可以采用下面的步驟。需要注意下面的步驟是一般的改造步驟,完成這些步驟后,可以識別出常見問題,逐個解決這些問題。
增加依賴關系
在dependencyManagement里面導入servicecomb的依賴管理,dependencyManage能夠簡化依賴管理的工作量,減少三方件沖突,詳細可以參考使用maven管理復雜依賴關系的技巧。
然后引入servicecomb對于spring boot 2提供的支持組件包。
2.? ? ?啟用ServiceComb能力
通過@EnableServiceComb標簽在Spring Boot 2中啟用和加載servicecomb。在Spring Boot 2中,開發者會將服務通過DispatcherServlet發布為REST接口,在Spring Boot 2默認實現中,REST接口通過DispatcherServlet發布,集成servicecomb后,服務通過servicecomb提供的RestServlet進行發布。集成后,兩個Servlet可以并存,可以將他們的上下文設置為不同的前綴,以避免沖突。具體參考步驟3。
@SpringBootApplication???? @EnableServiceComb???? public?class?UserMain?{???? ??public?static?void?main(String[]?args)?throws?Exception?{???? ????try?{???? ??????SpringApplication.run(UserMain.class,?args);???? ????}?catch?(Exception?e)?{???? ??????e.printStackTrace();???? ????}???? ??}???? }
3.?????? 發布服務接口
和Spring Boot 2一樣,servicecom也會掃描@RestContoller標簽的類,并將這些類發布為REST接口。同時將接口信息注冊到服務中心。可以在application.yml中指定服務中心地址,并提供簡單的微服務信息。其中service_description.name可以使用原來項目的名字,servicecomb.rest.address采用tomcat的監聽端口server.port進行發布。其中server.servlet.path=/mvc和servicecomb.rest.servlet.urlPattern=/cse/*分別是Spring Boot的DispatcherServlet和servicecom的RestServlet前綴。
APPLICATION_ID:???MY_APPLICATION service_description: ??name:?${spring.application.name} ??version:?0.0.1 ? servicecomb: ??service: ????registry: ??????address:?http://localhost:30100 ??????instance: ????????watch:?false ??rest: ????address:?0.0.0.0:9091 ?? ??servlet: ????urlPattern:?/cse/* ???? server: ??servlet:? ????path:?/mvc
集成效果
在上面的例子中,很簡單的將原來的Spring Boot 2.0應用的運行時轉換成了了servicecom。但是轉換本身不是目的,下面通過一些變化來說明轉換后給業務系統帶來的收益以及可能的功能丟失和工作量,以方便用戶評估是否值得做這樣的集成。
運行時變化
運行時變化是收益和損失的直接來源。在上面的改造中,客戶端代碼和服務端代碼均沒有變化(或者極少變化),客戶端仍然使用RestTemplate調用服務端代碼,服務端仍然提供的是REST接口,可以使用post man等工具訪問。運行時變化不修改微服務對外的接口行為,這個是改造的基礎。
改造前,Spring Boot 2的運行時簡圖如下。在客戶端,可以使用Spring RestTemplate提供的各種MessageConverters處理請求消息編碼和響應消息解碼,在服務端,可以使用Spring MVC提供的各種功能對用戶參數進行校驗。
改造后,運行時簡圖如下。servicecomb客戶端和服務端均提供了統一一致的處理鏈,并默認實現了負載均衡、熔斷容錯、灰度發布等功能。
運行時功能的一個核心特征是快速完成了應用微服務化改造。微服務的一個基本特征是多實例,通過網絡接口進行通信。因此解決服務發現問題以及通信不可靠性問題是進行微服務化的一個基本保障。通過集成servicecomb,幫用戶快速構建這些能力,減少了需要學習和開發其他Spring Boot、Spring Cloud組件的成本。
servicecomb本身也提供了豐富的開發和擴展能力,可以從設計選型參考了解servicecomb的更多信息。
開發方式變化
使用Spring Boot 2,開發者可以使用RestTemplate或者使用Feign來訪問服務端接口。servicecomb也支持兩種方式RestTemplate和RPC。相比較于Feign,servicecomb的RPC更加簡潔,無需在客戶端定義和使用REST標簽。
@RpcReference(microserviceName ? = "hello", schemaId = "hello")
private ? Hello hello;
System.out.println(hello.sayHi("Java ? Chassis"));
這種方式適用于采用servicecomb框架開發的微服務之間的訪問。如果訪問第三方,servicecomb已提供非常簡單的方式,詳細參考調用第三方服務
通過集成servicecomb,開發者可以方便的在代碼中隨時使用REST和RPC,非常靈活,大大節省書寫代碼的時間。
周邊工具變化
上面的討論都限制在微服務本身。為了保證業務功能能夠持續高效運行運維,還需要給微服務提供一個功能強大的運行環境,實現微服務運行狀況的監控、微服務功能的實時調整(流量控制、灰度發布、熔斷容錯等)。這里可以借助于商業解決方案快速實現或者開源解決方案自行搭建。
l? 商業解決方案
華為[微服務引擎]( https://console.huaweicloud.com/cse/)提供了一站式微服務管理功能。將改造的應用部署到微服務引擎,即可實現微服務目錄查看、接口管理、動態治理等多種功能。
微服務引擎的核心組件包括服務中心、配置中心和治理中心。除了將業務部署到云上,開發者可以在本地使用這些服務,只需要有可用的網絡連接,注冊華為云微服務引擎并獲取AK/SK身份信息。
l? 開源解決方案
[服務中心]( https://github.com/apache/incubator-servicecomb-service-center)。服務中心提供了注冊發現服務,還提供了前端服務,用于查看服務目錄和進行接口測試。
[配置中心]( https://github.com/ctripcorp/apollo)。這個是攜程開發的配置中心。CSE支持通過Netflix Archaius擴展,使用各種配置服務。
[調用鏈zipkin]( https://github.com/openzipkin/zipkin)。這個標準的zipkin調用鏈服務。CSE支持通過Hanlder擴展實現了與zipkin調用鏈對接。
[調用鏈skywalking]( https://github.com/apache/incubator-skywalking/tree/master/apm-sniffer/apm-sdk-plugin/servicecomb-plugin)。
可以從開發指南了解如何集成和使用這些開源組件。
servicecomb本身作為Spring Boot 2.0的一個Servlet運行,因此Spring Boot、Spring Cloud提供的大多數組件,用戶也可以選擇使用。Spring Cloud場景會選擇eureka等作為服務發現服務,CSE需要使用服務中心作為服務發現。在服務中心選擇上,目前還未有統一的標準,配套的SDK只能采用推薦的服務發現工具。
開啟metrics監控
servicecomb提供了強大的metrics功能,能夠幫助開發者分析性能問題。改造后的引用只需要引入metrics相關jar包,并在application.yml增加開關啟用metrics,即可使用。metrics數據可以通過兩種方式獲取。
l? 通過接口查詢
地址: http://localhost:9091/metrics
輸出參考:(截取了執行時間和平均調用次數,統計周期為60s)
"servicecomb.invocation(operation=huawei-cloud-ioccity-app-basemgmt.EquipmentInfoController.getEquipmentList,role=PRODUCER,stage=execution,statistic=totalTime,status=200,transport=rest)":0.011417577750000001,
"servicecomb.invocation(operation=huawei-cloud-ioccity-app-basemgmt.EquipmentInfoController.getEquipmentList,role=PRODUCER,stage=total,statistic=count,status=200,transport=rest)":0.016666666666666666
l? 輸出到日志文件
配置項: cse.metrics.publisher.defaultLog.enabled=true
輸出參考:(截取了性能部分)
producer:
tps???? latency(ms) ? max-latency(ms) queue(ms) max-queue(ms) execute(ms) max-execute(ms) operation
rest.200:
0?????? 0.000?????? 727.756???????? 0.000???? 23.542??????? 0.000?????? 704.214???????? ? huawei-cloud-ioccity-app-basemgmt.EquipmentInfoController.getEquipmentList
常見問題
在使用新的框架對業務進行改造的時候,都會碰到一些問題。原理介紹了改造過程中可能碰到問題,以及一些通用的模式,可以閱讀這個文章以評估改造的工作量。下面列舉了在改造IoT系統中碰到的幾個常見問題及其解決方案。
三方件沖突
在引入新的框架或者組件的時候,三方件沖突是非常常見的問題。解決三方件沖突的前提是版本之間能夠兼容。沖突的原因可能很多,解決這類問題沒有固定的思路,但掌握了maven依賴關系管理技巧以及理解沖突產生的原因后,通常分析和解決這類問題會變得更加簡單。建議閱讀maven管理技巧。
SpringMVC數據類型支持
servicecomb支持SpringMVC的標簽定義REST接口,一般情況下,將SpringMVC的應用改造為servicecomb都會非常簡單。但是servicecomb和SpringMVC的運行時不同,設計目標也有差異,所以還會存在一些差異的地方。這塊的主要差異點是使用CSE定義REST接口,支持的annotation和數據類型相對于SpringMVC變少了,詳細說明參考。
比如,下面的一些REST接口定義在servicecomb中是不能使用或者有限制使用的。
import???org.springframework.data.domain.Page; @GetMapping(params???=?{?"pageNumber",?"pageSize"?}) public?ResponseEntity
該接口在定義的時候,Page是一個interface。servicecomb不支持在接口定義上使用泛型,包括interface、abstract class等。servicecomb做出這個限制的原因是因為servicecomb需要遵循open API規范,接口定義必須能夠存在對應的swagger描述。如果使用interface和abstract class,那么則無法通過swagger來描述這個接口。
l? 解決方案
業務代碼應該采用合理的分層設計,這樣就可以保證代碼能夠非常靈活的在不同框架下進行遷移。如果使用Spring開發,分層設計可以遵循Spring的一些建議。業務邏輯在@Service中實現,框架接口發布在@Controller實現。當在不同框架發布服務的時候(比如Servlet、Spring MVC、servicecomb等),只需要簡單的調整@Controller代碼,不需要修改@Service代碼。以上面的接口舉個例子。
@Service public?class?MyService?{ ??public?Page
發布為Spring MVC的Endpoint:
@RestController public?class???SpringMVCEndpoint?{ ??@Autowired private?MyService?service; ? ??@PostMapping(value?=?"/search") public?ResponseEntity
發布為Servlet:
public?class???ServletEndpoint?extends?HttpServlet?{ ??@Autowired ???private?MyService?service; ? ???void?doPost(HttpServletRequest?req,?HttpServletResponse?resp)???{ ????//???extract?request ?????service.findAll(request,?HttpStatus.OK); ?????//?send?response ???} }
發布為servicecomb的接口:
Class?PageModel>(result,?HttpStatus.OK); ??} }
依賴于Spring MVC特定機制的業務邏輯
在我們的改造步驟二中,去掉了DispatcherServletAutoConfiguration,即Spring MVC REST 提供的相關功能被移除了。Spring MVC提供的有些接口需要依賴于這個功能,移除后,會導致這部分功能無法使用。比如:
import???org.springframework.web.context.request.RequestContextHolder; import???org.springframework.web.context.request.ServletRequestAttributes; @Before("webLog()") public???void?doBefore(JoinPoint?joinPoint)?throws?Throwable?{ ????//?接收到請求,記錄請求內容 ????ServletRequestAttributes?attributes?=???(ServletRequestAttributes)?RequestContextHolder.getRequestAttributes(); ????HttpServletRequest?request?=???attributes.getRequest(); ? ????//?記錄下請求內容 log.info("URL?:?"?+???request.getRequestURL().toString()); }
上面這段代碼通過RequestContextHolder獲取Servlet請求,并從請求中獲取一些頭信息來記錄日志。RequestContextHolder依賴于Spring MVC REST來設置請求上下文,在整改后,獲取到的attributes為空,從而導致拋出NPE異常。
l? 解決方案
這種依賴于平臺提供的特定功能,在進行改造的時候,都需要結合使用的平臺,看是否有替代方案。這段代碼的本意是實現審計日志或者調用鏈等邏輯,servicecomb提供Handler來獲取這些信息,并已經實現了調用鏈等功能,所以可以直接使用,或者通過自定義Handler、HttpFilter等機制實現類似的功能。
Spring Boot IoT Spring
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。