准备两个maven项目,eureka-sales、eureka-user,经过访问eureka-sales服务调用eureka-user服务,三种访问方式下 eureka-user 代码不变,只是为了提供被访问接口。git
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.ymlspring
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 注解:bash
@SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
pom依赖:app
<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 方式:maven
@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(); } } }
方法实现:ide
@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(); }
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 + "] "; } }
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 便可。
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; } }
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次,结果说明有进行负载均衡
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 服务:
@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; } }
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次,结果说明有进行负载均衡
就是本身封装一个 httpclient 的 get 方法,而后访问:
http://127.0.0.1:8081/sales/queryGoodsList/3,而后观察结果,发现并无自动进行负载均衡:
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 中