背景: 我需要在网关实现一种功能,某个用户的请求永远打在后台指定的服务,也就是根据ip地址进行负载均衡
原理: 在ribbon的配置类下:
那我们自己创建一个IRule的实现类,模仿ZoneAvoidanceRule,该类的继承体系:
所以我们只要继成AbstractLoadBalancerRule
package com.yang.xiao.hui.filter; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.List; @Component //这里注入容器,将会对所有的服务都生效 public class MyRule extends AbstractLoadBalancerRule { @Override public void initWithNiwsConfig(IClientConfig clientConfig) { } @Override public Server choose(Object key) { ILoadBalancer loadBalancer = getLoadBalancer(); List<Server> allServers = loadBalancer.getAllServers(); if(allServers.size()==1){ return allServers.get(0); } int size = allServers.size(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String remoteAddr = request.getRemoteAddr(); int hashCode = Math.abs(remoteAddr.hashCode()); //据说hashcode会有负数导致索引越界 int index=hashCode%size; return allServers.get(index); } }
上面的配置是对所有服务生效,如果我想指定某个服务生效:
回到源码:
继续跟进:
我们看看classNameProperty有哪些值:
现在我要指定自定义规则只对Product服务生效:
1.先将MyRule的Component注解去掉,不然对全部服务生效
2. 在yml中配置:
同理,配置单个服务的其他属性也是一样,如NFLoadBalancerClassName,NIWSServerListClassName 等