springCloud学习03之api服务网关zuul反向代理及重试配置

版权声明: https://blog.csdn.net/dream_broken/article/details/76973834

     在前面学习ribbon,feign的时候,向api提供者发起请求的时候,实际用的是http://提供者服务名称这形式,如果提供者api自身进行了集群,没有使用类似nginx的反向代理,而消费者又没有连接eureka的话,那就麻烦了。spring cloud中的zuul其中的一个功能就担任了反向代理的功能,还能连接eureka进行服务发现。

     如果使用nginx对提供者集群进行反向代理,架构类似如下


  如果消费者服务集群新增或减少或ip端口变更,那对应的nginx也要变更,然后重启。

  如果使用zuul+eureka,则消费者服务集群变更的时候,zuul重eureka中获取到最新的消费者集群信息。


   当然也可以只弄一个zuul服务代理多个服务集群。


 服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务

路由、均衡负载功能之外,它还具备了权限控制等功能。Spring Cloud Netflix中的Zuul就担任了这样的一个角色,

为微服务架构提供了前门保护的作用,同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面,使得服务集

群主体能够具备更高的可复用性和可测试性。

      

   使用spring boot搭建zuul服务


pom.xml

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.2.RELEASE</version>
		<relativePath />

	</parent>

	<dependencies>
        <!-- 服务发现 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
       <!-- 服务网关 -->
        <dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-zuul</artifactId>
		</dependency>
		<!-- 重试机制 ,必须配,否则重试不生效 -->
		<dependency>
    		<groupId>org.springframework.retry</groupId>
    		<artifactId>spring-retry</artifactId>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Dalston.RELEASE</version>
				<type>pom</type>
				<scope>import</scope><!-- 这个不能丢 -->
			</dependency>

		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

启动类Application.java

package com.fei.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy   
@SpringCloudApplication 
public class Application {

	public static void main(String[] args) {

		SpringApplication.run(Application.class, args);
	}
}
@EnableZuulProxy 是zuul代理生效,@SpringCloudApplication 里面集合了springboot,eureka客户端,断路器hystrix

/**
 * @author Spencer Gibb
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}

application.properties

logging.config=classpath:logback.xml
logging.path=d:/logs

##tomcat set###

# eureka的默认端口是8761
server.port=8888
server.session-timeout=60
###########

spring.application.name=zuul-server

#像eureka服务注册信息时,使用ip地址,默认使用hostname
eureka.instance.preferIpAddress=true
eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${server.port}
eureka.client.serviceUrl.defaultZone=http://01.server.eureka:8081/eureka/

#开启健康检查(需要spring-boot-starter-actuator依赖)
eureka.client.healthcheck.enabled=true
#租期到期时间,默认90秒
eureka.instance.lease-expiration-duration-in-seconds=30
#租赁更新时间间隔,默认30,即30秒发送一次心跳
eureka.instance.lease-renewal-interval-in-seconds=10

#启动负载均衡的重试机制,默认false
spring.cloud.loadbalancer.retry.enabled=true
#Hystrix是否启用超时时间
hystrix.command.default.execution.timeout.enabled=true
#Hystrix断路器的超时时间,默认是1s,断路器的超时时间需要大于ribbon的超时时间,不然不会触发重试。
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000

#ribbon请求连接的超时时间
ribbon.ConnectTimeout=250
#请求处理的超时时间
ribbon.ReadTimeout=1000
#对所有请求操作都进行重试
ribbon.OkToRetryOnAllOperations=true
#对当前服务的重试次数(第一次分配给9082的时候,如果404,则再重试MaxAutoRetries次,如果还是404,则切换到其他服务MaxAutoRetriesNextServer决定)
ribbon.MaxAutoRetries=0
#切换服务的次数(比如本次请求分配给9082处理,发现404,则切换分配给9081处理,如果还是404,则返回404给客户端)
ribbon.MaxAutoRetriesNextServer=1



##反向代理配置,类似nginx

#####用户管理服务#####
zuul.routes.user-api.path=/user-api/**
#当stripPrefix=true,http://127.0.0.1:7081/user-api/user/find =>http://127.0.0.1:7081/user/find
#当stripPrefix=false,http://127.0.0.1:7081/user-api/user/find =>http://127.0.0.1:7081/user-api/user/find
zuul.routes.user-api.stripPrefix=true
#eureka中对应的服务名称
zuul.routes.user-api.serviceId=api-user-server
#重试,默认false
zuul.routes.user-api.retryable=true
#ribbo负载均衡策略配置,默认是依次轮询
#api-user-server.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule


#####积分管理服务#####
zuul.routes.integral-api.path=/integral-api/**
zuul.routes.integral-api.stripPrefix=true
zuul.routes.integral-api.serviceId=API-INTEGRAL


 重试机制pom.xml必须有spring-retry,同时spring.cloud.loadbalancer.retry.enabled=true,具体的某个服务zuul.routes.user-api.retryable=true,其中的user-api是路由名称,可自行自定义。


   前面学习已经搭建有eureka服务了127.0.0.1:8081,eureka-api提供者api-user-server,这里就不重复了,完整代码见github.

    启动eureka服务127.0.0.1:8081,启动zuul服务127.0.0.1:8888,eureka-api提供者中的UserProvider.java

package com.fei.springcloud.provider;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserProvider {

	@GetMapping(value="/find/{id}")
	public String find(@PathVariable("id") String id,HttpServletRequest request){
		long startTime = System.currentTimeMillis();
		System.out.println("服务端端口:"+request.getLocalPort()+"    接收到请求。。。。");
		//实际项目中,这里可以使用JSONObject,返回json字符串
		//为了便于测试消费者app的负载均衡,返回服务端端口
	//	try {
	//		Thread.sleep(5000);//休眠5秒钟,测试网关超时
	//	} catch (InterruptedException e) {
	//		e.printStackTrace();
	//	}
		long endTime = System.currentTimeMillis();
		String s = "张三"+"     服务端端口:"+request.getLocalPort()+"   耗时毫秒=" + (endTime - startTime);
		
		System.out.println("服务端端口:"+request.getLocalPort()+"    返回数据。。。。。耗时毫秒=" + (endTime - startTime));
		return s;
	}
}
 修改端口为9081启动,然后修改端口为9082启动,也就是127.0.0.1:9081,127.0.0.1:9082.


  浏览器请求http://127.0.0.1:8888/user-api/user/find/1,不停刷新,显示的信息来源9081,9082轮询。说明代理起作用了。

   zuul的配置文件,把重试配置关闭,同时停止9082。重启zuul,然后刷新http://127.0.0.1:8888/user-api/user/find/1,发现信息来源9081时正常,请求到9082时就报错了,zuul没有再次把请求放到9081去。停止zuul,修改配置文件,把重试配置开启,启动zuul,稍等十几秒后再刷http://127.0.0.1:8888/user-api/user/find/1,发现不报错了,说明但分配请求到9082时,发现404,立刻转发请求到9081去了。

   经测试,当请求时404时才会触发重试。测试例子,api中的代码加入Thread.slepp(5000),模拟api的处理时间超过了zuul中配置的超时时间,超时引起的错误不会触发重试。


  完整代码














猜你喜欢

转载自blog.csdn.net/dream_broken/article/details/76973834