前面已經(jīng)講了在使用nacos做服務(wù)治理時(shí),使用RestTemplate+ Ribbon實(shí)現(xiàn)微服務(wù)之間的調(diào)用和負(fù)載均衡。
出現(xiàn)的問(wèn)題:
- 代碼可讀性不好(整個(gè)地址是拼接出來(lái)的)
- 編程風(fēng)格不統(tǒng)一(調(diào)用本地服務(wù)和調(diào)用遠(yuǎn)程服務(wù))
現(xiàn)在介紹一下SpringCloud服務(wù)間的調(diào)用的另一種方式:Feign。
Feign是Spring Cloud提供的一個(gè)聲明式的偽Http客戶端, 它使得調(diào)用遠(yuǎn)程服務(wù)就像調(diào)用本地服務(wù)一樣簡(jiǎn)單, 只需要?jiǎng)?chuàng)建一個(gè)接口并添加一個(gè)注解@FeignClient即可。
Nacos很好的兼容了Feign, Feign默認(rèn)集成了 Ribbon, 所以在Nacos下使用Fegin默認(rèn)就實(shí)現(xiàn)了負(fù)載均衡的效果。
1. 加入Feign的依賴
<!--feign組件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2. 在主類上添加Feign的注解
@SpringBootApplication
@MapperScan("com.test.shop.order.dao")
@EnableDiscoveryClient
@EnableFeignClients
public class ShopOrderApplication {
3. 創(chuàng)建一個(gè)service接口,并添加@FeignClient("***")注解,并用RequestMapping(GetMapping或者PostMapping指定請(qǐng)求的URI部分)
/**
* @FeignClient+@GetMapping 就是一個(gè)完整的請(qǐng)求路徑 http://service-product/shop-product/product/{pid}
* 相當(dāng)于使用 RestTemplate 的 請(qǐng)求地址部分
*/
@FeignClient(value = "service-product") // value用于指定調(diào)用nacos下的微服務(wù)的名字
public interface ProductService {
@GetMapping("/shop-product/product/{pid}") // 指定請(qǐng)求的URI部分
Product findByPid(@PathVariable("pid") Integer pid);
}
4. 在業(yè)務(wù)中進(jìn)行接口的調(diào)用
package com.test.shop.order.service.impl;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.test.shop.common.constant.Constant;
import com.test.shop.common.entity.Order;
import com.test.shop.common.entity.Product;
import com.test.shop.common.entity.Result;
import com.test.shop.order.dao.OrderDao;
import com.test.shop.order.service.OrderService;
import com.test.shop.order.service.ProductService;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
@Resource
private OrderDao orderDao;
// @Autowired
// private RestTemplate restTemplate;
// @Autowired
// private DiscoveryClient discoveryClient;
@Resource
private ProductService productService;
@Override
public Result<String> createOrder(Integer pid) {
log.info("商品{}下單", pid);
/*************未使用ribbon時(shí),自定義的負(fù)載均衡********************/
// // 從nacos中獲取服務(wù)地址
// List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances("service-product");
// // 自定義負(fù)載均衡
// int index = new Random().nextInt(serviceInstanceList.size());
// ServiceInstance serviceInstance = serviceInstanceList.get(index);
// String url = serviceInstance.getHost() + ":" + serviceInstance.getPort();
// log.info("\n=====>>從nacos中獲取到的微服務(wù)地址為:" + url);
// Product p = restTemplate.getForObject("http://" + url + "/shop-product/product/" + pid, Product.class);
/*****************************************************/
/************使用Ribbon*******************/
//直接使用微服務(wù)名字, 從nacos中獲取服務(wù)地址
// String url = "service-product";
// //通過(guò)restTemplate調(diào)用商品微服務(wù)
// Product p = restTemplate.getForObject("http://" + url + "/shop-product/product/" + pid, Product.class);
/*************使用Ribbon結(jié)束****************/
/************使用Feign調(diào)用*******************/
//通過(guò)Feign調(diào)用商品微服務(wù)
Product p = productService.findByPid(pid);
/*************使用Feign結(jié)束****************/
log.info("\n查詢商品{}成功,內(nèi)容:{}", pid, JSONUtil.parse(p).toJSONString(1));
Order o = new Order();
o.setNumber(2);
o.setPid(pid);
o.setPname(p.getPname());
o.setPprice(p.getPprice());
o.setUid(123);
o.setUsername("張三");
int n = orderDao.insert(o);
if (n == 1) {
return new Result<String>().success(o);
}
return new Result<String>().error(Constant.ERROR_MSG);
}
}