跟着yang哥的视频学,来简单做一下入门笔记,新手使用Markdown,如果有写的不对的地方请多多指教_
openFeign是一个微服务调用框架,主要作用在消费者端,即调用服务。
是个声明式的web服务客户端,让编写web服务客户端变得更加容易,只需创建一个接口并在接口上添加注解即可–>@FeignClient,即只需要提供一个与provider服务一模一样的接口,并加上@GetMapping/@PostMapping,Feign就会帮我们调用这个ProVider的方法
SpringCloud对Feign进行了封装,指出Spring mvc标准注解以及HttpMessageConverters。
入门案例所需环境IDEA+eureka(做服务注册与发现,现已停更可以改用zookeeper/consul)+OpenFeign+SpringCloud H+mybatis
一、provider服务
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zipkinartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.psfgroupId>
<artifactId>cloud-api-commonsartifactId>
<version>${project.version}version>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
dependencies>
配置yml
server:
port: 8001
#配置名字
spring:
application:
name: cloud-payment-service
datasource:
# 当前数据源操作类型
type: com.alibaba.druid.pool.DruidDataSource
# mysql驱动类
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123
url: jdbc:mysql://localhost:3306/db2019?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
mybatis:
//在resources下创建一个Mapper目录管理mybatis的xml
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: com.psf.springcloud.entities
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
# 单击版
# defaultZone: http://localhost:7001/eureka
# 集群版
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
#配置访问7001端口的时候显示的信息
instance:
instance-id: payment8001
#显示ip地址
prefer-ip-address: true
lease-renewal-interval-in-seconds: 1
lease-expiration-duration-in-seconds: 2
编写主启动类
@SpringBootApplication
//使注解生效
@EnableEurekaClient
@EnableDiscoveryClient
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}
编写dao
@Mapper
public interface PaymentDao {
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id);
}
编写service(这里还要编写一个实现类,就不写出)
public interface PaymentService {
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id);
}
编写controller
@RestController
@Slf4j
public class PaymentController {
@Autowired
private PaymentService paymentService;
@Value("${server.port}")
private String serverPort;
/**CommonResult是个实体类,如果没看过yang哥的视频的同学可以参考下面属性去创建,主要属性有
private Integer code;
private String message;
private T data;
*/
@GetMapping("/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id){
Payment payment = paymentService.getPaymentById(id);
log.info("*****查询结果"+payment);
if (payment !=null){
return new CommonResult(200,"查询成功,端口号:"+serverPort,payment);
}else {
return new CommonResult(444,"没有对应记录,查询id"+id,null);
}
}
}
controller写完
二、customer服务
由于customer是调用provider端的,所以可以不用dao层,service层也有一点变化
pom其实就是多了个OpenFeign的starter
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
配置yml
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
#这里配置的是集群
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka
主启动类
@SpringBootApplication
@EnableFeignClients
public class OrderFeignMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderFeignMain80.class);
}
}
编写service
//要添加component注解
@Component
//这里要添加一个新的注解
@FeignClient(value = "cloud-payment-service")
public interface PaymentFeignService {
@GetMapping("/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
}
编写controlelr
@RestController
@Slf4j
public class OrderFeignController {
@Resource
private PaymentFeignService paymentFeignService;
@GetMapping("/customer/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
//这里也是只需要调用service的方法就行
return paymentFeignService.getPaymentById(id);
}
}
到这里customer服务也写完了
三、discovery and regist(注册与发现)服务
pom
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
yml
server:
port: 7001
##搭建集群的话:相互守望,相互注册
eureka:
#初始化主机名字
instance:
hostname: eureka7001.com #eureka服务端的实例名字
client:
fetch-registry: false
#不注册自己
register-with-eureka: false
#注册的ur,开启集群模式,需要指向对方
service-url:
defaultZone: http://eureka7002.com:7002/eureka/
# defaultZone: http://eureka7001.com:7001/eureka/
#关闭自我保护机制
server:
enable-self-preservation: false
eviction-interval-timer-in-ms: 2000
配置主启动类
@SpringBootApplication
//这里要引入一个注解,才能使eureka生效
@EnableEurekaServer
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class);
}
}
到这里就完全结束啦
先把注册服务启动,再把消费者与provider服务启动
访问localhost:/customer/payment/get/1 就能看到信息
意思就是在provider端,需要处理3秒钟,但是customer端只能等1秒钟,这样就会报错
status 404 reading PaymentFeignService#paymentFeignTimeout()
案例演示:
provider的controller添加如下方法
//模拟超时控制
@GetMapping("/payment/feign/timeout")
public String paymentFeignTimeout(){
try {
//模拟处理三秒钟
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return serverPort;
}
customer的service添加上面方法的一个接口
customer的controller添加接口的方法
@GetMapping("/customer/payment/feign/timeout")
public String paymentFeignTimeout(){
//openFeign底层是ribbon,客户端默认等待1秒钟,但是支付端要处理三秒钟
return paymentFeignService.paymentFeignTimeout();
}
那我们需要解决这种问题,feign的超时控制是由ribbon控制的,所以我们可以在yml中配置一下超时控制。解决某些请求确实要超过默认时间,把默认等待时间和默认处理时间调整一致
在customer的yml添加
#与server同级
ribbon:
ReadTimeout: 5000
ConnectTimeout: 5000
对feign接口的调用情况进行监控和输出
配置yml
logging:
level:
com.atguigu.springcloud.service.PaymentFeignService: debug
配置config类
@Configuration
public class FeignConfig {
/**
*feign的日志打印有5中
FULL:除了HEAD,全部打印
BASE:仅记录请求方法,URL,响应装代码
HEAD:除BASE,打印
NONE:不打印
*/
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}