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