疯狂Spring Cloud连载(8)Spring Cloud与Ribbon

来源:互联网 发布:js urldecode 在线 编辑:程序博客网 时间:2024/06/06 18:02

 本文节选自《疯狂Spring Cloud微服务架构实战》

Spring Cloud教学视频:http://blog.csdn.net/boxiong86/article/details/78399104

Spring CloudRibbonRibbon

本章要点

    Spring Cloud中使用Ribbon

Spring Cloud集成了Ribbon,结合Eureka,可实现客户端的负载均衡。我们前面章节所使用的RestTemplate(被@LoadBalanced修饰)、还有后面章节的Feign,都已经拥有负载均衡功能。本小节将以RestTemplate为基础,讲述及测试Eureka中的Ribbon配置。

准备工作

为了本小节的测试准备,按顺序进行以下工作:

     新建Eureka服务器端项目,名为“cloud-server,端口8761,代码目录codes\04\4.4\cloud-server

     新建Eureka服务提供者项目,命名为“cloud-provider,代码目录codes\04\4.4\cloud-provider,该项目主要进行以下工作:

    控制器里面,发布一个REST服务,地址为/person/{personId},请求后返回Person实例,其中PersonmessageHTTP请求的URL

    服务提供者需要启动两次因此在控制台中需要输入启动端口。

     新建Eureka服务调用者项目,命名为“cloud-invoker,对外端口为9000,代码目录codes\04\4.4\cloud-invoker。本例的负载均衡配置主要针对服务调用者。

以上项目准备完成并启动后,结构如图4-2所示。


4-2准备的项目结构图

注意:Eureka相关项目的建立,可参见本书的3.2章节。

使用代码配置Ribbon

前面章节讲述了负载规则以及Ping,在Spring Cloud中,可将自定义的负载规则以及Ping类,放到服务调用者中,查看效果。新建自定义的IRuleIPing,两个实现类请见代码清单4-11

代码清单4-11

codes\04\4.4\cloud-invoker\src\main\java\org\crazyit\cloud\MyRule.java

codes\04\4.4\cloud-invoker\src\main\java\org\crazyit\cloud\MyPing.java

public class MyRule implements IRule {

private ILoadBalancer lb;

 

public Server choose(Object key) {

List<Server> servers = lb.getAllServers();

System.out.println("这是自定义服务器定规则类,输出服务器信息:");

for(Server s : servers) {

System.out.println("        " + s.getHostPort());

}

return servers.get(0);

}

...省略settergetter方法

}

public class MyPing implements IPing {

 

public boolean isAlive(Server server) {

System.out.println("自定义Ping类,服务器信息:" + server.getHostPort());

returntrue;

}

}

根据两个自定义的IRuleIPing类可知,实际上跟4.3章节中的自定义实现类似,服务器选择规则中只返回集合中的第一个实例,IPing实现仅仅是控制输入服务器信息。接下来,新建配置类,返回规则与PingBean,请见代码清单4-12

代码清单4-12

codes\04\4.4\cloud-invoker\src\main\java\org\crazyit\cloud\config\MyConfig.java

04\4.4\cloud-invoker\src\main\java\org\crazyit\cloud\config\CloudProviderConfig.java

public class MyConfig {

@Bean

public IRule getRule() {

return new MyRule();

}

@Bean

public IPing getPing() {

return new MyPing();

}

}

 

@RibbonClient(name="cloud-provider", configuration=MyConfig.class)

public class CloudProviderConfig {

 

}

 

代码清单4-12中,CloudProviderConfig配置类,使用了@RibbonClient注解,配置了RibbonClient的名称为“cloud-provider对应的配置类为“MyConfig”,也就是名称为“cloud-provider”的客户端,将使用MyRuleMyPing两个类。在服务调用者的控制器中,加入对外服务,服务中调用RestTemplate,如代码清单4-13

代码清单4-13codes\04\4.4\cloud-invoker\src\main\java\org\crazyit\cloud\InvokerController.java

@RestController

@Configuration

public class InvokerController {

 

@LoadBalanced

@Bean

public RestTemplate getRestTemplate() {

return new RestTemplate();

}

@RequestMapping(value = "/router", method = RequestMethod.GET,

produces = MediaType.APPLICATION_JSON_VALUE)

public String router() {

RestTemplate restTpl = getRestTemplate();

//根据名称调用服务

String json = restTpl.getForObject(

"http://cloud-provider/person/1", String.class);

return json;

}

}

以上的控制器中,为RestTemplate加入了@LoadBalanced修饰,与第3章类似,在此不再赘述,关于RestTemplate的原理,将在本章后面章节讲述。进行以下操作,查看本例效果:

    启动一个Eureka服务器(cloud-server)。

    启动两次Eureka服务提供者(cloud-provider),分别输入80808081端口。

    启动一个Eureka服务调用者(cloud-invoker)。

    打开浏览器访问http://localhost:9000/router,可以看到调用服务后返回的JSON字符串,不管刷新多少次,最终都只会访问其中一个端口

使用配置文件设置Ribbon

在前面使用Ribbon时,可以通过配置来定义各个属性,在使用Spring Cloud时,这些属性同样可以配置到application.yml中,以下的配置同样生效:

cloud-provider:

  ribbon:

    NFLoadBalancerRuleClassName: org.crazyit.cloud.MyRule

    NFLoadBalancerPingClassName: org.crazyit.cloud.MyPing

    listOfServers: http://localhost:8080/,http://localhost:8081/

cloud-provider这个客户端,配置了规则处理类、Ping类以及服务器列表,以同样的方式运行本小节例子,可看到同样的效果,在此不再赘述。

代码与配置文件的方式进行配置,两种方式的效果一致,但对比起来,明显是配置文件的方式更加简便。

注意:本案例的cloud-invoker模块中,默认使用了代码的方式来配置Ribbon,配置文件中的配置已被注释。

Spring使用RibbonAPI

Spring CloudRibbon进行封装,例如像负载客户端、负载均衡器等,我们可以直接使用SpringLoadBalancerClient来处理请求以及服务选择。代码清单4-14,在服务器调用者的控制器中使用LoadBalancerClient

代码清单4-14codes\04\4.4\cloud-invoker\src\main\java\org\crazyit\cloud\InvokerController.java

@Autowired

private LoadBalancerClient loadBalancer;

 

@RequestMapping(value = "/uselb", method = RequestMethod.GET,

produces = MediaType.APPLICATION_JSON_VALUE)

public ServiceInstance uselb() {

//查找服务器实例

ServiceInstance si = loadBalancer.choose("cloud-provider");

return si;

}

除了使用Spring封装的负载客户端外,还可以直接使用RibbonAPI,代码4-15,直接获取Spring Cloud默认环境中,各个Ribbon的实现类。

代码清单4-15codes\04\4.4\cloud-invoker\src\main\java\org\crazyit\cloud\InvokerController.java

@Autowired

private SpringClientFactory factory;

@RequestMapping(value = "/defaultValue", method = RequestMethod.GET,

produces = MediaType.APPLICATION_JSON_VALUE)

public String defaultValue() {

System.out.println("====输出默认配置:");

//获取默认的配置

ZoneAwareLoadBalancer alb = (ZoneAwareLoadBalancer) factory

.getLoadBalancer("default");

System.out.println("    IClientConfig: "

+ factory.getLoadBalancer("default").getClass()

.getName());

System.out.println("    IRule: " + alb.getRule().getClass().getName());

System.out.println("    IPing: " + alb.getPing().getClass().getName());

System.out.println("    ServerList: "

+ alb.getServerListImpl().getClass().getName());

System.out.println("    ServerListFilter: "

+ alb.getFilter().getClass().getName());

System.out.println("    ILoadBalancer: " + alb.getClass().getName());

System.out.println("    PingInterval: " + alb.getPingInterval());

System.out.println("====输出cloud-provider配置:");

//获取cloud-provider的配置

ZoneAwareLoadBalancer alb2 = (ZoneAwareLoadBalancer) factory

.getLoadBalancer("cloud-provider");

System.out.println("    IClientConfig: "

+ factory.getLoadBalancer("cloud-provider").getClass()

.getName());

System.out.println("    IRule: " + alb2.getRule().getClass().getName());

System.out.println("    IPing: " + alb2.getPing().getClass().getName());

System.out.println("    ServerList: "

+ alb2.getServerListImpl().getClass().getName());

System.out.println("    ServerListFilter: "

+ alb2.getFilter().getClass().getName());

System.out.println("    ILoadBalancer: " + alb2.getClass().getName());

System.out.println("    PingInterval: " + alb2.getPingInterval());

return "";

}

代码中使用了SpringClientFactory通过该实例,可获取各个默认的实现类以及配置分别输出了默认配置以及“cloud-provider”配置。运行代码清单4-15,浏览器中访问地址http://localhost:8080/defaultValue,可看到控制台输出如下:

==== 输出默认配置:

    IClientConfig: com.netflix.loadbalancer.ZoneAwareLoadBalancer

    IRule: com.netflix.loadbalancer.ZoneAvoidanceRule

    IPing: com.netflix.niws.loadbalancer.NIWSDiscoveryPing

    ServerList: org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList

    ServerListFilter: org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter

    ILoadBalancer: com.netflix.loadbalancer.ZoneAwareLoadBalancer

    PingInterval: 30

==== 输出cloud-provider配置:

    IClientConfig: com.netflix.loadbalancer.ZoneAwareLoadBalancer

    IRule: org.crazyit.cloud.MyRule

    IPing: org.crazyit.cloud.MyPing

    ServerList: org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList

    ServerListFilter: org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter

    ILoadBalancer: com.netflix.loadbalancer.ZoneAwareLoadBalancer

    PingInterval: 30

根据输出可知,cloud-provider客户端使用的负载规则类以及Ping类,是我们自定义的实现类。

一般情况下,Spring已经帮我们封装好了Ribbon,我们只需要直接调用RestTemplateAPI来访问服务即可

 本文节选自《疯狂Spring Cloud微服务架构实战》

Spring Cloud教学视频:http://blog.csdn.net/boxiong86/article/details/78399104

本书代码共享地址:https://gitee.com/yangenxiong/SpringCloud

阅读全文
0 0