springCloud后续步骤配置

先把以下链接的代码完成在根据笔记网下走

https://blog.csdn.net/weixin_38305440/article/details/102775484

随堂笔记

这是随堂笔记, 详细内容请参考在线笔记:
https://blog.csdn.net/weixin_38305440

笔记乱码问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wW1NmhEq-1605679244364)(note.assets/image-20200501102330884.png)]

# 课前准备

先做这几件事

  1. 注册csdn账号

  2. 注册 github 和 gitee.com 账号

  3. 创建项目,使用课前资料中的pom.xml,更新下载依赖

  4. 下载课前资料

    天翼网盘不限速:
    https://cloud.189.cn/t/2auEfqVZFJNv (访问码:jp2d)
    百度网盘非会员限速:
    https://pan.baidu.com/s/19tOuVOYJsplssj3kLvfzcA

在线笔记地址
https://blog.csdn.net/weixin_38305440

课程安排

Spring Cloud - 6天(重点)

RabbitMQ - 2天(重点)

Lucene Solr - 1天

Docker + Kubernetes - 5天(重点)

课程要求

严格按照笔记来做

  • 项目名
  • 包名
  • 类名

好处

  • 少踩坑
  • 快速回退

贯穿项目

  • 6天spring cloud是一个贯穿项目, 前后尽量保持一致

sp01-commons

public interface ItemService {
	// 获取订单中的商品列表
	List<Item> getItems(String orderId);
	
	// 减少商品库存
	void decreaseNumbers(List<Item> items);
}

public interface OrderService {
	// 获取订单
	Order getOrder(String orderId);
	
	// 保存订单
	void addOrder(Order order);
}

public interface UserService {
	// 获取用户
	User getUser(Integer id);
	
	// 增加用户集分
	void addScore(Integer userId, Integer score);
}

eureka

单台eureka服务器, 会自动配置一台默认的集群服务器 - localhost:8761

如果默认服务器不存在, 就会一次次反复尝试连接, 一次次反复出错.

自己配置集群后, 错误会消失.

VMware

最好使用最新版本的 VMware 15.x

能用 15 都用 15, 如果实在用不了也可以使用 12

课前资料\软件\VMware.zip 解压缩

可以先卸载旧版本, 然后安装 15.5.2

虚拟机

VMware15.x, 使用 CentOS-7-1908.zip

VMware12.x, 使用 CentOS-7-1908-vmware-12.zip

解压缩

双击 CentOS-7-1908.vmx

启动时选择 已复制该虚拟机

输入用户名密码

login: root
Password: root # 输入时没有任何反应, 但已经输入进去了

设置 NAT 网络网段

使用 192.168.64 网段

编辑–虚拟网络编辑器

如果没有管理员权限, 点击右下角更改设置获取管理员权限

选择 VMnet8 网卡

设置虚拟机ip

在我给的虚拟机中, 添加了两个脚本文件, 可以方便地设置ip地址

./ip-static # 设置固定ip

./ip-dhcp # 动态分配ip

# 设置完ip后, 可以查看ip
ifconfig

# 测试网络通不通, ctrl+c结束
ping 192.168.64.1  # ping windows宿主机
ping www.baidu.com


VMware 网络设置笔记

https://blog.csdn.net/weixin_38305440/article/details/105082294

安装配置 RabbitMQ

  1. 把 CentOS-7-1908 虚拟机创建链接克隆: rabbitmq

  2. 启动 rabbitmq, 配置ip地址

    ./ip-static
    ip: 192.168.64.140
    
    ifconfig
    ping 192.168.64.1
    
  3. windows中, 用xshell 和 win-scp (或filezilla) 连接 140 服务器

    • win-scp或filezilla连接时, 使用 SFTP 协议
  4. 课前资料\亿发课前资料(需要解压)\rabbitmq\rabbitmq-install.zip

  5. 解压rabbitmq-install.zip

  6. 用win-scp或filezilla上传 rabbitmq-install 目录

  7. 切换到这个目录, 安装离线文件

    cd rabbitmq-install
    rpm -ivh *.rpm
    

Order

  1. 添加依赖:
    • feign
    • hystrix
    • actuator
  2. yml
    • feign.hystrx.enabled=true
    • m.e.w.e.i=hystrix.stream
  3. 主程序注解
    • @SpringCloudApplication
    • @EnableFeignClients

RabbitMQ

package rabbitmq.m1_simple;

import java.io.IOException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class Test1 {
	public static void main(String[] args) throws Exception {
		//1. 连接
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setPort(5672); // 注意不是15672, 如果是默认5672端口, 这个设置可以省略
		f.setUsername("admin");
		f.setPassword("admin");
		
		Connection con = f.newConnection();
		Channel c = con.createChannel();
		
		//2. 向服务器发送指令,要求服务器准备好队列: helloworld
		//定义队列
		c.queueDeclare("helloworld",false,false,false,null);
		
		//3. 向指定的队列发送数据
		//第四个参数是发送的消息数据, 必须是 byte[] 数组
		c.basicPublish("", "helloworld", null, 
				("Hello world! "+System.currentTimeMillis()).getBytes());
		System.out.println("消息已发送");
		
		c.close();
		con.close();
	}
}

package rabbitmq.m1_simple;

import java.io.IOException;

import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;

public class Test2 {
	public static void main(String[] args) throws Exception {
		//1. 连接
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setPort(5672); //默认端口5672可以不设置
		f.setUsername("admin");
		f.setPassword("admin");
		Connection con = f.newConnection();
		Channel c = con.createChannel();
		
		//2. 定义队列
		//参数: 队列名,是否是持久队列,是否是消费者独占队列,没有消费者时是否自动删除,其他的参数属性配置
		c.queueDeclare("helloworld",false,false,false,null);
		
		//回调对象
		DeliverCallback deliverCallback = new DeliverCallback() {
			public void handle(String consumerTag, Delivery message) throws IOException {
				byte[] a = message.getBody();
				String msg = new String(a);
				System.out.println("收到: "+msg);
			}
		};
		CancelCallback cancelCallback = new CancelCallback() {
			public void handle(String consumerTag) throws IOException {
			}
		};
		
		//3. 从队列接收数据
		c.basicConsume("helloworld", true, deliverCallback, cancelCallback);
	}
}
package rabbitmq.m2_work;

import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;

public class Test1 {
	public static void main(String[] args) throws Exception {
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setUsername("admin");
		f.setPassword("admin");
		//f.setVirtualHost("/wht");
		
		Channel c = f.newConnection().createChannel();
		
		//定义队列
		c.queueDeclare("helloworld",false,false,false,null);
		
		//发送数据
		while (true) {
			System.out.print("输入:");
			String msg = new Scanner(System.in).nextLine();
			c.basicPublish("", "helloworld", null, msg.getBytes());
		}
	}
}

package rabbitmq.m2_work;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;

public class Test2 {
	public static void main(String[] args) throws Exception {
		//1. 连接
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setUsername("admin");
		f.setPassword("admin");
		//f.setVirtualHost("/wht");
		
		Channel c = f.newConnection().createChannel();
		
		//2. 定义队列
		c.queueDeclare("helloworld",false,false,false,null); //是否持久队列,是否排他队列,是否自动删除,其他属性
		
		DeliverCallback deliverCallback = new DeliverCallback() {
			public void handle(String consumerTag, Delivery message) throws IOException {
				byte[] a = message.getBody();
				String msg = new String(a);
				System.out.println("收到: "+msg);
				// "sdfs.dfs........sdf....sdf.......sd.sdfs........sf....sdf.........."
				for (int i = 0; i < msg.length(); i++) {
					if ('.' == msg.charAt(i)) {
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
						}
					}
				}
				System.out.println("消息处理结束\n");
			}
		};
		CancelCallback cancelCallback = new CancelCallback() {
			public void handle(String consumerTag) throws IOException {
			}
		};
		
		//3. 消费数据
		c.basicConsume("helloworld", true, deliverCallback, cancelCallback);
	}
}

ACK 和 qos=1

package rabbitmq.m2_work;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;

public class Test2 {
	public static void main(String[] args) throws Exception {
		//1. 连接
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setUsername("admin");
		f.setPassword("admin");
		//f.setVirtualHost("/wht");
		
		Channel c = f.newConnection().createChannel();
		
		//2. 定义队列
		c.queueDeclare("helloworld",false,false,false,null); //是否持久队列,是否排他队列,是否自动删除,其他属性
		
		DeliverCallback deliverCallback = new DeliverCallback() {
			public void handle(String consumerTag, Delivery message) throws IOException {
				byte[] a = message.getBody();
				String msg = new String(a);
				System.out.println("收到: "+msg);
				// "sdfs.dfs........sdf....sdf.......sd.sdfs........sf....sdf.........."
				for (int i = 0; i < msg.length(); i++) {
					if ('.' == msg.charAt(i)) {
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
						}
					}
				}
				
				//发送回执
				//回执, 是否确认之前收到的所有消息
				c.basicAck(message.getEnvelope().getDeliveryTag(), false);
				System.out.println("消息处理结束\n");
			}
		};
		CancelCallback cancelCallback = new CancelCallback() {
			public void handle(String consumerTag) throws IOException {
			}
		};
		
		// qos - 1 每次只抓取一条消息, 消息处理完成之前, 不抓取下一条
		//       只在手动确认模式下有效
		c.basicQos(1);
		
		//3. 消费数据
		/*
		 * 第二个参数
		 * 		true - 自动ACK
		 * 		false - 手动确认, 需要手动发送消息回执
		 */
		c.basicConsume("helloworld", false, deliverCallback, cancelCallback);
	}
}

发布和订阅

package rabbitmq.m3_publishsubscribe;

import java.util.Scanner;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;

public class Test1 {
	public static void main(String[] args) throws Exception {
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setUsername("admin");
		f.setPassword("admin");
		//f.setVirtualHost("/wht");
		
		Channel c = f.newConnection().createChannel();
		
		//定义交换机
		c.exchangeDeclare("logs", "fanout");
		
		//发送数据
		while (true) {
			System.out.print("输入:");
			String msg = new Scanner(System.in).nextLine();
			/*
			 * 第一个参数
			 *     空串 - 默认的直连交换机(direct)
			 * 
			 * 第二个参数
			 *     对于发布和订阅模式无效
			 */
			c.basicPublish("logs", "", null, msg.getBytes());
		}
	}
}

作业

  1. 下载第5章代码, 重做 7到19
  2. 下载第17章代码, 重做 18,19

rabbitmq

package rabbitmq.m3_publishsubscribe;

import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;

public class Test2 {
	public static void main(String[] args) throws Exception {
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); // www.wht6.cn
		f.setPort(5672);
		f.setUsername("admin");
		f.setPassword("admin");
		//f.setVirtualHost("/xxxxxxxx");
		
		Channel c = f.newConnection().createChannel();
		
		// 1.定义交换机   2.定义队列   3.绑定
		c.exchangeDeclare("logs", "fanout");
		// 服务器随机命名,非持久,排他(独占),自动删除,其他属性
		String queue = c.queueDeclare().getQueue();
		// 第三个参数,对于fanout交换机无效
		c.queueBind(queue, "logs", "");
		
		DeliverCallback deliverCallback = new DeliverCallback() {
			public void handle(String consumerTag, Delivery message) throws IOException {
				String msg = new String(message.getBody());
				System.out.println("收到: "+msg);
			}
		};
		CancelCallback cancelCallback = new CancelCallback() {
			public void handle(String consumerTag) throws IOException {
			}
		};
		
		// 正常从队列接收数据
		c.basicConsume(queue, true, deliverCallback, cancelCallback);
	}
}
package rabbitmq.m4_routing;

import java.util.Scanner;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;

public class Test1 {
	public static void main(String[] args) throws Exception {
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setUsername("admin");
		f.setPassword("admin");
		//f.setVirtualHost("/wht");
		
		Channel c = f.newConnection().createChannel();
		
		// 定义交换机
		//c.exchangeDeclare("direct_logs", "direct");
		c.exchangeDeclare("direct_logs", BuiltinExchangeType.DIRECT);
		
		while (true) {
			System.out.print("输入消息:");
			String msg = new Scanner(System.in).nextLine();
			System.out.print("输入路由键:");
			String key = new Scanner(System.in).nextLine();
			
			// 第二个参数是路由键, 用路由键做关键词匹配,决定把消息发到哪个队列
			c.basicPublish("direct_logs", key, null, msg.getBytes());
		}
		
	}
}

package rabbitmq.m4_routing;

import java.io.IOException;
import java.util.Scanner;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;

public class Test2 {
	public static void main(String[] args) throws Exception {
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setUsername("admin");
		f.setPassword("admin");
		//f.setVirtualHost("/wht");
		
		Channel c = f.newConnection().createChannel();
		
		//1.定义交换机   2.定义随机队列   3.绑定
		c.exchangeDeclare("direct_logs", BuiltinExchangeType.DIRECT);
		String queue = c.queueDeclare().getQueue();
		System.out.println("输入绑定键,用空格隔开: "); // "aaaa   bbb   cccccc"
		String s = new Scanner(System.in).nextLine();
		String[] a = s.split("\\s+");
		for (String key : a) {
			c.queueBind(queue, "direct_logs", key);
		}
		
		DeliverCallback deliverCallback = new DeliverCallback() {
			public void handle(String consumerTag, Delivery message) throws IOException {
				// 取出消息数据, 和路由键
				String msg = new String(message.getBody());
				String key = message.getEnvelope().getRoutingKey();
				
				System.out.println("收到: "+key+" - "+msg);
			}
		};
		CancelCallback cancelCallback = new CancelCallback() {
			public void handle(String consumerTag) throws IOException {
			}
		};
		
		//正常接收消费数据
		c.basicConsume(queue, true, deliverCallback, cancelCallback);
		
		
	}
}

package rabbitmq.m5_topic;

import java.util.Scanner;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;

public class Test1 {
	public static void main(String[] args) throws Exception {
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setUsername("admin");
		f.setPassword("admin");
		//f.setVirtualHost("/wht");
		
		Channel c = f.newConnection().createChannel();
		
		// 定义交换机
		c.exchangeDeclare("topic_logs", BuiltinExchangeType.TOPIC);
		
		//发送数据
		while (true) {
			System.out.print("输入消息: ");
			String msg = new Scanner(System.in).nextLine();
			System.out.print("输入路由键: ");
			String key = new Scanner(System.in).nextLine(); // aaaa.bbb.ccccccc.ddd
			
			c.basicPublish("topic_logs", key, null, msg.getBytes());
		}
		
	}
}

package rabbitmq.m5_topic;

import java.io.IOException;
import java.util.Scanner;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;

public class Test2 {
	public static void main(String[] args) throws Exception {
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setUsername("admin");
		f.setPassword("admin");
		//f.setVirtualHost("/wht");
		
		Channel c = f.newConnection().createChannel();
		
		// 定义交换机, 定义随机队列, 绑定
		c.exchangeDeclare("topic_logs", BuiltinExchangeType.TOPIC);
		String queue = c.queueDeclare().getQueue();
		System.out.println("输入绑定键,用空格隔开: ");
		String s = new Scanner(System.in).nextLine();
		String[] a = s.split("\\s+");
		for (String key : a) {
			c.queueBind(queue, "topic_logs", key);
		}
		
		DeliverCallback deliverCallback = new DeliverCallback() {
			public void handle(String consumerTag, Delivery message) throws IOException {
				// 取出消息和路由键
				String msg = new String(message.getBody());
				String key = message.getEnvelope().getRoutingKey();
				System.out.println("收到: "+key+" - "+msg);
			}
		};
		CancelCallback cancelCallback = new CancelCallback() {
			public void handle(String consumerTag) throws IOException {
			}
		};
		
		// 消费数据
		c.basicConsume(queue, true, deliverCallback, cancelCallback);
	}
}

配置中心

  1. 远程仓库
    • 远程仓库四个文件
    • 如果自己的仓库不能用,可以用我的仓库
    • https://gitee.com/benwang6/sp-config
  2. 搭建配置中心
    • uri - 远程仓库的地址
    • search-path - config子目录
    • @EnableConfigServer
    • 确认
      • http://eureka1:2001/ 需要看到 config-server的注册信息
      • http://localhost:6001/item-service/dev
      • http://localhost:6001/user-service/dev
      • http://localhost:6001/order-service/dev
      • http://localhost:6001/zuul/dev
  3. 配置中心客户端服务
    • 添加 config client 依赖(注意不是config client(PCF))
    • bootstrap.yml
  4. 启动测试
    • 先启动 5, 等待5完全启动!!!
    • 再启动12, 等待12完全启动!!!
    • 确认 http://eureka1:2001/ 有 config-server的注册信息
    • 启动2,3,4,11
      • 确认
      • 控制台是否在连接 6001, 下载配置信息

bus

  1. 修改 2,3,4,11,12 项目

    • 添加bus和rabbitmq依赖
    • 配置rabbitmq的连接信息
      • 12项目 - 直接修改 application.yml
      • 2,3,4,11项目 - config项目中的四个配置文件, 修改后推送到远程仓库
  2. 修改 12 项目, 暴露 bus-refresh 端点

  3. 按顺序启动项目

    1. 启动 rabbitmq 服务器

    2. 启动5, 等待完全启动!!!

    3. 启动12, 等待完全启动!!! 确认 http://eureka1:2001 有没有注册信息

      1. 确认配置文件可访问

        http://localhost:6001/item-service/dev

        http://localhost:6001/user-service/dev

        http://localhost:6001/order-service/dev

        http://localhost:6001/zuul/dev

    4. 再启动 2,3,4,11, 确认控制台有连接 6001 的日志

    5. 确认 http://localhost:6001/actuator 有没有 bus-refresh

sleuth+zipkin

  • 添加sleuth依赖, 产生链路跟踪数据
  • 添加zipkin client依赖
  • rabbitmq 依赖, 配置rabbitmq连接信息
  • spring.zipkin.sender.type=rabbit

rpc模式

package rabbitmq.m6_rpc;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;

public class RpcServer {
	public static void main(String[] args) throws Throwable {
		//1. 接收客户端的调用数据: n值, 返回队列名, 关联id		
		//2. 执行运算求出斐波那契数		
		//3. 发回计算结果, 要携带关联id

		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setUsername("admin");
		f.setPassword("admin");
		//f.setVirtualHost("/wht");

		Channel c = f.newConnection().createChannel();
		
		//定义调用队列
		c.queueDeclare("rpc_queue",false,false,false,null);
		
		DeliverCallback deliverCallback = new DeliverCallback() {
			public void handle(String consumerTag, Delivery message) throws IOException {
				//收到调用数据, n值, 返回队列名, 关联id
				String msg = new String(message.getBody());
				String replyTo = message.getProperties().getReplyTo();
				String cid = message.getProperties().getCorrelationId();
				System.out.println(msg+", "+replyTo+", "+cid);
				
				//执行运算
				long result = fbnq(Integer.parseInt(msg));
				
				//发回计算结果, 向 replyTo 队列发送, 携带 cid
				BasicProperties props = 
					new BasicProperties.Builder()
					.correlationId(cid)
					.build();
				
				c.basicPublish("", replyTo, props, (""+result).getBytes());
				System.out.println("已向客户端发回结果");
			}
		};
		CancelCallback cancelCallback = new CancelCallback() {
			public void handle(String consumerTag) throws IOException {
			}
		};
		
		//从rpc_queue消费数据
		c.basicConsume("rpc_queue", true, deliverCallback, cancelCallback);
	}

	/*
	 * 计算斐波那契数的服务
	 * 接收的参数是求第几个斐波那契数
	 * 
	 * 1 1 2 3 5 8 13 21 34 55 89 144 233 ....
	 */
	static long fbnq(int n) {
		if (n == 1 || n == 2) {
			return 1;
		}
		return fbnq(n-1) + fbnq(n-2);
	}

}

package rabbitmq.m6_rpc;

import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class TestABQ {
	static BlockingQueue<Double> q = new ArrayBlockingQueue<>(10);
	
	public static void main(String[] args) {
		//放数据
		new Thread() {
			public void run() {
				System.out.println("\n线程1 - 按回车放入数据");
				new Scanner(System.in).nextLine();
				double d = Math.random();
				q.offer(d);//放入数据
				System.out.println("线程1 - 放入数据:"+d);
			}
		}.start();
		
		//取数据
		new Thread() {
			public void run() {
				try {
					System.out.println("线程2 - 正在获取数据");
					Double d = q.take();
					System.out.println("线程2 - 已经获取数据: "+d);
				} catch (InterruptedException e) {
				}
				
			}
		}.start();
	}
}

package rabbitmq.m6_rpc;

import java.io.IOException;
import java.util.Scanner;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;

public class RpcClient {
	static BlockingQueue<String> q = new ArrayBlockingQueue<>(10);
	
	public static void main(String[] args) throws Exception {
		while (true) {
			System.out.print("求第几个斐波那契数:");
			int n = new Scanner(System.in).nextInt();
			long r = f(n);
			System.out.println(r);
		}
	}

	private static long f(int n) throws Exception {
		//1. 发送调用数据
		//2. 接收执行结果
		ConnectionFactory f = new ConnectionFactory();
		f.setHost("192.168.64.140"); //www.wht6.cn
		f.setUsername("admin");
		f.setPassword("admin");
		//f.setVirtualHost("/wht");

		Channel c = f.newConnection().createChannel();
		
		// 发送的数据: n, 返回队列的队列名, 关联id
		c.queueDeclare("rpc_queue",false,false,false,null);
		String queue = c.queueDeclare().getQueue(); //服务器随机命名,非持久,排他,自动删除
		String cid = UUID.randomUUID().toString();
		
		BasicProperties props = 
			new BasicProperties.Builder()
			.replyTo(queue)
			.correlationId(cid)
			.build();
		
		c.basicPublish("", "rpc_queue", props, (""+n).getBytes());
		System.out.println("已发送调用");
		System.out.println("主线程不必等待, 继续执行其他运算......");
		
		System.out.println("直到需要结果时, 再取结果");
		
		DeliverCallback deliverCallback = new DeliverCallback() {
			public void handle(String consumerTag, Delivery message) throws IOException {
				//处理从服务器返回的计算结果
				//把计算结果放入一个集合
				String msg = new String(message.getBody());
				String cid2 = message.getProperties().getCorrelationId();
				//模拟判断关联id的匹配
				if (cid.equals(cid2)) {
					q.offer(msg);
				}
			}
		};
		CancelCallback cancelCallback = new CancelCallback() {
			public void handle(String consumerTag) throws IOException {
			}
		};
		
		//接收结果
		c.basicConsume(queue, true, deliverCallback, cancelCallback);
		
		//主线程从集合取结果
		return Long.parseLong(q.take());
	}
}

作业

  1. 下载第5章代码, 从第7章重做
  2. 下载第17章代码, 从第18章重做
  3. 下载第21章代码, 从第23章重做

拼多商城

  1. 导入项目

    • 亿发课前资料\solr\06-拼多项目
    • 项目解压缩
    • 导入eclipse, 导入"existing maven project"
  2. 导入数据库

    • 亿发课前资料\solr\04-拼多数据库\pd.sql

    • sqlyog 连接mysql, 导如 pd.sql

  3. oracle的mysql 8

  • pom.xml
    • mysql 驱动, 添加版本: <version>8.0.20</version>
  • application.yml
    • mysql连接地址, 添加timezone参数: &serverTimezone=Asia/Shanghai
  1. 启动项目
    • 启动类: RunPdApp
  2. 注册登录
    • 如果填的用户名,email,电话重复,不能注册
  3. 添加收货地址

Solr

准备服务器

  1. 克隆 centos-7-1908: solr

  2. 设置ip

    ./ip-static
    ip: 192.168.64.170
    
  3. xshell 和 winscp(或filezilla) 连接 170 服务器

安装配置JDK

  1. 上传 jdk-8u212-linux-x64.tar.gz
  2. 解压缩 jdk
tar xf jdk-8u212-linux-x64.tar.gz -C /usr/local/
  1. 配置环境变量
cd /usr/local/jdk1.8.0_212
pwd #查看jdk的完整路径, 并复制这个路径

# 一会一块做这个设置, 不要自己乱动
vim /etc/profile
# 在文件末尾添加:
JAVA_HOME=/usr/local/jdk1.8.0_212
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=.
export JAVA_HOME PATH CLASSPATH

#退出编辑后, 让配置文件立即生效
source /etc/profile

  1. 确认
java -version
javac -version

安装配置Solr

  1. 上传 solr-8.1.1.tgz

  2. 解压缩

cd ~
tar xf solr-8.1.1.tgz -C /usr/local
  1. 启动solr服务器
cd /usr/local/solr-8.1.1
bin/solr start -force
  1. 打开端口,访问测试
firewall-cmd --zone=public --add-port=8983/tcp --permanent
firewall-cmd --reload

http://192.168.64.170:8983

创建 core (核心): pd

在pd核心配置中文分词器: ik分词

pd核心设置文档的字段

配置从mysql导入数据

# mysql 5 或 mariadb
grant all on *.* to 'root'@'%' identified by 'root';

# mysql 8
create user 'root'@'%' identified by 'root';

grant all privileges on *.* to 'root'@'%';

dih-config.xml

数据库连接信息, 和查询语句

solrconfig.xml

指定上面的配置文件文件名

导入数据失败

  • 下载我的三个配置文件, 传到你的 solr 服务器
  • dih-config.xml, 使用 windows 的物理网络ip
  • 关闭windows防火墙
  • 检查 mysql 驱动jar文件有没有

Docker

  1. Centos-7-1908 克隆: docker
  2. 设置 ip
./ip-static
ip: 192.168.64.150

导入后面要是用的镜像

课前资料/devops课前资料/docker

5个 *-image.gz 文件, 上传到服务器

把镜像压缩文件, 导入到docker

docker load -i centos7-docker-image.gz
docker load -i mariadb-docker-image.gz
docker load -i redis-docker-image.gz
docker load -i solr-docker-image.gz
docker load -i tomcat-docker-image.gz

# 镜像列表
docker images

centos7 容器

docker run \
-it \
--name centos7 \
centos:7 \
bash

# 在容器内, 可以执行命令, 进行测试
ls
pwd
ps

# 退出容器, 回到宿主机
exit

容器命令

# 可以先把之前同名的 centos7 容器删除
docker rm -f centos7

# 启动一个新的容器, 命名为 centos7
docker run \
-dit \
--name centos7 \
centos:7

# 查看容器列表
docker ps        # 列出正在运行的容器
docker ps -a     # 列出全部容器, 包括已经关闭的容器

进入容器执行指定命令

docker exec -it centos7 ls
docker exec -it centos7 pwd
docker exec -it centos7 ps
docker exec -it centos7 mkdir dir1
docker exec -it centos7 ls # 查看容器内部新建的 dir1 目录
docker exec -it centos7 bash
# 退出命令行
exit

目录挂载

# 容器停止时,自动删除容器
# --rm \

# 如果左侧宿主机目录不存在, 会自动创建目录
#-v /usr/app:/opt/app \

docker run \
-dit \
--name centos7 \
--rm \
-v /usr/app:/opt/app \
centos:7

# 进入容器
docker exec -it centos7 bash
echo 111111111111 > /opt/app/f1
cd /opt/app
ls
cat f1

# 在宿主机查看文件
exit
cd /usr/app
ls
cat f1

# 停止容器(停止时,容器会被自动删除)
docker container stop centos7
docker ps -a

ls
cat f1
# 创建数据卷
docker volume create my-vol

# 查看数据卷
docker inspect my-vol

# 启动容器,挂载数据卷
docker run \
-dit \
--name centos7 \
--rm \
-v my-vol:/webapp \
centos:7

# 进入容器
docker exec -it centos7 bash
echo 111111111111 > /webapp/f1
cd /webapp
ls
cat f1
# 在宿主机查看文件
exit
cd /var/lib/docker/volumes/my-vol/_data
ls
cat f1

端口映射

docker run \
-d \
--name tomcat80 \
-p 80:8080 \
--rm \
tomcat

docker ps

docker logs tomcat80

# 浏览器访问
# http://192.168.64.150


Docker 虚拟网络

docker network create my-net

docker network ls
docker inspect my-net

ifconfig

# 启动容器,连入my-net网络
docker run -dit --name app1 --rm --network my-net centos:7

docker run -dit --name app2 --rm --network my-net centos:7

# 查看容器描述
docker inspect app1
docker inspect app2

# 从宿主机ping两个容器
ping 172.18.0.2
ping 172.18.0.3

# 从app1, ping宿主机和app2
docker exec -it app1 ping 172.18.0.1
docker exec -it app1 ping 172.18.0.3
docker exec -it app1 ping app2

Dockerfile构建镜像

  1. 新建文件夹, 把Dockerfile和其他需要的文件,放入这个目录

    mkdir tomcat7
    
    在tomcat7目录下, 放入:
        - Dockerfile
        - jdk-8u212-linux-x64.tar.gz
        - apache-tomcat-7.0.96.tar.gz
        
    cd tomcat7
    # 末尾的点, 表示当前目录, 在当前目录下寻找Dockerfile, 和其他所有文件
    docker build -t tomcat:7 .
    
    # 构建完成后, 查看镜像
    docker images
    

redis

docker run -d --name redis7000 -p 7000:6379 redis

docker exec -it redis7000 redis-cli
keys *
set a b
get a
flushall

docker run -d --name redis7001 -p 7001:6379 redis
docker run -d --name redis7002 -p 7002:6379 redis

docker exec -it redis7000 redis-cli
keys *
exit

docker exec -it redis7001 redis-cli
keys *
exit

docker exec -it redis7002 redis-cli
keys *
exit

web应用 + mysql

# 删除 my-net 网络
docker network rm my-net

# 创建 dockernet
docker network create --subnet 172.18.0.0/24 dockernet

# 创建 mysql-data 数据卷
docker volume create mysql-data

# 启动mysql
docker run \
-d \
--rm \
--name mysql \
-v mysql-data:/var/lib/mysql \
-p 3306:3306 \
--net dockernet \
--ip 172.18.0.11 \
-e MYSQL_ROOT_PASSWORD=root \
mariadb

# 准备web应用的 war 文件
rm -rf /opt/webapps
mkdir /opt/webapps

# 把 ROOT.war 上传到 /opt/webapps

# 启动tomcat
docker run \
-d \
--name tomcat \
--rm \
-v /opt/webapps:/usr/tomcat/webapps \
-p 80:8080 \
--net dockernet \
--ip 172.18.0.12 \
tomcat:7

eureka 和 item

不加配置中心,链路跟踪

  1. 下载 第18章 代码, 导入 1,2,5 三个项目

  2. 修改 2,5 项目的 application.yml, 注册ip地址

eureka:
  instance:
    prefer-ip-address: true

  1. 三个项目打包jar文件

    右键 — run as — maven build …

    ​ goal: install

    ​ 下面勾选: skip tests

构建镜像

准备三个目录

  • jdk8
    • Dockerfile
    • jdk-8u212-linux-x64.tar.gz
  • eureka
    • Dockerfile
    • sp05-eureka-0.0.1-SNAPSHOT.jar
  • item
    • Dockerfile
    • sp02-itemservice-0.0.1-SNAPSHOT.jar

jdk8的Dockerfile和镜像构建

cat <<EOF > Dockerfile
FROM centos:7
ADD jdk-8u212-linux-x64.tar.gz /opt/
ENV JAVA_HOME=/opt/jdk1.8.0_212 \
    PATH=$PATH:/opt/jdk1.8.0_212/bin
EOF

# 构建jdk8镜像
docker build -t jdk:8 .

eureka的Dockerfile和镜像构建

cat <<EOF > Dockerfile
FROM jdk:8
COPY sp05-eureka-0.0.1-SNAPSHOT.jar /opt/
ENTRYPOINT ["java", "-jar", "/opt/sp05-eureka-0.0.1-SNAPSHOT.jar"]
CMD ["--spring.profiles.active=eureka1", "--server.port=2001"]
EOF

# 构建eureka:1镜像
docker build -t eureka:1 .

item的Dockerfile和镜像构建

cat <<EOF > Dockerfile
FROM jdk:8
COPY sp02-itemservice-0.0.1-SNAPSHOT.jar /opt/
ENTRYPOINT ["java", "-jar", "/opt/sp02-itemservice-0.0.1-SNAPSHOT.jar"]
CMD ["--server.port=8001"]
EOF

# 构建item:8001镜像
docker build -t item:8001 .

# 重新构建 item 镜像
docker rmi -f item:8001  # 删镜像
docker rm -f item8001    # 删容器
# 进入 item 目录, 重新执行上面两步, 重修构建镜像

启动eureka容器

# 如果已经启动了eureka,先删除
docker rm -f eureka1

# 启动eureka,连接到dockernet网络
docker  run \
-d \
--name eureka1 \
-p 2001:2001 \
--net dockernet \
eureka:1

# 启动item,连接到dockernet网络
docker  run \
-d \
--name item8001 \
-p 8001:8001 \
--net dockernet \
item:8001

# 访问测试:
http://192.168.64.150:2001
http://192.168.64.150:8001/u56u56u45y3t


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RuEvEnH1-1605679244368)(note.assets/image-20200519115125418.png)]

作业

  1. 下载 第17章代码, 从第18章重做
  2. rabbitmq, 订单流量削峰

k8s部署spring cloud应用

5个文件夹

eureka
	Dockerfile
	sp05-eureka-0.0.1-SNAPSHOT.jar
	
item
	Dockerfile
	sp02-itemservice-0.0.1-SNAPSHOT.jar
	
jdk
	Dockerfile
	jdk-8u212-linux-x64.tar.gz
	
order
	Dockerfile
	sp04-orderservice-0.0.1-SNAPSHOT.jar
	
user
	Dockerfile
	sp03-userservice-0.0.1-SNAPSHOT.jar

上传到 191

  • 上传5个文件夹
  • 上传centos7的镜像, 或者可以在线拉取: docker pull centos:7
    • 把docker目录下的 centos7-docker-image.gz 传到服务器
    • 执行导入: docker load -i centos7-docker-image.gz

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pNKwgdgC-1605679244369)(note.assets/image-20200523143726045.png)]

Spring Cloud

  • 微服务全家桶
  • Netflix 开源项目
    • eureka
    • ribbon
    • hystrix
    • feign
    • zuul
    • hystrix dashboard+turbine
  • Spring Cloud Alibaba

RabbitMQ

  • 使用场景: 解耦, 削峰, 异步调用

  • 你的项目中如何使用RabbitMQ: 订单的流量削峰

  • 六种模式

    • 简单
    • 工作
    • 发布和订阅
    • 路由
    • 主题
    • RPC

Lucene Solr

  • 全文检索引擎

  • 索引: 倒排索引

Docker

  • 容器化

  • 开发,测试,运维, 环境完全一致

Kubernetes

  • 自动化容器部署工具
  • 核心组件
    • Pod
    • 控制器
      • ReplicationController
      • ReplicSet
    • Service
    • Deployment

item 镜像
docker rmi -f item:8001 # 删镜像
docker rm -f item8001 # 删容器

进入 item 目录, 重新执行上面两步, 重修构建镜像




### 启动eureka容器

```shell
# 如果已经启动了eureka,先删除
docker rm -f eureka1

# 启动eureka,连接到dockernet网络
docker  run \
-d \
--name eureka1 \
-p 2001:2001 \
--net dockernet \
eureka:1

# 启动item,连接到dockernet网络
docker  run \
-d \
--name item8001 \
-p 8001:8001 \
--net dockernet \
item:8001

# 访问测试:
http://192.168.64.150:2001
http://192.168.64.150:8001/u56u56u45y3t


[外链图片转存中…(img-RuEvEnH1-1605679244368)]

作业

  1. 下载 第17章代码, 从第18章重做
  2. rabbitmq, 订单流量削峰

k8s部署spring cloud应用

5个文件夹

eureka
	Dockerfile
	sp05-eureka-0.0.1-SNAPSHOT.jar
	
item
	Dockerfile
	sp02-itemservice-0.0.1-SNAPSHOT.jar
	
jdk
	Dockerfile
	jdk-8u212-linux-x64.tar.gz
	
order
	Dockerfile
	sp04-orderservice-0.0.1-SNAPSHOT.jar
	
user
	Dockerfile
	sp03-userservice-0.0.1-SNAPSHOT.jar

上传到 191

  • 上传5个文件夹
  • 上传centos7的镜像, 或者可以在线拉取: docker pull centos:7
    • 把docker目录下的 centos7-docker-image.gz 传到服务器
    • 执行导入: docker load -i centos7-docker-image.gz

[外链图片转存中…(img-pNKwgdgC-1605679244369)]

Spring Cloud

  • 微服务全家桶
  • Netflix 开源项目
    • eureka
    • ribbon
    • hystrix
    • feign
    • zuul
    • hystrix dashboard+turbine
  • Spring Cloud Alibaba

RabbitMQ

  • 使用场景: 解耦, 削峰, 异步调用

  • 你的项目中如何使用RabbitMQ: 订单的流量削峰

  • 六种模式

    • 简单
    • 工作
    • 发布和订阅
    • 路由
    • 主题
    • RPC

Lucene Solr

  • 全文检索引擎

  • 索引: 倒排索引

Docker

  • 容器化

  • 开发,测试,运维, 环境完全一致

Kubernetes

  • 自动化容器部署工具
  • 核心组件
    • Pod
    • 控制器
      • ReplicationController
      • ReplicSet
    • Service
    • Deployment
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值