搭建spring cloud微服务(一),包括Eureka服务,生产者消费者,RestFul调用,Hystrix容错机制(菜鸟学习)

前言

自学多日,写一个demo做个总结,从建项目开始,比较简单的实现spring cloud微服务,消费者对生产者调用,容错机制,供初学者参考,更快的理解spring cloud
一张图
引用课工场一张图,辅助理解
在这里插入图片描述

环境

win10
Idea2019.3
jdk1.8.0_241
spring boot 2.2.7
spring cloud Hoxton.SR4
根据官网伦敦车站命名法提示,Hoxton站对应springboot 2.2.X,所以选择2.2.7
在这里插入图片描述

创建项目

目标四个子项目,服务,消费者,生产者,公共实体类

Eureka服务

首先创建,Eureka注册中心,和dubbo的Zookeeper差不多的功能

在这里插入图片描述
起个名
在这里插入图片描述
创建第一个模块,Eureka
点击加号NewModule
在这里插入图片描述
选择spring boot项目
在这里插入图片描述
起个名字
在这里插入图片描述
勾选Eureka Server,选2.2.7版本,Next->Finish
分布式注册中心,也就是管理的分布式的项目叫服务,其他具有实际功能的但是要注册到注册中心里的叫客户端
在这里插入图片描述
ok
在这里插入图片描述
建好了,处理一下pom
在这里插入图片描述
配置文件 application.properties
都有注释,自己看
注意:defaultZone这个东西,有的帖子写default-zone,default-Zone都会报连接错误,我也不知道为什么这么写,反正就是defaultZone就对了

server.port=4460

#注册中心集群defalutZone填除你之外的注册中心地址,如下
#eureka.client.service-url.defaultZone=http://localhost:4461/eureka,http://localhost:4462/eureka
eureka.client.service-url.defaultZone=http://localhost:4460/eureka

#是否把当前项目添加到注册中心
eureka.client.register-with-eureka=false

#注册中心分布式集群设true
eureka.client.fetch-registry=false

#开启用户名密码
#spring.security.user.name=root
#spring.security.user.password=demo

如果给注册中心加用户名和密码,打开“开启用户名密码”的配置,并在pom中加下面包,
客户端请求改为 http://root:demo@localhost:4460/eureka
我开启后,客户端不能连接到注册中心,不知道咋回事,所以注掉了

<!--	开启用户名密码-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

启动类EurekaServerApplication
加入@EnableEurekaServer注解证明他是一个服务

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(EurekaServerApplication.class, args);
	}

}

Eureka服务完事,启动程序
浏览器访问http://localhost:4460
出现这个,服务搭建成功,Application模块为空,说明没有客户端注册进来
在这里插入图片描述

创建provider

添加一个子模块
在这里插入图片描述
同样分方法,点加号,New Module,spring boot项目
在这里插入图片描述
勾选web,client,选2.2.7版本,完成
在这里插入图片描述
配置文件
注册到4460端口上

server.port=4461
spring.application.name=provider-user

eureka.client.service-url.defaultZone=http://localhost:4460/eureka

启动类
加注解@EnableDiscoveryClient
老版本的@EnableEurekaClient,效果一样

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderUserApplication {

	public static void main(String[] args) {
		SpringApplication.run(ProviderUserApplication.class, args);
	}

}

其实现在启动已经可以注册到注册中心了,但是不要启动,再写一个Demo
创建一个controller包,建一个UserController类,做测试
在这里插入图片描述
代码,userp,表示生产者的user接口

package com.sunc.provideruser.controller;


import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @RequestMapping(value = "userp",method = RequestMethod.GET)
    public String getUser(@RequestParam("name") String name, @RequestParam("pass") String pass){
        return "hello "+name+",this is provider";
    }
}

启动项目
浏览器访问http://localhost:4461/userp?name=xiaohei&pass=123
在这里插入图片描述
成功,刷新Eureka服务页面,可以看到provider-user注册进来了
在这里插入图片描述

创建公共的User类

保证字段和类型在两个项目中不会出现不一致,生产者和消费者公用一个实体类
但是这个实体类不需要注册到Eureka,也不需要逻辑,所以只
创建maven项目
在这里插入图片描述
命名
在这里插入图片描述
创建User实体类

package com.sunc.bean;

public class Users {
    private String user_name;
    private String pass_word;

    public String getUser_name() {
        return user_name;
    }

    public void setUser_name(String user_name) {
        this.user_name = user_name;
    }

    public String getPass_word() {
        return pass_word;
    }

    public void setPass_word(String pass_word) {
        this.pass_word = pass_word;
    }

    @Override
    public String toString() {
        return "User{" +
                "user_name='" + user_name + '\'' +
                ", pass_word='" + pass_word + '\'' +
                '}';
    }
}

右边maven中,build一下
在这里插入图片描述
复制pom中地址给生产者
common中pom复制出来

<groupId>org.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>

粘贴到provider的pom中
在这里插入图片描述
修改provider-user模块中controller
此处使用了Users实体,请求改为post,判断用户名密码是否正确。
如果是“xiaobai”且密码“123”,返回true

package com.sunc.provideruser.controller;


import com.sunc.bean.Users;
import org.springframework.web.bind.annotation.*;

@RestController
public class UserController {

    @RequestMapping(value = "userp",method = RequestMethod.POST)
    public Integer getUser(@RequestBody Users user){
        Integer i = 0;
        if ("xiaobai".equals(user.getUser_name()) && "123".equals(user.getPass_word())){
            i = 1;
        }
        return i;
    }
}

公共实体完事

创建消费者

同样方法创建新模块,springboot项目,起名consumer-user
注意此处勾选feign,调用其他成员
在这里插入图片描述
实体类地址复制过来
在这里插入图片描述
配置文件类似,改个端口,改个喜欢的名字,我这里全都和项目同名,方便看
在这里插入图片描述
创建controller
此处地址用userc,消费者的user接口

package com.sunc.consumeruser.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @RequestMapping(value = "/userc",method = RequestMethod.GET)
    public String getUser(@RequestParam("name") String name, @RequestParam("pass") String pass){
        return "hello "+name+",this is consumer";
    }
}

启动类和生产者一样加@EnableDiscoveryClient

package com.sunc.consumeruser;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerUserApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConsumerUserApplication.class, args);
	}
}

启动…
此时,Eureka-server,provider-user均为启动状态,不要关闭
刷新浏览器
在这里插入图片描述
consumer-user也注册进来了,成功
浏览器访问
http://localhost:4462/userc?name=xiaobai&pass=123
在这里插入图片描述
成功
两个项目均注册进来了,也都能通过web访问,但是这完全是两个项目,现在要用consumer调用provider,这样才能将分开的项目联系起来。dubbo使用RPC连接,dubbox使用RPC和tcp,spring cloud使用tcp,三次握手,四次分手,客户端发送syn请求,服务端相应后返回syn,ack,客户端再发送。。。。。。此处省略925个字,tcp的好处就是各种语言之间都可以连接,springcloud 连接方式可以使用Ribbon+RestTemplate或者Feign,此处使用Feign
改造开始
consumeruser启动类加入@EnableFeignClients

package com.sunc.consumeruser;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
//调别人需要注解
@EnableFeignClients
public class ConsumerUserApplication {
	public static void main(String[] args) {
		SpringApplication.run(ConsumerUserApplication.class, args);
	}
}

创建service
provider-user为前面给给生产者配置文件中的spring.application.name=provider-user
准备以post方式请求userp,传递参数Users的属性,@RequestBody这个我不太理解,不加请求不过去

package com.sunc.consumeruser.service;

import com.sunc.bean.Users;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient(name = "provider-user")
public interface UserService {

    @RequestMapping(value = "/userp",method = RequestMethod.POST)
    public Integer getUser(@RequestBody Users user);

}

改造controller
如果返回true输出hello,如果false提示用户名或密码不对

package com.sunc.consumeruser.controller;

import com.sunc.bean.Users;
import com.sunc.consumeruser.service.UserService;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/userc",method = RequestMethod.GET)
    public String getUser(@RequestParam("name") String name, @RequestParam("pass") String pass){
        Users users = new Users();
        users.setUser_name(name);
        users.setPass_word(pass);
        String res = "";
        if(userService.getUser(users).equals(1)){
            res = "hello "+users.getUser_name()+", this is consumer";
        }else if(userService.getUser(users).equals(2)){
            res = "Sorry, user name or password is wrong ~~";
        }
        return res;
    }
}

重启consumer-user
访问 http://localhost:4462/userc?name=xiaobai&pass=1236
提示用户名或密码不对在这里插入图片描述
访问 http://localhost:4462/userc?name=xiaobai&pass=123
成功
在这里插入图片描述
此时已经证明consumer调用了provider中的方法,并判断了用户名和密码是否匹配,实现了用户登陆时的返回信息和判断登陆是否成功的分布式(可怜的demo)

熔断器Hystrix

作用就是,当服务端宕机,客户端请求不能实现,进入异常类做特殊处理
由于hystrix通属于feign包,所以不需要引入包直接建
配置文件
启用熔断器机制

server.port=4462
spring.application.name=consumer-user

eureka.client.service-url.defaultZone=http://localhost:4460/eureka

#启用熔断器机制
feign.hystrix.enabled=true

service包下建Impl实现类
在这里插入图片描述
如果provider宕机返回2

package com.sunc.consumeruser.service.Impl;

import com.sunc.bean.Users;
import com.sunc.consumeruser.service.UserService;
import org.springframework.stereotype.Component;

@Component
public class UserServiceFallback implements UserService {

    @Override
    public Integer getUser(Users user) {
        //如果请求不能发送,进入UserServiceFallback,返回2
        return 2;
    }
}

改造service
fallback = UserServiceFallback.class

package com.sunc.consumeruser.service;

import com.sunc.bean.Users;
import com.sunc.consumeruser.service.Impl.UserServiceFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient(name = "provider-user", fallback = UserServiceFallback.class)
public interface UserService {

    @RequestMapping(value = "/userp",method = RequestMethod.POST)
    public Integer getUser(@RequestBody Users user);

}

controller
添加一句话,对返回2判断

package com.sunc.consumeruser.controller;

import com.sunc.bean.Users;
import com.sunc.consumeruser.service.UserService;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/userc",method = RequestMethod.GET)
    public String getUser(@RequestParam("name") String name, @RequestParam("pass") String pass){
        Users users = new Users();
        users.setUser_name(name);
        users.setPass_word(pass);
        String res = "";
        if(userService.getUser(users).equals(1)){
            res = "hello "+users.getUser_name()+", this is consumer";
        } else if (userService.getUser(users).equals(0)){
            res = "Sorry, user name or password is wrong ~~";
        } else if (userService.getUser(users).equals(2)){
            res = "Sorry, 服务器挂了 ~~";
        }
        return res;
    }
}

重启consumer服务
访问浏览器,一切正常
在这里插入图片描述
关掉provider服务,模拟宕机
再访问浏览器
在这里插入图片描述

成功

项目结构
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
common的pom

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <groupId>org.example</groupId>
    <artifactId>common</artifactId>
    <version>1.0-SNAPSHOT</version>

consumer-user的pom

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.sunc</groupId>
	<artifactId>consumer-user</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>consumer-user</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Hoxton.SR4</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-openfeign</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<dependency>
			<groupId>org.example</groupId>
			<artifactId>common</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

eureka-server的pom

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.7.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.sunc</groupId>
	<artifactId>eureka-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>eureka-server</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Hoxton.SR4</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

provider-user的pom

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.7.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.sunc</groupId>
	<artifactId>provider-user</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>provider-user</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Hoxton.SR4</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<dependency>
			<groupId>org.example</groupId>
			<artifactId>common</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

做到这实现了,eureka服务,生产者,消费者搭建,消费者对生产者的调用,共用同一个实体类,容错机制。
最后才发现consumer-user用的springboot2.3.0。。。貌似也能用
如有偏颇敬请斧正,本厮邮箱:suncch@63.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值