(Vi) Spring Cloud Gateway Zuul

Zuul as a gateway, the following can be used as a role often in Spring Cloud

1. and eureka-client, Ribbon, Feign can be combined with intelligent routing and load balancing functions

2. The unified API for all services aggregation, by calling an API exposed by a unified external gateway outside, can play a role in protecting the API interface

3. The gateway can do a unified identity and permissions verification

 

 Here we will learn gateway Zuul, mainly routing, load balancing, fuses, filters, etc., to the design of the module

  eureka-server 7001 

  eureka-client  7002 7003

  eureka-ribbon-client 7004

  eureka-Zuul-client 8000

 Which eureka-server, eureka-client, eureka-ribbion-client module and our first few chapters of the same, in order to enhance memory, let us do a complete configuration

1. Create a new maven project eurekazuul

 Deleted src directory, add the pom 

<packaging>pom</packaging>

Configuring eureka-server

    2.1 pom.xml 

  

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

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

   2.2 startup class

   

package com.devin.eurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {

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

}

 2.3 Permissions configuration class

    

package com.devin.eurekaserver.config;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //关闭csrf
        super.configure(http);
        //开启认证
        http.csrf().disable();
    }
}

 

   2.4 application.yml profile

   eureka-server startup port 7001

Server: 
  Port: 7001 # Enable port 
the Spring: 
  # application name 
  the Application: 
    name: Eureka-Server 
  # Security Configuration 
  Security: 
    Basic: 
      Enabled: to true 
    the User: 
      name: dev 
      password: 123456 

#eureka configuration 
Eureka: 
  Server: 
    # Set scanning service failure interval 
    eviction-interval the-Timer-in-MS: 20000 
    enable-Self-Preservation: to true 
  instance: 
    hostname: localhost 
    leaseRenewalIntervalInSeconds: 10 
    Health-Check-URL-path: / Actuator / Health 
  Client: 
    Register-with-Eureka: to false #false: not registered with the registry as a client
    fetch-registry: when false # is true, you can start, but reported abnormal: the any of Can not ON the Execute Request Known Server
    url-Service: 
      defaultzone: HTTP: // $ {eureka.instance.hostname}: $ {server.port} / Eureka / 

# Health whether the endpoint must show all the details. By default, / actuator / health is disclosed, and does not show details. 
# Set switch actuator 
Management: 
  Security: 
    Enabled: to false 
  Endpoints: 
    Web: 
      Exposure: 
        the include: "*" 
  Endpoint: 
    Health: 
      Show-Details: ALWAYS

 

 

 3. eureka-client configuration

     3.1 pom.xml

   

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.8.RELEASE</version>
        </dependency>

 

     3.2 startup class

    

package com.devin.eurekaclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EnableEurekaClient
@SpringBootApplication
public class EurekaClientApplication {

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

}

 

     3.3 controller class

   

package com.devin.eurekaclient.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Devin Zhang
 * @className HelloController
 * @description TODO
 * @date 2020/3/31 10:26
 */
@RestController
public class HelloController {

    @Value("${server.port}")
    private String port;

    @GetMapping("/sayHello")
    public String sayHello(String name) {
        return "hello " + name + ", Warmly welcome from port:" + port;
    }
}

 

     3.4 application.yml configuration class

     Subsequent eureka-client will start two instances, 7002, 7003 

  

Eureka: 
  the auth: 
    User: dev 
    password: 123456 
  Client: 
    the serviceUrl: 
      defaultzone: HTTP: // eureka.auth.user} {$: $ {} @localhost eureka.auth.password: 7001 / Eureka / 
  instance: 
    # used for IP Register 
    the prefer-IP-address: to true 
    # configuration example registration ID 
    instance-ID: $ {address} spring.cloud.client.ip-: the server.port} {$ 
    # heartbeat time, i.e. renew the service interval time (default for the 30s) 
    Lease-renewal-in-seconds The interval The-: 5 
    # daze time, a service contract expires (the default is for 90s) 
    Lease-expiration-DURATION-in-seconds The: 10 
    Health-the Check-url-path: / Actuator / Health 
Server: 
  Port: 7002 
Spring: 
  file application: 
    name: Eureka-Client

 

4. eureka-ribbon-client

 The new project is mainly used for testing zuul gateway routing to eureka-ribbon-client

   4.1 pom.xml 

    

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.8.RELEASE</version>
        </dependency>

     4.2 startup class

        

package com.devin.eurekaribbonclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EnableEurekaClient
@SpringBootApplication
public class EurekaRibbonClientApplication {

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

}

  

          4.3 RibbonConfig

        

package com.devin.eurekaribbonclient.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @author Devin Zhang
 * @className RibbonConfig
 * @description TODO
 * @date 2020/3/31 10:48
 */
@Configuration
public class RibbonConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

  

     4.4 service by RestTemplate to call eureka-client load balancing

      

package com.devin.eurekaribbonclient.service;

import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * @author Devin Zhang
 * @className HelloService
 * @description TODO
 * @date 2020/3/31 10:50
 */

@Service
public class HelloService {

    @Resource
    private RestTemplate restTemplate;

    public String sayHello(String name) {
        return restTemplate.getForObject("http://eureka-client/sayHello?name=" + name, String.class);
    }
}

 

    4.5 controller  

     

package com.devin.eurekaribbonclient.controller;

import com.devin.eurekaribbonclient.service.HelloService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author Devin Zhang
 * @className RibbonHelloController
 * @description TODO
 * @date 2020/3/31 10:50
 */
@RestController
public class RibbonHelloController {

    @Resource
    private HelloService helloService;

    @GetMapping("/sayHelloFromRibbon")
    public String sayHelloFromRibbon(String name) {
        return helloService.sayHello(name);
    }

}

  

 4.6 application.yml configuration class

   eureka-ribbon-client poor port 7004 

   

Eureka: 
  the auth: 
    User: dev 
    password: 123456 
  Client: 
    the serviceUrl: 
      defaultzone: HTTP: // eureka.auth.user} {$: $ {} @localhost eureka.auth.password: 7001 / Eureka / 
  instance: 
    # used for IP Register 
    the prefer-IP-address: to true 
    # configuration example registration ID 
    instance-ID: $ {address} spring.cloud.client.ip-: the server.port} {$ 
    # heartbeat time, i.e. renew the service interval time (default for the 30s) 
    Lease-renewal-in-seconds The interval The-: 5 
    # daze time, a service contract expires (the default is for 90s) 
    Lease-expiration-DURATION-in-seconds The: 10 
    Health-the Check-url-path: / Actuator / Health 
Server: 
  Port: 7004 
Spring: 
  file application: 
    name: Eureka-Ribbon-Client

 

  5. eureka Zuul-client

     It defines a fuse, a filter, and a route disposed in eureka-zuul-client

     5.1 pom.yml

    

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.8.RELEASE</version>
        </dependency>

 

    5.2 startup class

    

package com.devin.eurekazuulclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableEurekaClient
@EnableZuulProxy
@SpringBootApplication
public class EurekaZuulClientApplication {

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

}

 

   5.3 class definition of the fuse process, when accessed by zuul service is not available, the method proceeds to fuse

   

package com.devin.eurekazuulclient.service;

import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author Devin Zhang
 * @className BaseZuulFallbackProvider
 * @description TODO
 * @date 2020/3/31 11:05
 */
@Component
class BaseZuulFallbackProvider the implements FallbackProvider {public 
            @Override
    @Override 
    public String getRoute () { 
        // return for the name of the service, if all the client are taking this fuse, then returns * 
        return "*"; 
    } 

    @Override 
    public ClientHttpResponse fallbackResponse (String route, the cause is Throwable) { 
        return new new ClientHttpResponse () { 
            @Override 
            public HttpStatus getStatusCode () throws IOException { 
                return HttpStatus.OK; 
            } 

            @Override 
            public int getRawStatusCode () throws IOException { 
                return 200 is; 
            } 

            public String getStatusText () throws IOException { 
                return "the OK";
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("sorry, the system is busy now ,pls try later ,response by zuul hystrix".getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }
        };
    }
}

 

    5.4 is defined filter, check for a unified authority, etc.

    For example, we do a simple token can not be blank check

     

package com.devin.eurekazuulclient.filter;


import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;


import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

/**
 * @author Devin Zhang
 * @className ZuulBaseFilter
 * @description TODO
 * @date 2020/3/31 11:18
 */
@Component
public class ZuulBaseFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        String token = request.getParameter("token");
        if (token == null) {
            try {
                currentContext.setSendZuulResponse(false);
                currentContext.setResponseStatusCode(301);
                currentContext.getResponse().getWriter().write("token is empty!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

  

  5.5 application.yml configured route map

    / Zuulapi / request will be routed to the Service eureka-client

   / Ribbonapi / request will be routed to the Service eureka-ribbon-client

    

Eureka: 
  the auth: 
    User: dev 
    password: 123456 
  Client: 
    the serviceUrl: 
      defaultzone: HTTP: // eureka.auth.user} {$: $ {} @localhost eureka.auth.password: 7001 / Eureka / 
  instance: 
    # used for IP Register 
    the prefer-IP-address: to true 
    # configuration example registration ID 
    instance-ID: $ {address} spring.cloud.client.ip-: the server.port} {$ 
    # heartbeat time, i.e. renew the service interval time (default for the 30s) 
    Lease-renewal-in-seconds The interval The-: 5 
    # daze time, a service contract expires (the default is for 90s) 
    Lease-expiration-DURATION-in-seconds The: 10 
    Health-the Check-url-path: / Actuator / Health 
Server: 
  Port: 8000 
the Spring: 
  the Application: 
    name: Zuul-Client
 Zuul:
  routes:
    zuulapi:
      path: /zuulapi/**
      serviceId: eureka-client
    ribbonapi:
      path: /ribbonapi/**
      serviceId: eureka-ribbon-client

 

  6. Test

  Start eureka-server 7001

  Start eureka-client 7002 7003 

  java -jar eureka-client-0.0.1-SNAPSHOT.jar --server.port=7002

  java -jar eureka-client-0.0.1-SNAPSHOT.jar --server.port=7003

  Start eureka-ribbon-client 7004

  Start eureka-zuul-client 8000

 

  Registration information after start following  http: // localhost: 7001 /

  

 

 

 

  6.1 Routing Forwarding check 

 

    Separate visits

   http://localhost:8000/zuulapi/sayHello?name=devin&token=123

   http://localhost:8000/ribbonapi/sayHelloFromRibbon?name=devin&token=123

   We can see already routed to eureka-client and eureka-ribbon-client interface

 

  6.2 token verification

 

 Visit   http: // localhost:? 8000 / zuulapi / sayHello name = devin  can see will prompt token is empty

 

 

 

 Visit   http: // localhost: 8000 / zuulapi  / sayHello name = devin & token = 123? Can see normal visit,

  DESCRIPTION request has been forwarded to the eureka-client while also checking the filter has passed, and switch between 7002 and 7003

 Access can be seen from the results, zuul eureka-client is automatically carried out between a load balance

 

 

 

 

 

 

  Also visit  http: // localhost:? 8000 / ribbonapi / sayHelloFromRibbon name = devin & token = 123  could achieve the same results

 

 6.3 zuul fuse verification

   Two were stopped eureka-client, and then go to the following address respectively, can be seen zuul fuse in force

   http://localhost:8000/zuulapi/sayHello?name=devin&token=123

   http://localhost:8000/ribbonapi/sayHelloFromRibbon?name=devin&token=123

   

 

 

 

 

So far, Zuul gateway to build and validate complete

 

 

 

   

 

 

 

Guess you like

Origin www.cnblogs.com/DevinZhang1990/p/12604589.html