【Fegin技术专题】「原生态」打开Fegin之RPC技术的开端,你会使用原生态的Fegin吗?(下)

内容简介

在项目开发中,除了考虑正常的调用之外,负载均衡和故障转移也是关注的重点,这也是feign + ribbon的优势所在,基于上面两篇文章的基础,接下来我们开展最后一篇原生态fegin结合ribbon服务进行服务远程调用且实现负载均衡机制,也帮助大家学习ribbon奠定基础。

maven依赖

xml 复制代码
<dependencies>
    <dependency>
        <groupId>com.netflix.feigngroupId>
        <artifactId>feign-coreartifactId>
        <version>8.18.0version>
    dependency>
    <dependency>
        <groupId>com.netflix.feigngroupId>
        <artifactId>feign-jacksonartifactId>
        <version>8.18.0version>
    dependency>
    <dependency>
        <groupId>com.netflix.feigngroupId>
        <artifactId>feign-ribbonartifactId>
        <version>8.18.0version>
    dependency>
	<dependency>
    <groupId>com.netflix.archaiusgroupId>
    <artifactId>archaius-coreartifactId>
dependency>

dependencies>
复制代码

其中feign-core和feign-ribbon是必须的,如果需要在服务消费端和服务生产端之间进行对象交互,建议使用feign-jackson

配置读取

java 复制代码
import com.netflix.config.ConfigurationManager;
import feign.Feign;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import feign.ribbon.RibbonClient;
public class AppRun {
    public static void main(String[] args) throws Exception {
        User param = new User();
        param.setUsername("test");
        RemoteService service = Feign.builder().client(RibbonClient.create())
				.encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
			    .options(new Options(1000, 3500))
                .retryer(new Retryer.Default(5000, 5000, 3))
			    .target(RemoteService.class, "http://remote-client/gradle-web");

        for (int i = 1; i 10; i++) {
            User result = service.getOwner(param);
            System.out.println(result.getId() + "," + result.getUsername());
        }
    }
}
复制代码
  • 声明了一个User类型的对象param,该对象将作为参数被发送至服务生产端。
  • 重点在于通过RibbonClient.create()使得Feign对象获得了Ribbon的特性。之后通过encoder,decoder设置编码器与解码器,并通过target方法将之前定义的接口RemoteService与一个URL地址http://remote-client/gradle-web进行了绑定。

现在来看remote-client.properties中的配置项,主要多是RemoteClient的配置机制

ini 复制代码
remote-client.ribbon.MaxAutoRetries=1
remote-client.ribbon.MaxAutoRetriesNextServer=1
remote-client.ribbon.OkToRetryOnAllOperations=true
remote-client.ribbon.ServerListRefreshInterval=2000
remote-client.ribbon.ConnectTimeout=3000
remote-client.ribbon.ReadTimeout=3000
remote-client.ribbon.listOfServers=127.0.0.1:8080,127.0.0.1:8085
remote-client.ribbon.EnablePrimeConnections=false
复制代码

所有的key都以remote-client开头,表明这些配置项作用于名为remote-client的服务。其实就是与之前绑定RemoteService接口的URL地址的schema相对应。
重点看remote-client.ribbon.listOfServers配置项,该配置项指定了服务生产端的真实地址。

在调用时会被替换为:

@RequestLine指定的地址进行拼接,得到最终请求地址。本例中最终请求地址为:

由于使用的ribbon,所以feign不再需要配置超时时长,重试策略。ribbon提供了更为完善的策略实现。

本例中,服务生产端是一个简单的springMvc,实现如下:

java 复制代码
public class UserController {

    public User list( User user) throws InterruptedException{
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        user.setId(new Long(request.getLocalPort()));
        user.setUsername(user.getUsername().toUpperCase());
        return user;
    }
}

复制代码

故障转移是通过remote-client.properties中的配置项进行配置。

  • 首先利用archaius项目的com.netflix.config.ConfigurationManager读取配置文件remote-client.properties,该文件位于src/main/resources下。

负载均衡的策略又是如何设置呢?

java 复制代码
import com.netflix.client.ClientFactory;
import com.netflix.client.config.IClientConfig;
import com.netflix.config.ConfigurationManager;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import feign.Feign;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import feign.ribbon.LBClient;
import feign.ribbon.LBClientFactory;
import feign.ribbon.RibbonClient;
public class AppRun {
    public static void main(String[] args) throws Exception {
        ConfigurationManager.loadPropertiesFromResources("remote-client.properties");
        User param = new User();
        param.setUsername("test");
        RibbonClient client = RibbonClient.builder().lbClientFactory(new LBClientFactory() {

            public LBClient create(String clientName) {
                IClientConfig config = ClientFactory.getNamedConfig(clientName);
                ILoadBalancer lb = ClientFactory.getNamedLoadBalancer(clientName);
                ZoneAwareLoadBalancer zb = (ZoneAwareLoadBalancer) lb;
                zb.setRule(new RandomRule());
                return LBClient.create(lb, config);
            }
        }).build();
        RemoteService service = Feign.builder().client(client).encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder()).options(new Options(1000, 3500))
                .retryer(new Retryer.Default(5000, 5000, 3)).target(RemoteService.class, "http://remote-client/gradle-web");

        for (int i = 1; i 10; i++) {
            User result = service.getOwner(param);
            System.out.println(result.getId() + "," + result.getUsername());
        }
    }
}
复制代码
java 复制代码
	private IRule zoneAvoidanceRule() {
        return new ZoneAvoidanceRule();
    }

    private IRule randomRule() {
        return new RandomRule();
    }
复制代码

不再使用RibbonClient.create()来创建默认的RibbonClient,而是通过RibbonClient.builder()获得feign.ribbon.Builder,进而设置LBClientFactory的实现来定制LBClient,在创建LBClient的过程中即可指定负载策略的具体实现。

分享资源

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tay3QQq8-1691467722037)(https://pic.imgdb.cn/item/64d0dc6a1ddac507cc857b30.png)

获取以上资源请访问开源项目 点击跳转

相关推荐
裕晟资质规划15 分钟前
三类资质变更报告时限差在哪?军工 15 日、集成印制 10 日
大数据·服务器·网络
96245619 分钟前
Go EVM 链上数据平台实践:从 RPC Demo 到可演进架构
rpc·架构·golang
轻舟技术A27 分钟前
Provider 不属于 Agent 核心:rpi 的分层理由与收益
服务器·网络
Escalating_xu1 小时前
【Linux 网络编程】TCP Socket 编程(上):从 listen、accept 到完整回显通信
linux·网络·tcp/ip
NetX行者1 小时前
Python 工程化入门:从脚本到规范的 Python 项目结构
网络·python
Yang96111 小时前
从相位噪声到实时带宽:HD-063B支撑的频谱实验项目
网络
happyprince1 小时前
01-整体观-DeepSeek-V4.1-Flash全貌解读
网络
是真的小外套1 小时前
2023年软考中级信息安全工程师|选择题考点+5道案例分析真题解析(含答案)
java·服务器·网络
一条泥憨鱼3 小时前
【计算机网络】| 从 MAC 到 NAT 的跨网段通信全链路
服务器·网络·学习·计算机网络·macos
Moyu_Friday3 小时前
网络安全基础-计算机网络应用与协议
网络协议·计算机网络