背景: 我需要在網關實現一種功能,某個用戶的請求永遠打在后台指定的服務,也就是根據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 等