spring Cloud 四:服务网关 Zuul

这篇文章大部分转载自http://blog.didispace.com/springcloud5/

服务路由

通过服务路由的功能,我们在对外提供服务的时候,只需要通过暴露Zuul中配置的调用地址就可以让调用方统一的来访问我们的服务,而不需要了解具体提供服务的主机信息了

在Zuul中提供了两种映射方式

1.通过url直接映射,我们可以如下配置

# routes to url
zuul.routes.api-a-url.path=/api-a-url/**
zuul.routes.api-a-url.url=http://localhost:2222/

该配置,定义了,所有到Zuul的中规则为:/api-a-url/**的访问都映射到http://localhost:2222/上,也就是说当我们访问http://localhost:5555/api-a-url/add?a=1&b=2的时候,Zuul会将该请求路由到:http://localhost:2222/add?a=1&b=2

其中,配置属性zuul.routes.api-a-url.path中的api-a-url部分为路由的名字,可以任意定义,但是一组映射关系的path和url要相同,下面讲serviceId时候也是如此

通过url映射的方式对于Zuul来说,并不是特别友好,Zuul需要知道我们所有为服务的地址,才能完成所有的映射配置。而实际上,我们在实现微服务架构时,服务名与服务实例地址的关系在eureka server中已经存在了,所以只需要将Zuul注册到eureka server上去发现其他服务,我们就可以实现对serviceId的映射。例如,我们可以如下配置

zuul.routes.api-a.path=/api-a/**
zuul.routes.api-a.serviceId=service-A

zuul.routes.api-b.path=/api-b/**
zuul.routes.api-b.serviceId=service-B

eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/


针对我们在准备工作中实现的两个微服务service-A和service-B,定义了两个路由api-a和api-b来分别映射。另外为了让Zuul能发现service-A和service-B,也加入了eureka的配置。

接下来,我们将eureka-server、service-A、service-B以及这里用Zuul实现的服务网关启动起来,在eureka-server的控制页面中,我们可以看到分别注册了service-A、service-B以及api-gateway

尝试通过服务网关来访问service-A和service-B,根据配置的映射关系,分别访问下面的url

http://localhost:5555/api-a/add?a=1&b=2 通过serviceId映射访问service-A中的add服务

http://localhost:5555/api-b/add?a=1&b=2 通过serviceId映射访问service-B中的add服务

http://localhost:5555/api-a-url/add?a=1&b=2 通过url映射访问service-A中的add服务

推荐使用serviceId的映射方式,除了对Zuul维护上更加友好之外,serviceId映射方式还支持了断路器,对于服务故障的情况下,可以有效的防止故障蔓延到服务网关上而影响整个系统的对外服务

上面说,seriviceId映射方式支持了断路器,我刚试了下

在一个加了断路器的方法里,消费者如下面这样调用

1.用serviceId直接调用服务提供方的接口,可以

@HystrixCommand(fallbackMethod = "addServiceFallback")
	public String addService(long num) {
		return restTemplate.getForEntity("http://SERVICE-B/add?a=1&b=2", String.class).getBody();
	}

2.用zuul的service直接调用服务提供方的接口,可以,(api-gateway是zuul服务的serviceId)

@HystrixCommand(fallbackMethod = "addServiceFallback")
	public String addService(long num) {
		return restTemplate.getForEntity("http://api-gateway/api-a/add?a=1&b=2", String.class).getBody();
	}

3.直接用url调用,不可以

	@HystrixCommand(fallbackMethod = "addServiceFallback")
	public String addService(long num) {
		return restTemplate.getForEntity("http://localhost:2222/add?a=1&b=2", String.class).getBody();
	}

4.直接用zuul的url去调用,不可以

@HystrixCommand(fallbackMethod = "addServiceFallback")
	public String addService(long num) {
		return restTemplate.getForEntity("http://localhost:5555/api-a/add?a=1&b=2", String.class).getBody();
	}

不过通过断路器的fallbackMethod的输出日志来看, java.lang.IllegalStateException: No instances available for localhost

在网上查了下,因为我给RestTemplate加上了Rabbon的@LoadBalanced,所以走这个类RibbonLoadBalancerClient,断点进入了如下的页面,serverid必须是我们访问的服务名称 ,当我们直接输入ip的时候获取的server是null,就会抛出异常

因为ribbon的作用是负载均衡,那么你直接使用ip地址,那么就无法起到负载均衡的作用,因为每次都是调用同一个服务,当你使用的是服务名称的时候,他会根据自己的算法去选择具有该服务名称的服务。

所以无法凭这个来判断,Hystrix断路器不支持url形式的调用,所以我先去掉@LoadBalanced,去掉负载均衡,看它还会不会报这个错

当我去掉@LoadBalanced注解后,可以成功调用

@HystrixCommand(fallbackMethod = "addServiceFallback")
	public String addService(long num) {
		return restTemplate.getForEntity("http://localhost:5555/api-a/add?a=1&b=2", String.class).getBody();
	}
@HystrixCommand(fallbackMethod = "addServiceFallback")
	public String addService(long num) {
		return restTemplate.getForEntity("http://localhost:2222/add?a=1&b=2", String.class).getBody();
	}

也就是说,断路器也是支持这个url形式的调用的,只不过url调用太死板了,不够灵活,而且也不支持Rabbon的LoadBalanced
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值