写在最前

如果这个项目让你有所收成,记住 Star 关注哦,这对我是非常不错的鼓舞与支撑。

源码地址(后端):gitee.com/csps/mingyu…

源码地址(前端):gitee.com/csps/mingyu…

文档地址:gitee.com/csps/mingyu…

长途调用

长途调用为分布式系统供应了一种便利、高效和可靠的通讯方法,使得不同部分的组件可以协同工作,并完结代码的模块化、解耦和重用。它是构建可扩展、活络和可保护的分布式系统的重要东西和技能。

为什么要运用长途调用?

  1. 分布式系统:在分布式系统中,不同的组件或服务可能分布在不同的机器或进程中。运用长途调用可以使这些组件可以通过网络互相通讯,进行数据交换和协作,完结系统的功用和事务逻辑。
  2. 模块化和解耦:长途调用使得系统的各个模块可以独立开发和安置,通过定义清晰的接口和协议,模块之间可以解耦并独立演化。这样,系统的不同部分可以独立进行批改、升级或替换,而不会对其他部分产生影响。
  3. 代码重用性:通过长途调用,可以将某些功用或服务封装为可复用的模块,供多个应用程序或系统共享和调用。这样可以避免重复开发相同的功用,前进代码的重用性和开发功率。
  4. 扩展性和弹性:长途调用可以完结系统的弹性扩展和水平扩展。当系统负载增加时,可以通过安置更多的服务实例,并运用负载均衡器进行流量分发,以应对更高的并发央求。
  5. 服务办理和监控:运用长途调用结构可以集成服务办理和监控功用,例如服务注册与发现、负载均衡、熔断器、日志记载等。这些功用可以供应更好的可用性、功用和可保护性,一同也可以帮助开发人员进行系统的监控和毛病排查。

技能选型

OpenFeign 与 Dobbo 3 都是优异的微服务架构下的长途调用结构,各有千秋。

维度 OpenFeign Dobbo 3
类型 依据 Java 的声明式 Web 服务客户端 RPC(长途进程调用)结构
协议支撑 支撑 RESTful API,一般依据 HTTP 协议进行通讯 支撑多种长途通讯协议,不只包含 Dubbo 自有的二进制协议,还支撑 HTTP、gRPC等,这使得 Dubbo 3 在不同场景下更加活络
编程模型 声明式的 API 定义和调用方法,通过 Java 接口和注解来描绘服务接口和方法,运用起来更加简练和直观 声明式的 API,但更多情况下运用 XML 配备或注解配备,一同支撑传统的编程式调用方法。
服务办理 集成了 Netflix 的负载均衡器 Ribbon,但相较 Dubbo 3在服务办理方面较为简略。 供应了更多功用,如负载均衡、服务注册与发现、熔断器等,适用于大规模分布式系统的构建。
生态和社区 2019年 Netflix 公司宣告 Feign 组件正式进入停更保护状况,所以 Spring 官便利推出了一个名为 OpenFeign 的组件作为 Feign 的代替方案。 2011年开源,2012年发布2.5.3版本后中止更新,2017年阿里重启 dubbo 项目,现在由 Apache 软件基金会进行保护和展开,具有安稳的社区支撑。

OpenFeign + OkHttp3

本架构将选用 OpenFeign + OkHttp3 作为长途调用东西。

  • 声明式 API 定义:OpenFeign 供应了声明式的 API 定义方法,运用接口和注解来描绘服务接口和方法。这使得代码更加简练、可读性更强,而且开发人员可以更专心于事务逻辑而不是底层的 HTTP 央求细节。
  • 健壮的 HTTP 功用:OkHttp3 是一个功用健壮的 HTTP 客户端库,供应了丰厚的功用和特性,如联接池办理、央求和照应阻挠器、央求重试、缓存等。通过将 OpenFeign 与 OkHttp3 结合运用,可以运用 OkHttp3 的这些功用来处理HTTP 央求和照应,前进功用和可靠性。
  • 高功用和可扩展性:OkHttp3 被广泛认为是一个高功用的 HTTP 客户端,具有优异的功用和功率。它支撑并发央求、联接复用和异步操作等,可以满足大规模和高并发的需求。一同,OkHttp3 也具备很好的可扩展性,可以通过自定义阻挠器和插件来扩展和定制其功用。
  • 网络层配备:OkHttp3 供应了丰厚的网络层配备选项,如联接超时、读写超时、署理设置等。通过运用 OkHttp3 作为OpenFeign 的底层 HTTP 客户端,可以活络地配备和办理网络层的行为,以满足特定的需求。
  • 生态和社区支撑:OpenFeign 和 OkHttp3 都是广受欢迎的开源项目,具有活跃的社区和安稳的保护。这意味着开发人员可以从社区中取得支撑、文档和更新的功用。

综上所述,将 OpenFeign 与 OkHttp3 结合运用可以享受到 OpenFeign 声明式 API 定义的便利性,并运用 OkHttp3 供应的健壮的 HTTP 功用和功用优势。这样的组合可以简化代码、前进功用,并为开发人员供应更好的可扩展性和配备活络性。

增加 mingyue-common-feign

引入依托

<dependencies>
 <dependency>
  <groupId>com.csp.mingyue</groupId>
  <artifactId>mingyue-common-core</artifactId>
 </dependency><!-- SpringCloud Openfeign -->
 <dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
 </dependency>
 <!-- okhttp 扩展 -->
 <dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-okhttp</artifactId>
 </dependency>
 <!-- LB 扩展 -->
 <dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-loadbalancer</artifactId>
 </dependency>
</dependencies>

自定义注解

覆盖 @EnableFeignClients 注解,默许 basePackages,客户端直接运用 @EnableMingYueFeignClients 注解即可,无须再指定 basePackages。

import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
​
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
​
/**
 * 翻开 Feign Client
 *
 * @author Strive
 * @date 2023/7/4
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EnableFeignClients
public @interface EnableMingYueFeignClients {
​
  /**
   * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
   * declarations e.g.: {@code @ComponentScan("org.my.pkg")} instead of
   * {@code @ComponentScan(basePackages="org.my.pkg")}.
   * @return the array of 'basePackages'.
   */
  String[] value() default {};
​
  /**
   * Base packages to scan for annotated components.
   * <p>
   * {@link #value()} is an alias for (and mutually exclusive with) this attribute.
   * <p>
   * Use {@link #basePackageClasses()} for a type-safe alternative to String-based
   * package names.
   * @return the array of 'basePackages'.
   */
  String[] basePackages() default { "com.csp.mingyue" };
​
  /**
   * Type-safe alternative to {@link #basePackages()} for specifying the packages to
   * scan for annotated components. The package of each class specified will be scanned.
   * <p>
   * Consider creating a special no-op marker class or interface in each package that
   * serves no purpose other than being referenced by this attribute.
   * @return the array of 'basePackageClasses'.
   */
  Class<?>[] basePackageClasses() default {};
​
  /**
   * A custom <code>@Configuration</code> for all feign clients. Can contain override
   * <code>@Bean</code> definition for the pieces that make up the client, for instance
   * {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
   *
   * @see FeignClientsConfiguration for the defaults
   */
  Class<?>[] defaultConfiguration() default {};
​
  /**
   * List of classes annotated with @FeignClient. If not empty, disables classpath
   * scanning.
   * @return
   */
  Class<?>[] clients() default {};
​
}

Nacos 翻开配备

application-common.yml

# feign 配备
feign:
 # 启用 okhttp 作为网络央求结构   
  okhttp:
   enabled: true
 # 关闭 httpclient 作为网络央求结构
  httpclient:
   enabled: false
  client:
   config:
   # 将调用的微服务称谓改成 default 就配备成大局的了
    default:
    # 相当于 Request.Optionsn 联接超时时刻
     connectTimeout: 10000
    # 相当于 Request.Options 读取超时时刻
     readTimeout: 10000
  compression:
   request:
   # 配备央求 GZIP 紧缩
    enabled: true
   response:
   # 配备照应 GZIP 紧缩
    enabled: true

批改 mingyue-system-api

引入依托

<dependency>
 <groupId>com.csp.mingyue</groupId>
 <artifactId>mingyue-common-feign</artifactId>
</dependency>

长途调用用户服务

import com.csp.mingyue.common.core.constant.ServiceNameConstants;
import com.csp.mingyue.common.core.vo.R;
import com.csp.mingyue.system.api.entity.SysUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
​
/**
 * 长途调用用户服务
 *
 * @author Strive
 * @date 2023/7/3 09:48
 */
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE)
public interface RemoteUserService {
​
  /**
   * 通过用户名查询用户、角色信息
   * @param username 用户名
   * @return R
   */
  @GetMapping(value = "/sysUser/getSysUserInfoByUsername")
  R<SysUser> getSysUserInfoByUsername(@RequestParam(value = "username") String username);
​
}

mingyue-auth 长途调用 mingyue-system

引入依托

<!-- 系统服务 API -->
<dependency>
 <groupId>com.csp.mingyue</groupId>
 <artifactId>mingyue-system-api</artifactId>
</dependency>

批改登录

public SaTokenInfo login(PasswordLoginDto dto) {
 R<SysUser> userInfoResp = remoteUserService.getSysUserInfoByUsername(dto.getUsername());
​
 if (Objects.isNull(userInfoResp) || Objects.isNull(userInfoResp.getData())) {
  return null;
  }
​
 SysUser userInfo = userInfoResp.getData();
​
 if (dto.getUsername().equals(userInfo.getUsername()) && dto.getPassword().equals(userInfo.getPassword())) {
  // 第1步,先登录上
  StpUtil.login(10001);
  // 第2步,获取 Token 相关参数
  SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
​
  return tokenInfo;
  }
​
 return null;
}

发动检验

curl -X 'POST' \
 'http://mingyue-gateway:9100/auth/login' \
 -H 'accept: */*' \
 -H 'Content-Type: application/json' \
 -d '{
 "username": "mingyue",
 "password": "123456"
}'

回来示例

{
 "code": 200,
 "msg": "登录成功",
 "data": "2GcAFW7UZ0XJjDe5H76CBAtj7zc7bm8S"
}

翻开或关闭 OkHttp3

默许的HttpURLConnection是 JDK 自带的,并不支撑联接池,如果要完结联接池的机制,还需要自己来办理联接对象。OkHttp3 自带联接池办理,提高吞吐量

中心依托

<!-- okhttp 扩展 -->
<dependency>
 <groupId>io.github.openfeign</groupId>
 <artifactId>feign-okhttp</artifactId>
</dependency>

运用方法

Nacos 配备 application-common.yml

# feign 配备
feign:
 # 启用 okhttp 作为网络央求结构   
  okhttp:
    # true 翻开 / false 关闭
   enabled: true

验证是否翻开

查看 Client 完结,实践发送央求是由 Feign 中的Client接口完结类去处理的,默许运用的是 Defalut 类,该类运用的是HttpURLConnection

015-从零建立微服务-长途调用(一)

默许完结,关闭 okhttp 后,对此方法断点查看是否进入

@Override
public Response execute(Request request, Options options) throws IOException {
 HttpURLConnection connection = convertAndSend(request, options);
 return convertResponse(connection, request);
}

翻开 OkHttpClient 类,查看 OkHttp3 源码,找到 execute 方法。翻开 okhttp 后,对此方法断点查看是否进入

@Override
public feign.Response execute(feign.Request input, feign.Request.Options options)
 throws IOException {
 okhttp3.OkHttpClient requestScoped = getClient(options);
 Request request = toOkHttpRequest(input);
 Response response = requestScoped.newCall(request).execute();
 return toFeignResponse(response, input).toBuilder().request(input).build();
}

小结

至此,mingyue-auth 现已可以通过长途调用获取 mingyue-system 服务。下一节,网关增加接口阻挠,引入白名单列表。