SpringCloud學習系列之二 ----- 服務消費者(Feign)和負載均衡(Ribbon)

来源:https://www.cnblogs.com/xuwujing/archive/2019/01/16/10273989.html
-Advertisement-
Play Games

本篇主要介紹的是SpringCloud中的服務消費者(Feign)和負載均衡(Ribbon)功能的實現以及使用Feign結合Ribbon實現負載均衡。 ...


前言

本篇主要介紹的是SpringCloud中的服務消費者(Feign)和負載均衡(Ribbon)功能的實現以及使用Feign結合Ribbon實現負載均衡。

SpringCloud Feign

Feign 介紹

Feign是一個聲明式的Web Service客戶端,它使得編寫Web Serivce客戶端變得更加簡單。我們只需要使用Feign來創建一個介面並用註解來配置它既可完成。它具備可插拔的註解支持,包括Feign註解和JAX-RS註解。Feign也支持可插拔的編碼器和解碼器。Spring Cloud為Feign增加了對Spring MVC註解的支持,還整合了Ribbon和Eureka來提供均衡負載的HTTP客戶端實現。

開發準備

開發環境

  • JDK:1.8
  • SpringBoot:2.1.1.RELEASE
  • SpringCloud:Finchley

註:不一定非要用上述的版本,可以根據情況進行相應的調整。需要註意的是SpringBoot2.x以後,jdk的版本必須是1.8以上!

確認了開發環境之後,我們再來添加相關的pom依賴。

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

註: 基於SpringBoot1.x以上SpringCloud是Dalston版本的eureka 依賴是 <artifactId>spring-cloud-starter-eureka</artifactId>,feign 依賴是 <artifactId>spring-cloud-starter-feign</artifactId> ,少了個 netflix 。SpringCloud的版本命名方式是通過倫敦的地方來命名的,版本順序是根據首字母的順序來的。

SpringCloud Feign 示例

服務端

首先建立一個springcloud-feign-eureka服務的工程,用於做註冊中心。配置和之前的基本一樣。application.properties添加如下的配置:

配置信息:

spring.application.name=springcloud-feign-eureka-server
server.port=8001
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://localhost:8001/eureka/

配置說明:

  • spring.application.name: 這個是指定服務名稱。
  • server.port:服務指定的埠。
  • eureka.client.register-with-eureka:表示是否將自己註冊到Eureka Server,預設是true。
  • eureka.client.fetch-registry:表示是否從Eureka Server獲取註冊信息,預設為true。
  • eureka.client.serviceUrl.defaultZone: 這個是設置與Eureka Server交互的地址,客戶端的查詢服務和註冊服務都需要依賴這個地址。

完成配置信息的添加後,我們再來看代碼如何實現。
在服務端這邊只需要在SpringBoot啟動類添加@EnableEurekaServer註解就可以了,該註解表示此服務是一個服務註冊中心服務。

代碼示例:

    @EnableEurekaServer
    @SpringBootApplication
    public class FeignEurekaApplication {
      public static void main(String[] args) {
          SpringApplication.run(FeignEurekaApplication.class, args);
          System.out.println("feign註冊中心服務啟動...");
      }
    }

客戶端

這裡我們定義兩個消費者,springcloud-feign-consumerspringcloud-feign-consumer2,一個使用feign做轉發,另一個為一個普通的項目。 添加如上的依賴之後,在application.properties添加如下的配置:

consumer 配置信息:

spring.application.name=springcloud-feign-consumer
server.port=9002
eureka.client.serviceUrl.defaultZone=http://localhost:8001/eureka/

consumer2 配置信息:

spring.application.name=springcloud-feign-consumer2
server.port=9003
eureka.client.serviceUrl.defaultZone=http://localhost:8001/eureka/

配置說明:

  • spring.application.name: 這個是客戶端的服務名稱。如果有多個服務使用同一個名稱但是訪問地址不同,結合ribbon 使用,則可以實現負載均衡功能。
  • server.port:服務指定的埠。
  • eureka.client.serviceUrl.defaultZone: 註冊中心服務端的地址。
springcloud-feign-consumer

springcloud-feign-consumer服務因為要實現fegin的功能,因此需要在啟動類上添加@EnableFeignClients該註解,使用該註解表示啟用feign進行遠程調用。

啟動類代碼示例:

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class FeignConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(FeignConsumerApplication.class, args);
              System.out.println("feign第一個消費者服務啟動...");
        }
    }

需要定義轉發的服務,這裡使用@FeignClient註解來實現,該註解表示需要轉發服務的名稱,該名稱在application.properties中進行配置。
這裡我們把請求轉發到第二個服務springcloud-feign-consumer2

轉發類代碼示例:


    @FeignClient(name= "springcloud-feign-consumer2") 
    public interface HelloRemote {
        @RequestMapping(value = "/hello")
         public String hello(@RequestParam(value = "name") String name);
    }

我們還需要提供一個入口供外部調用,然後調用上述的的方法進行轉發。

控制層代碼示例:

    @RestController
    public class ConsumerController {
    
        @Autowired
        HelloRemote helloRemote;
        
        @RequestMapping("/hello/{name}")
        public String index(@PathVariable("name") String name) {
            System.out.println("接受到請求參數:"+name+",進行轉發到其他服務");
            return helloRemote.hello(name);
        }
    }
springcloud-feign-consumer2

這個服務的代碼就比較簡單了,只是一個普通的服務,提供一個介面然後列印信息即可。

啟動類代碼示例:

    @SpringBootApplication
    @EnableDiscoveryClient
    public class FeignConsumerApplication2 {
        public static void main(String[] args) {
            SpringApplication.run(FeignConsumerApplication2.class, args);
              System.out.println("feign第二個消費者服務啟動...");
        }
    }

控制層代碼示例:

    @RestController
    public class ConsumerController {
    
        @RequestMapping("/hello")
        public String index(@RequestParam String name) {
            return name+",Hello World";
        }
    }

功能測試

完成如上的工程開發之後,我們依次啟動服務端和客戶端的三個程式,然後在瀏覽器界面輸入:http://localhost:8001/,即可查看註冊中心的信息。

在瀏覽器輸入:

http://localhost:9003/hello?name=pancm

返回:

pancm,Hello World

說明可以直接訪問第二個消費服務。

然後再輸入:

http://localhost:9002/hello/pancm

通過第一個消費服務調用第二個服務。

控制台列印:

接受到請求參數:pancm,進行轉發到其他服務

界面返回結果:

pancm,Hello World

示例圖:

在這裡插入圖片描述

在這裡插入圖片描述

出現以上結果說明客戶端已經成功的通過feign調用了遠程服務hello,並且將結果返回到了瀏覽器。

SpringCloud Ribbon

Ribbon 介紹

Ribbon是Netflix發佈的開源項目,主要功能是提供客戶端的軟體負載均衡演算法,將Netflix的中間層服務連接在一起。Ribbon客戶端組件提供一系列完善的配置項如連接超時,重試等。簡單的說,就是在配置文件中列出Load Balancer後面所有的機器,Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨即連接等)去連接這些機器。我們也很容易使用Ribbon實現自定義的負載均衡演算法。簡單地說,Ribbon是一個客戶端負載均衡器。

開發準備

開發環境

  • JDK:1.8
  • SpringBoot:2.1.1.RELEASE
  • SpringCloud:Finchley

註:不一定非要用上述的版本,可以根據情況進行相應的調整。需要註意的是SpringBoot2.x以後,jdk的版本必須是1.8以上!

確認了開發環境之後,我們再來添加相關的pom依賴。

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

註: 基於SpringBoot1.x以上SpringCloud是Dalston版本的eureka 依賴是 <artifactId>spring-cloud-starter-eureka</artifactId>,feign 依賴是 <artifactId>spring-cloud-starter-ribbon</artifactId> ,少了個 netflix 。SpringCloud的版本命名方式是通過倫敦的地方來命名的,版本順序是根據首字母的順序來的。

SpringCloud Ribbon 示例

服務端

首先建立一個springcloud-ribbon-eureka服務的工程,用於做註冊中心。配置和代碼之前的基本一樣,除了埠和列印信息,這裡就不在說明瞭。

客戶端

這裡我們定義三個服務,一個服務使用Ribbon做負載均衡,另外兩個做普通的服務,服務名稱依次為springcloud-ribbon-consumerspringcloud-ribbon-consumer2springcloud-ribbon-consumer3。 添加如上的依賴之後,在application.properties添加如下的配置:

consumer 配置信息:

spring.application.name=springcloud-ribbon-consumer
server.port=9006
eureka.client.serviceUrl.defaultZone=http://localhost:8003/eureka/

consumer2 配置信息:

spring.application.name=springcloud-ribbon-consumer2
server.port=9007
eureka.client.serviceUrl.defaultZone=http://localhost:8003/eureka/

consumer3 配置信息:

這裡的服務名稱和另一個服務的名稱保持一致才能實現負載均衡功能。

spring.application.name=springcloud-ribbon-consumer2
server.port=9008
eureka.client.serviceUrl.defaultZone=http://localhost:8003/eureka/

配置說明:

  • spring.application.name: 這個是客戶端的服務名稱。如果有多個服務使用同一個名稱但是訪問地址不同,結合ribbon 使用,則可以實現負載均衡功能。
  • server.port:服務指定的埠。
  • eureka.client.serviceUrl.defaultZone: 註冊中心服務端的地址。
springcloud-ribbon-consumer

使用Ribbon實現負載均衡,只需要在啟動類中實例化RestTemplate,通過@LoadBalanced註解開啟均衡負載能力.。

啟動類代碼示例:


    @SpringBootApplication
    @EnableDiscoveryClient
    public class RibbonConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(RibbonConsumerApplication.class, args);
            System.out.println("ribbon第一個消費者服務啟動...");
        }
    
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }

需要定義轉發的服務,這裡使用RestTemplate來進行調用,調用另外一個服務的名稱。

轉發類代碼示例:


    @RestController
    public class ConsumerController {
       
        @Autowired
        RestTemplate restTemplate;
        
        @RequestMapping("/hello")
        public String hello() {
            //進行遠程調用
            return restTemplate.getForObject("http://springcloud-ribbon-consumer2/hello/?name=xuwujing", String.class);
        }
    }
    

springcloud-ribbon-consumer2springcloud-ribbon-consumer3代碼基本和fegin中的springcloud-feign-consumer一樣,因此這裡就不在貼代碼了。

功能測試

完成如上的工程開發之後,我們依次啟動服務端和客戶端的四個程式,然後在瀏覽器界面輸入:http://localhost:8003/,即可查看註冊中心的信息。

在瀏覽器輸入:

http://localhost:9006//hello

然後進行重覆訪問,返回如下結果:

xuwujing,Hello World!
xuwujing,Hello World! 這是另一個服務!
xuwujing,Hello World!
xuwujing,Hello World! 這是另一個服務!
xuwujing,Hello World!
xuwujing,Hello World! 這是另一個服務!

說明已經實現了負載均衡功能了。

我們從上述的結果中發現了一點,這個調用貌似是有規律的,兩個服務進行來回調用。那麼根據這個我們發現了,負載均衡是由策略的。上述的這個示例的策略就是其中的一個RoundRobinRule輪詢策略。

這裡就順便說下Ribbon的策略,Ribbon一共有7中策略,預設使用的策略是輪詢。策略說明如下表格:

策略名 策略聲明 策略描述 實現說明
BestAvailableRule public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule 選擇一個最小的併發請求的server 逐個考察Server,如果Server被tripped了,則忽略,在選擇其中ActiveRequestsCount最小的server
AvailabilityFilteringRule public class AvailabilityFilteringRule extends PredicateBasedRule 過濾掉那些因為一直連接失敗的被標記為circuit tripped的後端server,並過濾掉那些高併發的的後端server(active connections 超過配置的閾值) 使用一個AvailabilityPredicate來包含過濾server的邏輯,其實就就是檢查status里記錄的各個server的運行狀態
WeightedResponseTimeRule public class WeightedResponseTimeRule extends RoundRobinRule 根據響應時間分配一個weight,響應時間越長,weight越小,被選中的可能性越低。 一個後臺線程定期的從status裡面讀取評價響應時間,為每個server計算一個weight。Weight的計算也比較簡單responsetime 減去每個server自己平均的responsetime是server的權重。當剛開始運行,沒有形成status時,使用roubine策略選擇server。
RetryRule public class RetryRule extends AbstractLoadBalancerRule 對選定的負載均衡策略機上重試機制。 在一個配置時間段內當選擇server不成功,則一直嘗試使用subRule的方式選擇一個可用的server
RoundRobinRule public class RoundRobinRule extends AbstractLoadBalancerRule roundRobin方式輪詢選擇server 輪詢index,選擇index對應位置的server
RandomRule public class RandomRule extends AbstractLoadBalancerRule 隨機選擇一個server 在index上隨機,選擇index對應位置的server
ZoneAvoidanceRule public class ZoneAvoidanceRule extends PredicateBasedRule 複合判斷server所在區域的性能和server的可用性選擇server 使用ZoneAvoidancePredicate和AvailabilityPredicate來判斷是否選擇某個server,前一個判斷判定一個zone的運行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用於過濾掉連接數過多的Server。

這裡也順便說明如何指定一個策略使用方法。

最簡單的方式

application.properties添加如下配置:

springcloud-ribbon-consumer2.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

該配置的意思是為springcloud-ribbon-consumer2服務指定隨機策略。

另一種方式

新建一個類,通過@Bean註解指定策略。


    @Configuration
    public class RibbonConfiguration{
          @Bean
          public IRule ribbonRule(){        
              return new RandomRule();
         }
    }

然後再通過@RibbonClien註解指定服務。


    @RibbonClient(name="springcloud-ribbon-consumer2", configuration=RibbonConfiguration.class)
    public class HelloRibbon{    
    }

註: 如果有的服務沒有在Eureka進行註冊,可以使用ribbon.listOfServers方式在配置文件中來指定服務。

例如:

springcloud-ribbon-consumer2.ribbon.listOfServers:localhost:9007,localhost:9008

添加好了該配置之後,我們重啟springcloud-ribbon-consumer服務,然後依舊重覆訪問 http://localhost:9006//hello 該地址,
訪問的結果如下:

xuwujing,Hello World!
xuwujing,Hello World! 這是另一個服務!
xuwujing,Hello World! 這是另一個服務!
xuwujing,Hello World!
xuwujing,Hello World!
xuwujing,Hello World!

可以看到已經成功實現了隨機訪問的策略!

SpringCloud Fegin結合Ribbon實現負載均衡

Fegin包含了Ribbon,可以直接實現負載均衡功能。這裡我們就在Ribbon的項目稍微進行改造下實現該功能。

首先在pom文件添加Fegin的依賴包。

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

然後在springcloud-ribbon-consumer項目的啟動類上添加@EnableFeignClients註解,啟用feign進行遠程調用。

添加完成之後,新建一個類,實現feign遠程調用。
代碼如下:

    @FeignClient(name= "springcloud-ribbon-consumer2") 
    public interface HelloRemote {
        @RequestMapping(value = "/hello")
        public String hello(@RequestParam(value = "name") String name);
    }

最後在提供一個新的介面供外部調用。這裡就直接在之前的代碼上新加一個介面了。
代碼如下:


    @RestController
    public class ConsumerController {
       
        @Autowired
        RestTemplate restTemplate;
        
        @RequestMapping("/hello")
        public String hello() {
            return restTemplate.getForObject("http://springcloud-ribbon-consumer2/hello/?name=xuwujing", String.class);
        }
        
       
        @Autowired
        HelloRemote helloRemote;
        
        @RequestMapping("/hello/{name}")
        public String index(@PathVariable("name") String name) {
            System.out.println("接受到請求參數:"+name+",進行轉發到其他服務!");
            return helloRemote.hello(name);
        }
    }

添加完之後,重啟springcloud-ribbon-consumer服務,然後依舊重覆訪問 http://localhost:9006//hello/pancm 該地址,
訪問的結果如下:

pancm,Hello World!
pancm,Hello World! 這是另一個服務!
pancm,Hello World!
pancm,Hello World! 這是另一個服務!
pancm,Hello World!
pancm,Hello World! 這是另一個服務!

示例圖:
在這裡插入圖片描述

在這裡插入圖片描述

其他

項目地址

基於SpringBoot1.x、SpringCloud的Dalston版本開發的地址:https://github.com/xuwujing/springcloud-study

基於SpringBoot1.x、SpringCloud 的Dalston版本開發的地址: https://github.com/xuwujing/springcloud-study-old

如果感覺項目不錯,希望能給個star,謝謝!

音樂推薦

一首非常棒的純音樂 NEXT TO YOU ,強烈推薦!

原創不易,如果感覺不錯,希望給個推薦!您的支持是我寫作的最大動力!
版權聲明:
作者:虛無境
博客園出處:http://www.cnblogs.com/xuwujing
CSDN出處:http://blog.csdn.net/qazwsxpcm    
個人博客出處:http://www.panchengming.com


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 智慧園區 --> --> 控制台 --> 退出 ... ...
  • 個人博客原文 "創建型模式:工廠方法" 簡介 姓名 :工廠方法 英文名 :Factory method Pattern 價值觀 :擴展是我的專屬 個人介紹 : Define an interface for creating an object,but let subclasses decide w ...
  • 前一陣子剛整理完RocketMQ4.3.x版本的相關配置的工作,接下來就來測試一下改變參數會帶來什麼好的結果 首先我就選中了useEpollNativeSelector 這個參數 預設這個參數是 false 這個參數的意思就是是否啟用Epoll IO模型。Linux環境建議開啟 然後我就打開了這個參 ...
  • 一、引言 生活中有很多模板,如:簡歷模板、論文模板,PPT模板,所謂模板就是有一個特定的格式,但是可以根據自身的需求進行改動,然後實現自己的功能。這樣的好處就是可以減少自身的工作量,想想網上那麼多好的PPT模板,改吧改吧就成自己的,這是一件多酸爽的事情! 二、例子入手 現在有兩個類,分別是泡茶和泡咖 ...
  • 一直想寫關於產品設計思路或者說方案策略性的文章,一直都不好下筆,因為產品設計是一個很大很空佷泛話題,而且每個人都有自己的一套思路。基於以上情況本文只是總結個人的一套思路,供大家參考。 1.以人為本的黃金設計定律 任何產品的設計都是基於目標用戶的需求而設計,其目的是為用戶解決需求的同時並提供更高的價值 ...
  • 一、引言 電商項目中一個常見場景:提交訂單操作,提交訂單後有很多後續動作,例如:檢查訂單, 創建訂單, 減庫存,創建支付鏈接等等,這些子類的內部操作都很複雜。如果我們的客戶端程式要直接跟這些內容子系統進行耦合,那麼客戶端就得隨著子系統的改動而改動。提交訂單操作在一個電商系統中很多地方都會出現,如果每 ...
  • 以下為DI控制反轉個人理解煩請各位大牛指教~ 編寫程式時我們應當遵循抵耦合高內聚的原則(各個功能模塊互不依賴). 我們可以利用面向對象裡面介面的特性來進行DI控制反轉,讓功能模塊全部依賴介面,而不依賴具體的實現類,當程式跑起來以後通過註入的方式註入具體的實現類如以下代碼: 這樣,購物車類就實現了松耦 ...
  • 內容過程,把做工程過程較好的內容片段備份一次,如下的內容是關於 JavaBean到JSon格式的轉換例子的內容,應該對各朋友有一些用處。 User u = new User(); u.setId(1); u.setName("lizhi"); u.setAge(24); u.setHeigh("17 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...