1 rebbion负载均衡
1.1 作用
我们的服务一般情况都是分布式的服务,所有同一个服务会在多个节点部署。当访问端访问的时候如图,具体用什么策略去访问服务节点这里会用到负载均衡。负载均衡策略,rebbion的实现有6个(这里可以去IRule的实现,直接搜寻类就可以看到),但是常用的有两个,随机,轮询。这里是没有使用gateway的情况,如果使用gateway会是访问端访问网关,网关去eureka拉取服务,路由转发请求。后面会有写作方法
1.2 如何使用
为了验证其作用,我们需要搭建如图一样的服务,创建两个服务模拟服务A。首先创建空的demo01项目模拟聚合,创建方式为File -> new -> project 选择 empty Project ,name修改为demo01 然后创建服务provider 模拟服务A。然后使用idea的编辑启动两个端口来运行服务。模拟两个服务器注册到eureka。
1.2.1 创建空项目
创建方式为File -> new -> project 选择 empty Project 修改项目名称name为demo01,点击create。
1.2.2 创建服务provider
右键点击demo01如图,右键moudel,创建一个provider服务,选择依赖spring web(web访问),eureka DiscoverClient(往eureka注册服务)
服务A中,在application中添加注解@EnableEurekaClient
修改配置文件
server:
port: 8090
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: product
1.2.3 创建eureka
右键点击demo01如图,右键moudel,创建eureka服务,注意springboot选择版本
在application中添加注解:@EnableEurekaServer
修改配置文件:
# 应用名称
spring:
application:
name: eureka
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
1.2.4 增加接口代码
因为我们要模拟负载,所有要有被调用的接口代码.在provider中增加接口。代码如下,代码中的接收参数是为了模拟轮训与随机,打印出来的结果,可以明显一些。
package com.example.provider.demo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
private final static Log log = LogFactory.getLog(TestController.class);
@PostMapping("/test")
public String test(@RequestBody String str){
log.info("被调用次数为 " + str);
return "success";
}
}
1.2.5 增加调用端服务
在实际开发中,我们暴露的端口是gateway网关的,所有的请求,都是请求的网关,所以实际中的负载也是在网关中配置的。这里我们起一个服务,来模拟下,只是模拟,这里不使用网关。新创建的服务,我们命名为consumer
修改配置文件:
server:
port: 8093
spring:
application:
name: consumer
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
#product:
# ribbon:
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
在application中添加注解@EnableEurekaClient 。 增加调用接口代码,接口中调用服务的接口中,是服务的名称product,加接口
接口中RestTemplate是没有初始化的,所以我们需要手动初始化生成bean。RestTemplate模拟调用,后面会用openFegin替换掉。
接口中的注解@LoadBalanced 为启动负载。默认的负载方式为轮训。
package com.example.consumer.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class TestController {
@Autowired
RestTemplate restTemplate;
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
@GetMapping("get")
public String test(String re){
re = "1";
ResponseEntity<String> str = restTemplate.postForEntity("http://product/test",re,String.class);
return str.getBody();
}
}
1.2.6 启动项目
先启动eureka
启动provider时,我们需要启动两个服务,所以这个时候我们需要复制一个服务启动出来。操作步骤如下:1 点击启动项的下三角 2 点击Edit Configurations进入编辑页面,如图操作
进入后选择Porvider服务,点击复制,复制后修改名称为provider02,修改端口信息,在VM option中增加 -Dserver.port=8094,如果没有VM option文本框,需要点击页面上的蓝色字母,Modify options增加,整体如下图操作
启动 provider、provider02、consumer服务;启动后访问http://localhost:8761/ 如下图所示
1.2.7 测试
在页面调用http://localhost:8093/get 无限刷新访问,但是这个方法比较笨,所以,我在consumer中直接写了个main方法调用。
并把consumer中的test接口中,re参数,设置值那块去掉。整体的代码修改为
package com.example.consumer.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class TestController {
@Autowired
RestTemplate restTemplate;
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
@GetMapping("get")
public String test(String re){
// 这里原先有re = "1" 是用浏览器调用的。但是浏览器调用不是很方便,所以直接用下面的main方法调用。
ResponseEntity<String> str = restTemplate.postForEntity("http://product/test",re,String.class);
return str.getBody();
}
public static void main(String[] args) {
RestTemplate restTemplate = new RestTemplate();
for (int i = 0; i < 10 ; i++){
restTemplate.getForEntity("http://localhost:8093/get?re="+i,String.class);
}
}
}
这个时候可以跑main方法来看结果。然后修改consumer配置文件中的机制为随机,再查看结果。就是需要把配置文件中的注释掉的部分打开。图中是我运行的结果。
可以清晰看到调用结果的转换。负载的简单使用到此结束。
2 openFegin的使用
openFegin需要在我们调用放引入feigin的依赖。在consumer中增加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
在启动类上面增加 @EnableFeignClients 注解
在consumer中增加接口,接口内容如下。其中注解@FeignClient("product") 中product是我们要调用的服务名称
package com.example.consumer.demo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
@FeignClient("product")
public interface IFeign {
@PostMapping("/test")
String test(String str);
}
consumer中的TestController类整体修改如下:
package com.example.consumer.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class TestController {
@Autowired
private IFeign iFeign;
@GetMapping("get")
public String test(String re){
return iFeign.test(re);
}
public static void main(String[] args) {
RestTemplate restTemplate = new RestTemplate();
for (int i = 0; i < 10 ; i++){
restTemplate.getForEntity("http://localhost:8093/get?re="+i,String.class);
}
}
}
重启consumer,测试如1.2.7中基本一样。