preface
introduce
The previous article has completed the call between services, but how can we implement the interface of external calling services.
First of all, we can call it by directly calling the public network ip + port. This method is certainly feasible, but it must be unsafe to expose the ip and port directly. In case someone hacked your server, This is a little uncomfortable (the victim who has been cleaned up the database data said that I am a student's server. What are you doing.
At this time, we introduce a term - reverse agent
Generally speaking, when you call the interface of a service, you will not directly access the real address of the interface, but send a request to the proxy server. The proxy server forwards the request to other services. After the service processing is completed, the result is returned to the proxy server, and then the proxy server forwards the result to you
In this process, the user does not know that he is calling the proxy server. If the user thinks he is calling the address of the real service, this process becomes the reverse proxy. See this for details Let's briefly talk about the forward agent and reverse agent I understand. It's pure vernacular
GateWay effect
The Gateway actually acts as a reverse proxy. It can also be considered that the Gateway is the entrance to all services. If the hardware supports it, I think the relatively simple architecture is shown in the figure below
In fact, you can set several more layers of nginx for one layer of agent, so that you can handle more concurrency.
Reverse Gateway implementation
pom.xml
The following are the dependencies to be introduced
<?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>test</artifactId> <groupId>com.xiaow</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>gateway</artifactId> <properties> <java.version>1.8</java.version> </properties> <!-- <dependencies>--> <!-- Configure dependencies --> <dependencies> <dependency> <groupId>com.xiaow</groupId> <artifactId>common</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-gateway --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </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-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </dependency> <dependency> <groupId>com.xiaow</groupId> <artifactId>common</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--fastjson rely on--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.73</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.7.RELEASE</version> <configuration> <mainClass>com.xiaow.test.Provider8001</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
configuration file
It is mainly about the configuration of routes
routes explanation
routes: - id: consumer #Set the routing ID (it can be written freely in theory) uri: lb://consumer # set the URL of the route LB: / / Nacos service registration name filters: - StripPrefix=1 predicates: - Path=/one/** #Path matching rule
Configure as above
id is just the id for configuring a route. This id can be written casually, but it cannot be repeated.
uri: lb:consumer consumer corresponds to the registered service name in Nacos
Path is a matching path
For example, if the interface call of the consumer service is / get, the path through the gateway call is / one/get
All profiles
stay server: port: 8050 #Service port spring: application: name: gateway cloud: nacos: discovery: server-addr: http://192.168.30.1:8848/ gateway: discovery: locator: enabled: true #Using service discovery routing routes: - id: consumer #Set the routing ID (it can be written freely in theory) uri: lb://consumer # set the URL of the route LB: / / Nacos service registration name filters: - StripPrefix=1 predicates: - Path=/one/** #Path matching rule - id: provider uri: lb://provider filters: - StripPrefix=1 predicates: - Path=/two/** #Path matching rule - id: account uri: lb://account filters: - StripPrefix=1 predicates: - Path=/account/** #Path matching rule management: endpoints: web: exposure: include: "*"
Handling cross domain
package com.xiaow.gateway.config; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; 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; import java.util.stream.Collectors; @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); } @Bean @ConditionalOnMissingBean public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) { return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList())); } }
Startup class
package com.xiaow.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class Gateway8050 { public static void main(String[] args) { SpringApplication.run(Gateway8050.class,args); } }
summary
Or review