018 微服务之间调用

1 服务说明

    准备两个maven项目,eureka-sales、eureka-user,通过访问eureka-sales服务调用eureka-user服务,三种访问方式下 eureka-user 代码不变,只是为了提供被访问接口。

    1-1 eureka

        pom依赖:

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka-server</artifactId>
		</dependency>
	</dependencies>
	
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-starter-parent</artifactId>
				<version>Camden.SR3</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

        application.yml

server:
  port: 8761
  
spring:
  application:
    name: eureka

eureka: 
  client:
    register-with-eureka: false
    fetch-registry: false
    server:
      waitTimeInMsWhenSyncEmpty: 0
    serviceUrl:
      defaultZone: http://localhost:${server.port}/eureka/

        启动类,加上 @EnableEurekaServer 注解:

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
	public static void main(String[] args) {
		SpringApplication.run(EurekaApplication.class, args);
	}
}

    1-2 eureka-sales

        pom依赖:

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-feign</artifactId>
		</dependency>
	</dependencies>
	
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-starter-parent</artifactId>
				<version>Camden.SR3</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

        定义接口:

@RequestMapping("/sales")
public interface SalesRest {
    @RequestMapping(value = "/queryGoodsList/{type}", method = RequestMethod.GET)
    Object queryGoodsList(Integer type);
}

        接口实现类,根据传入的type,决定以何种方式访问 eureka-user 服务,1 表示 ribbon 方式,2 表示feign 方式,其他数字表示 http 方式:

@RestController
public class SalesRestImpl implements SalesRest {

    @Autowired
    private SalesService salesService;

    @Override
    public String queryGoodsList(@PathVariable Integer type) {
    	System.out.println("start to queryGoodsList --->");
    	if(type.intValue() == 1) {
    		return salesService.queryGoodsListByRibbon();
    	}else if(type.intValue() == 2) {
    		return salesService.queryGoodsListByFeign();
    	}else {
            return salesService.queryGoodsListByHttp();
    	}
    }

}

        方法实现:

@Service
public class SalesService {
	
	@Autowired
	RestTemplate restTemplate;
	
	@Autowired
	UserFeignClient userFeignClient;
	
	private static final String RIBBON_URL = "http://user:8082/user/getUserInfo";
	private static final String HTTP_URL = "http://127.0.0.1:8082/user/getUserInfo";
	private static final String IP = IpUtil.getIp();

	public String queryGoodsListByRibbon() {
		String sales_result = "queryGoodsListByRibbon success : [sales_ip:" + IP + "] ";
		String result = restTemplate.getForObject(RIBBON_URL, String.class);
		return sales_result + result;
	}

	public String queryGoodsListByFeign() {
		String sales_result = "queryGoodsListByFeign success : [sales_ip:" + IP + "] ";
		String result = (String) userFeignClient.getUserInfo();
		return sales_result + result;
	}

	public String queryGoodsListByHttp() {
		String sales_result = "queryGoodsListByHttp success : [sales_ip:" + IP + "] ";
		String result = HttpClientUtil.doGet(HTTP_URL);
		return sales_result + result;
	}
}

        client

@FeignClient(name = "USER")
public interface UserFeignClient {
	@RequestMapping(value = "/user/getUserInfo", method = RequestMethod.GET)
	String getUserInfo();
}

    1-3 eureka-user

        pom依赖:

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
	</dependencies>
	
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-starter-parent</artifactId>
				<version>Camden.SR3</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

        接口:

@RequestMapping("/user")
public interface UserRest {
	@RequestMapping(value = "/getUserInfo", method = RequestMethod.GET)
	String getUserInfo();
}

        接口实现类:

@RestController
public class UserRestImpl implements UserRest{
	
	@Autowired
	private UserService userService;

	@Override
	public String getUserInfo() {
		System.out.println("start to getUserInfo --->");
		return userService.getUserInfo(); 
	}

}

        方法实现,为了验证 ribbon 的负载均衡,这里返回服务的端口号:

@Service("userService")
public class UserService {
	
	@Value("${server.port}")
	private Integer port;
	
	public String getUserInfo() {
		// 当前项目所在IP
		String ip = IpUtil.getIp();
		return "getUserInfo success : [user_ip:" + ip + "user_port:" + port + "] ";
	}

}

2 ribbon方式

        Ribbon 是 Netflix 发布的负载均衡器,与 Eureka 配合使用时,Ribbon 可以自动从 Eureka Server 获取服务提供者地址列表,并基于负载均衡算法,请求其中某个服务提供者实例。Ribbon的依赖是:

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

但是 spring-cloud-starter-eureka 中已经包含了 ribbon 依赖,所以直接添加 eureka 即可。

    2-1 eureka-sales

        pom依赖,这里直接有 eureka 就行,eureka 已经包含了 ribbon 依赖:

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
	</dependencies>
	
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-starter-parent</artifactId>
				<version>Camden.SR3</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

        application.yml

server:
  port: 8081

spring:
  application:
    name: sales
    
eureka:
  client:
    serviceUrl: 
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

        启动类,这里把 RestTemplate 注册一下,并且加上 @LoadBalanced 开启负载均衡:

@SpringBootApplication
@EnableDiscoveryClient
public class SalesApplication {
    
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
    	return new RestTemplate();
    }

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

}

       调用 eureka-user 服务,其中 RIBBON_URL 中的 user 是eureka-user注册到eureka中心的名称,也就是 application.name :

@Service
public class SalesService {
	
	@Autowired
	RestTemplate restTemplate;
	
	private static final String RIBBON_URL = "http://user:8082/user/getUserInfo";
	private static final String IP = IpUtil.getIp();

	public String queryGoodsListByRibbon() {
		String sales_result = "queryGoodsListByRibbon success : [sales_ip:" + IP + "] ";
		String result = restTemplate.getForObject(RIBBON_URL, String.class);
		return sales_result + result;
	}
}

    2-2 测试

        1. 启动 eureka 2. 启动 eureka-sales 3.启动 eureka-user 4.修改 eureka-user 的 application.yml 文件,将端口改为8083,启动第二个 eureka-user 服务。

        访问接口:http://127.0.0.1:8081/sales/queryGoodsList/1 

        此时以 ribbon 的方式访问10次,结果说明有进行负载均衡

3 feign方式

    3-1 eureka-sales

        pom依赖,添加 feign 依赖:

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-feign</artifactId>
		</dependency>
	</dependencies>
	</build>
	
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-starter-parent</artifactId>
				<version>Camden.SR3</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

        application.yml

server:
  port: 8081

spring:
  application:
    name: sales
    
eureka:
  client:
    serviceUrl: 
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

        启动类,添加 @EnableFeignClients 注解: 

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class SalesApplication {
    
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
    	return new RestTemplate();
    }

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

}

        创建 feign client 接口,这里的 USER 是 eureka-user 在 eureka 中心的注册名称,里面的接口定义成跟 eureka-user(被调用服务)中的接口一样:

@FeignClient(name = "USER")
public interface UserFeignClient {
	@RequestMapping(value = "/user/getUserInfo", method = RequestMethod.GET)
	String getUserInfo();
}

         调用 eureka-user 服务,其中 RIBBON_URL 中的 user 是eureka-user注册到eureka中心的名称,也就是 application.name :

@Service
public class SalesService {
	
	@Autowired
	UserFeignClient userFeignClient;
    private static final String IP = IpUtil.getIp();

	public String queryGoodsListByFeign() {
		String sales_result = "queryGoodsListByFeign success : [sales_ip:" + IP + "] ";
		String result = (String) userFeignClient.getUserInfo();
		return sales_result + result;
	}
}

    3-2 测试

        1. 启动 eureka 2. 启动 eureka-sales 3.启动 eureka-user 4.修改 eureka-user 的 application.yml 文件,将端口改为8083,启动第二个 eureka-user 服务。

        访问接口:http://127.0.0.1:8081/sales/queryGoodsList/2

        此时以 ribbon 的方式访问10次,结果说明有进行负载均衡

4 http方式

        就是自己封装一个 httpclient 的 get 方法,然后访问:

http://127.0.0.1:8081/sales/queryGoodsList/3,然后观察结果,发现并没有自动进行负载均衡:

5 附录

    eureka 项目:https://code.aliyun.com/995586041/eureka.git

    eureka-sales 项目:https://code.aliyun.com/995586041/ribbon_feign_http_sales.git

    eureka-user 项目:https://code.aliyun.com/995586041/ribbon_feign_http_user.git

    core-simple 项目:https://code.aliyun.com/995586041/core-simple.git

    上文中相关工具方法在 core-simple 中 

猜你喜欢

转载自my.oschina.net/u/2937605/blog/1806509