1.安装配置nacos以及实现服务支持
nacos简介
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速
实现动态服务发现、服务配置、服务元数据及流量管理。
从上面的介绍就可以看出,nacos的作用就是一个注册中心,用来管理注册上来的各个微服务。
nacos2.0.1版本: https://pan.baidu.com/s/1hXH5Eq3ZR1T1qZ0YOqD5Cg
提取码:8kb0
1.1:切换单体:
startup.cmd -m standalone
或者直接修改startup.cmd文件:
set MODE="standalone"
1.2:访问nacos:
打开浏览器输入http://localhost:8848/nacos,即可访问服务, 默认密码是nacos/nacos
1.3:模块依赖:
<!--nacos客户端-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
1.4:在模块启动类上添加注解:@EnableDiscoveryClient
package com.xujie.shop_product;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@EnableDiscoveryClient
@SpringBootApplication
public class ShopProductApplication {public static void main(String[] args) {SpringApplication.run(ShopProductApplication.class, args);}}
启动后查看nacos:
注:nacos中的服务名不能出现"_",这是nacos的格则(我出过这个错0.0)
实现服务调用的负载均衡
Ribbon实现负载均衡
package com.xujie.shop_order;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplication
public class ShopOrderApplication {public static void main(String[] args) {SpringApplication.run(ShopOrderApplication.class, args);}@Bean@LoadBalanced //使用ribbon方式实现负载均衡public RestTemplate restTemplate(){return new RestTemplate();}
}
log.info("客户下单,这时候要调用商品微服务查询商品信息");//定义微服务的服务名称,对应的是商品服务的双节点(8080和8081)String serverName="shop-product";log.info("远程调用地址为:{}","http://"+serverName+"/product/getOne/"+pid);Product product =restTemplate.getForObject("http://"+serverName+"/product/getOne/"+pid,Product.class);
DiscoveryClient实现负载均衡
package com.xujie.shop_order.controller;import com.alibaba.fastjson.JSON;
import com.xujie.common.model.Order;
import com.xujie.common.model.Product;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import java.util.List;
import java.util.Random;/*** @author 许缘* @company xxx公司* @create 2022-12-06 17:25*/
@Slf4j
@RestController
@RequestMapping("/order")
public class ordercontroller {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;@RequestMapping("/test/{pid}")public Order createOrder(@PathVariable("pid") Integer pid){log.info("客户下单,这时候要调用商品微服务查询商品信息");//定义微服务的服务名称,对应的是商品服务的双节点(8080和8081)String serverName="shop-product";//获取当前微服务所对应的实例数List<ServiceInstance> instances = discoveryClient.getInstances(serverName);//使用随机挑选的方式获取服务实例int index = new Random().nextInt(instances.size());//根据挑选的服务下标获取具体的服务实例(ip+端口)ServiceInstance instance = instances.get(index);//拼接生产者的服务的地址String url="http://"+instance.getHost()+":"+instance.getPort();log.info("远程调用地址为:{}",url+"/product/getOne/"+pid);Product product =restTemplate.getForObject(url+"/product/getOne/"+pid,Product.class);log.info("查询结果:"+ JSON.toJSONString(product));//创建订单Order order = new Order();order.setOid(System.currentTimeMillis());order.setUid(12);order.setUsername("张三");order.setPid(product.getPid());order.setPname(product.getPname());order.setPprice(product.getPprice());order.setNumber(product.getStock());return order;}
}
基于Feign实现服务调用
什么是Feign
Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务
一样简单, 只需要创建一个接口并添加一个注解即可。
Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负载均衡的效果。
Feign的使用
pom.xml依赖:
<!--fegin组件-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
添加注解:@EnableFeignClients启用远程调用
package com.xujie.shop_order;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableFeignClients //启用远程调用
@EnableDiscoveryClient
@SpringBootApplication
public class ShopOrderApplication {public static void main(String[] args) {SpringApplication.run(ShopOrderApplication.class, args);}@Bean//@LoadBalanced //使用ribbon方式实现负载均衡public RestTemplate restTemplate(){return new RestTemplate();}
}
接口:
package com.xujie.shop_order.service;import com.xujie.common.model.Product;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;/*** @author 许缘* @company xxx公司* @create 2022-12-07 14:39* @FeignClient:指定微服务的服务名称* shop-product === http://193.168.1.144:8081/*/
@FeignClient("shop-product") //调用是哪个服务
public interface IProductService {/*** http://193.168.1.144:8081/product/getOne/{pid}* @param pid* @return*/@RequestMapping("/product/getOne/{pid}")Product getOne(@PathVariable("pid") Integer pid);}
package com.xujie.shop_order.controller;import com.alibaba.fastjson.JSON;
import com.xujie.common.model.Order;
import com.xujie.common.model.Product;
import com.xujie.shop_order.service.IProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import java.util.List;
import java.util.Random;/*** @author 许缘* @company xxx公司* @create 2022-12-06 17:25*/
@Slf4j
@RestController
@RequestMapping("/order")
public class ordercontroller {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;/*** 相当于本地调用*/@Autowiredprivate IProductService productService;@RequestMapping("/test/{pid}")public Order createOrder(@PathVariable("pid") Integer pid){log.info("客户下单,这时候要调用商品微服务查询商品信息");Product product = productService.getOne(pid);log.info("查询结果:"+ JSON.toJSONString(product));//创建订单Order order = new Order();order.setOid(System.currentTimeMillis());order.setUid(12);order.setUsername("张三");order.setPid(product.getPid());order.setPname(product.getPname());order.setPprice(product.getPprice());order.setNumber(product.getStock());return order;}
}
Feign参数传递
package com.xujie.shop_product.controller;import com.xujie.common.model.Product;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;@Slf4j
@RestController
@RequestMapping("/feign")
public class FeignDemoController {@RequestMapping("/findByParameter")public String findByParameter(String name,Double price){log.info("服务提供者日志:{}",name);return "hello:"+name;}@RequestMapping("/findByParameter2")public String findByParameter2(@RequestParam("name") String name,@RequestParam("price") Double price){log.info("服务提供者日志:{},{}",name,price);return "hello:"+name+price;}@RequestMapping("/findByPathVariable")public String findByPathVariable(@PathVariable String name){log.info("服务提供者日志:{}",name);return "hello:"+name;}@RequestMapping("/findByRequestBody")public Product findByRequestBody(@RequestBody Product product){log.info("服务提供者日志:{}",product.getPname());return product;}
}
消费者:
package com.xujie.shop_order.service;import com.xujie.common.model.Product;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;/*** @author 许缘* @company xxx公司* @create 2022-12-07 15:14* 在这边必须按照生产者的传参要求传参* 调用生产者的方法时必须要加注解*/
@FeignClient("shop-product")
public interface IFeignService {@RequestMapping("/feign/findByParameter")String findByParameter(@RequestParam("name") String name,@RequestParam("price") Double price);@RequestMapping("/feign/findByParameter2")String findByParameter2(@RequestParam("name") String name,@RequestParam("price") Double price);@RequestMapping("/feign/findByPathVariable/{name}")String findByPathVariable(@PathVariable("name") String name);@RequestMapping("/feign/findByRequestBody")Product findByRequestBody(@RequestBody Product product);}
controller可以不按照生产者的要求传参:
package com.xujie.shop_order.controller;import com.alibaba.fastjson.JSON;
import com.xujie.common.model.Order;
import com.xujie.common.model.Product;
import com.xujie.shop_order.service.IFeignService;
import com.xujie.shop_order.service.IProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;import java.util.List;
import java.util.Random;/*** @author 许缘* @company xxx公司* @create 2022-12-06 17:25*/
@Slf4j
@RestController
@RequestMapping("/order")
public class ordercontroller {@Autowiredprivate IFeignService feignService;@RequestMapping("/findByParameter")public String findByParameter(String name,Double price){return feignService.findByParameter(name,price);}@RequestMapping("/findByParameter2")public String findByParameter2(String name, Double price){return feignService.findByParameter2(name, price);}@RequestMapping("/findByPathVariable")public String findByPathVariable(String name){return feignService.findByPathVariable(name);}@RequestMapping("/findByRequestBody")public Product findByRequestBody(Product product){return feignService.findByRequestBody(product);}
}