SpringCloudAlibaba Gateway (1) Simple integration

SpringCloudAlibaba Gateway (1) Simple integration

As the service module increases, multiple interface addresses will inevitably be generated. Then the client can only use multiple addresses when calling multiple interfaces. It is very inconvenient to maintain multiple addresses. At this time, the service address needs to be unified. At the same time, unified authentication and authentication requirements can also be implemented. Then the service gateway plays such a role.

Gateway

​ The gateway stands in front of many microservices and performs functions such as routing and forwarding, monitoring, current limiting, and authentication. SpringCloudGateway is one of its implementations. SpringCloudGatewayDrawing on the ideas of Spring Cloud Netfilix Zuul, its goal is to replace Zuul.

GatewayIt is WebFluximplemented based on a framework, and the bottom layer of WebFlux uses a high-performance framework Netty. The performance is 1.6 times that of Zuul, with powerful functions and elegant design.

The core of Gateway is 路由, Predicate(断言), Filter(过滤器). Routing is a forwarding rule, Predicate is a judgment, and Filter can be thought of as adding a little custom logic before or after the request is routed.

SpringCloudGateway requires SpringBoot2.0+ and above, and cannot be run in Servlet containers such as Tomcat or Jetty. It must be run as a Jar package! ! !

Integrate Gateway

Build a Gateway service and create two services: user service and product service. The architecture is as follows:

Insert image description here

user serviceUserController,用户服务端口8002

@RestController
public class UserController {
    
    
    private final Map<Integer, String> userInfo = new HashMap<Integer, String>() {
    
    {
    
    
        put(1, "Zhangsan");
        put(2, "Lisi");
    }};
    @RequestMapping("/user/findById")
    public String findById(@RequestParam("id") Integer id) {
    
    
        return userInfo.getOrDefault(id, null);
    }
}

shop serviceShopController,商品服务端口8003

@RestController
public class ShopController {
    
    
    private final Map<Integer, String> shopInfo = new HashMap<Integer, String>() {
    
    {
    
    
        put(1, "这是苹果");
        put(1024, "芒果");
    }};
    @RequestMapping("/shop/findById")
    public String findById(@RequestParam("id") Integer id) {
    
    
        return shopInfo.getOrDefault(id, null);
    }
}

Create a gateway service

rely

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Remove spring-boot-starter-webthe dependency in Gateway. There is webflux dependency in gateway, which starter-webconflicts with it.

bootstrap.ymlAdd configuration

server:
  port: 8083

spring:
  application:
    name: gateway   # 服务名
  
  cloud:
    gateway:
	  routes: # 路由,可配置多个
        - id: user_route  # 路由id,唯一即可,默认UUID
          uri: http://localhost:8002  # 路由地址(匹配成功后的服务地址)
          order: 1  # 路由优先级,默认0,越低优先级越高
          predicates:
            - Path=/user/**   # 断言,匹配规则

        - id: shop_route
          uri: http://localhost:8003
          order: 1
          predicates:
          - Path=/shop/**

Gateway configuration can also use JavaConfig, but it is not recommended.

The configuration indicates that when 网关the address in the request path starts with, it will /user/be routed to the user service, and if the address starts with, /shop/it will be routed to the product service.

have a test

C:\Users\Admin>curl http://localhost:8083/user/findById?id=1
Zhangsan
C:\Users\Admin>curl http://localhost:8083/shop/findById?id=1024
芒果

Gateway integrates nacos

In the above case, the uri is something hard-coded. If the corresponding specific service address is changed, then the configuration file needs to be modified. Moreover, if you want to increase the user capacity and do load balancing, there are many nodes, and you must not just configure it. A service address.

Then you need to use nacos to uniformly manage service registration and discovery. The address for gateway routing and forwarding can be obtained from nacos.

Then 用户服务it is 商品服务necessary to introduce nacos service discovery registration dependency

<!-- 服务注册  服务发现需要引入的 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!--健康监控-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

bootstrap.yml file

------------------------User服务
server:
  port: 8002
spring:
  application:
    name: user # 应用名

  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # nacos服务地址
        
--------------------------Shop服务
server:
  port: 8003
spring:
  application:
    name: shop # 应用名

  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # nacos服务地址

Finally, remember to start the nacos service registration discovery in the startup class.

@SpringBootApplication
@EnableDiscoveryClient	// 启用服务注册发现
public class UserApp {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(UserApp.class, args);
    }
}

Ok, then similarly, the gateway service must also enable service registration discovery.

rely

<!-- 服务注册  服务发现需要引入的 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

bootstrap.ymlThe configuration is as follows:

server:
  port: 8083

spring:
  application:
    name: gateway   # 服务名

  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # nacos地址
    gateway:
      discovery:
        locator:
          enabled: true # 让gateway可以发现nacos中的服务,gateway自动根据服务发现为每一个服务创建了一个router,# 这个router将以服务名开头的请求路径转发到对应的服务
      routes: # 路由,可配置多个
      - id: user_route  # 路由id,唯一即可,默认UUID
        uri: lb://user  # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称
        order: 1  # 路由优先级,默认0,越低优先级越高
        predicates:
        - Path=/user/**   # 断言,匹配规则

      - id: shop_route
        uri: lb://shop  # 路由地址(匹配成功后的服务地址) shop是商品服务的服务名称
        order: 1
        predicates:
        - Path=/shop/**

Try starting:

C:\Users\Admin>curl http://localhost:8083/user/findById?id=1
{
    
    "timestamp":"2023-08-05T00:34:40.684+00:00","path":"/user/findById","status":503,"error":"Service Unavailable","requestId":"f5f6d217-1"}
C:\Users\Admin>curl http://localhost:8083/user/findById?id=1
{
    
    "timestamp":"2023-08-05T00:35:50.223+00:00","path":"/user/findById","status":503,"error":"Service Unavailable","requestId":"21a722a2-1"}

ha? The service is unavailable. After consulting the information, we learned that ReactiveLoadBalancerClientFilterfilters are missing and LoadBalancerClientFactoryclasses are required, but related dependencies need to be introduced.

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

Okay, try again:

C:\Users\Admin>curl http://localhost:8083/shop/findById?id=1024
{
    
    "timestamp":"2023-08-05T01:19:34.183+00:00","status":404,"error":"Not Found","path":"/findById"}
C:\Users\Admin>curl http://localhost:8083/user/findById?id=1
{
    
    "timestamp":"2023-08-05T01:19:34.183+00:00","status":404,"error":"Not Found","path":"/findById"}

So beautiful, I stepped on a big trap! ! ! 404 all the time! ! !

After struggling in every possible way, checking information, looking at the source code, debugging, etc., I understand the reason...

spring:
  application:
    name: gateway   # 服务名
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # nacos地址
    gateway:
      discovery:
        locator:
          enabled: true # 让gateway可以发现nacos中的服务,gateway自动根据服务发现为每一个服务创建了一个router,# 这个router将以服务名开头的请求路径转发到对应的服务

Here comes the key point. Pay attention:

When your gateway is configured locator.enabled: true, the gateway automatically creates a router for each service based on service discovery. This router will forward the request path starting with the service name to the corresponding service 相当于人家给你自动生成了route规则,你自己都不用配置了.

However: your request must include the service name of the server before you can access it.

Take the above as an example: If you want to access userthe service /user/findById, the request address islocalhost:8083/user/user/findById

C:\Users\Admin>curl http://localhost:8083/user/user/findById?id=1
Zhangsan

how to choose

Two writing methods are provided:

  • In fact, if the project path is relatively simple, just use gateway and 自动生成nacos

    spring:
      application:
        name: gateway   # 服务名
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 # nacos地址
        gateway:
          discovery:
            locator:
              enabled: true # 让gateway可以发现nacos中的服务,gateway自动根据服务发现为每一个服务创建了一个router,# 这个router将以服务名开头的请求路径转发到对应的服务
    

    When requesting, remember to bring the name of the server application.name. For example locahost:8083/user/user/findById, the first one useris the service name.

  • If you don't want to do this and want to jump directly to the corresponding service using a path without writing the service name, then we need to customize routes.

    server:
      port: 8083
    
    spring:
      application:
        name: gateway   # 服务名
    
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 # nacos地址
        gateway:
          routes: # 路由,可配置多个
          - id: user_route  # 路由id,唯一即可,默认UUID
            uri: lb://user  # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称
            order: 1  # 路由优先级,默认0,越低优先级越高
            predicates:
            - Path=/user/**   # 断言,匹配规则
    

    If you don't use the routes automatically generated by nacos and define them yourself, then we localhost:8083/user/findByIdcan normally access the resources userunder the service when we access them /user/findById.

    C:\Users\Admin>curl http://localhost:8083/user/findById?id=1
    Zhangsan
    

Both methods can be used, depending on the actual situation of the project. locator.enabled: trueAs long as it is configured in the gateway, when you perform gateway routing, the first directory in the request address must be the service name .

Guess you like

Origin blog.csdn.net/weixin_45248492/article/details/132634732