package org.cloudbus.cloudsim.examples;
/*
程序说明:整个项目利用Cloudsim3.0的云计算仿真框架进行云任务的仿真。
该程序总共有两个类,一个为fuxian5.java,一个为Bee.java,其中在fuxian5.java中创建了多个实验需要用到的全局变量,方便在下边的云任务输出函数中进行调用。
由于vm列表和云任务列表都设置为全局变量,因此,赋值时,需要单独创建对应的函数进行传参,并返回一个值,否则在其他函数中调用该值时将为0。
我们先在主函数中调用虚拟机和云任务列表的创建函数,并赋值,以此来方便其他函数中对这两个列表进行调用。为了使实验更好的进行,我们还对一些虚拟机和云任务的参数进行随机数的产生,进而会生成不同的虚拟机序列和云任务序列,并上传至数据中心。
我们在CreateVmholdIndex()函数中调用Bee类中求出来的最优解以及相关系数,并利用这些值经过计算来返回特定虚拟机的序列号,方便之后的调用。
在createDatacenter()函数中,在进行主机列表,数据中心列表的创建后,调用了costs数组,用来计算云任务的成本值。
在printCloudletList()函数中,先定义了信用值,云任务长度,信用度优先级,存放负载等数组,通过设置各种循环并调用其它函数进行赋值。
通过相应的credit值的设置,通过相关公式来计算实验需要得出的分配任务的长度、任务的优先级、成本和任务的截止日期等参数,并利用这些参数
进而实现将蜜蜂优化算法用于负载平衡,并利用蜂蜜算法的负载对可信任务进行调度的目的。
这里只给出fuxian5.java类,至于蜜蜂优化算法这里不做描述。
*/
import java.text.DecimalFormat;
import java.util.*;
import org.cloudbus.cloudsim.Cloudlet;
import org.cloudbus.cloudsim.CloudletSchedulerTimeShared;
import org.cloudbus.cloudsim.Datacenter;
import org.cloudbus.cloudsim.DatacenterBroker;
import org.cloudbus.cloudsim.DatacenterCharacteristics;
import org.cloudbus.cloudsim.Host;
import org.cloudbus.cloudsim.Log;
import org.cloudbus.cloudsim.Pe;
import org.cloudbus.cloudsim.Storage;
import org.cloudbus.cloudsim.UtilizationModel;
import org.cloudbus.cloudsim.UtilizationModelFull;
import org.cloudbus.cloudsim.Vm;
import org.cloudbus.cloudsim.VmAllocationPolicySimple;
import org.cloudbus.cloudsim.VmSchedulerTimeShared;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.lists.CloudletList;
import org.cloudbus.cloudsim.lists.PeList;
import org.cloudbus.cloudsim.provisioners.BwProvisionerSimple;
import org.cloudbus.cloudsim.provisioners.PeProvisionerSimple;
import org.cloudbus.cloudsim.provisioners.RamProvisionerSimple;
/**
* A simple example showing how to create a datacenter with one host and run one
* cloudlet on it.
*/
public class fuxian5 {
//创建云任务列表
public static List<Cloudlet> cloudletList;
//创建虚拟机列表
public static List<Vm> vmlist;
//定义信任值
public static int credit;
//每个云任务的总成本
public static double costtotal;
//创建Bee类的对象,方便下面的调用
static Bee b2=new Bee();
//用来存储特定虚拟机的序列号
public static int VmholdIndex;
//用来存储特定虚拟机的存储容量
public static double Vmhold;
//特定虚拟机的处理时间
public static double processtime;
/**
* @param userId the args
* 创建虚拟机的函数,方便全局传参
*/
private static List<Vm> createVM(int userId, int vms) {
//创建一个容器用于存储虚拟机,放入列表中
LinkedList<Vm> list = new LinkedList<Vm>();
//设置虚拟机的mips为随机数
int [] mips1=new int[vms];
for(int j=0;j<vms;j++){
mips1[j]=(int)(Math.random()*999+500);
}
//VM 参数
//设置大小
long size = 10000;
//设置虚拟机内存
int ram = 512;
long bw = 1000;
//cpu数量
int pesNumber = 1;
//虚拟机的名字
String vmm = "Xen";
//创建Vms
Vm[] vm = new Vm[vms];
for(int i=0;i<vms;i++){
vm[i] = new Vm(i, userId, mips1[i], pesNumber, ram, bw, size, vmm, new CloudletSchedulerTimeShared());
//为云任务创建一个空间的时间策略
list.add(vm[i]);
}
return list;
}
//创建云任务序列的函数
private static List<Cloudlet> createCloudlet(int userId, int cloudlets){
// 创建一个容器用来存储云任务列表
LinkedList<Cloudlet> list = new LinkedList<Cloudlet>();
//设置循环用于创建云任务长度的随机数
int [] length1=new int[cloudlets];
for(int j=0;j<cloudlets;j++){
length1[j]=(int)(Math.random()*999+1);
}
long fileSize = 300;
long outputSize = 300;
int pesNumber = 1;
UtilizationModel utilizationModel = new UtilizationModelFull();
Cloudlet[] cloudlet = new Cloudlet[cloudlets];
for(int i=0;i<cloudlets;i++){
cloudlet[i] = new Cloudlet(i, length1[i], pesNumber, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel);
cloudlet[i].setUserId(userId);
list.add(cloudlet[i]);
}
return list;
}
public static void main(String[] args) {
// Bee1 x=new Bee1();
Log.printLine("Starting 云计算仿真实验...");
try {
//初始化Cloudsim的包
//云任务使用者的数量
int num_user = 1;
Calendar calendar = Calendar.getInstance();
// mean trace events
boolean trace_flag = false;
// 初始化Cloudsim
CloudSim.init(num_user, calendar, trace_flag);
//创建数据中心的对象,用于仿真
Datacenter datacenter0 = createDatacenter("Datacenter_0");
Datacenter datacenter1 = createDatacenter("Datacenter_1");
// 创建 Broker
DatacenterBroker broker = createBroker();
int brokerId = broker.getId();
//创建20台虚拟机
vmlist = createVM(brokerId,20);
// 创建40个云任务
cloudletList = createCloudlet(brokerId,40);
broker.submitVmList(vmlist);
//递交云任务到broker中
broker.submitCloudletList(cloudletList);
// Starts the simulation
CloudSim.startSimulation();
List<Cloudlet> newList = broker.getCloudletReceivedList();
CloudSim.stopSimulation();
printCloudletList(newList);
datacenter0.printDebts();
datacenter1.printDebts();
Log.printLine("CloudSimExample1 finished!");
} catch (Exception e) {
e.printStackTrace();
Log.printLine("Unwanted errors happen");
}
}
public static int CreateVmholdIndex(int vmholdIndex){
int iter=0;
int j=0;
b2.initial(); /*初始化所有食物源 ,这里为云任务的参数*/
b2.MemorizeBestSource(); /*记录最优解*/
for (iter=0;iter<b2.maxCycle;iter++)
{
b2.SendEmployedBees(); /*雇佣蜂阶段*/
b2.CalculateProbabilities(); /*计算食物源适应度*/
b2.SendOnlookerBees(); /*观察蜂阶段*/
//bee.MemorizeBestSource(); /*记录最优解*/
b2.SendScoutBees(); /*侦查蜂阶段*/
}
for(j=0;j<b2.D;j++) /*循环打印4个最优解的参数*/
{
System.out.println("利用蜜蜂优化算法得出的影响最优解计算的参数["+(j+1)+"]:"+b2.GlobalParams[j]);
}
VmholdIndex=(int)b2.GlobalMin;
if(VmholdIndex>20){
VmholdIndex= VmholdIndex%20;
//由于虚拟机数量为20,所以这里我们必须取余,不然会超出虚拟机列表的长度
}//这里利用人工蜂群算法算出的最优解来求解特定的虚拟机的下角标
return VmholdIndex;
}
//创建数据中心函数
public static Datacenter createDatacenter(String name) {
DatacenterBroker broker = createBroker();
int brokerId = broker.getId();
//创建一个主机列表进行存储
List<Host> hostList = new ArrayList<Host>();
//创建一个云任务列表
List<Cloudlet>cloudletList=new ArrayList<Cloudlet>();
//创建虚拟机列表
List<Vm>vmList=new ArrayList<Vm>();
//这些为创建上述列表的过程中将会用到的参数
int mips = 1000;
long size = 10000;
int ram = 512;
long bw = 1000;
String vmm = "Xen";
int id = 0;
int vmid = 0;
long length = 400000;
long fileSize = 300;
long outputSize = 300;
int pesNumber = 1;
UtilizationModel utilizationModel = new UtilizationModelFull();
//给云任务列表传参
Cloudlet cloudlet = new Cloudlet(id, length, pesNumber, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel);
cloudlet.setVmId(vmid);
// 添加云任务到云任务列表中
cloudletList.add(cloudlet);
//创建用于存放每个任务成本的数组
double [] costs=new double[cloudletList.size()];
Vm vm = new Vm(vmid, brokerId, mips, pesNumber, ram, bw, size, vmm, new CloudletSchedulerTimeShared());
// 添加虚拟机到虚拟机列表中
vmList.add(vm);
//创建PE列表
List<Pe> peList1 = new ArrayList<Pe>();
//创建PE并放入列表中
//需要一个存储pe的id和MIPS比率
peList1.add(new Pe(0, new PeProvisionerSimple(mips)));
peList1.add(new Pe(1, new PeProvisionerSimple(mips)));
peList1.add(new Pe(2, new PeProvisionerSimple(mips)));
peList1.add(new Pe(3, new PeProvisionerSimple(mips)));
List<Pe> peList2 = new ArrayList<Pe>();
peList2.add(new Pe(0, new PeProvisionerSimple(mips)));
peList2.add(new Pe(1, new PeProvisionerSimple(mips)));
//创建主机时,给相关参数赋值
int hostId = 0;
//主机内存
int ram1 = 2048;
//主机的存储空间
long storage = 1000000;
int bw1 = 10000;
hostList.add(
new Host(
hostId,
new RamProvisionerSimple(ram1),
new BwProvisionerSimple(bw1),
storage,
peList1,
new VmSchedulerTimeShared(peList1)
)
);//第一台主机
hostId++;
hostList.add(
new Host(
hostId,
new RamProvisionerSimple(ram),
new BwProvisionerSimple(bw),
storage,
peList2,
new VmSchedulerTimeShared(peList2)
)
); // 第二台主机
//系统框架
String arch = "x86";
//操作系统名称
String os = "Linux";
double time_zone = 10.0;
//在这个资源中进程在使用时的消耗
double cost = 3.0;
//在这个资源中使用内存的消耗
double costPerMem = 0.05;
//存储空间的消耗
double costPerStorage = 0.001;
// 在这个资源中Bw的消耗
double costPerBw = 0.0;
LinkedList<Storage> storageList = new LinkedList<Storage>();
DatacenterCharacteristics characteristics = new DatacenterCharacteristics(
arch, os, vmm, hostList, time_zone, cost, costPerMem,
costPerStorage, costPerBw);
//该循环用于获取云任务的成本
for(int o=0;o<cloudletList.size();o++){
costs[o]=characteristics.getCostPerMem()*vmList.get(o).getRam()+ characteristics.getCostPerStorage()*vmList.get(o).getSize();
}
//创建一个Power数据中心
Datacenter datacenter = null;
try {
datacenter = new Datacenter(name, characteristics, new VmAllocationPolicySimple(hostList), storageList, 0);
} catch (Exception e) {
e.printStackTrace();
}
return datacenter;
}
//创建broker
public static DatacenterBroker createBroker() {
DatacenterBroker broker = null;
try {
broker = new DatacenterBroker("Broker");
} catch (Exception e) {
e.printStackTrace();
return null;
}
return broker;
}
//创建云任务列表的函数
public static void printCloudletList(List<Cloudlet> list) {
int size = list.size();
Cloudlet cloudlet;
String indent = " ";
Log.printLine();
Log.printLine("========== OUTPUT ==========");
Log.printLine("Cloudlet ID" + indent + "STATUS" + indent
+ "Data center ID" + indent + "VM ID" + indent + "Time" + indent
+ "Start Time" + indent + "Finish Time");
DecimalFormat dft = new DecimalFormat("###.##");
int k;//g为MIPS最大值的虚拟机编码,k为中间替换参数,这里和上边一样用冒泡排序
int [] b =new int[size];//b数组用于存放每个任务的长度
int [] c =new int[size];//最终存放每个任务的信用值
int [] q =new int[size];//q数组为经过计算后的每个任务的长度
double [] d =new double[size]; //创建信用度优先级的数组
int [] e =new int[vmlist.size()];//创建vm的数组,用来存放数组列表中所有的mips长度
double [] deadline=new double[size]; //创建用来放置Deadline_task的数组
double [] Load=new double[size];//用来存放虚拟机中负载的数组
double cost=0.8;//确定成本系数
double [] vmholds=new double[vmlist.size()];//创建用来存储各个虚拟机总容量的数组
double vmaverrage;//虚拟机的标准差
int [] a=new int[vmlist.size()];//该数组用于存放存储过载虚拟机的序列号,等价于将过载的虚拟机放入过载序列中
for (int i = 0; i < size; i++) {
cloudlet = list.get(i);
//用于存放每个任务的长度
b[i]= (int) list.get(i).getCloudletLength();
//int [] c =new int[size];//用于存放每个调度任务的credit值
Log.print(indent + cloudlet.getCloudletId() + indent + indent);
if (cloudlet.getCloudletStatus() == Cloudlet.SUCCESS) {
Log.print("SUCCESS");
Log.printLine(indent + indent + cloudlet.getResourceId()
+ indent + indent + indent + cloudlet.getVmId()
+ indent + indent
+ dft.format(cloudlet.getActualCPUTime()) + indent
+ indent + dft.format(cloudlet.getExecStartTime())
+ indent + indent
+ dft.format(cloudlet.getFinishTime()));
}
}
for (int f=0;f< vmlist.size();f++){
e[f]=(int) vmlist.get(f).getMips();
//该循环用于获取虚拟机列表中各个元素的MIPS长度
}
//通过冒泡法将MIPS最大的虚拟机置换到最前边,即MIPS长度最大的虚拟机的数组编码为0
for (int h=0;h< vmlist.size();h++){
if(e[h]<e[h++]){
k=e[h];
e[h]=e[h++];
e[h++]=k;
}
}
double total=0.0;
for(int j=0;j<size;j++){
int t;//作为下边交换的中间值
int m=0,n;//m为任务列表中每个任务的长度,n为平均值
m=(int) (m+b[j]);
n=m/(j+1);
q[j]=(int)Math.abs(n-b[j]+1);//这里调用Math里面的绝对值函数
//均为实验中计算信用值的参数
int a1,a2,a3,a4;
//该循环用来求出所有任务的长度的最大值
for(int y=1;y<size;y++){
if (b[y]>b[j]){
t=b[y];
b[y]=b[j];
b[j]=t;
}//这块需要注意,要放在大循环的外边,因为必须等待云任务列表中所有的云任务被分配完毕后,才能调用
}
a1=b[0]/5;
a2=b[0]/4;
a3=a2+a1;
a4=a3+a2;
//设置if语句用来设置信用值
if (q[j] <= a1 || a1 == 1) {
credit = 5;
} else if (a1 < q[j] && q[j] <= a2) {
credit = 4;
} else if (a2 < q[j] && q[j] <= a3) {
credit = 3;
} else if (a3 < q[j] && q[j] <= a4) {
credit = 2;
} else {
credit = 1;
}
//最终存放每个任务的信用值
c[j]=credit;
//d[j]为每个任务的优先级的权重,方便之后的调用
d[j]=c[j]*1000/q[j];//这里的可分除因素我们选用上边的q[i]
//用来放置Deadline_task
deadline[j]= (c[j]*d[j]/e[0]);
//计算出所有云任务的总成本costs[i]
costtotal=c[j]*d[j]*deadline[j]*cost;
//设置if语句,由于虚拟机在创建时的个数为20,云任务为40,则输出20个虚拟机中的负载的大小
if(j<20) {
Load[j] = vmlist.get(j).getSize() * b[j] / (vmlist.get(j).getMips()*10);
Log.printLine(" ");
Log.printLine("虚拟机"+j+"负载量为:"+Load[j]);
}
//这里创建Bee类的对象,获取Bee类的参数
b2.NP= vmlist.size();
b2.FoodNumber= list.size();
for (int i=0;i< b2.FoodNumber;i++){
b2.Credit[i]=c[i];
b2.Cost[i]=cost;
b2.deadline[i]=deadline[i];
b2.length[i]=list.size();
}
Log.printLine("");
Log.printLine("云任务"+j+"的长度为:"+q[j]);
Log.printLine("云任务"+j+"的优先级权重为:"+d[j]);
Log.printLine("云任务"+j+"的成本为:"+costtotal);
total=total+costtotal;
}
Log.printLine("云任务的总成本数:"+total);
//计算特定虚拟机的序列号
VmholdIndex=CreateVmholdIndex((int)b2.GlobalMin);
Log.printLine("特定虚拟机的序列号为:"+VmholdIndex);
//计算特定虚拟机的总容量
Vmhold=vmlist.size()*vmlist.get(VmholdIndex).getMips()+vmlist.get(VmholdIndex).getBw();
Log.printLine("特定虚拟机的总容量为:"+Vmhold);
Log.printLine("特定虚拟机的负荷为:"+Load[VmholdIndex]);
//计算该虚拟机处理的时间
processtime=Load[VmholdIndex]/Vmhold;
Log.printLine("处理时间:"+processtime+"ms");
double o=0;
double y;
//设置循环,用来存储所有虚拟机的容量,方便计算虚拟机的标准差
for(int p=0;p<vmlist.size();p++){
vmholds[p]=vmlist.size()*vmlist.get(p).getMips()+vmlist.get(p).getBw();
//o用来存放所有虚拟机的总容量
o=o+vmholds[p];
}
//虚拟机容量的平均值
y=o/vmlist.size();
double fangcha=0;
for(int n=0;n<vmlist.size();n++){
fangcha=fangcha+(vmholds[n]-y)*(vmholds[n]-y);
}
//这里获取虚拟机的标准差
vmaverrage=Math.sqrt(fangcha);
Log.printLine("虚拟机容量的标准差"+vmaverrage);
//这里设置循环,存放超载的虚拟机的序列号
for(int f=0;f<vmlist.size();f++){
if(vmholds[f]<vmaverrage){
a[f]=f;
}
}
List l=new java.util.ArrayList();
//该循环进行数组中相同数的过滤
for(int t=0;t<a.length;t++){
if(!l.contains(a[t]))
l.add(a[t]);
}
Log.printLine("20台虚拟机中超负载虚拟机的序号:(注意:这里由于输出的为过载的虚拟机序列号,根据实验要求将会停止仿真)");
//设置循环,将上述数组中过滤后的数值给输出出来
for(Iterator ll = l.iterator(); ll.hasNext();){
Log.printLine(ll.next());
CloudSim.stopSimulation();
}
Log.printLine(" ");
Log.printLine("仿真完毕!!!");
}
}
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in
给定两个大小相等的数组,如何找到不考虑位置的匹配元素的数量?例如:[0,0,5]和[0,5,5]将返回2的匹配项,因为有一个0和一个5共同;[1,0,0,3]和[0,0,1,4]将返回3的匹配项,因为0有两场,1有一场;[1,2,2,3]和[1,2,3,4]将返回3的匹配项。我尝试了很多想法,但它们都变得相当粗糙和令人费解。我猜想有一些不错的Ruby习惯用法,或者可能是一个正则表达式,可以很好地回答这个解决方案。 最佳答案 您可以使用count完成它:a.count{|e|index=b.index(e)andb.delete_at
我想开始使用“Sinatra”框架进行编码,但我找不到该框架的“MVC”模式。是“MVC-Sinatra”模式或框架吗? 最佳答案 您可能想查看Padrino这是一个围绕Sinatra构建的框架,可为您的项目提供更“类似Rails”的感觉,但没有那么多隐藏的魔法。这是使用Sinatra可以做什么的一个很好的例子。虽然如果您需要开始使用这很好,但我个人建议您将它用作学习工具,以对您来说最有意义的方式使用Sinatra构建您自己的应用程序。写一些测试/期望,写一些代码,通过测试-重复:)至于ORM,你还应该结帐Sequel其中(imho