1.安装配置nacos以及实现服务支持
nacos简介
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速
实现动态服务发现、服务配置、服务元数据及流量管理。
从上面的介绍就可以看出,nacos的作用就是一个注册中心,用来管理注册上来的各个微服务。
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 {
@Autowired
private RestTemplate restTemplate;
@Autowired
private 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 {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
/**
* 相当于本地调用
*/
@Autowired
private 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 {
@Autowired
private 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);
}
}