# springcloud_study **Repository Path**: it-wenbei/cloud ## Basic Information - **Project Name**: springcloud_study - **Description**: 学习springcloud的demo程序。 boot-myeureka、boot-orderservice、boot-shopportal。服务发现与注册中心eureka,订单服务,商场门户服务。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-13 - **Last Updated**: 2021-08-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [toc] ![Image](http://gitee.com/static/images/logo.gif?20171106) # springcloud_study #### 介绍 学习spring cloud Netflix的demo程序,练习,入门 #### 项目架构 项目软件架构说明 - eureka服务发现与注册中心 - order-service订单服务 - shopportal电商门户(前台服务) 项目结构如下图: ![img](doc/contract.png) eureka的application.yml如下: ```yml server: port: ${server.port} spring: application: name: walking-eureka eureka: client: register-with-eureka: false instance: hostname: u1 fetch-registry: false service-url: defaultZone: http://u1:8761/eureka,http://u2:8762/eureka ``` server.port通过${server.port}可动态配置,你可以写死。配置了两个eureka实例,可以自行调整个数,hostname如果写成如上所示,一定要在hosts配置域名和IP的映射关系 在IDEA中启动时可配置VM参数,下: ![img](doc/eureka-config.png) #### springcloud模块 1. eureka 2. ribbon 3. feign #### 使用说明 1. 启动eureka,多实例启动 2. 启动order-service订单服务 3. 启动shopportal电商门户服务 shopportal调用order-service订单服务的方式: 1、首先使用RestTemplate调用,我们需要自己从eureka拿到服务提供者的IP和端口,然后选取一个进行调用。但是这样我们还要考虑如果服务提供者多个实例的话我们选取哪个?以及当调用失败是否需要重试,以及重试策略。 所以,我们引入了ribbon。 ```java @SpringBootApplication @EnableEurekaClient public class BootShopportalApplication { public static void main(String[] args) { SpringApplication.run(BootShopportalApplication.class, args); } @Bean("restTemplateV1") public RestTemplate restTemplateV1() { return new RestTemplate(); } } ``` ```java /** * 服务发现客户端 */ @Autowired private DiscoveryClient client; /** * http调用工具,类似httpclient */ @Autowired @Qualifier("restTemplateV1") private RestTemplate restTemplate; /** * RestTemplate方式调用微服务,需要获取服务列表,自己选一个服务地址进行调用 * * @return */ @GetMapping("/buy/{productId}") public Map buy(@PathVariable String productId) { // 获取订单服务地址列表 自己写逻辑用于选取一个地址 List list = this.client.getInstances("order-service"); String uri = ""; for (ServiceInstance instance : list) { if (instance.getUri() != null && !"".equals(instance.getUri())) { uri = instance.getUri().toString(); break; } } // 微服务调用 调下单接口 Map result = restTemplate.postForObject(uri + "/order/create/{productId}", null, Map.class, productId); Map response = new HashMap(); response.put("response", result); return response; } ``` 2、ribbon是客户端负载均衡的组件,他可以和eureka集合,ribbon可以自己从eureka获取服务列表,然后实现负载均衡 用法也很简单,只需要在原来的RestTemplate上加上@LoadBalanced注解即可赋予RestTemplate自动从eureka拉取服务列表以及负载均衡的能力。 ```java @SpringBootApplication @EnableEurekaClient public class BootShopportalApplication { public static void main(String[] args) { SpringApplication.run(BootShopportalApplication.class, args); } @Bean("restTemplateV1") public RestTemplate restTemplateV1() { return new RestTemplate(); } @Bean("restTemplateV2") @LoadBalanced public RestTemplate restTemplateV2() { return new RestTemplate(); } } ``` ```java /** * 引入ribbon,将负载均衡的能力赋予给RestTemplate */ @Autowired @Qualifier("restTemplateV2") private RestTemplate restTemplate; /** * ribbon方式调用微服务,具有负载均衡的功能 * * @param productId * @return */ @GetMapping("/buyAutoLB/{productId}") public Map buyAutoLB(@PathVariable String productId) { // 调下单接口 Map result = restTemplate.postForObject("http://order-service/order/create/{productId}", null, Map.class, productId); Map response = new HashMap(); response.put("result", result); return response; } ``` 3、原本以为这样已经很方便了,但是后来出现了feign。它让我们更加方便了,有了它我们直接就不需要显式的使用RestTemplate去调用服务了,就像mybatis中的mapper接口一样, 只需要声明一个接口,写上方法,在方法上注解接口的调用方式即可像调用本地方法一样调用微服务的接口。如下: ```java /** * @author walking * 公众号:编程大道 */ @FeignClient(value = "order-service") // value是要调用的服务名 标注该类是一个feign接口 public interface OrderClient { @PostMapping("/order/create/{productId}") Map createOrder(@PathVariable("productId") String productId); } ``` @FeignClient声明该接口由feign接管,value指明所调用的微服务名,queryUserById方法上的注解@GetMapping(使用get方式是为了便于演示)即为所调用的微服务的api ```java @Autowired private OrderClient orderClient; @GetMapping("/buyByFeign/{productId}") public Map queryUserById(@PathVariable String productId){ /** * feign方式调用微服务,不需要通过RestTemplate调用。像mybatis的mapper接口一样,feign内部从eureka获取服务列表后 * 通过ribbon负载均衡拿到一个服务地址进行调用,采用代理的方式,生成动态代理对象进行服务的调用 */ Map user = this.orderClient.createOrder(productId); return user; } ``` #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request