Feign-独立使用-实战
疯狂创客圈,一个Java 高并发研习社群 【博客园 总入口 】
疯狂创客圈,倾力推出: 《Netty Zookeeper Redis 高并发实战》一书, 面试必备 + 面试必备 + 面试必备
写在前面
大家好,我是作者尼恩。目前和几个小伙伴一起,组织了一个高并发的实战社群【疯狂创客圈】。正在开始高并发、亿级流程的 IM 聊天程序 学习和实战
顺便说明下:
本文的内容只是一个初稿、初稿,本文的知识,在《Netty Zookeeper Redis 高并发实战》一书时,进行大篇幅的完善和更新,并且进行的源码的升级。 博客和书不一样,书的内容更加系统化、全面化,更加层层升入、层次分明、更多次的错误排查,请大家以书的内容为准。
本文的最终内容, 具体请参考疯狂创客圈 倾力编著,机械工业出版社出版的 《Netty Zookeeper Redis 高并发实战》一书 。
使用场景
在疯狂创客圈的 亿级流程的 IM 聊天程序 学习项目中,短连接Web服务器和长连接IM服务器之间,是相互配合的。在分布式集群的环境下,用户首先通过短连接登录Web服务器。Web服务器在完成用户的账号/密码验证,返回uid和token时,还需要通过一定策略,获取目标IM服务器的IP地址和端口号列表,返回给客户端。客户端开始连接IM服务器,连接成功后,发送鉴权请求,鉴权成功则授权的长连接正式建立。
短连接的调用,使用Feign 技术。下面是详解。
看完之后,Feign 独立使用,完全可以替换掉目前的Http 客户端调用方法。
1.1. Feign短连接Restful调用
一般来说,短连接的服务接口,都是基于应用层Http协议的Http api 或者RESTful api实现,通过JSON文本格式返回数据。如何在Java服务端调用其他节点的Http api 或者RESTful api呢?
至少有以下几种方式:
(1)JDK原生的URLConnection
(2)Apache的Http Client/HttpComponents
(3)Netty的异步HTTP Client
(4)Spring的RestTemplate
目前用的最多的,基本上是第二种,这也是在单体服务时代,最为成熟和稳定的方式,也是效率较高的短连接方式。
插入一个解释: 什么是RESTful api。REST的全称是 Representational State Transfer,它是一种API接口的风格、也而不是标准,只是提供了一组调用的原则和约束条件。也就是说,在短连接服务的领域,它算是一种特殊格式的HTTP api。
回到前面的话题,如果同一个Http api/RESTful api 接口,倘若不止一个短连接服务器提供,而是有多个节点提供服务,那么,简单的使用Http Client调用,就无能为力了。
Http Client/HttpComponents调用不能根据接口的负载、或者其他的条件,去判断哪一个接口应该调用,哪一个接口不应该调用。解决这个问题的方式是啥呢?
可以使用Feign来调用多个服务器的同一个接口。Feign不仅仅可以进行同接口多服务器的负载均衡,一旦使用了Feign作为http api的客户端,调用远程的http接口就会变得像调用本地方法一样简单。
Feign是何方神圣?它是Netflix开发的一个声明式、模板化的HTTP客户端, Feign的目标是帮助Java工程师更快捷、优雅地调用HTTP API//RESTful api。另外,Feign被无缝集成到了SpringCloud微服务框架,使用Feign后,可以非常方便项目SpringCloud微服务技术。
如果项目使用了SpringCloud技术,那就就可以更加方便的声明式使用Feign。如果没有使用SpringCloud,使用Feign也非常之简单。Netflix Feign目前改名为OpenFeign,最新版本是2018.5发布的9.7.0。OpenFeign在Java应用中,负责处理与远程Web服务的请求响应,最大限度降低编码复杂性。可以说是Java应用中调用Web服务的客户端的利器。
下面就看看在单独使用Feign的场景下,是怎么调用远程的http服务。
引入Feign依赖的jar包到pom.xml:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>9.7.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
<version>9.7.0</version>
</dependency>
接下来,就可以开始使用Feign来调用远程的Http API了。
1.1.1. 短连接API的接口准备
前面讲到,高并发的IM系统中,用户的登录与认证、好友的更新与获取等等一些低频的请求,这些都使用短连接来实现。
作为演示,这里仅仅列举两个短连接的API接口:
(1) http://localhost:8080/user/{userid}
这个接口的功能,是用户获取用户信息,是一个典型的RESTful类型的接口。{userid}是一个占位符,调用的时候,需要替换成用户id。 比如说如果用户id为1,调用的链接为:http://localhost:8080/user/1 。
(2) http://localhost:8080/login/{username}/{password}
这个接口的功能,用户登录的认证。占位符{username}是表示用户名称,占位符{password}表示用户密码。 比如说如果用户名称为zhangsan,密码为123调用的链接为:http://localhost:8080/login/zhangsan/123 。
上面的接口很简单,仅仅是为了演示,不能用于生产场景。这些API可以使用Spring MVC 等常见的WEB技术来实现。
1.1.2. 申明远程接口的本地代理
如何通过Feign技术,来调用上面的这些Http API呢?
第一步,需要创建一个本地的API的代理接口。具体如下:
package com.crazymakercircle.imServer.feignClient;
import feign.Param;
import feign.RequestLine;
public interface UserAction
{
@RequestLine("GET /login/{username}/{password}")
public String loginAction(
@Param("username") String username,
@Param("password") String password);
@RequestLine("GET /user/{userid}")
public String getById(
@Param("userid") Integer userid);
}
在代理接口中,为每一个远程Http API定义一个方法。
如何将方法对应到远程接口呢?
在方法的前面,加上一个@RequestLine 注解,注明远程Http API的请求地址。这个地址不需要从域名和端口开始,只需要从URI的根目录“/”开始即可。
比如,如果远程Http API的URL为:http://localhost:8080/user/{userid} ,@RequestLine 声明的值,只需要配成 /user/{userid} 即可。
如何给接口传递参数值呢?
在方法的参数前面, 加上一个 @Param 注解即可。 @Param内容为HTTP链接中参数占位符的名称。绑定好之后,实际这个Java接口中的参数值,会替换到@Param注解中的占位符。
比如:由于getById的唯一参数 userid的 @Param注解中,用到的占位符是userid。那么,通过调用 userAction.getById(100) ,那么userid的值100,就会用来替换掉请求链接http://localhost:8080/user/{userid} 中占位符userid,最终得到的请求链接为:http://localhost:8080/user/100。
1.1.3. 远程API的本地调用
在完成远程API的本地代理接口的定以后,接下来的工作就是调用本地代理,这个工作也是非常的简单。
还是以疯狂创客圈的实战项目,获取用户信息、和用户登录两个API的代理接口的调用为例。
实战的代码如下:
import com.crazymakercircle.imServer.feignClient.UserAction;
import feign.Feign;
import feign.Request;
import feign.Retryer;
import feign.codec.StringDecoder;
import org.junit.Test;
/**
* Created by 尼恩 at 疯狂创客圈
*/
//@ContextConfiguration(
// locations = { "classpath:application.properties" })
//@RunWith(SpringJUnit4ClassRunner.class)
//@Configuration
//自动加载配置信息
//@EnableAutoConfiguration
public class LoginActionTest
{
/* // 服务器ip地址
@Value("${server.web.user.url}")
private String userBase;*/
@Test
public void testLogin()
{
UserAction action = Feign.builder()
// .decoder(new GsonDecoder())
.decoder(new StringDecoder())
.options(new Request.Options(1000, 3500))
.retryer(new Retryer.Default(5000, 5000, 3))
.target(
UserAction.class,
// userBase
"http://localhost:8080/"
);
String s = action.loginAction(
"zhangsan",
"zhangsan"
);
System.out.println("s = " + s);
}
@Test
public void testGetById()
{
UserAction action = Feign.builder()
// .decoder(new GsonDecoder())
.decoder(new StringDecoder())
.target(
UserAction.class,
"http://localhost:8080/"
);
String s = action.getById(2);
System.out.println("s = " + s);
}
}
主要的也是最为核心的就一步,构建一个远程代理接口的本地实例。使用Feign.builder() 构造器模式方法,带上一票配置方法的链式调用。主要的链式调用的配置方法介绍如下:
(1)target 配置方法
为构造器配置本地的代理接口,和远程的根目录。代理接口类的每一个接口方法前@RequestLine 声明的值,最终都会加上这个根目录。这个是最为重要的一个配置方法。代理接口类很重要,最终Feign.builder() 构造器返回的本地代理实例类型,就这个接口。
(2)options配置方法
options方法指定连接超时时长及响应超时时长。
(3)retryer配置方法
retryer方法主要是指定重试策略。
(4)decoder配置方法
decoder方法指定对象解码方式,这里用的是基于String字符串的解码方式。如果需要使用Jackson的解码方式,需要在pom.xml中添加Jackson的依赖。
主要的配置方法,就介绍这些,具体使用和其他的方法,请参见官网。
通过Feign.builder() 构造完成代理实例后,调用远程API,就变成了调用Java函数一样的简单。
建议,如果是独立调用Http服务,尽量使用Feign。
一是简单,
二是如果采用httpclient或其他相对较重的框架,对初学者来说编码量与学习曲线都会是一个挑战。
三是,既可以独立使用Feign,又可以方便后续的和Spring Could微服务框架继承。
总之,何乐而不为呢?
写在最后
下一篇: zookeeper + netty 实现高并发IM 聊天
疯狂创客圈 亿级流量 高并发IM 学习实战
- Java (Netty) 聊天程序【 亿级流量】实战 开源项目实战
- Netty 源码、原理、JAVA NIO 原理
- Java 面试题 一网打尽
- 疯狂创客圈 【 博客园 总入口 】
Feign-独立使用-实战的更多相关文章
- 注解式HTTP请求Feign (F版)
Spring Cloud 为开发者提供了在分布式系统中的一些常用的组件(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁定,决策竞选,分布式会话集群状态).使用Sprin ...
- 《深入理解Java虚拟机》-----第10章 程序编译与代码优化-早期(编译期)优化
概述 Java语言的“编译期”其实是一段“不确定”的操作过程,因为它可能是指一个前端编译器(其实叫“编译器的前端”更准确一些)把*.java文件转变成*.class文件的过程;也可能是指虚拟机的后端运 ...
- springcloud微服务实战:Eureka+Zuul+Feign/Ribbon+Hystrix Turbine+SpringConfig+sleuth+zipkin
相信现在已经有很多小伙伴已经或者准备使用springcloud微服务了,接下来为大家搭建一个微服务框架,后期可以自己进行扩展.会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新 ...
- springcloud 实战 feign使用中遇到的相关问题
springcloud 实战 feign使用中遇到的相关问题 1.使用feign客户端调用其他微服务时,session没有传递成功,sessionId不一样. /** * @author xbchen ...
- SpringCloud(五)之Spring Cloud 中 Feign结合Hystrix断路器开发实战
1.先讲hystrx(断路器) 在springcloub 中的使用 1.1 加入依赖 注意:网上新旧版本问题,所以要以官网为主,不然部分注解会丢失最新版本 2.0 <dependency> ...
- 小D课堂 - 新版本微服务springcloud+Docker教程_5-04 feign结合hystrix断路器开发实战下
笔记 4.Feign结合Hystrix断路器开发实战<下> 简介:讲解SpringCloud整合断路器的使用,用户服务异常情况 1.feign结合Hystrix ...
- 小D课堂 - 新版本微服务springcloud+Docker教程_5-03 feign结合hystrix断路器开发实战上
笔记 3.Feign结合Hystrix断路器开发实战<上> 简介:讲解SpringCloud整合断路器的使用,用户服务异常情况 1.加入依赖 注意:网上新旧版本问 ...
- 小D课堂 - 新版本微服务springcloud+Docker教程_4-05 微服务调用方式之feign 实战 订单调用商品服务
笔记 5.微服务调用方式之feign 实战 订单调用商品服务 简介:改造电商项目 订单服务 调用商品服务获取商品信息 Feign: 伪RPC客户端(本质还是用http) ...
- ②SpringCloud 实战:引入Feign组件,完善服务间调用
这是SpringCloud实战系列中第二篇文章,了解前面第一篇文章更有助于更好理解本文内容: ①SpringCloud 实战:引入Eureka组件,完善服务治理 简介 Feign 是一个声明式的 RE ...
随机推荐
- IntelliJ IDEA 快捷键整理-from imooc
IntelliJ IDEA 快捷键整理-from imooc 学习了:https://www.imooc.com/learn/9241, main2, 100.for 3, new Date().so ...
- springboot @Configuration
有了@Configuration,原来的springBean的配置文件可以去掉了, 原来在application.xml中配置的bean可以配置在@Configuration注解的来类中,使用@Bea ...
- 字符串截取 及 substr 和 substring 的区别
1..字符串截取 str.substr(0, 1) // 获取字符串第一个字符 str.substr(-1) // 获取字符串最后一个字符 str.charAt(str.length - 1) // ...
- IOS压缩解压缩
#import <zlib.h> 压缩 -(NSData *)compressData:(NSData *)uncompressedData { if ([uncompressedData ...
- sort-colors——排序3种数字
题目描述 Given an array with n objects colored red, white or blue, sort them so that objects of the same ...
- Java Swing界面编程(21)---事件处理:窗口事件
WindowLIstener是专门处理窗口的事件监听窗口.一个窗口的全部变化.如窗口的打开.关闭等都能够使用这个接口进行监听. 实现WIndowListener: package com.beyole ...
- jquery文件上传控件 Uploadify(转)
原文:http://www.cnblogs.com/mofish/archive/2012/11/30/2796698.html 基于jquery的文件上传控件,支持ajax无刷新上传,多个文件同时上 ...
- 文件json
import jsondef op_data(filename,dic=None): if dic:#写入进去 with open(filename,'w',encoding='utf-8') as ...
- 解决java.math.BigDecimal divide方法运算结果为无限小数问题
http://samueli.iteye.com/blog/224755 BigDecimal除法运算报错,错误如下:Non-terminating decimal expansion; no exa ...
- 500 lines or less
今天碰到一本书 <500 lines or less>突然就想在博客上记录一下自己的阅读经历了. 现在记录一下这本书的地址 http://aosabook.org/en/index.htm ...