上文中已经讲述了基本环境搭建,本文基于上文环境https://www.cnblogs.com/xxpandong/p/10485172.html

  spring-cloud中微服务之间通信主要有俩种形式:

  1. RestTemplate方式
  2. Feign方式

  RestTempalte方式请求url硬编码在客户端,当有注册中心有多个服务时,注册中心无法知道服务由谁提供。

  Feign方式由于是以接口的形式进行通信,更适合这种架构。

  先来说RestTemplate方式,构建一个名为custom-common的maven-project。

  pom.xml:

  

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.custom.mg</groupId>
<artifactId>custom.root</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>custom.common</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
</project>

application.yml:

server:
port: 8001 spring:
application:
name: custom-common #注册中心指向start
eureka:
instance:
instance-id: custom-common
appname: ${spring.application.name}
client:
service-url:
#url前面增加注册中心账号以及密码
defaultZone: http://admin:123@127.0.0.1:8080/eureka/ #注册中心指向end

编写controller

 package custom.common.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; /**
*
*
* @Title SayController.java
* @Packge custom.common.controller
* @Description TODO(用一句话描述该类的作用)
* @Author Pandong
* @Date 2019年2月14日
*/
@RestController
@RequestMapping(value="/common")
public class SayController { @Value("${server.port}")
private String port; @GetMapping(value="/hello")
public String say() {
return "Hello!!I'm server :"+port;
} }
 

编写入口类启动注册到注册中心。

再构建一个名为custom-role的maven-project

  pom.xml:

  

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.custom.mg</groupId>
<artifactId>custom.root</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>custom.role</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
</project>

  application.yml:

server:
port: 8002 spring:
application:
name: custom-role #注册中心指向start
eureka:
instance:
instance-id: custom-role
appname: ${spring.application.name}
client:
service-url:
#url前面增加注册中心账号以及密码
defaultZone: http://admin:123@127.0.0.1:8888/eureka/ #注册中心指向end

 注意:

    这里使用了defaultZone: http://admin:123@127.0.0.1:8888/eureka/。@前面的是对应注册中心设置的账号、密码。

    上篇章讲述到访问注册中心会出现红字提醒,是因为没有为注册中心配置密码,任何服务都能注册进来,这里将密码配置进来,修改注册中心的相关文件

——————————————————————————————————————————————————————————————————————————————————————

  pom.xml中增加依赖:

<!-- 密码配置依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

application.yml完整配置:

server:
port: 8080
spring:
security:
user:
name: admin # 配置登录的账号是admin
password: 123 # 配置登录的密码是123
eureka:
instance:
hostname: localhost
client:
# 是否要注册到其他Eureka Server实例
register-with-eureka: false
# 是否要从其他Eureka Server实例获取数据
fetch-registry: false
service-url:
defaultZone: http://{spring.security.user.name}:{spring.security.user.password}@{hostname}:{server.port}/eureka/
server:
# 关闭注册中心对服务的保护措施(如果服务挂掉了,又没进行该配置,那么服务会以UP状态一直存在于注册中心。反之会在3分钟内容在注册中心下线)
enableSelfPreservation: false

增加安全策略配置:

package com.server.config;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /**
* Spring Cloud Finchley及更高版本,必须添加如下代码,部分关闭掉Spring Security的CSRF保护功能,否则应用无法正常注册!
* {@link http://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#_securing_the_eureka_server}
*
* @title SecurityConfig.java
* @package com.server.config
* @description TODO(一句话描述该类作用)
* @author Pandong
* @date 2019年2月18日
*/
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().ignoringAntMatchers("/eureka/**");
super.configure(http);
}
}

启动注册中心,访问localhost:8080,会出现登录页面,输入配置的账号、密码即可访问,进去后会发现之前的红字提醒不见了,但是,又出现新的红字警示,这是因为application.yml中增加了enableSelfPreservation: false该项配置所引起,可以不用理会。

——————————————————————————————————————————————————————————————————————————————————————

编写新建工程入口类:

package com.user;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication
@EnableEurekaClient
public class RoleApplication { public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
} }

编写Controller:

package custom.role.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; /**
*
*
* @Title SayApiController.java
* @Packge custom.role.controller
* @Description TODO(用一句话描述该类的作用)
* @Author Pandong
* @Date 2019年2月14日
*/
@RestController
@RequestMapping(value="/api")
public class SayApiController { @Value("${server.port}")
private String port; @Autowired
private RestTemplate restTemplate; @Autowired
private LoadBalancerClient loadBalancerClient; /**
* 第一种方式,直接使用RestTemplate,url写死。
* 因为服务端的 api 被硬编码在客户端,因此有两个缺点:
* – 当注册中心有很多服务时,我们可能不知道我们需要的服务由谁提供、api是多少,因此就可能无法调用到服务。
* –当某个服务部署了多个,例如 api 是: “localhost:8080/hello,localhost:8081/hello “,那么此时就需要负载均衡,这种硬编码显然不符合场景。
* @return
*/
@GetMapping(value="/say")
public String say() {
RestTemplate template = new RestTemplate();
return template.getForObject("http://127.0.0.1:8001/common/hello", String.class);
} /**
* 第二种方式:客户端通过 LoadBalancerClient 来获取应用名,进而获取地址和端口,在格式化拼接地址,从而调用 product服务。
* 缺点是每次调用服务都要这样写,编码很麻烦。
*/
@GetMapping("/say2")
public String say2() { RestTemplate restTemplate = new RestTemplate();
ServiceInstance serviceInstance = loadBalancerClient.choose("custom-common"); // serviceId 为提供服务的应用名
String url = String.format("http://%s:%s",serviceInstance.getHost(),serviceInstance.getPort() + "/common/hello");
String response = restTemplate.getForObject( url, String.class);
return response;
} /**
* 第三种方式:通过 @LoadBalanced,可在restTemplate 直接使用应用名字。
* 这种方式需要编写配置类,{@link custom.role.config.ConfigBeans}
*/
@GetMapping("/say3")
public String say3() {
return restTemplate.getForObject("http://custom-common/common/hello", String.class);
} }

RestTemplate配置类

package custom.role.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate; @Configuration
public class ConfigBeans { @Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
} }

启动服务,一次访问,你会发现最后都会调用到custom-comon的服务中,这种硬编码在代码中的方式,显然是不合适的。

下面来说使用Feign方式进行通信。

在custom-role中添加依赖:

<!-- feign组件依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

入口类上面添加注解@EnableFeignClients。

然后编写feign通信接口:

package custom.role.service;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; /**
* 定义Feign接口
* @Title ServerService.java
* @Packge custom.role.service
* @Description TODO(用一句话描述该类的作用)
* @Author Pandong
* @Date 2019年2月14日
*/
@FeignClient(name = "custom-common") // 调用服务名
public interface ServerService { @RequestMapping(method = RequestMethod.GET,value = "/common/hello") // 访问路径,要与服务中提供的一致
String hello(); }

@FeignClient(name = "custom-common"),custom-common对应的是服务提供者的服务名

编写FeignController控制器:

package custom.role.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import custom.role.service.ServerService; /**
* Feign通信控制器
* @Title FeignClientController.java
* @Packge custom.role.controller
* @Description 以Feign方式进行服务之间的通信
* @Author Pandong
* @Date 2019年2月14日
*/ @RestController
@RequestMapping(value="/feign")
public class FeignClientController { @Autowired
private ServerService service; @RequestMapping(method = RequestMethod.GET,value = "/say")
public String say() {
return service.hello();
} }

方法上只能使用RequestMapping,不能使用GetMapping之类的注解。

启动服务后访问/feign/say,你会发现同样会调用的custom-common中的服务。

相信到这里大家对于选择哪种方式就不用多说了。

最后说一句,由于在写学习日记的时候是另外一个版本,后面有重新搭建了一个更新的版本,文中都是从本地写好的日记中拷贝的,有些地方对应不上基础篇的地方就自行修改一下。

spring-cloud - 服务之间的通信的更多相关文章

  1. Spring Cloud 服务之间调用

    微服务之多个服务间调用 现在又一个学生微服务 user 和 学校微服务 school,如果user需要访问school,我们应该怎么做? 1.使用RestTemplate方式 添加config imp ...

  2. Spring Cloud服务注册中心交付至kubernetes

    前言 服务发现原则: 各个微服务在启动时,会将自己的网络地址等信息注册到服务发现组件中,服务发现组件会存储这些信息 服务消费者可以从服务发现组件中查询到服务提供者的网络地址,并使用该地址来远程调用服务 ...

  3. spring cloud 服务A调用服务B自定义token消失,记录

    后端:spring cloud 前端:vue 场景:前端ajax请求,包装自定义请求头token到后台做验证,首先调用A服务,A服务通过Feign调用B服务发现自定义token没有传到B服务去; 原因 ...

  4. Spring Cloud 服务网关Zuul

    Spring Cloud 服务网关Zuul 服务网关是分布式架构中不可缺少的组成部分,是外部网络和内部服务之间的屏障,例如权限控制之类的逻辑应该在这里实现,而不是放在每个服务单元. Spring Cl ...

  5. 10月9日Android学习笔记:活动与服务之间的通信

    最近在照着<第一行代码>这本书来学安卓,顺便记下笔记.主要的内容是Android中服务的第二种启动方式,通过活动绑定服务来启动服务,实现活动与服务之间的通信. 一. 首先创建一个服务类 p ...

  6. Spring Cloud 服务端注册与客户端调用

    Spring Cloud 服务端注册与客户端调用 上一篇中,我们已经把Spring Cloud的服务注册中心Eureka搭建起来了,这一章,我们讲解如何将服务注册到Eureka,以及客户端如何调用服务 ...

  7. 【spring cloud】在spring cloud服务中,打包ms-core失败,报错Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.0.4.RELEASE:repackage (default) on project

    在spring cloud服务中,有一个ms-code项目,只为所有的微服务提供核心依赖和工具类,没有业务意义,作为核心依赖使用.所以没有main方法,没有启动类. 在spring cloud整体打包 ...

  8. spring cloud 服务注册中心eureka高可用集群搭建

    spring cloud 服务注册中心eureka高可用集群搭建 一,准备工作 eureka可以类比zookeeper,本文用三台机器搭建集群,也就是说要启动三个eureka注册中心 1 本文三台eu ...

  9. 【spring cloud】spring cloud服务发现注解之@EnableDiscoveryClient与@EnableEurekaClient

    spring cloud服务发现注解之@EnableDiscoveryClient与@EnableEurekaClient的区别

随机推荐

  1. Unity 与Mono和.Net的关系

    一.分析 首先,我们要知道Unity,Mono,.Net 三者的关系.需要简单说一下.Net. .Net拥有跨语言,跨平台性. 跨语言:就是只要是面向.Net平台的编程语言,用其中一种语言编写的类型就 ...

  2. Python 包导入

    首先我们先了解下python中寻找模块的顺序 是否是内建模块 ->主目录 ->PYTHONPATH环境变量 ->标准库 -> 首先判断这个model是否是built-in,即内 ...

  3. PostgreSql基础命令及问题总结

    本章内容: 1.基本命令 基本命令 1.psql -U cdnetworks_beian -d cdnetworks_beian         #-U指定用户,-d指定数据库 2.\l        ...

  4. PHP 获取上一个页面的url

    php $_SERVER["HTTP_REFERER"]变量可以获取上一个或前一个页面的URL地址. 比如有一个a.php页面,这个页面上有一个链接指向b.php页面,如果我们在a ...

  5. 聊聊、Tomcat中文乱码和JVM设置

    set JAVA_OPTS=%JAVA_OPTS% -server -Xms512m -Xmx512m -Dfile.encoding=GBK -Dsun.jnu.encoding=GBK

  6. valuestack 根对象CompoundRoot 源码

    /* * Copyright 2002-2006,2009 The Apache Software Foundation. * * Licensed under the Apache License, ...

  7. 设计模式(一)单例模式:2-懒汉模式(Lazy)

    思想: 相比于饿汉模式,懒汉模式实际中的应用更多,因为在系统中,“被用到时再初始化”是更佳的解决方案. 设计思想与饿汉模式类似,同样是持有一个自身的引用,只是将 new 的动作延迟到 getinsta ...

  8. BZOJ 1877:[SDOI2009]晨跑(最小费用最大流)

    晨跑DescriptionElaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个 ...

  9. ubuntu--基础环境瞎搞集合

    安装ubuntu系统后有很多东西需要自己瞎搞一下,这里把一些瞎搞的过程记录在这里,方便以后重新装系统后重新配置. 一.安装. 可以在windows下制作启动盘(软碟通),然后开机u盘启动即可安装,预留 ...

  10. Python 读取 pkl文件

    使用python 的cPickle 库中的load函数,可以读取pkl文件的内容 import cPickle as pickle fr = open('mnist.pkl') #open的参数是pk ...