Spring cloud各个微服务使用过程中,通过Eureka进行服务的注册与发现。ZUUL网管及服务间请求调用,默认都是通过Eureka进行。

    服务间请求处理过程,一般是通过服务名,到Eureka中获取实际的服务请求地址,然后根据实际地址进行HTTP请求。

    默认情况下,通过服务名到Eureka获取服务所在地址一般是如下构成的:

    http://${eureka.instance.hostName}:${server.port}/

    但是在微服务部署过程中,Docker镜像部署是我们常用的部署方式,这样就可能会出现一种情况,由于一些特殊的原因,docker映射出来的访问端口跟应用端口(server.port)不一致,如果我们注册Eureka上的服务端口还是应用端口(server.port)的话,服务间请求调用将会报链接超时(connect timed out),请求不到相应服务。这种情况也经常发生在Docker部署到K8s时,服务端口与应用端口通常由于端口冲突会不一样。

    如何解决呢?

  •     Eureka已经考虑到了各种部署情况,在Cloud Foundry上使用时,服务有全局的路由,故注册服务时也需要定制服务端口,情况类似,定制方式如下:
eureka:
  instance:
    hostname: ${vcap.application.uris[0]}
    nonSecurePort: 80

可见,通过设置eureka.instance.nonSecurePort来指定服务端口,这样就可以解决服务端口与应用端口(server.port)不一致情况。

  • Eureka注册时还有一个参数,定制完整的服务URL,这个服务URL就是服务间通过服务名在Eureka中获取的服务地址,其配置如下:
    eureka:
      instance:
        homePageUrl: http://${eureka.hostname}:8009/

    如果Spring boot的application.yml中配置了eureka.instance.homePageUrl地址,则根据服务名在Eureka中获取的服务地址就是eureka.instance.homePageUrl配置的地址。

  • Eureka还支持服务间HTTPS请求,其配置如下:

    eureka:
      instance:
        securePortEnabled: true
        statusPageUrl: https://${eureka.hostname}/info
        healthCheckUrl: https://${eureka.hostname}/health
        homePageUrl: https://${eureka.hostname}/

    这样通过服务名Eureka返回地址就是HTTPS加密请求的URL。

  • Eureka定制能力很强具体,可以参考官方文档:http://cloud.spring.io/spring-cloud-static/Finchley.SR1/single/spring-cloud.html#_eureka_metadata_for_instances_and_clients,里面详细介绍比较全面的配置,通常在遇到问题时作为字典使用,不过在时间允许的情况下还是可以详细了解一下,避免走各种弯路。

    如何验证配置的服务地址已生效呢?Eureka提供了EurekaClient请求接口,便于我们交互,我们可以通过该接口,获取Eureka提供的各种能力,满足我们业务需要,其中服务注册与服务发现接口应该是最常用的了。通过EurekaClient提供了扩展能力。所以我们可以通过EurekaClient接口,使用服务名获取服务请求地址。示例如下:

package com.king.business.controller;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;

@RestController
public class BusinessController {
	
	private final static Logger LOG = LoggerFactory.getLogger(BusinessController.class);
	
	@Autowired
	private EurekaClient discoveryClient;
	
	

	@RequestMapping(path="/getServiceUrl/{servicename}", method=RequestMethod.GET)
	public String getServiceUrl(@PathVariable("servicename") String serviceName) {
		InstanceInfo instance = discoveryClient.getNextServerFromEureka(serviceName, false);
		String serviceUrl = "";
		if(null != instance) {
			serviceUrl = instance.getHomePageUrl();
		}
		return serviceUrl;
	}
}

   其请求结果如下所示:

    

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐