<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
API閘道器出現的原因是微服務架構的出現,不同的微服務一般會有不同的網路地址,而外部使用者端可能需要呼叫多個服務的介面才能完成一個業務需求,如果讓使用者端直接與各個微服務通訊,會有以下的問題:
(1)使用者端會多次請求不同的微服務,增加了使用者端的複雜性。
(2)存在跨域請求,在一定場景下處理相對複雜。
(3)認證複雜,每個服務都需要獨立認證。
(4)難以重構,隨著專案的迭代,可能需要重新劃分微服務。例如,可能將多個服務合併成一個或者將一個服務拆分成多個。如果使用者端直接與微服務通訊,那麼重構將會很難實施。
(5)某些微服務可能使用了防火牆/瀏覽器不友好的協定,直接存取會有一定的困難。
以上這些問題可以藉助API閘道器解決。API閘道器是介於使用者端和伺服器端之間的中間層,所有的外部請求都會先經過API閘道器這一層。也就是說,API的實現方面更多的考慮業務邏輯,而安全、效能、監控可以交由API閘道器來做,這樣既提高業務靈活性又不缺安全性
(6)getway可以實現nginx的請求轉發和跨域(@CrossOrigin也可以實現跨域)。
負載均衡:把請求平均分配到多臺伺服器上。叢集部署,部署2臺service-edu服務,只有埠號不同,專案都一樣。
Spring cloud gateway是spring官方基於Spring 5.0、Spring Boot2.0和Project Reactor等技術開發的閘道器,Spring Cloud Gateway旨在為微服務架構提供簡單、有效和統一的API路由管理方式,Spring Cloud Gateway作為Spring Cloud生態系統中的閘道器,目標是替代Netflix Zuul,其不僅提供統一的路由方式,並且還基於Filer鏈的方式提供了閘道器基本的功能,例如:安全、監控/埋點、限流等。
閘道器和服務都在Nacos註冊,註冊之後通過Getway閘道器在存取相應的服務
閘道器提供API全託管服務,豐富的API管理功能,輔助企業管理大規模的API,以降低管理成本和安全風險,包括協定適配、協定轉發、安全策略、防刷、流量、監控紀錄檔等貢呢。一般來說閘道器對外暴露的URL或者介面資訊,我們統稱為路由資訊。如果研發過閘道器中介軟體或者使用過Zuul的人,會知道閘道器的核心是Filter以及Filter Chain(Filter責任鏈)。Sprig Cloud Gateway也具有路由和Filter的概念。下面介紹一下Spring Cloud Gateway中幾個重要的概念。
(1)路由。路由是閘道器最基礎的部分,路由資訊有一個ID、一個目的URL、一組斷言和一組Filter組成。如果斷言路由為真,則說明請求的URL和設定匹配
(2)斷言。Java8中的斷言函數。Spring Cloud Gateway中的斷言函數輸入型別是Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的斷言函數允許開發者去定義匹配來自於http request中的任何資訊,比如請求頭和引數等,簡單來講就是一個匹配規則,如果匹配到就到Handler去處理。
(3)過濾器。一個標準的Spring webFilter。Spring cloud gateway中的filter分為兩種型別的Filter,分別是Gateway Filter和Global Filter。過濾器Filter將會對請求和響應進行修改處理,統一例外處理,統一跨域處理等。
如上圖所示,Spring cloud Gateway發出請求。然後再由Gateway Handler Mapping中找到與請求相匹配的路由,將其傳送到Gateway web handler。Handler再通過指定的過濾器鏈將請求傳送到我們實際的服務執行業務邏輯,然後返回。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>infrastructure</artifactId> <groupId>com.stu</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>api_gateway</artifactId> <dependencies> <dependency> <groupId>com.stu</groupId> <artifactId>common-utils</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--gson--> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> </dependency> <!--服務呼叫--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> </project>
3、編寫application.properties組態檔
# 伺服器埠 server.port=8222 # 服務名 spring.application.name=service-gateway # nacos服務地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 #使用服務發現路由,通過openfeign找到服務(nginx是通過組態檔的路徑匹配發現服務) spring.cloud.gateway.discovery.locator.enabled=true #服務路由名小寫 #spring.cloud.gateway.discovery.locator.lower-case-service-id=true #設定service-edu服務 #設定路由id(id可以隨便命名,建議用服務名稱) spring.cloud.gateway.routes[0].id=service-edu #設定路由的uri spring.cloud.gateway.routes[0].uri=lb://service-edu #設定路由斷言,代理servicerId為auth-service的/auth/路徑 spring.cloud.gateway.routes[0].predicates= Path=/eduservice/** #設定service-edu服務 spring.cloud.gateway.routes[1].id=service-msm ## 服務名 #spring.application.name=service-msm spring.cloud.gateway.routes[1].uri=lb://service-msm spring.cloud.gateway.routes[1].predicates= Path=/edumsm/**
yml檔案:
server: port: 8222 spring: application: cloud: gateway: discovery: locator: enabled: true routes: - id: SERVICE-ACL uri: lb://SERVICE-ACL predicates: - Path=/*/acl/** # 路徑匹配 - id: SERVICE-EDU uri: lb://SERVICE-EDU predicates: - Path=/eduservice/** # 路徑匹配 - id: SERVICE-UCENTER uri: lb://SERVICE-UCENTER predicates: - Path=/ucenter/** # 路徑匹配 nacos: discovery: server-addr: 127.0.0.1:8848
package com.stu.getway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient//Nacos註冊 public class ApiGetwayApplication { public static void main(String[] args) { SpringApplication.run(ApiGetwayApplication.class,args); } }
通過nginx設定存取(8001)
通過getway設定存取(8222)
(1)建立設定類
package com.stu.getway.config; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator; import org.springframework.cloud.gateway.discovery.DiscoveryLocatorProperties; import org.springframework.cloud.gateway.route.RouteDefinitionLocator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.http.codec.support.DefaultServerCodecConfigurer; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsUtils; import org.springframework.web.cors.reactive.CorsWebFilter; import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import org.springframework.web.util.pattern.PathPatternParser; import reactor.core.publisher.Mono; /** * <p> * 處理跨域 * </p> * * @author qy * @since 2019-11-21 */ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsWebFilter; import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; import org.springframework.web.util.pattern.PathPatternParser; /** * description: * * @author wangpeng * @date 2019/01/02 */ @Configuration public class CorsConfig { @Bean public CorsWebFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedMethod("*"); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser()); source.registerCorsConfiguration("/**", config); return new CorsWebFilter(source); } }
package com.stu.getway.filter; import com.google.gson.JsonObject; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.util.AntPathMatcher; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.nio.charset.StandardCharsets; import java.util.List; /** * <p> * 全域性Filter,統一處理會員登入與外部不允許存取的服務 * </p> * * @author qy * @since 2019-11-21 */ @Component public class AuthGlobalFilter implements GlobalFilter, Ordered { private AntPathMatcher antPathMatcher = new AntPathMatcher(); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String path = request.getURI().getPath(); //校驗使用者必須登入 if(antPathMatcher.match("/api/**/auth/**", path)) { List<String> tokenList = request.getHeaders().get("token"); if(null == tokenList) { ServerHttpResponse response = exchange.getResponse(); return out(response); } else { // Boolean isCheck = JwtUtils.checkToken(tokenList.get(0)); // if(!isCheck) { ServerHttpResponse response = exchange.getResponse(); return out(response); // } } } //內部服務介面,不允許外部存取 if(antPathMatcher.match("/**/inner/**", path)) { ServerHttpResponse response = exchange.getResponse(); return out(response); } return chain.filter(exchange); } @Override public int getOrder() { return 0; } private Mono<Void> out(ServerHttpResponse response) { JsonObject message = new JsonObject(); message.addProperty("success", false); message.addProperty("code", 28004); message.addProperty("data", "鑑權失敗"); byte[] bits = message.toString().getBytes(StandardCharsets.UTF_8); DataBuffer buffer = response.bufferFactory().wrap(bits); //response.setStatusCode(HttpStatus.UNAUTHORIZED); //指定編碼,否則在瀏覽器中會中文亂碼 response.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); return response.writeWith(Mono.just(buffer)); } }
服務閘道器呼叫服務時可能會有一些異常或服務不可用,它返回錯誤資訊不友好,需要我們覆蓋處理
ErrorHandlerConfig
package com.stu.getway.handler; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.web.ResourceProperties; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.reactive.error.ErrorAttributes; import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.web.reactive.result.view.ViewResolver; import java.util.Collections; import java.util.List; /** * 覆蓋預設的例外處理 * * @author yinjihuan * */ @Configuration @EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class}) public class ErrorHandlerConfig { private final ServerProperties serverProperties; private final ApplicationContext applicationContext; private final ResourceProperties resourceProperties; private final List<ViewResolver> viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public ErrorHandlerConfig(ServerProperties serverProperties, ResourceProperties resourceProperties, ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer, ApplicationContext applicationContext) { this.serverProperties = serverProperties; this.applicationContext = applicationContext; this.resourceProperties = resourceProperties; this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); this.serverCodecConfigurer = serverCodecConfigurer; } @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) { JsonExceptionHandler exceptionHandler = new JsonExceptionHandler( errorAttributes, this.resourceProperties, this.serverProperties.getError(), this.applicationContext); exceptionHandler.setViewResolvers(this.viewResolvers); exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters()); exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders()); return exceptionHandler; } }
JsonExceptionHandler
package com.stu.getway.handler; import org.springframework.boot.autoconfigure.web.ErrorProperties; import org.springframework.boot.autoconfigure.web.ResourceProperties; import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler; import org.springframework.boot.web.reactive.error.ErrorAttributes; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpStatus; import org.springframework.web.reactive.function.server.*; import java.util.HashMap; import java.util.Map; /** * 自定義例外處理 * * <p>異常時用JSON代替HTML異常資訊<p> * * @author yinjihuan * */ public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler { public JsonExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) { super(errorAttributes, resourceProperties, errorProperties, applicationContext); } /** * 獲取異常屬性 */ @Override protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) { Map<String, Object> map = new HashMap<>(); map.put("success", false); map.put("code", 20005); map.put("message", "閘道器失敗"); map.put("data", null); return map; } /** * 指定響應處理方法為JSON處理的方法 * @param errorAttributes */ @Override protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) { return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse); } /** * 根據code獲取對應的HttpStatus * @param errorAttributes */ @Override protected int getHttpStatus(Map<String, Object> errorAttributes) { return 200; } }
到此這篇關於getway閘道器的文章就介紹到這了,更多相關getway閘道器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45