微服务架构上,都是采用Restful风格进行通信的。
进程间通信,Inter-Process Communication指至少两个进程或线程间传送数据或信号的一些技术或方法。每个进程都有自己的一部分独立的系统资源,彼此是隔离的。为了能使不同的进程互相访问资源并进行协调工作,就有了进程间通信。这些进程可以运行在同一计算机上或网络连接的不同计算机上。
本地过程调用,使得同时运行的任务能互相会话。这些任务共享内存空间使任务同步和互相发送信息。
远程过程调用,本地机器和远程机器的进程进行通信。
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.2.6.RELEASEversion>
<relativePath/>
parent>
<properties>
<java.version>1.8java.version>
<spring-cloud.version>Hoxton.SR4spring-cloud.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.2.1.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
Service层:
public interface MemberService {
@GetMapping("/getUser")
String getUser(Integer userId);
}
@RestController
public class MemberServiceImpl implements MemberService {
@Value("${server.port}")
private String port;
@Override
public String getUser(Integer userId) {
return "生产者调用牛逼" + port;
}
}
配置文件:
spring:
application:
name: member-producer
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
server:
port: 8081
OpenFeign接口代码:
@FeignClient("member-producer") //希望调用的微服务名称
public interface MemberOpenFeign {
@GetMapping("/getUser") //希望调用的微服务的路径
String getUser(@RequestParam("userId") Integer id);
}
Service代码:
@RestController
public class OrderService {
@Autowired
private MemberOpenFeign memberOpenFeign;
@GetMapping("orderToMember")
public String orderToMember() {
String result = memberOpenFeign.getUser(222);
return result;
}
}
配置文件:
spring:
application:
name: order-consumer
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
server:
port: 9090
@SpringBootApplication
@EnableFeignClients
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
}
生产者的Service方法那里故意睡他个2秒。
@RestController
public class MemberServiceImpl implements MemberService {
@Value("${server.port}")
private String port;
@Override
public String getUser(Integer userId) {
String result = "生产者调用牛逼" + port;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return result;
}
}
访问直接报错。
去控制台查看错误。
访问报了错,因为OpenFeign默认等待时间是一秒钟,会员服务线程直接睡了两秒,那RPC调用肯定超时了。
解决方法,可以在消费者配置文件中增加下面的配置提高容错性(OpenFeign自带Ribbon负载均衡)。感觉写的有点反人类(ribbon具体配置后面会讲,这里如果最前面没有带上服务名称的话,默认是全局的)。。。
ribbon:
ConnectTimeout: 4000 #指的是和服务器建立连接后读取资源的最大连接时间
ReadTimeout: 5000 #指的是和服务器建立连接的最大等待时间
再次访问就成功了。
需要整合Sentinel才能实现该功能,配置文件添加下面配置:
feign:
sentinel:
enabled: true
so esay。实现之前OpenFeign的接口,返回数据。
public class MemberFallbackService implements MemberOpenFeign {
@Override
public String getUser(Integer id) {
return "会员服务发生异常";
}
}
并且在之前的接口上增加属性fallback。
@FeignClient(value = "member-producer", fallback= MemberFallbackService.class)
停止生产者服务,测试RPC远程调用自定义异常成功。
…实测,以下配置对于Cloud版本为Hoxton.SR4也就是最新版根本没调用好吧。
feign:
client:
config:
member-producer:
loggerLevel: full
要想打印RPC远程调用的日志,还是得靠SpringBoot自带的AOP日志工具logger。加上下面的配置。
logging:
level:
com.cj.cn.service.order.openfeign.MemberOpenFeign: debug
当然你还可以通过java代码控制显示的日志级别。
public class FeignClientConfiguration {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
加入到接口属性里。@FeignClient(value = "member-producer", configuration = FeignClientConfiguration.class)
测试。
下阶段打算整理Ribbon系列。