Spring Cloud 實戰系列之 Zuul 微服務網關搭建及配置

一、創建SpringBoot項目

在這里插入圖片描述
在這里插入圖片描述
用mavan搭建也可以。(重要的是后面pom里應該引入那些依賴,application.yml怎么配置)
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述

由于開始構建項目時選擇了Eureka Server,所以pom.xml中不需要手動添加依賴了

首先在啟動類SpringcloudApplication中添加EurekaServer的注解:@EnableEurekaServer
在這里插入圖片描述
在這里插入圖片描述

二、application.yml

server:port: 9000  #eureka注冊中心服務端口eureka:instance:hostname: localhostclient:register-with-eureka: false #不向eureka注冊中心注冊。也就是為了關閉自己向自己注冊,eureka默認要向自己注冊fetch-registry: falseservice-url:defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

在這里插入圖片描述
訪問注冊中心:按照配置的端口號訪問。我這里配了9000,端口隨意,如下圖代表Eureka注冊中心部署成功了。
顯示沒有實例在此中心注冊。沒事接下來我們開始配置zuul網關,它也是一個服務需要注冊到此注冊中心來。
在這里插入圖片描述

三、提供Service服務

eurekaservice01,eurekaservice02,eurekaservice03,eurekaservice04,第一個如下,第二三四個按著第一個的建,修改一下名字,端口號還有方法返回值
在這里插入圖片描述
需要用到mvc
在這里插入圖片描述
服務提供者同樣需要注冊到注冊中心
在這里插入圖片描述
在這里插入圖片描述

接下來是同樣的套路,改yml,啟動類添加注解:@EnableEurekaClient
yml配置如下(因為是測試所有很簡陋):

server:port: 8900 # 服務提供方# 指定當前eureka客戶端的注冊地址,
eureka:client:service-url:defaultZone: http://${eureka.instance.hostname}:9000/eureka/instance:hostname: localhost#當前服務名稱
spring:application:name: eurekaservice1

注意當前服務名稱。這里用于注冊到注冊中心的名字,還可以啟動很多同樣為eurekaservice1的名字的微服務到注冊中心,zuul從注冊中心Eureka Server獲取所有服務名為eurekaservice01的服務列表后,會采用負載均衡策略訪問其中一臺服務提供者獲取資源。

下圖我們之前zuul中的配置serviceId就是指向這里的服務名稱,這是微服務調用的精髓,通過服務名調用。
既然是服務提供者 ,這里要編寫controller類了:新建controller包,新建Test01類,編寫REST的方法。返回服務1
在這里插入圖片描述
按照服務提供者1的搭建方式,現在搭建服務提供者2:
同樣是新建模組,名字改為…02,yml配置文件中端口號與服務1要不同,服務名稱相同,為了測試負載均衡,REST方法返回值設為服務2。
在這里插入圖片描述
在這里插入圖片描述

server:port: 8901 # 服務提供方# 指定當前eureka客戶端的注冊地址,
eureka:client:service-url:defaultZone: http://${eureka.instance.hostname}:9000/eureka/instance:hostname: localhost#當前服務名稱
spring:application:name: eurekaservice1

同樣的方法再建兩個服務提供者3和4,服務名稱都為eurekaservice2,端口號分別為8902,和8903。REST方法返回值分別為,服務3和服務4。
在這里插入圖片描述
在這里插入圖片描述

四、Zuul網關服務

搭建了注冊中心,和服務的提供者,我們現在開始搭建Zuul網關服務,最后通過zuul訪問注冊中心獲取服務列表,然后訪問服務提供者。
在這里插入圖片描述
這里模組名設為zuul。包名設置為zuul,等會生成的啟動類就會是帶有zuul了。EurekaServer也可以這樣只是我開始搭的時候沒有注意到。
在這里插入圖片描述
要Eureka的客戶端組件,和zuul組件,點next
在這里插入圖片描述
在這里插入圖片描述
模組名設為zuul,不強制
在這里插入圖片描述
項目結構:
在這里插入圖片描述
在啟動類配置注解 @EnableEurekaClient,@EnableZuulProxy,@EnableZuulProxy可以稱為@EnableZuulServer的增強版,當Zuul與Eureka、Ribbon等組件配合使用時,我們使用@EnableZuulProxy
在這里插入圖片描述
配置pom文件:

在這里插入圖片描述
啟動項目
在這里插入圖片描述
再去注冊中心看就能看見zuul服務已經被注冊到注冊中心了
在這里插入圖片描述

五、Zuul的訪問

有一個網關服務zuul,一個注冊中心eurekaserver,4個服務提供者eurekaservice,4個服務提供者

其中兩個提供服務名為eurekaservice1的服務,另外兩個提供eurekaservice2的服務,現在我們來啟動4個服務提供者,在注冊中心查看,并通過網關訪問測試網關的服務是否正常。

總項目結構:
在這里插入圖片描述
啟動后注冊中心查看:
在這里插入圖片描述

如之前所想,兩個服務名下各兩臺服務提供者。
現在回想之前zuul的路由配置:
在這里插入圖片描述
訪問zuul網關的test01/**下的任何服務都會給我轉發到服務名為eurekaservice1下的01和02服務下。

第一次訪問:test01
在這里插入圖片描述
第二次訪問:test01
在這里插入圖片描述
可以看見zuul網關做了轉發和負載均衡,使用的是ribbon輪詢的方式負載均衡。
那么可以猜想到我們訪問test02,zuul網關會在服務名為eurekaservice2的服務3和服務4之間去訪問了。我們來看看:
在這里插入圖片描述
在這里插入圖片描述
至此已經實踐完成zuul網關的基本功能轉發和負載均衡。

Zuul網關的應用

通過zuul訪問服務的,URL地址默認格式為:http://zuulHostIp:port/要訪問的服務名稱/服務中的URL

服務名稱:properties配置文件中的spring.application.name
服務的URL:就是對應的服務對外提供的URL路徑監聽

一、網關依賴注入

<!-- spring cloud Eureka Client 啟動器 -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<!-- zuul網關的重試機制,不是使用ribbon內置的重試機制是借助spring-retry組件實現的重試開啟zuul網關重試機制需要增加下述依賴-->
<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId>
</dependency>

二、啟動類

/*** @EnableZuulProxy - 開啟Zuul網關。*  當前應用是一個Zuul微服務網關。會在Eureka注冊中心中注冊當前服務。并發現其他的服務。*  Zuul需要的必要依賴是spring-cloud-starter-zuul。*/
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {public static void main(String[] args) {SpringApplication.run(ZuulApplication.class, args);}
}

三、配置文件:網關全局變量配置

# URL路徑匹配
# 使用路徑方式匹配路由規則。
# 參數key結構:zuul.routes.customName.path=xxx
# 用于配置路徑匹配規則。
# 其中customName自定義。通常使用要調用的服務名稱,方便后期管理
# 可使用的通配符有:* ** ?
# ? 單個字符
# * 任意多個字符,不包含多級路徑
# ** 任意多個字符,包含多級路徑
zuul.routes.eureka-application-service.path=/api/**
# 參數key結構:zuul.routes.customName.url=xxx
# url用于配置符合path的請求路徑路由到的服務地址。
zuul.routes.eureka-application-service.url=http://127.0.0.1:8080/# 服務名稱匹配
# service id pattern 通過服務名稱路由
# key結構 :zuul.routes.customName.path=xxx
# 路徑匹配規則  符合path的請求路徑直接路由到customName對應的服務上
zuul.routes.eureka-application-service.path=/api/**
# key結構 :zuul.routes.customName.serviceId=xxx
# serviceId用于配置符合path的請求路徑路由到的服務名稱。如果只配置path,不配置serviceId。則customName相當于服務名稱
zuul.routes.eureka-application-service.serviceId=eureka-application-service# 路由排除配置
# 配置不被zuul管理的服務列表。多個服務名稱使用逗號','分隔。
# 配置的服務將不被zuul代理。
zuul.ignored-services=eureka-application-service# 此方式相當于給所有新發現的服務默認排除zuul網關訪問方式,只有配置了路由網關的服務才可以通過zuul網關訪問
# 通配方式配置排除列表。
zuul.ignored-services=*
# 使用服務名稱匹配規則配置路由列表,相當于只對已配置的服務提供網關代理。
zuul.routes.eureka-application-service.path=/api/**# 通配方式配置排除網關代理路徑。所有符合ignored-patterns的請求路徑都不被zuul網關代理。
zuul.ignored-patterns=/**/test/**
zuul.routes.eureka-application-service.path=/api/**# 路由前綴配置
# prefix URL pattern 前綴路由匹配
# 配置請求路徑前綴,所有基于此前綴的請求都由zuul網關提供代理。
zuul.prefix=/api
# 使用服務名稱匹配方式配置請求路徑規則。
# 這里的配置將為:http://ip:port/api/appservice/**的請求提供zuul網關代理,可以將要訪問服務進行前綴分類。
# 并將請求路由到服務eureka-application-service中。
zuul.routes.eureka-application-service.path=/appservice/**

網關配置方式有多種,默認、URL、服務名稱、排除|忽略、前綴。
網關配置沒有優劣好壞,應該在不同的情況下選擇合適的配置方案。

zuul網關其底層使用ribbon來實現請求的路由,并內置Hystrix,可選擇性提供網關fallback邏輯。使用zuul的時候,并不推薦使用Feign作為application client端的開發實現。畢竟Feign技術是對ribbon的再封裝,使用Feign本身會提高通訊消耗,降低通訊效率,只在服務相互調用的時候使用Feign來簡化代碼開發就夠了。而且商業開發中,使用Ribbon+RestTemplate來開發的比例更高。

四、路由網關過濾器

Zuul中提供了過濾器定義,可以用來過濾代理請求,提供額外功能邏輯。如:權限驗證,日志記錄等。

Zuul提供的過濾器是一個父類。父類是ZuulFilter。通過父類中定義的抽象方法filterType,來決定當前的Filter種類是什么。有前置過濾、路由后過濾、后置過濾、異常過濾。

  • 前置過濾:是請求進入Zuul之后,立刻執行的過濾邏輯
  • 路由后過濾:是請求進入Zuul之后,并Zuul實現了請求路由后執行的過濾邏輯,路由后過濾,是在遠程服務調用之前過濾的邏輯。
  • 后置過濾:遠程服務調用結束后執行的過濾邏輯。
  • 異常過濾:是任意一個過濾器發生異常或遠程服務調用無結果反饋的時候執行的過濾邏輯。無結果反饋,就是遠程服務調用超時。

過濾器實現方式

繼承父類ZuulFilter。在父類中提供了4個抽象方法,分別是:filterType, filterOrder, shouldFilter, run。其功能分別是:

  • filterType:方法返回字符串數據,代表當前過濾器的類型。可選值有-pre, route, post, error。pre - 前置過濾器,在請求被路由前執行,通常用于處理身份認證,日志記錄等;
  • route - 在路由執行后,服務調用前被調用;
  • error - 任意一個filter發生異常的時候執行或遠程服務調用沒有反饋的時候執行(超時),通常用于處理異常;
  • post - 在route或error執行后被調用,一般用于收集服務信息,統計服務性能指標等,也可以對response結果做特殊處理。
  • filterOrder:返回int數據,用于為同filterType的多個過濾器定制執行順序,返回值越小,執行順序越優先
  • shouldFilter:返回boolean數據,代表當前filter是否生效
  • run:具體的過濾執行邏輯。如pre類型的過濾器,可以通過對請求的驗證來決定是否將請求路由到服務上;如post類型的過濾器,可以對服務響應結果做加工處理(如為每個響應增加footer數據)。

過濾器的生命周期
在這里插入圖片描述

/*** Zuul過濾器,必須繼承ZuulFilter父類。* 當前類型的對象必須交由Spring容器管理。使用@Component注解描述。* 繼承父類后,必須實現父類中定義的4個抽象方法。* shouldFilter、 run、 filterType、 filterOrder*/
@Component
public class LoggerFilter extends ZuulFilter {private static final Logger logger = LoggerFactory.getLogger(LoggerFilter.class);/*** 返回boolean類型。代表當前filter是否生效。* 默認值為false。* 返回true代表開啟filter。*/@Overridepublic boolean shouldFilter() {return true;}/*** run方法就是過濾器的具體邏輯。* return 可以返回任意的對象,當前實現忽略。(spring-cloud-zuul官方解釋)* 直接返回null即可。*/@Overridepublic Object run() throws ZuulException {// 通過zuul,獲取請求上下文RequestContext rc = RequestContext.getCurrentContext();HttpServletRequest request = rc.getRequest();logger.info("LogFilter1.....method={},url={}",request.getMethod(),request.getRequestURL().toString());// 可以記錄日志、鑒權,給維護人員記錄提供定位協助、統計性能return null;}/*** 過濾器的類型。可選值有:* pre - 前置過濾* route - 路由后過濾* error - 異常過濾* post - 遠程服務調用后過濾*/@Overridepublic String filterType() {return "pre";}/*** 同種類的過濾器的執行順序。* 按照返回值的自然升序執行。*/@Overridepublic int filterOrder() {return 0;}
}

五、Zuul網關的容錯(與Hystrix的無縫結合)

在spring cloud中,Zuul啟動器中包含了Hystrix相關依賴,在Zuul網關工程中,默認是提供了Hystrix Dashboard服務監控數據的(hystrix.stream),但是不會提供監控面板的界面展示。可以說,在spring cloud中,zuul和Hystrix是無縫結合的。

1、Zuul中的服務降級處理

在Edgware版本之前,Zuul提供了接口ZuulFallbackProvider用于實現fallback處理。從Edgware版本開始,Zuul提供了ZuulFallbackProvider的子接口FallbackProvider來提供fallback處理。

Zuul的fallback容錯處理邏輯,只針對timeout異常處理,當請求被Zuul路由后,只要服務有返回(包括異常),都不會觸發Zuul的fallback容錯邏輯。

因為對于Zuul網關來說,做請求路由分發的時候,結果由遠程服務運算的。那么遠程服務反饋了異常信息,Zuul網關不會處理異常,因為無法確定這個錯誤是否是應用真實想要反饋給客戶端的。

2、代碼示例

/*** 如果需要在Zuul網關服務中增加容錯處理fallback,需要實現接口ZuulFallbackProvider* spring-cloud框架,在Edgware版本(包括)之后,聲明接口ZuulFallbackProvider過期失效,* 提供了新的ZuulFallbackProvider的子接口 - FallbackProvider* 在老版本中提供的ZuulFallbackProvider中,定義了兩個方法。*  - String getRoute()*    當前的fallback容錯處理邏輯處理的是哪一個服務。可以使用通配符‘*’代表為全部的服務提供容錯處理。*    如果只為某一個服務提供容錯,返回對應服務的spring.application.name值。*  - ClientHttpResponse fallbackResponse()*    當服務發生錯誤的時候,如何容錯。* 新版本中提供的FallbackProvider提供了新的方法。*  - ClientHttpResponse fallbackResponse(Throwable cause)*    如果使用新版本中定義的接口來做容錯處理,容錯處理邏輯,只運行子接口中定義的新方法。也就是有參方法。*    是為遠程服務發生異常的時候,通過異常的類型來運行不同的容錯邏輯。*/
@Component
public class TestFallBbackProvider implements FallbackProvider {/*** return - 返回fallback處理哪一個服務。返回的是服務的名稱* 推薦 - 為指定的服務定義特性化的fallback邏輯。* 推薦 - 提供一個處理所有服務的fallback邏輯。* 好處 - 服務某個服務發生超時,那么指定的fallback邏輯執行。如果有新服務上線,未提供fallback邏輯,有一個通用的。*/@Overridepublic String getRoute() {return "eureka-application-service";}/*** fallback邏輯。在早期版本中使用。* Edgware版本之后,ZuulFallbackProvider接口過期,提供了新的子接口FallbackProvider* 子接口中提供了方法ClientHttpResponse fallbackResponse(Throwable cause)。* 優先調用子接口新定義的fallback處理邏輯。*/@Overridepublic ClientHttpResponse fallbackResponse() {System.out.println("ClientHttpResponse fallbackResponse()");List<Map<String, Object>> result = new ArrayList<>();Map<String, Object> data = new HashMap<>();data.put("message", "服務正忙,請稍后重試");result.add(data);ObjectMapper mapper = new ObjectMapper();String msg = "";try {msg = mapper.writeValueAsString(result);} catch (JsonProcessingException e) {msg = "";}return this.executeFallback(HttpStatus.OK, msg, "application", "json", "utf-8");}/*** fallback邏輯。優先調用。可以根據異常類型動態決定處理方式。*/@Overridepublic ClientHttpResponse fallbackResponse(Throwable cause) {System.out.println("ClientHttpResponse fallbackResponse(Throwable cause)");if(cause instanceof NullPointerException){List<Map<String, Object>> result = new ArrayList<>();Map<String, Object> data = new HashMap<>();data.put("message", "網關超時,請稍后重試");result.add(data);ObjectMapper mapper = new ObjectMapper();String msg = "";try {msg = mapper.writeValueAsString(result);} catch (JsonProcessingException e) {msg = "";}return this.executeFallback(HttpStatus.GATEWAY_TIMEOUT, msg, "application", "json", "utf-8");}else{return this.fallbackResponse();}}/*** 具體處理過程。* @param status 容錯處理后的返回狀態,如200正常GET請求結果,201正常POST請求結果,404資源找不到錯誤等。*  使用spring提供的枚舉類型對象實現。HttpStatus* @param contentMsg 自定義的響應內容。就是反饋給客戶端的數據。* @param mediaType 響應類型,是響應的主類型, 如:application、text、media。* @param subMediaType 響應類型,是響應的子類型, 如:json、stream、html、plain、jpeg、png等。* @param charsetName 響應結果的字符集。這里只傳遞字符集名稱,如:utf-8、gbk、big5等。* @return ClientHttpResponse 就是響應的具體內容。*  相當于一個HttpServletResponse。*/private final ClientHttpResponse executeFallback(final HttpStatus status, String contentMsg, String mediaType, String subMediaType, String charsetName) {return new ClientHttpResponse() {/*** 設置響應的頭信息*/@Overridepublic HttpHeaders getHeaders() {HttpHeaders header = new HttpHeaders();MediaType mt = new MediaType(mediaType, subMediaType, Charset.forName(charsetName));header.setContentType(mt);return header;}/*** 設置響應體* zuul會將本方法返回的輸入流數據讀取,并通過HttpServletResponse的輸出流輸出到客戶端。*/@Overridepublic InputStream getBody() throws IOException {String content = contentMsg;return new ByteArrayInputStream(content.getBytes());}/*** ClientHttpResponse的fallback的狀態碼 返回String*/@Overridepublic String getStatusText() throws IOException {return this.getStatusCode().getReasonPhrase();}/*** ClientHttpResponse的fallback的狀態碼 返回HttpStatus*/@Overridepublic HttpStatus getStatusCode() throws IOException {return status;}/*** ClientHttpResponse的fallback的狀態碼 返回int*/@Overridepublic int getRawStatusCode() throws IOException {return this.getStatusCode().value();}/*** 回收資源方法* 用于回收當前fallback邏輯開啟的資源對象的。* 不要關閉getBody方法返回的那個輸入流對象。*/@Overridepublic void close() {}};}
}

六、Zuul網關的限流保護

Zuul網關組件也提供了限流保護。當請求并發達到閥值,自動觸發限流保護,返回錯誤結果。只要提供error錯誤處理機制即可。

Zuul的限流保護需要額外依賴spring-cloud-zuul-ratelimit組件。

<dependency><groupId>com.marcosbarbero.cloud</groupId><artifactId>spring-cloud-zuul-ratelimit</artifactId><version>1.3.4.RELEASE</version>
</dependency>

1、全局限流配置

使用全局限流配置,zuul會對代理的所有服務提供限流保護。

# 開啟限流保護
zuul.ratelimit.enabled=true
# 60s內請求超過3次,服務端就拋出異常,60s后可以恢復正常請求
zuul.ratelimit.default-policy.limit=3
zuul.ratelimit.default-policy.refresh-interval=60
# 針對IP進行限流,不影響其他IP
zuul.ratelimit.default-policy.type=origin

2、局部限流配置
使用局部限流配置,zuul僅針對配置的服務提供限流保護。

# 開啟限流保護
zuul.ratelimit.enabled=true
# hystrix-application-client服務60s內請求超過3次,服務拋出異常。
zuul.ratelimit.policies.hystrix-application-client.limit=3
zuul.ratelimit.policies.hystrix-application-client.refresh-interval=60
# 針對IP限流。
zuul.ratelimit.policies.hystrix-application-client.type=origin

3、限流參數簡介
在這里插入圖片描述

七、Zuul網關性能調優:網關的兩層超時調優

使用Zuul的spring cloud微服務結構圖:
在這里插入圖片描述
從上圖中可以看出。整體請求邏輯還是比較復雜的,在沒有zuul網關的情況下,app client請求app service的時候,也有請求超時的可能。那么當增加了zuul網關的時候,請求超時的可能就更明顯了。

當請求通過zuul網關路由到服務,并等待服務返回響應,這個過程中zuul也有超時控制。zuul的底層使用的是Hystrix+ribbon來實現請求路由。結構如下:
在這里插入圖片描述
zuul中的Hystrix內部使用線程池隔離機制提供請求路由實現,其默認的超時時長為1000毫秒。ribbon底層默認超時時長為5000毫秒。如果Hystrix超時,直接返回超時異常。如果ribbon超時,同時Hystrix未超時,ribbon會自動進行服務集群輪詢重試,直到Hystrix超時為止。如果Hystrix超時時長小于ribbon超時時長,ribbon不會進行服務集群輪詢重試。

那么在zuul中可配置的超時時長就有兩個位置:Hystrix和ribbon。具體配置如下:

# 開啟zuul網關重試
zuul.retryable=true
# hystrix超時時間設置
# 線程池隔離,默認超時時間1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=8000# ribbon超時時間設置:建議設置比Hystrix小
# 請求連接的超時時間: 默認5000ms
ribbon.ConnectTimeout=5000
# 請求處理的超時時間: 默認5000ms
ribbon.ReadTimeout=5000
# 重試次數:MaxAutoRetries表示訪問服務集群下原節點(同路徑訪問);MaxAutoRetriesNextServer表示訪問服務集群下其余節點(換臺服務器)
ribbon.MaxAutoRetries=1
ribbon.MaxAutoRetriesNextServer=1
# 開啟重試
ribbon.OkToRetryOnAllOperations=true

Spring-cloud中的zuul網關重試機制是使用spring-retry實現的。工程必須依賴下述資源:

<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId>
</dependency>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/712515.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/712515.shtml
英文地址,請注明出處:http://en.pswp.cn/news/712515.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringBoot項目連接Redis報錯:Connection refused: no further information

今天在使用SpringBoot連接Redis時發生了報錯 明明Jedis能夠連接成功為什么StringRedisTemplate就不行? 然后在網上找了一下說是關閉防火墻或者修改配置文件但是都不管用 最后發現是Redis在SpringBoot3之后yml的配置方式發生了改變 相較于之前多了一個前綴, 由于我剛開始沒有…

項目風險管理的前提是對風險的認知

大家好&#xff0c;我是不會魔法的兔子&#xff0c; 一枚北京執業律師&#xff0c;創建[項目管理者的法小院兒]&#xff0c;持續從法律的角度分享項目管理中的風險問題及預防&#xff0c;讓項目管理者能夠提早發現與解決項目執行過程中的風險&#xff0c;同時歡迎大家一起交流…

論文解讀--Mutual Interference Mitigation in PMCW Automotive Radar

PMCW汽車雷達的相互干擾抑制 摘要 針對相位調制連續波(PMCW)毫米波(mmWave)汽車雷達系統中存在的相互干擾問題進行了研究。對先進駕駛輔助系統(ADAS)的需求日益增長&#xff0c;導致配備在同一頻段工作的毫米波雷達系統的車輛激增&#xff0c;導致相互干擾&#xff0c;可能會降…

WPF 滑動條樣式

效果圖&#xff1a; 淺色&#xff1a; 深色&#xff1a; 滑動條部分代碼&#xff1a; <Style x:Key"RepeatButtonTransparent" TargetType"{x:Type RepeatButton}"><Setter Property"OverridesDefaultStyle" Value"true"/&g…

【Oracle】Oracle清理日志空間

&#xff08;一&#xff09;通過adrci清理日志空間 1.通過find命令查詢大數據文件 find / -type f -size 100M 2.登錄oracle數據庫服務器用戶 su - oracle 3.執行故障診斷命令 adrci 4.查詢ADR目錄 show home 5.切換到對應目錄 set homepath diag/rdbms/orcl 6.執行日志清理命令…

枚舉類、泛型、API

枚舉類 枚舉類可以實現單例設計模式。 枚舉的常見應用場景&#xff1a;用來表示一組信息&#xff0c;然后作為參數進行傳輸。 泛型 API

Qt 中Qwidget相關屬性

文章目錄 1. QWidget 核心屬性1.1 enabled1.2 geometry1.2.1 window frame 的影響 1.3 windowTitle1.4 windowIcon1.4.1 qrc的使用 1.5 windowOpacity1.6 cursor1.7 focusPolicy1.8 styleSheet 1. QWidget 核心屬性 在 Qt 中, 使? QWidget 類表? “控件”. 像按鈕, 視圖, 輸…

今年Android面試必問的這些技術面,2024Android常見面試題

都說程序員是在吃青春飯&#xff0c;這一點的確有一點對的成分&#xff0c;以前我不這么認為&#xff0c;但隨著年齡的增長&#xff0c;事實告訴我的確是這樣的&#xff0c;過了30以后&#xff0c;就會發現身體各方面指標下降&#xff0c;體力和身心上都多少有點跟不上了&#…

Node.js中的緩存策略和緩存技巧

在Node.js中&#xff0c;緩存策略和緩存技巧是提升應用性能和用戶體驗的關鍵因素。通過有效地利用緩存&#xff0c;我們可以顯著減少系統資源的消耗&#xff0c;加快數據訪問速度&#xff0c;從而提升整體的網站性能。本文將針對Node.js中的緩存策略和緩存技巧展開深入探討&…

Newtonsoft.Json

目錄 引言 1、簡單使用 1.1、官方案例 1.2、JsonConvert 2、特性 2.1、默認模式[JsonObject(MemberSerialization.OptIn/OptOut)] 2.2、序列化為集合JsonArrayAttribute/JsonDictionaryAttribute 2.3、序列化該元素JsonProperty 2.4、忽略元素JsonIgnoreAttribute 2.5、…

iOS CVPixelBufferCreate 創建 CVPixelBufferRef 時屏幕拉伸或像素偏移(花屏)

先說結論&#xff1a; CVPixelBufferCreate 創建的 CVPixelBufferRef 可能由以下的原因導致的&#xff1a; 1.pixelFormatType 格式錯誤&#xff0c;換一下格式嘗試 2.width和height 非 32 的整數倍 3.視頻幀的寬高比非標準比例&#xff08;4:3,16:9,1:1&#xff09; 另外說明&…

今天面試招了個18K的人,從騰訊出來的果然都有兩把刷子···

公司前段時間缺人&#xff0c;也面了不少測試&#xff0c;前面一開始瞄準的就是中級的水準&#xff0c;也沒指望來大牛&#xff0c;提供的薪資在15-20k&#xff0c;面試的人很多&#xff0c;但平均水平很讓人失望。看簡歷很多都是4年工作經驗&#xff0c;但面試中&#xff0c;不…

docker save 命令 docker load 命令 快速復制容器

docker save 命令 docker load 命令 1、docker save 命令2、docker load 命令 1、docker save 命令 docker save 命令用于在系統上把正在使用的某個容器鏡像 導出成容器鏡像文件保存下載&#xff0c;以便在其他系統上導入這個容器鏡像文件 以便快速在其他服務器上啟動相同的容…

讀書筆記:《思考 . 快與慢》- 1 系統1 系統2

《思考 . 快與慢》 [美] 丹尼爾 . 卡尼曼 著 胡曉姣 李愛民 何夢瑩 譯 這本書會改變你的思考方式 利用閑談發現和分析別人犯的錯誤比分析自己的錯誤更容易&#xff0c;也更有意思 在人生最輝煌的時候&#xff0c;我們很難對自己的信念和需求產生懷疑&#xff0c;越是在最…

【Web】Java反序列化之CC2——commons-collections4的新鏈之一

目錄 關于commons-collections4 一個重要的思維模型 觸發Transform的關鍵類&#xff1a;TransformingComparator 反序列化的入口&#xff1a;PriorityQueue Exp 關于commons-collections4 commons-collections4 是 Apache Commons 組件庫中的一個項目&#xff0c;它是對舊…

在Linux上定時執行腳本

在Linux上定時執行腳本通常可以使用 ?cron?任務來實現。?cron?是一個系統服務&#xff0c;用于在預定時間自動執行命令或腳本。下面是如何在Linux上設置定時執行腳本的步驟&#xff1a; 編寫腳本&#xff1a;首先&#xff0c;你需要編寫需要定時執行的腳本文件&#xff0c;…

找不到msvcp140.dll無法運行程序如何處理?分享5種解決方法

在計算機系統運行過程中&#xff0c;如果無法找到必要的動態鏈接庫文件msvcp140.dll&#xff0c;可能會引發一系列的問題與故障。這個特定的dll文件是Microsoft Visual C Redistributable Package的一部分&#xff0c;對于許多基于此編譯環境開發的應用程序至關重要。缺失msvcp…

C++的常用排序(未完待續)

注&#xff1a;本文以升序為例 一、冒泡排序 1.1 操作方法 步驟1比較相鄰元素&#xff0c;如果前者比后者大&#xff0c;則交換它們。步驟2對頭到尾&#xff0c;對所有元素按序執行一輪這樣的操作(這樣可以找到第一最大值)步驟3再從第一個元素開始&#xff0c;重復上述比較操…

jax可微分編程的筆記(8)

jax可微分編程的筆記(8) 第八章 循環神經網絡 神經網絡是可微分編程中最為重要的模型構造形式&#xff0c;也是當代 深度學習的基本組成部分&#xff0c;深度學習中的“深度”一詞&#xff0c;便是對 神經網絡的層數的形容。 8.1 神經網絡的生物學基礎 通過層層近似&#x…

智能駕駛規劃控制理論學習02-基于搜索的路徑規劃方法

目錄 一、路徑搜索問題 二、圖論基礎 三、圖搜索方法 1、廣度優先搜索&#xff08;BFS&#xff09; bfs與dfs的區別 bfs的搜索過程 bfs的算法實現 2、迪杰斯特拉算法&#xff08;Dijkstra&#xff09; 核心思想 優先級隊列 Dijkstra搜索過程 Dijkstra優缺點…